slim-select 2.0.2 → 2.2.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 (66) hide show
  1. package/README.md +8 -0
  2. package/dist/index.d.ts +1 -1
  3. package/dist/render.d.ts +10 -3
  4. package/dist/select.d.ts +6 -6
  5. package/dist/settings.d.ts +0 -3
  6. package/dist/slimselect.cjs.js +202 -67
  7. package/dist/slimselect.css +1 -1
  8. package/dist/slimselect.css.map +1 -1
  9. package/dist/slimselect.es.js +202 -67
  10. package/dist/slimselect.global.js +202 -67
  11. package/dist/slimselect.js +202 -67
  12. package/dist/slimselect.min.js +1 -1
  13. package/dist/slimselect.umd.js +202 -67
  14. package/dist/slimselect.umd.min.js +1 -1
  15. package/dist/store.d.ts +5 -0
  16. package/docs/assets/data.js +7 -3
  17. package/docs/assets/home.css +1 -1
  18. package/docs/assets/home.js +1 -1
  19. package/docs/assets/index.css +1 -1
  20. package/docs/assets/index.js +7 -7
  21. package/docs/assets/index2.js +119 -35
  22. package/docs/assets/index3.js +39 -23
  23. package/docs/assets/index4.js +1 -1
  24. package/docs/assets/index5.js +147 -9
  25. package/docs/assets/install.js +4 -4
  26. package/docs/assets/selects.js +1 -1
  27. package/package.json +11 -3
  28. package/src/docs/app.vue +6 -5
  29. package/src/docs/{images → assets/images}/check-mark.svg +0 -0
  30. package/src/docs/{images → assets/images}/chrome.svg +0 -0
  31. package/src/docs/{images → assets/images}/firefox.svg +0 -0
  32. package/src/docs/{images → assets/images}/github.png +0 -0
  33. package/src/docs/{images → assets/images}/ie.svg +0 -0
  34. package/src/docs/{images → assets/images}/npm.png +0 -0
  35. package/src/docs/{images → assets/images}/opera.svg +0 -0
  36. package/src/docs/{images → assets/images}/safari.svg +0 -0
  37. package/src/docs/assets/scss/misc.scss +7 -0
  38. package/src/docs/env.d.ts +1 -0
  39. package/src/docs/pages/data.vue +4 -0
  40. package/src/docs/pages/events/addable.vue +22 -6
  41. package/src/docs/pages/events/before_after_change.vue +15 -1
  42. package/src/docs/pages/events/search.vue +31 -16
  43. package/src/docs/pages/frameworks/vue.vue +375 -7
  44. package/src/docs/pages/home.vue +104 -57
  45. package/src/docs/pages/methods/get_data.vue +2 -1
  46. package/src/docs/pages/methods/open_close.vue +1 -1
  47. package/src/docs/pages/settings/closable.vue +128 -0
  48. package/src/docs/pages/settings/index.vue +6 -3
  49. package/src/docs/pages/settings/select_all.vue +88 -0
  50. package/src/slim-select/index.ts +4 -2
  51. package/src/slim-select/render.ts +247 -59
  52. package/src/slim-select/rollup.config.mjs +5 -0
  53. package/src/slim-select/select.ts +48 -31
  54. package/src/slim-select/settings.ts +0 -4
  55. package/src/slim-select/slimselect.scss +112 -11
  56. package/src/slim-select/store.ts +19 -1
  57. package/src/vue/README.md +48 -0
  58. package/src/vue/dist/slimselectvue.es.js +1752 -0
  59. package/src/vue/dist/slimselectvue.global.js +1755 -0
  60. package/src/vue/dist/slimselectvue.ssr.js +1754 -0
  61. package/src/vue/hello.ts +5 -0
  62. package/src/vue/package.json +28 -0
  63. package/src/vue/rollup.config.mjs +44 -0
  64. package/src/vue/slimselect.vue +39 -5
  65. package/src/vue/tsconfig.json +14 -0
  66. package/src/docs/pages/settings/select_by_group.vue +0 -46
@@ -51,6 +51,8 @@ class Optgroup {
51
51
  constructor(optgroup) {
52
52
  this.id = !optgroup.id || optgroup.id === '' ? generateID() : optgroup.id;
53
53
  this.label = optgroup.label || '';
54
+ this.selectAll = optgroup.selectAll === undefined ? false : optgroup.selectAll;
55
+ this.closable = optgroup.closable || 'off';
54
56
  this.options = [];
55
57
  if (optgroup.options) {
56
58
  for (const o of optgroup.options) {
@@ -197,6 +199,14 @@ class Store {
197
199
  });
198
200
  return selectedIDs;
199
201
  }
202
+ getOptgroupByID(id) {
203
+ for (let dataObj of this.data) {
204
+ if (dataObj instanceof Optgroup && dataObj.id === id) {
205
+ return dataObj;
206
+ }
207
+ }
208
+ return null;
209
+ }
200
210
  getOptionByID(id) {
201
211
  let options = this.filter((opt) => {
202
212
  return opt.id === id;
@@ -231,7 +241,7 @@ class Store {
231
241
  }
232
242
  });
233
243
  if (optOptions.length > 0) {
234
- dataSearch.push(new Optgroup({ id: dataObj.id, label: dataObj.label, options: optOptions }));
244
+ dataSearch.push(new Optgroup(dataObj));
235
245
  }
236
246
  }
237
247
  }
@@ -272,11 +282,18 @@ class Render {
272
282
  list: 'ss-list',
273
283
  optgroup: 'ss-optgroup',
274
284
  optgroupLabel: 'ss-optgroup-label',
275
- optgroupSelectable: 'ss-optgroup-selectable',
285
+ optgroupLabelText: 'ss-optgroup-label-text',
286
+ optgroupActions: 'ss-optgroup-actions',
287
+ optgroupSelectAll: 'ss-selectall',
288
+ optgroupSelectAllBox: 'M60,10 L10,10 L10,90 L90,90 L90,50',
289
+ optgroupSelectAllCheck: 'M30,45 L50,70 L90,10',
290
+ optgroupClosable: 'ss-closable',
276
291
  option: 'ss-option',
277
- optionSelected: 'ss-option-selected',
278
292
  optionDelete: 'M10,10 L90,90 M10,90 L90,10',
279
293
  highlighted: 'ss-highlighted',
294
+ open: 'ss-open',
295
+ close: 'ss-close',
296
+ selected: 'ss-selected',
280
297
  error: 'ss-error',
281
298
  disabled: 'ss-disabled',
282
299
  hide: 'ss-hide',
@@ -286,8 +303,6 @@ class Render {
286
303
  this.callbacks = callbacks;
287
304
  this.main = this.mainDiv();
288
305
  this.content = this.contentDiv();
289
- this.renderValues();
290
- this.renderOptions(this.store.getData());
291
306
  this.settings.contentLocation.appendChild(this.content.main);
292
307
  }
293
308
  enable() {
@@ -395,7 +410,21 @@ class Render {
395
410
  if (!this.settings.isEnabled) {
396
411
  return;
397
412
  }
398
- this.callbacks.setSelected(['']);
413
+ let shouldDelete = true;
414
+ const before = this.store.getSelectedOptions();
415
+ const after = [];
416
+ if (this.callbacks.beforeChange) {
417
+ shouldDelete = this.callbacks.beforeChange(after, before) === true;
418
+ }
419
+ if (shouldDelete) {
420
+ this.callbacks.setSelected(['']);
421
+ if (this.settings.closeOnSelect) {
422
+ this.callbacks.close();
423
+ }
424
+ if (this.callbacks.afterChange) {
425
+ this.callbacks.afterChange(after);
426
+ }
427
+ }
399
428
  };
400
429
  const deselectSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
401
430
  deselectSvg.setAttribute('viewBox', '0 0 100 100');
@@ -701,23 +730,48 @@ class Render {
701
730
  this.content.search.input.focus();
702
731
  return;
703
732
  }
733
+ const runFinish = (oo) => {
734
+ let newOption = new Option(oo);
735
+ this.callbacks.addOption(newOption);
736
+ if (this.settings.isMultiple) {
737
+ let values = this.store.getSelected();
738
+ values.push(newOption.value);
739
+ this.callbacks.setSelected(values);
740
+ }
741
+ else {
742
+ this.callbacks.setSelected([newOption.value]);
743
+ }
744
+ this.callbacks.search('');
745
+ if (this.settings.closeOnSelect) {
746
+ setTimeout(() => {
747
+ this.callbacks.close();
748
+ }, 100);
749
+ }
750
+ };
704
751
  const addableValue = this.callbacks.addable(inputValue);
705
- if (typeof addableValue === 'string') {
706
- this.callbacks.addOption(new Option({
752
+ if (addableValue instanceof Promise) {
753
+ addableValue.then((value) => {
754
+ if (typeof value === 'string') {
755
+ runFinish({
756
+ text: value,
757
+ value: value,
758
+ });
759
+ }
760
+ else {
761
+ runFinish(value);
762
+ }
763
+ });
764
+ }
765
+ else if (typeof addableValue === 'string') {
766
+ runFinish({
707
767
  text: addableValue,
708
768
  value: addableValue,
709
- }));
769
+ });
710
770
  }
711
771
  else {
712
- this.callbacks.addOption(new Option(addableValue));
713
- }
714
- this.callbacks.setSelected([inputValue]);
715
- this.callbacks.search('');
716
- if (this.settings.closeOnSelect) {
717
- setTimeout(() => {
718
- this.callbacks.close();
719
- }, 100);
772
+ runFinish(addableValue);
720
773
  }
774
+ return;
721
775
  };
722
776
  main.appendChild(addable);
723
777
  searchReturn.addable = {
@@ -761,25 +815,23 @@ class Render {
761
815
  }
762
816
  for (let i = 0; i < options.length; i++) {
763
817
  if (options[i].classList.contains(this.classes.highlighted)) {
764
- options[i].classList.remove(this.classes.highlighted);
765
- if (dir === 'down') {
766
- if (i + 1 < options.length) {
767
- options[i + 1].classList.add(this.classes.highlighted);
768
- this.ensureElementInView(this.content.list, options[i + 1]);
769
- }
770
- else {
771
- options[0].classList.add(this.classes.highlighted);
772
- this.ensureElementInView(this.content.list, options[0]);
818
+ const prevOption = options[i];
819
+ prevOption.classList.remove(this.classes.highlighted);
820
+ const prevParent = prevOption.parentElement;
821
+ if (prevParent && prevParent.classList.contains(this.classes.open)) {
822
+ const optgroupLabel = prevParent.querySelector('.' + this.classes.optgroupLabel);
823
+ if (optgroupLabel) {
824
+ optgroupLabel.click();
773
825
  }
774
826
  }
775
- else {
776
- if (i - 1 >= 0) {
777
- options[i - 1].classList.add(this.classes.highlighted);
778
- this.ensureElementInView(this.content.list, options[i - 1]);
779
- }
780
- else {
781
- options[options.length - 1].classList.add(this.classes.highlighted);
782
- this.ensureElementInView(this.content.list, options[options.length - 1]);
827
+ let selectOption = options[dir === 'down' ? (i + 1 < options.length ? i + 1 : 0) : i - 1 >= 0 ? i - 1 : options.length - 1];
828
+ selectOption.classList.add(this.classes.highlighted);
829
+ this.ensureElementInView(this.content.list, selectOption);
830
+ const selectParent = selectOption.parentElement;
831
+ if (selectParent && selectParent.classList.contains(this.classes.close)) {
832
+ const optgroupLabel = selectParent.querySelector('.' + this.classes.optgroupLabel);
833
+ if (optgroupLabel) {
834
+ optgroupLabel.click();
783
835
  }
784
836
  }
785
837
  return;
@@ -824,18 +876,95 @@ class Render {
824
876
  optgroupEl.classList.add(this.classes.optgroup);
825
877
  const optgroupLabel = document.createElement('div');
826
878
  optgroupLabel.classList.add(this.classes.optgroupLabel);
827
- optgroupLabel.innerHTML = d.label;
828
- if (this.settings.selectByGroup && this.settings.isMultiple) {
829
- optgroupLabel.classList.add(this.classes.optgroupSelectable);
879
+ optgroupEl.appendChild(optgroupLabel);
880
+ const optgroupLabelText = document.createElement('div');
881
+ optgroupLabelText.classList.add(this.classes.optgroupLabelText);
882
+ optgroupLabelText.textContent = d.label;
883
+ optgroupLabel.appendChild(optgroupLabelText);
884
+ const optgroupActions = document.createElement('div');
885
+ optgroupActions.classList.add(this.classes.optgroupActions);
886
+ optgroupLabel.appendChild(optgroupActions);
887
+ if (this.settings.isMultiple && d.selectAll) {
888
+ const selectAll = document.createElement('div');
889
+ selectAll.classList.add(this.classes.optgroupSelectAll);
890
+ let allSelected = true;
891
+ for (const o of d.options) {
892
+ if (!o.selected) {
893
+ allSelected = false;
894
+ break;
895
+ }
896
+ }
897
+ if (allSelected) {
898
+ selectAll.classList.add(this.classes.selected);
899
+ }
900
+ const selectAllText = document.createElement('span');
901
+ selectAllText.textContent = 'Select All';
902
+ selectAll.appendChild(selectAllText);
903
+ const selectAllSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
904
+ selectAllSvg.setAttribute('viewBox', '0 0 100 100');
905
+ selectAll.appendChild(selectAllSvg);
906
+ const selectAllBox = document.createElementNS('http://www.w3.org/2000/svg', 'path');
907
+ selectAllBox.setAttribute('d', this.classes.optgroupSelectAllBox);
908
+ selectAllSvg.appendChild(selectAllBox);
909
+ const selectAllCheck = document.createElementNS('http://www.w3.org/2000/svg', 'path');
910
+ selectAllCheck.setAttribute('d', this.classes.optgroupSelectAllCheck);
911
+ selectAllSvg.appendChild(selectAllCheck);
912
+ selectAll.addEventListener('click', (e) => {
913
+ e.preventDefault();
914
+ e.stopPropagation();
915
+ const currentSelected = this.store.getSelected();
916
+ if (allSelected) {
917
+ const newSelected = currentSelected.filter((s) => {
918
+ for (const o of d.options) {
919
+ if (s === o.value) {
920
+ return false;
921
+ }
922
+ }
923
+ return true;
924
+ });
925
+ this.callbacks.setSelected(newSelected);
926
+ return;
927
+ }
928
+ else {
929
+ const newSelected = currentSelected.concat(d.options.map((o) => o.value));
930
+ this.callbacks.setSelected(newSelected);
931
+ }
932
+ });
933
+ optgroupActions.appendChild(selectAll);
934
+ }
935
+ if (d.closable !== 'off') {
936
+ const optgroupClosable = document.createElement('div');
937
+ optgroupClosable.classList.add(this.classes.optgroupClosable);
938
+ const optgroupClosableSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
939
+ optgroupClosableSvg.setAttribute('viewBox', '0 0 100 100');
940
+ optgroupClosableSvg.classList.add(this.classes.arrow);
941
+ optgroupClosable.appendChild(optgroupClosableSvg);
942
+ const optgroupClosableArrow = document.createElementNS('http://www.w3.org/2000/svg', 'path');
943
+ optgroupClosableArrow.setAttribute('d', this.classes.arrow);
944
+ optgroupClosableSvg.appendChild(optgroupClosableArrow);
945
+ if (d.closable === 'open') {
946
+ optgroupEl.classList.add(this.classes.open);
947
+ optgroupClosableArrow.setAttribute('d', this.classes.arrowOpen);
948
+ }
949
+ else if (d.closable === 'close') {
950
+ optgroupEl.classList.add(this.classes.close);
951
+ optgroupClosableArrow.setAttribute('d', this.classes.arrowClose);
952
+ }
830
953
  optgroupLabel.addEventListener('click', (e) => {
831
954
  e.preventDefault();
832
955
  e.stopPropagation();
833
- for (const childEl of optgroupEl.children) {
834
- if (childEl.className.indexOf(this.classes.option) !== -1) {
835
- childEl.click();
836
- }
956
+ if (optgroupEl.classList.contains(this.classes.close)) {
957
+ optgroupEl.classList.remove(this.classes.close);
958
+ optgroupEl.classList.add(this.classes.open);
959
+ optgroupClosableArrow.setAttribute('d', this.classes.arrowOpen);
960
+ }
961
+ else {
962
+ optgroupEl.classList.remove(this.classes.open);
963
+ optgroupEl.classList.add(this.classes.close);
964
+ optgroupClosableArrow.setAttribute('d', this.classes.arrowClose);
837
965
  }
838
966
  });
967
+ optgroupActions.appendChild(optgroupClosable);
839
968
  }
840
969
  optgroupEl.appendChild(optgroupLabel);
841
970
  for (const o of d.options) {
@@ -887,10 +1016,10 @@ class Render {
887
1016
  optionEl.classList.add(this.classes.hide);
888
1017
  }
889
1018
  if (option.selected) {
890
- optionEl.classList.add(this.classes.optionSelected);
1019
+ optionEl.classList.add(this.classes.selected);
891
1020
  }
892
1021
  else {
893
- optionEl.classList.remove(this.classes.optionSelected);
1022
+ optionEl.classList.remove(this.classes.selected);
894
1023
  }
895
1024
  optionEl.addEventListener('click', (e) => {
896
1025
  e.preventDefault();
@@ -1073,7 +1202,9 @@ class Select {
1073
1202
  }
1074
1203
  observeWrapper(mutations) {
1075
1204
  if (this.onSelectChange) {
1205
+ this.changeListen(false);
1076
1206
  this.onSelectChange(this.getData());
1207
+ this.changeListen(true);
1077
1208
  }
1078
1209
  }
1079
1210
  addObserver() {
@@ -1081,15 +1212,12 @@ class Select {
1081
1212
  this.disconnectObserver();
1082
1213
  this.observer = null;
1083
1214
  }
1084
- this.observer = new MutationObserver(this.observeWrapper);
1215
+ this.observer = new MutationObserver(this.observeWrapper.bind(this));
1085
1216
  }
1086
1217
  connectObserver() {
1087
1218
  if (this.observer) {
1088
1219
  this.observer.observe(this.select, {
1089
- attributes: true,
1090
1220
  childList: true,
1091
- characterData: true,
1092
- subtree: true,
1093
1221
  });
1094
1222
  }
1095
1223
  }
@@ -1113,8 +1241,10 @@ class Select {
1113
1241
  }
1114
1242
  getDataFromOptgroup(optgroup) {
1115
1243
  let data = {
1116
- id: '',
1244
+ id: (optgroup.dataset ? optgroup.dataset.id : false) || '',
1117
1245
  label: optgroup.label,
1246
+ selectAll: optgroup.dataset ? optgroup.dataset.selectall === 'true' : false,
1247
+ closable: optgroup.dataset ? optgroup.dataset.closable : 'off',
1118
1248
  options: [],
1119
1249
  };
1120
1250
  const options = optgroup.childNodes;
@@ -1125,6 +1255,22 @@ class Select {
1125
1255
  }
1126
1256
  return data;
1127
1257
  }
1258
+ getDataFromOption(option) {
1259
+ return {
1260
+ id: (option.dataset ? option.dataset.id : false) || '',
1261
+ value: option.value,
1262
+ text: option.text,
1263
+ html: option.innerHTML,
1264
+ selected: option.selected,
1265
+ display: option.style.display === 'none' ? false : true,
1266
+ disabled: option.disabled,
1267
+ mandatory: option.dataset ? option.dataset.mandatory === 'true' : false,
1268
+ placeholder: option.dataset.placeholder === 'true',
1269
+ class: option.className,
1270
+ style: option.style.cssText,
1271
+ data: option.dataset,
1272
+ };
1273
+ }
1128
1274
  getSelectedValues() {
1129
1275
  let values = [];
1130
1276
  const options = this.select.childNodes;
@@ -1149,22 +1295,6 @@ class Select {
1149
1295
  }
1150
1296
  return values;
1151
1297
  }
1152
- getDataFromOption(option) {
1153
- return {
1154
- id: (option.dataset ? option.dataset.id : false) || generateID(),
1155
- value: option.value,
1156
- text: option.text,
1157
- html: option.innerHTML,
1158
- selected: option.selected,
1159
- display: option.style.display === 'none' ? false : true,
1160
- disabled: option.disabled,
1161
- mandatory: option.dataset ? option.dataset.mandatory === 'true' : false,
1162
- placeholder: option.dataset.placeholder === 'true',
1163
- class: option.className,
1164
- style: option.style.cssText,
1165
- data: option.dataset,
1166
- };
1167
- }
1168
1298
  setSelected(value) {
1169
1299
  const options = this.select.childNodes;
1170
1300
  for (const o of options) {
@@ -1219,6 +1349,12 @@ class Select {
1219
1349
  const optgroupEl = document.createElement('optgroup');
1220
1350
  optgroupEl.id = optgroup.id;
1221
1351
  optgroupEl.label = optgroup.label;
1352
+ if (optgroup.selectAll) {
1353
+ optgroupEl.dataset.selectAll = 'true';
1354
+ }
1355
+ if (optgroup.closable !== 'off') {
1356
+ optgroupEl.dataset.closable = optgroup.closable;
1357
+ }
1222
1358
  if (optgroup.options) {
1223
1359
  for (const o of optgroup.options) {
1224
1360
  optgroupEl.appendChild(this.createOption(o));
@@ -1275,8 +1411,6 @@ class Settings {
1275
1411
  this.isOpen = false;
1276
1412
  this.triggerFocus = true;
1277
1413
  this.intervalMove = null;
1278
- this.mainHeight = 30;
1279
- this.contentHeight = 0;
1280
1414
  if (!settings) {
1281
1415
  settings = {};
1282
1416
  }
@@ -1298,7 +1432,6 @@ class Settings {
1298
1432
  this.allowDeselect = settings.allowDeselect !== undefined ? settings.allowDeselect : false;
1299
1433
  this.hideSelected = settings.hideSelected !== undefined ? settings.hideSelected : false;
1300
1434
  this.showOptionTooltips = settings.showOptionTooltips !== undefined ? settings.showOptionTooltips : false;
1301
- this.selectByGroup = settings.selectByGroup !== undefined ? settings.selectByGroup : false;
1302
1435
  this.minSelected = settings.minSelected || 0;
1303
1436
  this.maxSelected = settings.maxSelected || 1000;
1304
1437
  this.timeoutDelay = settings.timeoutDelay || 200;
@@ -1405,6 +1538,8 @@ class SlimSelect {
1405
1538
  afterChange: this.events.afterChange,
1406
1539
  };
1407
1540
  this.render = new Render(this.settings, this.store, callbacks);
1541
+ this.render.renderValues();
1542
+ this.render.renderOptions(this.store.getData());
1408
1543
  if (this.selectEl.parentNode) {
1409
1544
  this.selectEl.parentNode.insertBefore(this.render.main.main, this.selectEl.nextSibling);
1410
1545
  }