selectic 3.0.21 → 3.1.0

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 (43) hide show
  1. package/dist/selectic.common.js +545 -67
  2. package/dist/selectic.esm.js +546 -69
  3. package/doc/changeIcons.md +118 -0
  4. package/doc/changeText.md +1 -1
  5. package/doc/domProperties.md +57 -19
  6. package/doc/extendedProperties.md +83 -72
  7. package/doc/main.md +2 -0
  8. package/doc/params.md +177 -112
  9. package/doc/properties.md +42 -0
  10. package/package.json +4 -4
  11. package/src/ExtendedList.tsx +53 -6
  12. package/src/Filter.tsx +11 -9
  13. package/src/Icon.tsx +199 -0
  14. package/src/List.tsx +12 -6
  15. package/src/MainInput.tsx +15 -11
  16. package/src/Store.tsx +290 -123
  17. package/src/css/selectic.css +24 -0
  18. package/src/icons/caret-down.tsx +21 -0
  19. package/src/icons/caret-up.tsx +21 -0
  20. package/src/icons/check.tsx +23 -0
  21. package/src/icons/question.tsx +21 -0
  22. package/src/icons/search.tsx +21 -0
  23. package/src/icons/spinner.tsx +21 -0
  24. package/src/icons/strikeThrough.tsx +21 -0
  25. package/src/icons/times.tsx +21 -0
  26. package/src/index.tsx +78 -37
  27. package/test/Store/Store_computed.spec.js +84 -0
  28. package/test/Store/changeIcons.spec.js +154 -0
  29. package/test/Store/selectGroup.spec.js +389 -0
  30. package/test/Store/selectItem.spec.js +100 -46
  31. package/test/helper.js +38 -34
  32. package/types/ExtendedList.d.ts +7 -2
  33. package/types/Icon.d.ts +25 -0
  34. package/types/Store.d.ts +142 -5
  35. package/types/icons/caret-down.d.ts +6 -0
  36. package/types/icons/caret-up.d.ts +6 -0
  37. package/types/icons/check.d.ts +6 -0
  38. package/types/icons/question.d.ts +6 -0
  39. package/types/icons/search.d.ts +6 -0
  40. package/types/icons/spinner.d.ts +6 -0
  41. package/types/icons/strikeThrough.d.ts +6 -0
  42. package/types/icons/times.d.ts +6 -0
  43. package/types/index.d.ts +74 -1
package/doc/params.md CHANGED
@@ -2,46 +2,93 @@
2
2
 
3
3
  [Back to documentation index](main.md)
4
4
 
5
+ [List of all properties](properties.md)
6
+
5
7
  In property `params` you can configure selectic to behave the way you want.
6
8
  All configurations set in this property should not change during the component life.
7
9
 
8
10
  This property is an object with several attributes which are listed below.
9
11
 
12
+ * [allowClearSelection](params.md#allowclearselection)
13
+ * [allowRevert](params.md#allowrevert)
14
+ * [autoDisabled](params.md#autodisabled)
15
+ * [autoSelect](params.md#autoselect)
16
+ * [disableGroupSelection](params.md#disableGroupSelection)
17
+ * [emptyValue](params.md#emptyvalue)
18
+ * [fetchCallback](params.md#fetchcallback)
19
+ * [forceSelectAll](params.md#forceselectall)
20
+ * [formatOption](params.md#formatoption)
21
+ * [formatSelection](params.md#formatselection)
22
+ * [getItemsCallback](params.md#getitemscallback)
23
+ * [hideFilter](params.md#hidefilter)
24
+ * [keepOpenWithOtherSelectic](params.md#keepopenwithotherselectic)
25
+ * [listPosition](params.md#listposition)
26
+ * [optionBehavior](params.md#optionbehavior)
27
+ * [pageSize](params.md#pagesize)
28
+ * [selectionOverflow](params.md#selectionoverflow)
29
+ * [strictValue](params.md#strictvalue)
10
30
 
11
- ## hideFilter
31
+ ## allowClearSelection
12
32
 
13
- Type: `boolean` | `'auto'` | `'open'`
33
+ Type: `boolean`
14
34
 
15
- If `hideFilter` is set to `true`, the handler to open the filter panel is hidden and it will not be possible to search for options.
35
+ If `allowClearSelection` is set to `true`, it will be possible to remove the selection to have nothing selected.
16
36
 
17
- If `hideFilter` is set to `'auto`, the handler to open the filter panel is hidden only if there is less than 10 options (when there is no scroll), and is displayed otherwise. _This is the default value_.
37
+ If `allowClearSelection` is set to `false`, it won't be possible to have nothing selected since an item has been selected. _This is the default value_.
18
38
 
19
- If `hideFilter` is set to `false`, the handler to open the filter panel is always displayed.
39
+ ```html
40
+ <selectic
41
+ :params="{
42
+ allowClearSelection: true,
43
+ }"
44
+ :options="optionList"
45
+ />
46
+ ```
20
47
 
21
- If `hideFilter` is set to `'open'`, the handler to open or close the filter panel
22
- will not be displayed and the filter panel is always open.
48
+ ## allowRevert
49
+
50
+ Type: `boolean` | `undefined`
51
+
52
+ In _multiple_ mode, it is possible to invert the selection.
53
+ However in _dynamic_ mode selectic does not know all options so it cannot select the opposite selections.
54
+
55
+ To allow this feature in _dynamic_ mode, there is a property `selectionIsExcluded` which means that values returned by `getValue()`, `getSelection()` or emitted events are the ones which are not selected.
56
+
57
+ As this behavior is more complex, it is needed to set `allowRevert` to `true` to enable it.
58
+
59
+ Read [the dynamic documentation](dynamic.md) for more information.
60
+
61
+ If `allowRevert` is set to `false`, the action to invert the selection will always be disabled.
62
+
63
+ If `allowRevert` is set to `true`, the action to invert the selection will always be enabled. The parent of selectic component should support `selectionIsExcluded` property (which can be applied in _dynamic_ mode).
64
+
65
+ If `allowRevert` is set to `undefined` (is not set), the action to invert the selection will be enabled only if the `selectionIsExcluded` property is not needed (always in _static_ mode, and in _dynamic_ mode when all options are already fetched).
66
+
67
+ Read [the extended properties documentation](extendedProperties.md) for more information about `selectionIsExcluded`.
23
68
 
24
69
  ```html
25
70
  <selectic
26
71
  :params="{
27
- hideFilter: false,
72
+ allowRevert: true,
28
73
  }"
29
74
  :options="optionList"
30
75
  />
31
76
  ```
32
77
 
33
- ## allowClearSelection
78
+ ## autoDisabled
34
79
 
35
80
  Type: `boolean`
36
81
 
37
- If `allowClearSelection` is set to `true`, it will be possible to remove the selection to have nothing selected.
82
+ If `autoDisabled` is set to `true`, it will disable automatically the component if the list of options is empty or if there is only one which must be selected (`allowClearSelection` is not set).
38
83
 
39
- If `allowClearSelection` is set to `false`, it won't be possible to have nothing selected since an item has been selected. _This is the default value_.
84
+ It doesn't apply for dynamic list ([see dynamic configuration](dynamic.md)).
85
+
86
+ By default, it is set to `true`.
40
87
 
41
88
  ```html
42
89
  <selectic
43
90
  :params="{
44
- allowClearSelection: true,
91
+ autoDisabled: true,
45
92
  }"
46
93
  :options="optionList"
47
94
  />
@@ -66,73 +113,108 @@ By default, it is set to `true` if `multiple` is not set, to `false` otherwise.
66
113
  />
67
114
  ```
68
115
 
69
- ## autoDisabled
116
+ ## disableGroupSelection
70
117
 
71
118
  Type: `boolean`
72
119
 
73
- If `autoDisabled` is set to `true`, it will disable automatically the component if the list of options is empty or if there is only one which must be selected (`allowClearSelection` is not set).
120
+ In multiple mode, if there are groups. It is possible to select all items
121
+ under this group by clicking only on the group name.
74
122
 
75
- It doesn't apply for dynamic list ([see dynamic configuration](dynamic.md)).
123
+ If `disableGroupSelection` is set to `true`, it will not be possible to click on the group (and so it will not select the items inside it).
76
124
 
77
- By default, it is set to `true`.
125
+ By default, it is set to `false`.
126
+
127
+ Note: Enabling this option may improve performance with long list of options.
78
128
 
79
129
  ```html
80
130
  <selectic
81
131
  :params="{
82
- autoDisabled: true,
132
+ autoSelect: false,
83
133
  }"
84
134
  :options="optionList"
85
135
  />
86
136
  ```
87
137
 
88
- ## strictValue
138
+ ### group selection
89
139
 
90
- Type: `boolean`
140
+ Clicking on a group name, will select all items inside it.
91
141
 
92
- If `strictValue` is set to `true`, it will consider value as `undefined` if its value is not an id of `options`.
142
+ If all items are already selected, then they all become unselected.
93
143
 
94
- By default, it is set to `false`.
144
+ This behavior works only with the following condition:
145
+
146
+ * multiple mode should be enabled: we should be able to select several items.
147
+
148
+ * the component should be in static mode: otherwise it will not be possible to know which items are not loaded yet.
149
+
150
+ * the group should not be disabled: this is a way to forbid this action on some groups.
151
+
152
+ * the parameter `disableGroupSelection` should not be `true`: this is to disabled this behavior.
153
+
154
+ Moreover in the group some items may be not (un)selected:
155
+
156
+ * The item should not be disabled: it should not be possible to select a disabled item
157
+
158
+ * The item should not use exclusive mode: because otherwise only this one should be selected.
159
+
160
+ * Only items that matches the search will be selected: only visible items are (un)selected.
161
+
162
+ ## emptyValue
163
+
164
+ Type: `OptionId`
165
+
166
+ By default, if there is no selected options, the result given by `getValue()` returns `null` (or `[]` in _multiple_ mode).
167
+
168
+ `emptyValue` allows to change this default value.
95
169
 
96
170
  ```html
97
171
  <selectic
98
172
  :params="{
99
- strictValue: true,
173
+ emptyValue: '',
100
174
  }"
101
175
  :options="optionList"
102
176
  />
103
177
  ```
104
178
 
105
- ## selectionOverflow
179
+ ## fetchCallback
106
180
 
107
- Type: `'collapsed'` | `'multiline'`
181
+ Type: `function (search, offset, limit) => Promise<{total, result}>`
108
182
 
109
- `selectOverflow` is to describe how selected options should be displayed when they are not enough space to display them all (in _multiple_ mode).
183
+ The purpose of this function is to return a list of option dynamically. With it, it is possible to fetch data build the list asynchronously (useful for very large list).
110
184
 
111
- Currently there are two supported behavior:
112
- * `'collapsed'`: the size of selectic input is not changed. If there is not enough space to display all selected options then it displays the possible ones then displays a _"+x others"_ in a badge (_x_ is the number of not displayed options). It is possible to watch these options with `title` or by opening selectic and see which options are selected. _This is the default value_.
113
- * `'multiline'`: If there is not enough space to display all selected options then it displays the others on another line. The size of the component can be higher than the allowed space.
185
+ Read [the dynamic documentation](dynamic.md) for more information.
186
+
187
+ It should return a promise which resolves with an object which contains the total number of items and the list of options asked by the request.
114
188
 
115
189
  ```html
116
190
  <selectic
117
191
  :params="{
118
- selectionOverflow: 'multiple',
192
+ fetchCallback: (search, offset, limit) => fetch(`list?search=${search}&offset=${offset}&limit=${limit}`),
119
193
  }"
120
194
  :options="optionList"
121
195
  />
122
196
  ```
123
197
 
124
- ## emptyValue
198
+ ## forceSelectAll
125
199
 
126
- Type: `OptionId`
200
+ Type: `'auto' | 'visible'`
127
201
 
128
- By default, if there is no selected options, the result given by `getValue()` returns `null` (or `[]` in _multiple_ mode).
202
+ Default value: `'auto'`
129
203
 
130
- `emptyValue` allows to change this default value.
204
+ In _multiple_ mode, there is a "select all" action.
205
+ If the selection inversion is not available and all data are not fetched (in
206
+ _dynamic_ mode) it will not be possible to select all items. So this action
207
+ will be disabled.
208
+
209
+ This option allows you to change the behavior.
210
+
211
+ * `'auto'`: The action is disabled when not possible.
212
+ * `'visible'`: The action is displayed even when all data are not fetched.
131
213
 
132
214
  ```html
133
215
  <selectic
134
216
  :params="{
135
- emptyValue: '',
217
+ forceSelectAll: 'auto',
136
218
  }"
137
219
  :options="optionList"
138
220
  />
@@ -184,25 +266,6 @@ As argument, it receives an option item and should also return an option item.
184
266
  />
185
267
  ```
186
268
 
187
- ## fetchCallback
188
-
189
- Type: `function (search, offset, limit) => Promise<{total, result}>`
190
-
191
- The purpose of this function is to return a list of option dynamically. With it, it is possible to fetch data build the list asynchronously (useful for very large list).
192
-
193
- Read [the dynamic documentation](dynamic.md) for more information.
194
-
195
- It should return a promise which resolves with an object which contains the total number of items and the list of options asked by the request.
196
-
197
- ```html
198
- <selectic
199
- :params="{
200
- fetchCallback: (search, offset, limit) => fetch(`list?search=${search}&offset=${offset}&limit=${limit}`),
201
- }"
202
- :options="optionList"
203
- />
204
- ```
205
-
206
269
  ## getItemsCallback
207
270
 
208
271
  Type: `function (optionId[]) => Promise<option[]>`
@@ -225,85 +288,48 @@ It should return a promise which resolves with an array of options corresponding
225
288
  />
226
289
  ```
227
290
 
228
- ## pageSize
229
-
230
- Type: `number`
231
-
232
- `pageSize` is the number of options requested in dynamic mode when selectic needs to display more options than it has in cache.
233
-
234
- By changing this value you can optimize performance result (more or less requests vs memory cache consumption).
235
-
236
- Read [the dynamic documentation](dynamic.md) for more information.
237
-
238
- Selectic displays 10 options at a time, but it will call for a new request as soon as the last option index reach the half of page size.
239
-
240
- _`pageSize` default value is `100`._
241
-
242
- ```html
243
- <selectic
244
- :params="{
245
- pageSize: 500,
246
- }"
247
- :options="optionList"
248
- />
249
- ```
250
-
251
- ## allowRevert
252
-
253
- Type: `boolean` | `undefined`
254
-
255
- In _multiple_ mode, it is possible to invert the selection.
256
- However in _dynamic_ mode selectic does not know all options so it cannot select the opposite selections.
257
-
258
- To allow this feature in _dynamic_ mode, there is a property `selectionIsExcluded` which means that values returned by `getValue()`, `getSelection()` or emitted events are the ones which are not selected.
259
-
260
- As this behavior is more complex, it is needed to set `allowRevert` to `true` to enable it.
291
+ ## hideFilter
261
292
 
262
- Read [the dynamic documentation](dynamic.md) for more information.
293
+ Type: `boolean` | `'auto'` | `'open'`
263
294
 
264
- If `allowRevert` is set to `false`, the action to invert the selection will always be disabled.
295
+ If `hideFilter` is set to `true`, the handler to open the filter panel is hidden and it will not be possible to search for options.
265
296
 
266
- If `allowRevert` is set to `true`, the action to invert the selection will always be enabled. The parent of selectic component should support `selectionIsExcluded` property (which can be applied in _dynamic_ mode).
297
+ If `hideFilter` is set to `'auto`, the handler to open the filter panel is hidden only if there is less than 10 options (when there is no scroll), and is displayed otherwise. _This is the default value_.
267
298
 
268
- If `allowRevert` is set to `undefined` (is not set), the action to invert the selection will be enabled only if the `selectionIsExcluded` property is not needed (always in _static_ mode, and in _dynamic_ mode when all options are already fetched).
299
+ If `hideFilter` is set to `false`, the handler to open the filter panel is always displayed.
269
300
 
270
- Read [the extended properties documentation](extendedProperties.md) for more information about `selectionIsExcluded`.
301
+ If `hideFilter` is set to `'open'`, the handler to open or close the filter panel
302
+ will not be displayed and the filter panel is always open.
271
303
 
272
304
  ```html
273
305
  <selectic
274
306
  :params="{
275
- allowRevert: true,
307
+ hideFilter: false,
276
308
  }"
277
309
  :options="optionList"
278
310
  />
279
311
  ```
280
312
 
281
- ## forceSelectAll
282
-
283
- Type: `'auto' | 'visible'`
313
+ ## keepOpenWithOtherSelectic
284
314
 
285
- Default value: `'auto'`
315
+ Type: `boolean`
286
316
 
287
- In _multiple_ mode, there is a "select all" action.
288
- If the selection inversion is not available and all data are not fetched (in
289
- _dynamic_ mode) it will not be possible to select all items. So this action
290
- will be disabled.
317
+ Default value: `false`
291
318
 
292
- This option allows you to change the behavior.
319
+ By default, only one selectic component can be open at the same time. So if another Selectic component is open (mainly programmatically) then any previously open component is closed.
320
+ If `keepOpenWithOtherSelectic` is set to `true`, this component stays open when another Selectic component opens.
293
321
 
294
- * `'auto'`: The action is disabled when not possible.
295
- * `'visible'`: The action is displayed even when all data are not fetched.
322
+ Note: This attribute does not prevent closing when user clicks outside the component.
296
323
 
297
324
  ```html
298
325
  <selectic
299
326
  :params="{
300
- forceSelectAll: 'auto',
327
+ keepOpenWithOtherSelectic: true,
301
328
  }"
302
329
  :options="optionList"
303
330
  />
304
331
  ```
305
332
 
306
-
307
333
  ## listPosition
308
334
 
309
335
  Type: `'auto' | 'bottom' | 'top'`
@@ -363,21 +389,60 @@ Display only one source (the first which is not empty).
363
389
  />
364
390
  ```
365
391
 
366
- ## keepOpenWithOtherSelectic
392
+ ## pageSize
367
393
 
368
- Type: `boolean`
394
+ Type: `number`
369
395
 
370
- Default value: `false`
396
+ `pageSize` is the number of options requested in dynamic mode when selectic needs to display more options than it has in cache.
371
397
 
372
- By default, only one selectic component can be open at the same time. So if another Selectic component is open (mainly programmatically) then any previously open component is closed.
373
- If `keepOpenWithOtherSelectic` is set to `true`, this component stays open when another Selectic component opens.
398
+ By changing this value you can optimize performance result (more or less requests vs memory cache consumption).
374
399
 
375
- Note: This attribute does not prevent closing when user clicks outside the component.
400
+ Read [the dynamic documentation](dynamic.md) for more information.
401
+
402
+ Selectic displays 10 options at a time, but it will call for a new request as soon as the last option index reach the half of page size.
403
+
404
+ _`pageSize` default value is `100`._
376
405
 
377
406
  ```html
378
407
  <selectic
379
408
  :params="{
380
- keepOpenWithOtherSelectic: true,
409
+ pageSize: 500,
410
+ }"
411
+ :options="optionList"
412
+ />
413
+ ```
414
+
415
+ ## selectionOverflow
416
+
417
+ Type: `'collapsed'` | `'multiline'`
418
+
419
+ `selectOverflow` is to describe how selected options should be displayed when they are not enough space to display them all (in _multiple_ mode).
420
+
421
+ Currently there are two supported behavior:
422
+ * `'collapsed'`: the size of selectic input is not changed. If there is not enough space to display all selected options then it displays the possible ones then displays a _"+x others"_ in a badge (_x_ is the number of not displayed options). It is possible to watch these options with `title` or by opening selectic and see which options are selected. _This is the default value_.
423
+ * `'multiline'`: If there is not enough space to display all selected options then it displays the others on another line. The size of the component can be higher than the allowed space.
424
+
425
+ ```html
426
+ <selectic
427
+ :params="{
428
+ selectionOverflow: 'multiple',
429
+ }"
430
+ :options="optionList"
431
+ />
432
+ ```
433
+
434
+ ## strictValue
435
+
436
+ Type: `boolean`
437
+
438
+ If `strictValue` is set to `true`, it will consider value as `undefined` if its value is not an id of `options`.
439
+
440
+ By default, it is set to `false`.
441
+
442
+ ```html
443
+ <selectic
444
+ :params="{
445
+ strictValue: true,
381
446
  }"
382
447
  :options="optionList"
383
448
  />
@@ -0,0 +1,42 @@
1
+ # Properties
2
+
3
+ [Back to documentation index](main.md)
4
+
5
+ ## DOM properties
6
+
7
+ * [className](domProperties.md#classname) (instead of `class` in order to be
8
+ applied on main element and on the list element)
9
+ * [disabled](domProperties.md#disabled)
10
+ * [id](domProperties.md#id)
11
+ * [multiple](domProperties.md#multiple)
12
+ * [placeholder](domProperties.md#placeholder)
13
+ * [title](domProperties.md#title)
14
+ * [value](domProperties.md#value)
15
+
16
+ ## Extended properties
17
+
18
+ * [groups](extendedProperties.md#groups)
19
+ * [noCache](extendedProperties.md#nocache)
20
+ * [open](extendedProperties.md#open)
21
+ * [options](extendedProperties.md#options)
22
+ * [selectionIsExcluded](extendedProperties.md#selectionisexcluded)
23
+ * [texts](extendedProperties.md#texts)
24
+ * [params](extendedProperties.md#params)
25
+ * [allowClearSelection](params.md#allowclearselection)
26
+ * [allowRevert](params.md#allowrevert)
27
+ * [autoDisabled](params.md#autodisabled)
28
+ * [autoSelect](params.md#autoselect)
29
+ * [disableGroupSelection](params.md#disableGroupSelection)
30
+ * [emptyValue](params.md#emptyvalue)
31
+ * [fetchCallback](params.md#fetchcallback)
32
+ * [forceSelectAll](params.md#forceselectall)
33
+ * [formatOption](params.md#formatoption)
34
+ * [formatSelection](params.md#formatselection)
35
+ * [getItemsCallback](params.md#getitemscallback)
36
+ * [hideFilter](params.md#hidefilter)
37
+ * [keepOpenWithOtherSelectic](params.md#keepopenwithotherselectic)
38
+ * [listPosition](params.md#listposition)
39
+ * [optionBehavior](params.md#optionbehavior)
40
+ * [pageSize](params.md#pagesize)
41
+ * [selectionOverflow](params.md#selectionoverflow)
42
+ * [strictValue](params.md#strictvalue)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selectic",
3
- "version": "3.0.21",
3
+ "version": "3.1.0",
4
4
  "description": "Smart Select for VueJS 3.x",
5
5
  "main": "dist/selectic.common.js",
6
6
  "module": "dist/selectic.esm.js",
@@ -38,13 +38,13 @@
38
38
  "test": "npm run build && tape test/**/*.spec.js"
39
39
  },
40
40
  "dependencies": {
41
- "vtyx": "4.0.5"
41
+ "vtyx": "4.2.1"
42
42
  },
43
43
  "devDependencies": {
44
- "@babel/types": "^7.21.2",
44
+ "@babel/types": "^7.23.6",
45
45
  "rollup": "^2.79.1",
46
46
  "rollup-plugin-postcss": "^4.0.2",
47
- "tape": "^4.16.2",
47
+ "tape": "^4.17.0",
48
48
  "typescript": "~4.8"
49
49
  }
50
50
  }
@@ -4,10 +4,12 @@
4
4
  */
5
5
 
6
6
  import {Vue, Component, Prop, Watch, h} from 'vtyx';
7
+ import { unref } from 'vue';
7
8
 
8
- import Store, { OptionId } from './Store';
9
+ import Store, { OptionId, OptionItem } from './Store';
9
10
  import Filter from './Filter';
10
11
  import List from './List';
12
+ import Icon from './Icon';
11
13
 
12
14
  export interface Props {
13
15
  store: Store;
@@ -50,7 +52,8 @@ export default class ExtendedList extends Vue<Props> {
50
52
  /* }}} */
51
53
  /* {{{ data */
52
54
 
53
- private topGroup = ' ';
55
+ private topGroupName = ' ';
56
+ private topGroupId: OptionId = null;
54
57
  private listHeight = 0;
55
58
  private listWidth = 200;
56
59
  private availableSpace = 0;
@@ -224,6 +227,32 @@ export default class ExtendedList extends Vue<Props> {
224
227
  `;
225
228
  }
226
229
 
230
+ get topGroup(): OptionItem | undefined {
231
+ const topGroupId = this.topGroupId;
232
+
233
+ if (!topGroupId) {
234
+ return undefined;
235
+ }
236
+
237
+ const group = this.store.state.filteredOptions.find((option) => {
238
+ return option.id === topGroupId;
239
+ });
240
+
241
+ return group;
242
+ }
243
+
244
+ get topGroupSelected(): boolean {
245
+ const group = this.topGroup;
246
+
247
+ return !!group?.selected;
248
+ }
249
+
250
+ get topGroupDisabled(): boolean {
251
+ const group = this.topGroup;
252
+
253
+ return !!group?.disabled;
254
+ }
255
+
227
256
  /* }}} */
228
257
  /* {{{ watch */
229
258
 
@@ -244,7 +273,8 @@ export default class ExtendedList extends Vue<Props> {
244
273
  const group = this.store.state.groups.get(id);
245
274
  const groupName = group || ' ';
246
275
 
247
- this.topGroup = groupName;
276
+ this.topGroupName = groupName;
277
+ this.topGroupId = id;
248
278
  }
249
279
 
250
280
  private computeListSize() {
@@ -254,6 +284,10 @@ export default class ExtendedList extends Vue<Props> {
254
284
  this.listWidth = box.width;
255
285
  }
256
286
 
287
+ private clickHeaderGroup() {
288
+ this.store.selectGroup(this.topGroupId, !this.topGroupSelected);
289
+ }
290
+
257
291
  /* }}} */
258
292
  /* {{{ Life cycles */
259
293
 
@@ -296,9 +330,22 @@ export default class ExtendedList extends Vue<Props> {
296
330
 
297
331
  {isGroup && (
298
332
  <span
299
- class="selectic-item selectic-item--header selectic-item__is-group"
333
+ class={[
334
+ 'selectic-item selectic-item--header selectic-item__is-group',
335
+ {
336
+ selected: this.topGroupSelected,
337
+ selectable: unref(this.store.allowGroupSelection) && !this.topGroupDisabled,
338
+ disabled: this.topGroupDisabled,
339
+ },
340
+ ]}
341
+ on={{
342
+ click: () => this.clickHeaderGroup(),
343
+ }}
300
344
  >
301
- {this.topGroup}
345
+ {this.topGroupSelected && (
346
+ <Icon icon="check" store={this.store} class="selectic-item_icon" />
347
+ )}
348
+ {this.topGroupName}
302
349
  </span>
303
350
  )}
304
351
  <List
@@ -314,7 +361,7 @@ export default class ExtendedList extends Vue<Props> {
314
361
  )}
315
362
  {this.searching && (
316
363
  <div class="selectic__message">
317
- <span class="fa fa-spinner fa-spin"></span>
364
+ <Icon icon="spinner" store={this.store} spin />
318
365
  {this.searchingLabel}
319
366
  </div>
320
367
  )}
package/src/Filter.tsx CHANGED
@@ -6,6 +6,7 @@ import {Vue, Component, Prop, Watch, h} from 'vtyx';
6
6
  import { unref } from 'vue';
7
7
 
8
8
  import Store from './Store';
9
+ import Icon from './Icon';
9
10
 
10
11
  export interface Props {
11
12
  store: Store;
@@ -185,9 +186,11 @@ export default class FilterPanel extends Vue<Props> {
185
186
  }}
186
187
  ref="filterInput"
187
188
  />
188
- <span class="fa fa-search selectic-search-scope
189
- form-control-feedback"
190
- ></span>
189
+ <Icon
190
+ icon="search"
191
+ store={this.store}
192
+ class="selectic-search-scope form-control-feedback"
193
+ />
191
194
  </div>
192
195
  {state.multiple && (
193
196
  <div class="toggle-selectic">
@@ -236,12 +239,11 @@ export default class FilterPanel extends Vue<Props> {
236
239
  'click.prevent.stop': this.togglePanel,
237
240
  }}
238
241
  >
239
- <span class="fa fa-search"></span>
240
- <span class={{
241
- 'fa': true,
242
- 'fa-caret-down': this.closed,
243
- 'fa-caret-up': !this.closed,
244
- }}></span>
242
+ <Icon icon="search" store={this.store} />
243
+ <Icon
244
+ icon={this.closed ? 'caret-down' : 'caret-up'}
245
+ store={this.store}
246
+ />
245
247
  </div>
246
248
  )}
247
249
  </div>