selective-ui 1.2.4 → 1.2.6
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/README.md +7 -0
- package/dist/selective-ui.css +64 -58
- package/dist/selective-ui.css.map +1 -1
- package/dist/selective-ui.esm.js +4396 -1344
- 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 +4401 -1345
- package/dist/selective-ui.umd.js.map +1 -1
- package/package.json +3 -3
- package/src/css/components/accessorybox.css +1 -1
- package/src/css/components/directive.css +2 -2
- package/src/css/components/option-handle.css +4 -4
- package/src/css/components/placeholder.css +1 -1
- package/src/css/components/popup/empty-state.css +3 -3
- package/src/css/components/popup/loading-state.css +3 -3
- package/src/css/components/popup/popup.css +5 -5
- package/src/css/components/searchbox.css +2 -2
- package/src/css/components/selectbox.css +7 -7
- package/src/css/views/group-view.css +8 -8
- package/src/css/views/option-view.css +22 -22
- package/src/ts/adapter/mixed-adapter.ts +248 -92
- package/src/ts/components/accessorybox.ts +170 -73
- package/src/ts/components/directive.ts +55 -26
- package/src/ts/components/option-handle.ts +127 -60
- package/src/ts/components/placeholder.ts +73 -35
- package/src/ts/components/popup/empty-state.ts +71 -35
- package/src/ts/components/popup/loading-state.ts +73 -33
- package/src/ts/components/popup/popup.ts +19 -39
- package/src/ts/components/searchbox.ts +189 -50
- package/src/ts/components/selectbox.ts +401 -40
- package/src/ts/core/base/adapter.ts +160 -79
- package/src/ts/core/base/fenwick.ts +147 -0
- package/src/ts/core/base/lifecycle.ts +118 -35
- package/src/ts/core/base/model.ts +94 -36
- package/src/ts/core/base/recyclerview.ts +0 -1
- package/src/ts/core/base/view.ts +54 -23
- package/src/ts/core/base/virtual-recyclerview.ts +365 -283
- package/src/ts/core/model-manager.ts +172 -92
- package/src/ts/core/search-controller.ts +166 -93
- package/src/ts/global.ts +26 -5
- package/src/ts/index.ts +22 -3
- package/src/ts/models/group-model.ts +138 -32
- package/src/ts/models/option-model.ts +197 -53
- package/src/ts/services/dataset-observer.ts +72 -10
- package/src/ts/services/ea-observer.ts +87 -10
- package/src/ts/services/effector.ts +181 -32
- package/src/ts/services/refresher.ts +32 -7
- package/src/ts/services/resize-observer.ts +136 -19
- package/src/ts/services/select-observer.ts +115 -50
- package/src/ts/types/core/base/view.type.ts +3 -3
- package/src/ts/types/core/base/virtual-recyclerview.type.ts +1 -1
- package/src/ts/types/plugins/plugin.type.ts +46 -0
- package/src/ts/types/utils/ievents.type.ts +6 -1
- package/src/ts/types/utils/istorage.type.ts +8 -4
- package/src/ts/types/utils/libs.type.ts +2 -2
- package/src/ts/types/utils/selective.type.ts +14 -1
- package/src/ts/utils/callback-scheduler.ts +115 -37
- package/src/ts/utils/ievents.ts +91 -29
- package/src/ts/utils/libs.ts +41 -65
- package/src/ts/utils/selective.ts +412 -79
- package/src/ts/views/group-view.ts +142 -31
- package/src/ts/views/option-view.ts +272 -60
|
@@ -1,41 +1,106 @@
|
|
|
1
|
-
|
|
2
1
|
import { View } from "../core/base/view";
|
|
3
2
|
import { Libs } from "../utils/libs";
|
|
4
3
|
import type { GroupViewTags, GroupViewResult } from "../types/views/view.group.type";
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* GroupView
|
|
7
|
+
*
|
|
8
|
+
* View implementation for rendering grouped collections of selectable items.
|
|
9
|
+
*
|
|
10
|
+
* ### Responsibility
|
|
11
|
+
* - Renders a semantic group structure: header (label) + items container.
|
|
12
|
+
* - Manages group-level visibility based on child item state.
|
|
13
|
+
* - Supports collapse/expand interactions with accessibility annotations.
|
|
14
|
+
* - Provides typed access to DOM structure via {@link view}.
|
|
15
|
+
*
|
|
16
|
+
* ### Structure
|
|
17
|
+
* ```
|
|
18
|
+
* GroupView (root)
|
|
19
|
+
* ├─ GroupHeader (label, role="presentation")
|
|
20
|
+
* └─ GroupItems (container, role="group")
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* ### Lifecycle (View-based FSM)
|
|
24
|
+
* - **Construction**: Accepts parent container, transitions `NEW → INITIALIZED`.
|
|
25
|
+
* - **{@link mount}**: Creates DOM structure, appends to parent, transitions `INITIALIZED → MOUNTED`.
|
|
26
|
+
* - **{@link update}**: Refreshes group header label, transitions `MOUNTED → UPDATED → MOUNTED`.
|
|
27
|
+
* - **{@link destroy}**: Removes DOM nodes, transitions to `DESTROYED`.
|
|
28
|
+
*
|
|
29
|
+
* ### Visibility semantics
|
|
30
|
+
* - {@link updateVisibility} hides the entire group when all child items are hidden.
|
|
31
|
+
* - Checks for `"hide"` class on children (does not inspect `display` or `visibility` styles).
|
|
9
32
|
*
|
|
10
|
-
*
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
33
|
+
* ### Accessibility
|
|
34
|
+
* - Root container: `role="group"`, `aria-labelledby` points to header.
|
|
35
|
+
* - Header: `role="presentation"`, unique ID for labeling.
|
|
36
|
+
* - Items container: `role="group"` (nested group).
|
|
37
|
+
* - Collapse state: `aria-expanded` attribute on header (managed by {@link setCollapsed}).
|
|
38
|
+
*
|
|
39
|
+
* ### DOM side effects
|
|
40
|
+
* - {@link mount} creates and appends DOM structure.
|
|
41
|
+
* - {@link updateLabel} mutates header `textContent`.
|
|
42
|
+
* - {@link setCollapsed} toggles CSS classes and ARIA attributes.
|
|
43
|
+
* - {@link updateVisibility} toggles `"hide"` class on root.
|
|
44
|
+
*
|
|
45
|
+
* ### No-op / Idempotency
|
|
46
|
+
* - {@link updateLabel}, {@link updateVisibility}, {@link setCollapsed} are no-ops if not mounted (early return guards).
|
|
47
|
+
* - Safe to call multiple times without side effects beyond DOM state updates.
|
|
13
48
|
*
|
|
14
49
|
* @extends View<GroupViewTags>
|
|
50
|
+
* @template GroupViewTags - Type descriptor for the group's DOM structure.
|
|
51
|
+
* @see {@link GroupViewResult}
|
|
52
|
+
* @see {@link View}
|
|
15
53
|
*/
|
|
16
54
|
export class GroupView extends View<GroupViewTags> {
|
|
17
55
|
|
|
18
56
|
/**
|
|
19
57
|
* Strongly-typed reference to the mounted group view structure.
|
|
20
|
-
*
|
|
58
|
+
*
|
|
59
|
+
* Structure:
|
|
60
|
+
* - **view**: Root container element.
|
|
61
|
+
* - **tags**: Named references to header and items container.
|
|
62
|
+
*
|
|
63
|
+
* Lifecycle:
|
|
64
|
+
* - `null` until {@link mount} completes.
|
|
65
|
+
* - Cleared during {@link destroy}.
|
|
66
|
+
*
|
|
67
|
+
* @public
|
|
21
68
|
*/
|
|
22
69
|
public view: GroupViewResult | null = null;
|
|
23
70
|
|
|
24
71
|
/**
|
|
25
72
|
* Mounts the group view into the DOM.
|
|
26
73
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
74
|
+
* Creation flow:
|
|
75
|
+
* 1. Generates unique group ID (7-character random string).
|
|
76
|
+
* 2. Creates DOM structure via {@link Libs.mountNode}:
|
|
77
|
+
* - Root: `<div role="group" aria-labelledby="seui-{id}-header">`
|
|
78
|
+
* - Header: `<div role="presentation" id="seui-{id}-header">`
|
|
79
|
+
* - Items: `<div role="group">` (nested group for child items)
|
|
80
|
+
* 3. Appends root to {@link parent} container.
|
|
81
|
+
* 4. Transitions `INITIALIZED → MOUNTED` via `super.mount()`.
|
|
82
|
+
*
|
|
83
|
+
* Accessibility setup:
|
|
84
|
+
* - Root `aria-labelledby` associates group with header text.
|
|
85
|
+
* - Header `role="presentation"` hides it from navigation (purely visual label).
|
|
86
|
+
* - Items container `role="group"` creates semantic boundary for children.
|
|
87
|
+
*
|
|
88
|
+
* Postcondition:
|
|
89
|
+
* - {@link view} is populated with typed DOM references.
|
|
90
|
+
*
|
|
91
|
+
* @public
|
|
92
|
+
* @returns {void}
|
|
93
|
+
* @override
|
|
94
|
+
* @throws {Error} If {@link parent} is null (should never occur due to base `View` constructor).
|
|
30
95
|
*/
|
|
31
96
|
public override mount(): void {
|
|
32
97
|
const group_id = Libs.randomString(7);
|
|
33
98
|
|
|
34
|
-
this.view = Libs.
|
|
99
|
+
this.view = Libs.mountNode<GroupViewResult>({
|
|
35
100
|
GroupView: {
|
|
36
101
|
tag: {
|
|
37
102
|
node: "div",
|
|
38
|
-
classList: ["
|
|
103
|
+
classList: ["seui-group"],
|
|
39
104
|
role: "group",
|
|
40
105
|
ariaLabelledby: `seui-${group_id}-header`,
|
|
41
106
|
id: `seui-${group_id}-group`,
|
|
@@ -44,7 +109,7 @@ export class GroupView extends View<GroupViewTags> {
|
|
|
44
109
|
GroupHeader: {
|
|
45
110
|
tag: {
|
|
46
111
|
node: "div",
|
|
47
|
-
classList: ["
|
|
112
|
+
classList: ["seui-group-header"],
|
|
48
113
|
role: "presentation",
|
|
49
114
|
id: `seui-${group_id}-header`,
|
|
50
115
|
},
|
|
@@ -52,13 +117,13 @@ export class GroupView extends View<GroupViewTags> {
|
|
|
52
117
|
GroupItems: {
|
|
53
118
|
tag: {
|
|
54
119
|
node: "div",
|
|
55
|
-
classList: ["
|
|
120
|
+
classList: ["seui-group-items"],
|
|
56
121
|
role: "group",
|
|
57
122
|
},
|
|
58
123
|
},
|
|
59
124
|
},
|
|
60
125
|
},
|
|
61
|
-
})
|
|
126
|
+
});
|
|
62
127
|
|
|
63
128
|
// Parent is guaranteed to exist by the base View constructor.
|
|
64
129
|
this.parent!.appendChild(this.view.view);
|
|
@@ -67,10 +132,19 @@ export class GroupView extends View<GroupViewTags> {
|
|
|
67
132
|
}
|
|
68
133
|
|
|
69
134
|
/**
|
|
70
|
-
*
|
|
135
|
+
* Updates the group view in response to state changes.
|
|
136
|
+
*
|
|
137
|
+
* Behavior:
|
|
138
|
+
* - Refreshes the group header label via {@link updateLabel}.
|
|
139
|
+
* - Transitions `MOUNTED → UPDATED → MOUNTED` via `super.update()`.
|
|
71
140
|
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
141
|
+
* Notes:
|
|
142
|
+
* - Currently performs only label refresh; extend for additional update logic.
|
|
143
|
+
* - Does **not** update visibility or collapse state automatically.
|
|
144
|
+
*
|
|
145
|
+
* @public
|
|
146
|
+
* @returns {void}
|
|
147
|
+
* @override
|
|
74
148
|
*/
|
|
75
149
|
public override update(): void {
|
|
76
150
|
this.updateLabel();
|
|
@@ -80,8 +154,18 @@ export class GroupView extends View<GroupViewTags> {
|
|
|
80
154
|
/**
|
|
81
155
|
* Updates the text content of the group header.
|
|
82
156
|
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
157
|
+
* Behavior:
|
|
158
|
+
* - No-op if not mounted ({@link view} is `null`).
|
|
159
|
+
* - If `label` is `null`, preserves existing header text.
|
|
160
|
+
* - Otherwise, replaces header `textContent` with new label.
|
|
161
|
+
*
|
|
162
|
+
* Notes:
|
|
163
|
+
* - Does **not** escape HTML (uses `textContent`, not `innerHTML`).
|
|
164
|
+
* - Safe to call multiple times with same value (idempotent).
|
|
165
|
+
*
|
|
166
|
+
* @public
|
|
167
|
+
* @param {string | null} [label=null] - New label to display; `null` preserves current label.
|
|
168
|
+
* @returns {void}
|
|
85
169
|
*/
|
|
86
170
|
public updateLabel(label: string | null = null): void {
|
|
87
171
|
if (!this.view) return;
|
|
@@ -93,11 +177,15 @@ export class GroupView extends View<GroupViewTags> {
|
|
|
93
177
|
}
|
|
94
178
|
|
|
95
179
|
/**
|
|
96
|
-
* Returns the container element
|
|
97
|
-
* belonging to this group.
|
|
180
|
+
* Returns the container element for child item views.
|
|
98
181
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
182
|
+
* Usage:
|
|
183
|
+
* - Caller appends `OptionView` or other child views to this container.
|
|
184
|
+
* - Container provides semantic grouping (`role="group"`).
|
|
185
|
+
*
|
|
186
|
+
* @public
|
|
187
|
+
* @returns {HTMLDivElement} The items container element.
|
|
188
|
+
* @throws {Error} If the view has not been mounted yet ({@link view} is `null`).
|
|
101
189
|
*/
|
|
102
190
|
public getItemsContainer(): HTMLDivElement {
|
|
103
191
|
if (!this.view) {
|
|
@@ -107,10 +195,22 @@ export class GroupView extends View<GroupViewTags> {
|
|
|
107
195
|
}
|
|
108
196
|
|
|
109
197
|
/**
|
|
110
|
-
* Updates the visibility
|
|
198
|
+
* Updates the group's visibility based on child item state.
|
|
199
|
+
*
|
|
200
|
+
* Visibility rules:
|
|
201
|
+
* - Iterates through direct children of the items container.
|
|
202
|
+
* - Counts children **without** the `"hide"` CSS class.
|
|
203
|
+
* - Toggles `"hide"` class on root container:
|
|
204
|
+
* - **Added** if all children are hidden (zero visible).
|
|
205
|
+
* - **Removed** if any child is visible.
|
|
206
|
+
*
|
|
207
|
+
* Notes:
|
|
208
|
+
* - No-op if not mounted ({@link view} is `null`).
|
|
209
|
+
* - Only checks for `"hide"` class; does **not** inspect `display` or `visibility` styles.
|
|
210
|
+
* - Safe to call repeatedly (idempotent based on current child state).
|
|
111
211
|
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
212
|
+
* @public
|
|
213
|
+
* @returns {void}
|
|
114
214
|
*/
|
|
115
215
|
public updateVisibility(): void {
|
|
116
216
|
if (!this.view) return;
|
|
@@ -126,11 +226,22 @@ export class GroupView extends View<GroupViewTags> {
|
|
|
126
226
|
/**
|
|
127
227
|
* Sets the collapsed/expanded state of the group.
|
|
128
228
|
*
|
|
129
|
-
*
|
|
130
|
-
* -
|
|
131
|
-
* -
|
|
229
|
+
* State updates:
|
|
230
|
+
* - **CSS**: Toggles `"collapsed"` class on root container.
|
|
231
|
+
* - **ARIA**: Sets `aria-expanded` attribute on header (`"true"` or `"false"`).
|
|
232
|
+
*
|
|
233
|
+
* Visual effects:
|
|
234
|
+
* - CSS class typically controls item container visibility (via stylesheet).
|
|
235
|
+
* - ARIA attribute communicates state to assistive technologies.
|
|
236
|
+
*
|
|
237
|
+
* Notes:
|
|
238
|
+
* - No-op if not mounted ({@link view} is `null`).
|
|
239
|
+
* - Does **not** animate or transition; relies on CSS for presentation.
|
|
240
|
+
* - Safe to call with same value repeatedly (idempotent).
|
|
132
241
|
*
|
|
133
|
-
* @
|
|
242
|
+
* @public
|
|
243
|
+
* @param {boolean} collapsed - `true` to collapse the group; `false` to expand.
|
|
244
|
+
* @returns {void}
|
|
134
245
|
*/
|
|
135
246
|
public setCollapsed(collapsed: boolean): void {
|
|
136
247
|
if (!this.view) return;
|