@danielgindi/selectbox 1.0.146 → 2.0.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.
@@ -1,19 +1,26 @@
1
-
2
- ul.droplist {
1
+ .droplist_wrapper {
3
2
  box-sizing: border-box;
4
3
  z-index: 10000;
5
4
  float: left;
6
5
  margin: 0;
7
6
  padding: 0;
8
- list-style: none;
9
7
  border: 1px solid #b1b1b1;
10
- overflow-y: auto;
11
- overflow-x: hidden;
12
- max-height: 300px;
13
- max-width: 100%;
14
8
  outline: 0;
15
9
  border-radius: 5px;
16
10
  background: #fff;
11
+ max-height: 300px;
12
+ max-width: 100%;
13
+
14
+ .droplist_header {
15
+ position: relative;
16
+ padding: 0.5em;
17
+ box-sizing: inherit;
18
+
19
+ input[type=search] {
20
+ box-sizing: inherit;
21
+ width: 100%;
22
+ }
23
+ }
17
24
 
18
25
  &.droplist__is_above {
19
26
  border-bottom-left-radius: 0;
@@ -27,131 +34,155 @@ ul.droplist {
27
34
  margin: -1px 0 0 0;
28
35
  }
29
36
 
30
- li {
31
- box-sizing: border-box;
32
- position: relative;
37
+ ul {
38
+ list-style: none;
33
39
  margin: 0;
34
- padding: 3px 11px 4px 11px;
35
- height: 23px;
36
- font-size: 13px;
37
- line-height: 17px;
38
- color: #3e3f48;
39
- white-space: nowrap;
40
- cursor: pointer;
41
-
42
- /** avoid jumpy scroll issues in RTL mode (Chrome),
43
- by force-clipping the item's width, so parent's scroll properties do not change */
44
- width: 100%;
45
- overflow: hidden;
46
-
47
- &.droplist__item_focus {
48
- /* background-color: #4c8fbd; */
49
- background-color: #3e3f48;
50
- color: #fff;
40
+ padding: 0;
41
+ border: 0;
42
+ overflow-y: auto;
43
+ overflow-x: hidden;
44
+ max-height: 100%;
45
+ max-width: 100%;
46
+ background: none;
47
+
48
+ li {
49
+ box-sizing: border-box;
50
+ position: relative;
51
+ margin: 0;
52
+ padding: 3px 11px 4px 11px;
53
+ height: 23px;
54
+ font-size: 13px;
55
+ line-height: 17px;
56
+ color: #3e3f48;
57
+ white-space: nowrap;
58
+ cursor: pointer;
59
+
60
+ /** avoid jumpy scroll issues in RTL mode (Chrome),
61
+ by force-clipping the item's width, so parent's scroll properties do not change */
62
+ width: 100%;
63
+ overflow: hidden;
64
+
65
+ &.droplist__item_focus {
66
+ /* background-color: #4c8fbd; */
67
+ background-color: #3e3f48;
68
+ color: #fff;
69
+ }
51
70
  }
52
- }
53
71
 
54
- li {
55
- .checkbox {
56
- position: absolute;
57
- left: 6px;
58
- top: 3px;
59
- display: block;
60
- width: 16px;
61
- height: 16px;
72
+ li {
73
+ .checkbox {
74
+ position: absolute;
75
+ left: 6px;
76
+ top: 3px;
77
+ display: block;
78
+ width: 16px;
79
+ height: 16px;
80
+
81
+ /* unchecked style */
82
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %236ca1c6; fill: %23dae7f1;'%3E%3C/rect%3E%3C/svg%3E");
83
+ background-size: 100% 100%;
84
+ }
62
85
 
63
- /* unchecked style */
64
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %236ca1c6; fill: %23dae7f1;'%3E%3C/rect%3E%3C/svg%3E");
65
- background-size: 100% 100%;
66
- }
67
- &:hover .checkbox {
68
- /* unchecked hover style */
69
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %236ca1c6; fill: %23fff;'%3E%3C/rect%3E%3C/svg%3E");
70
- }
71
- &:active .checkbox,
72
- &:hover:active .checkbox {
73
- /* unchecked active style */
74
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %23396d93; fill: %23b5cfe3;'%3E%3C/rect%3E%3C/svg%3E");
75
- }
76
- }
86
+ &:hover .checkbox {
87
+ /* unchecked hover style */
88
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %236ca1c6; fill: %23fff;'%3E%3C/rect%3E%3C/svg%3E");
89
+ }
77
90
 
78
- li.droplist__item_multi.droplist__item_checked {
79
- .checkbox {
80
- /* checked style */
81
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %236ca1c6; fill: %23dae7f1;'%3E%3C/rect%3E%3Cpath fill='%236ca1c6' d='m364.136 158.276-172.589 171.204c-4.705 4.667-12.303 4.637-16.97-.068l-90.781-91.516c-4.667-4.705-4.637-12.303.069-16.971l22.719-22.536c4.705-4.667 12.303-4.637 16.97.069l59.792 60.277 141.352-140.216c4.705-4.667 12.303-4.637 16.97.068l22.536 22.718c4.667 4.706 4.637 12.304-.068 16.971z'/%3E%3C/svg%3E%0A");
91
+ &:active .checkbox,
92
+ &:hover:active .checkbox {
93
+ /* unchecked active style */
94
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %23396d93; fill: %23b5cfe3;'%3E%3C/rect%3E%3C/svg%3E");
95
+ }
82
96
  }
83
- &:hover .checkbox {
84
- /* checked hover style */
85
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %236ca1c6; fill: %23fff;'%3E%3C/rect%3E%3Cpath fill='%236ca1c6' d='m364.136 158.276-172.589 171.204c-4.705 4.667-12.303 4.637-16.97-.068l-90.781-91.516c-4.667-4.705-4.637-12.303.069-16.971l22.719-22.536c4.705-4.667 12.303-4.637 16.97.069l59.792 60.277 141.352-140.216c4.705-4.667 12.303-4.637 16.97.068l22.536 22.718c4.667 4.706 4.637 12.304-.068 16.971z'/%3E%3C/svg%3E%0A");
97
+
98
+ li.droplist__item_multi.droplist__item_checked {
99
+ .checkbox {
100
+ /* checked style */
101
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %236ca1c6; fill: %23dae7f1;'%3E%3C/rect%3E%3Cpath fill='%236ca1c6' d='m364.136 158.276-172.589 171.204c-4.705 4.667-12.303 4.637-16.97-.068l-90.781-91.516c-4.667-4.705-4.637-12.303.069-16.971l22.719-22.536c4.705-4.667 12.303-4.637 16.97.069l59.792 60.277 141.352-140.216c4.705-4.667 12.303-4.637 16.97.068l22.536 22.718c4.667 4.706 4.637 12.304-.068 16.971z'/%3E%3C/svg%3E%0A");
102
+ }
103
+
104
+ &:hover .checkbox {
105
+ /* checked hover style */
106
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %236ca1c6; fill: %23fff;'%3E%3C/rect%3E%3Cpath fill='%236ca1c6' d='m364.136 158.276-172.589 171.204c-4.705 4.667-12.303 4.637-16.97-.068l-90.781-91.516c-4.667-4.705-4.637-12.303.069-16.971l22.719-22.536c4.705-4.667 12.303-4.637 16.97.069l59.792 60.277 141.352-140.216c4.705-4.667 12.303-4.637 16.97.068l22.536 22.718c4.667 4.706 4.637 12.304-.068 16.971z'/%3E%3C/svg%3E%0A");
107
+ }
108
+
109
+ &:active .checkbox,
110
+ &:hover:active .checkbox {
111
+ /* checked active style */
112
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %23396d93; fill: %23b5cfe3;'%3E%3C/rect%3E%3Cpath fill='%23396d93' d='m364.136 158.276-172.589 171.204c-4.705 4.667-12.303 4.637-16.97-.068l-90.781-91.516c-4.667-4.705-4.637-12.303.069-16.971l22.719-22.536c4.705-4.667 12.303-4.637 16.97.069l59.792 60.277 141.352-140.216c4.705-4.667 12.303-4.637 16.97.068l22.536 22.718c4.667 4.706 4.637 12.304-.068 16.971z'/%3E%3C/svg%3E%0A");
113
+ }
86
114
  }
87
- &:active .checkbox,
88
- &:hover:active .checkbox {
89
- /* checked active style */
90
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 448'%3E%3Crect x='14' y='14' width='420' height='420' rx='84' style='stroke-width: 28px; stroke: %23396d93; fill: %23b5cfe3;'%3E%3C/rect%3E%3Cpath fill='%23396d93' d='m364.136 158.276-172.589 171.204c-4.705 4.667-12.303 4.637-16.97-.068l-90.781-91.516c-4.667-4.705-4.637-12.303.069-16.971l22.719-22.536c4.705-4.667 12.303-4.637 16.97.069l59.792 60.277 141.352-140.216c4.705-4.667 12.303-4.637 16.97.068l22.536 22.718c4.667 4.706 4.637 12.304-.068 16.971z'/%3E%3C/svg%3E%0A");
115
+
116
+ li.droplist__item_single.droplist__item_checked {
117
+ opacity: 0.5;
91
118
  }
92
- }
93
119
 
94
- li.droplist__item_single.droplist__item_checked {
95
- opacity: 0.5;
96
- }
120
+ li.droplist__item_multi:not(.droplist__item_multi_nocheck) {
121
+ padding: 1px 6px 2px 2px;
97
122
 
98
- li.droplist__item_multi:not(.droplist__item_multi_nocheck) {
99
- padding: 1px 6px 2px 2px;
123
+ .droplist__item_label {
124
+ display: block;
125
+ margin: 1px 0 0 24px;
126
+ }
127
+ }
100
128
 
101
- .droplist__item_label {
102
- display: block;
103
- margin: 1px 0 0 24px;
129
+ li.droplist__item_group {
130
+ font-weight: bold;
104
131
  }
105
- }
106
132
 
107
- li.droplist__item_group {
108
- font-weight: bold;
109
- }
133
+ li.droplist__item_child.droplist__item_multi:not(.droplist__item_multi_nocheck) {
134
+ padding-left: 15px;
135
+ }
110
136
 
111
- li.droplist__item_child.droplist__item_multi:not(.droplist__item_multi_nocheck) {
112
- padding-left: 15px;
113
- }
137
+ li.droplist__item_child.droplist__item_single,
138
+ li.droplist__item_child.droplist__item_multi_nocheck {
139
+ padding-left: 24px;
140
+ }
114
141
 
115
- li.droplist__item_child.droplist__item_single,
116
- li.droplist__item_child.droplist__item_multi_nocheck {
117
- padding-left: 24px;
118
- }
142
+ li.droplist__item_nointeraction {
143
+ cursor: default;
144
+ }
119
145
 
120
- .droplist__no_results_content {
121
- text-align: center;
122
- }
146
+ .droplist__no_results_content {
147
+ text-align: center;
148
+ }
123
149
 
124
- .remove {
125
- display: none;
126
- position: absolute;
127
- top: 0;
128
- right: 2px;
129
- width: 34px;
130
- height: 20px;
131
- padding: 0;
132
- border: 0;
133
- background: none;
134
- line-height: 20px;
135
- vertical-align: middle;
136
- text-align: center;
137
- direction: ltr;
138
- font-size: 15px;
139
- cursor: pointer;
140
-
141
- &:before {
142
- display: inline-block;
143
- content: 'x';
144
- color: #fff;
150
+ li .remove {
151
+ display: none;
152
+ position: absolute;
153
+ top: 0;
154
+ right: 2px;
155
+ width: 34px;
156
+ height: 20px;
157
+ padding: 0;
158
+ border: 0;
159
+ background: none;
160
+ line-height: 20px;
161
+ vertical-align: middle;
162
+ text-align: center;
163
+ direction: ltr;
164
+ font-size: 15px;
165
+ cursor: pointer;
166
+
167
+ &:before {
168
+ display: inline-block;
169
+ content: 'x';
170
+ color: #fff;
171
+ }
145
172
  }
146
- }
147
173
 
148
- .droplist__item_focus .remove {
149
- display: block;
174
+ .droplist__item_focus .remove {
175
+ display: block;
176
+ }
150
177
  }
151
178
 
152
- &.droplist__rtl, [dir=rtl] &:not(.droplist__ltr) {
179
+ &.droplist__rtl,
180
+ [dir=rtl] &:not(.droplist__ltr) {
153
181
  direction: rtl;
182
+ }
154
183
 
184
+ &.droplist__rtl ul,
185
+ [dir=rtl] &:not(.droplist__ltr) ul {
155
186
  li {
156
187
  .checkbox {
157
188
  left: auto;
@@ -178,7 +209,7 @@ ul.droplist {
178
209
  padding-right: 24px;
179
210
  }
180
211
 
181
- .remove {
212
+ li .remove {
182
213
  right: auto;
183
214
  left: 2px;
184
215
  }
package/vue/DropList.vue CHANGED
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <span v-show="false" />
2
+ <span v-show="false" />
3
3
  </template>
4
4
 
5
5
  <script>
@@ -53,6 +53,38 @@ export default {
53
53
  type: Boolean,
54
54
  default: false,
55
55
  },
56
+ searchable: {
57
+ type: Boolean,
58
+ default: false,
59
+ },
60
+ noResultsText: {
61
+ type: String,
62
+ default: 'No matching results',
63
+ },
64
+ filterThrottleWindow: {
65
+ type: Number,
66
+ default: 300,
67
+ },
68
+ filterOnEmptyTerm: {
69
+ type: Boolean,
70
+ default: false,
71
+ },
72
+ filterGroups: {
73
+ type: Boolean,
74
+ default: false,
75
+ },
76
+ filterEmptyGroups: {
77
+ type: Boolean,
78
+ default: false,
79
+ },
80
+ filterFn: {
81
+ type: Function,
82
+ default: undefined,
83
+ },
84
+ // eslint-disable-next-line vue/require-prop-types
85
+ filterDependencies: {
86
+ default: undefined,
87
+ },
56
88
  keyDownHandler: {
57
89
  type: Function,
58
90
  },
@@ -108,6 +140,10 @@ export default {
108
140
  positionOptions: {
109
141
  type: Object,
110
142
  },
143
+ autoRelayoutOnItemsChange: {
144
+ type: Boolean,
145
+ default: true,
146
+ },
111
147
  },
112
148
 
113
149
  emits: [
@@ -150,6 +186,7 @@ export default {
150
186
  computedOptions() {
151
187
  let opts = {
152
188
  on: this._handleListEvents.bind(this),
189
+ positionOptionsProvider: () => this.positionOptions,
153
190
  };
154
191
 
155
192
  if (this.baseClassName) {
@@ -166,7 +203,9 @@ export default {
166
203
 
167
204
  for (let key of ['autoItemBlur', 'capturesFocus', 'multi',
168
205
  'autoCheckGroupChildren', 'useExactTargetWidth', 'constrainToWindow',
169
- 'autoFlipDirection', 'estimateWidth']) {
206
+ 'autoFlipDirection', 'estimateWidth',
207
+ 'searchable', 'filterOnEmptyTerm',
208
+ 'filterGroups', 'filterEmptyGroups']) {
170
209
  if (typeof this[key] === 'boolean') {
171
210
  opts[key] = this[key];
172
211
  }
@@ -188,10 +227,7 @@ export default {
188
227
  opts.keyDownHandler = this.keyDownHandler;
189
228
  }
190
229
 
191
- opts.renderItem = this.renderItem;
192
- if (!opts.renderItem) {
193
- opts.renderItem = createSlotBasedRenderFunc(this, 'item');
194
- }
230
+ opts.renderItem = this.renderItem ?? createSlotBasedRenderFunc(this, 'item');
195
231
 
196
232
  opts.unrenderItem = this.unrenderItem;
197
233
  if (!opts.unrenderItem) {
@@ -201,6 +237,17 @@ export default {
201
237
  }
202
238
  }
203
239
 
240
+ opts.renderNoResultsItem = this.computedRenderNoResultsItem ?? createSlotBasedRenderFunc(this, 'no-results-item');
241
+
242
+ opts.unrenderNoResultsItem = this.computedUnrenderNoResultsItem;
243
+
244
+ if (!opts.unrenderNoResultsItem) {
245
+ let fn = createSlotBasedUnrenderFunc(this, 'no-results-item');
246
+ if (fn) {
247
+ opts.unrenderNoResultsItem = (item, el) => fn(el);
248
+ }
249
+ }
250
+
204
251
  return opts;
205
252
  },
206
253
 
@@ -216,9 +263,10 @@ export default {
216
263
  watch: {
217
264
  items(value) {
218
265
  if (this.nonReactive.instance) {
219
- this.nonReactive.instance.setItems(
220
- Array.isArray(value) ? value : []
221
- );
266
+ const instance = this.nonReactive.instance;
267
+ instance.setItems(Array.isArray(value) ? value : []);
268
+ if (this.autoRelayoutOnItemsChange && instance.isVisible())
269
+ instance.relayout();
222
270
  }
223
271
  },
224
272
 
@@ -246,6 +294,36 @@ export default {
246
294
  this.nonReactive.instance.setDirection(value);
247
295
  },
248
296
 
297
+ noResultsText(value) {
298
+ if (this.nonReactive.instance)
299
+ this.nonReactive.instance.setNoResultsText(value);
300
+ },
301
+
302
+ filterThrottleWindow(value) {
303
+ if (this.nonReactive.instance)
304
+ this.nonReactive.instance.setFilterThrottleWindow(value || 0);
305
+ },
306
+
307
+ filterOnEmptyTerm(value) {
308
+ if (this.nonReactive.instance)
309
+ this.nonReactive.instance.setFilterOnEmptyTerm(value);
310
+ },
311
+
312
+ filterGroups(value) {
313
+ if (this.nonReactive.instance)
314
+ this.nonReactive.instance.setFilterGroups(value);
315
+ },
316
+
317
+ filterEmptyGroups(value) {
318
+ if (this.nonReactive.instance)
319
+ this.nonReactive.instance.setFilterEmptyGroups(value);
320
+ },
321
+
322
+ filterFn() {
323
+ if (this.nonReactive.instance)
324
+ this.nonReactive.instance.setFilterFn(this.filterFn);
325
+ },
326
+
249
327
  renderItem() {
250
328
  this._recreateList();
251
329
  },
@@ -254,6 +332,18 @@ export default {
254
332
  this._recreateList();
255
333
  },
256
334
 
335
+ renderNoResultsItem() {
336
+ this._recreateList();
337
+ },
338
+
339
+ unrenderNoResultsItem() {
340
+ this._recreateList();
341
+ },
342
+
343
+ searchable() {
344
+ this._recreateList();
345
+ },
346
+
257
347
  positionOptions: {
258
348
  deep: true,
259
349
  handler() {
@@ -347,7 +437,7 @@ export default {
347
437
  list.setSingleSelectedItemByValue(modelValue === null ? undefined : modelValue);
348
438
  }
349
439
 
350
- list.show(this.positionOptions);
440
+ list.show();
351
441
 
352
442
  this._setupAutoRelayout();
353
443
  },
@@ -413,7 +503,7 @@ export default {
413
503
 
414
504
  relayout() {
415
505
  if (this.nonReactive.instance)
416
- this.nonReactive.instance.relayout(this.positionOptions);
506
+ this.nonReactive.instance.relayout();
417
507
  },
418
508
 
419
509
  elContains(other, considerSublists = true) {
package/vue/SelectBox.vue CHANGED
@@ -119,6 +119,14 @@
119
119
  type: Boolean,
120
120
  default: false,
121
121
  },
122
+ filterFn: {
123
+ type: Function,
124
+ default: undefined,
125
+ },
126
+ // eslint-disable-next-line vue/require-prop-types
127
+ filterDependencies: {
128
+ default: undefined,
129
+ },
122
130
  labelProp: {
123
131
  type: String,
124
132
  default: 'label',
@@ -187,14 +195,6 @@
187
195
  type: Function,
188
196
  default: undefined,
189
197
  },
190
- filterFn: {
191
- type: Function,
192
- default: undefined,
193
- },
194
- // eslint-disable-next-line vue/require-prop-types
195
- filterDependencies: {
196
- default: undefined,
197
- },
198
198
  virtualMinItems: {
199
199
  type: Number,
200
200
  default: 10,
@@ -533,6 +533,11 @@
533
533
  this.nonReactive.instance.setFilterOnEmptyTerm(value || false);
534
534
  },
535
535
 
536
+ filterFn() {
537
+ if (this.nonReactive.instance)
538
+ this.nonReactive.instance.setFilterFn(this.filterFn);
539
+ },
540
+
536
541
  labelProp(value) {
537
542
  if (this.nonReactive.instance)
538
543
  this.nonReactive.instance.setLabelProp(value);
@@ -626,11 +631,6 @@
626
631
  this.nonReactive.instance.setListOptions(this.computedListOptions);
627
632
  },
628
633
 
629
- filterFn() {
630
- if (this.nonReactive.instance)
631
- this.nonReactive.instance.setFilterFn(this.filterFn);
632
- },
633
-
634
634
  ...(isVue3 ? {} : {
635
635
  $scopedSlots() { // Vue 2
636
636
  if (this.nonReactive.instance)