@danielgindi/selectbox 2.0.1 → 2.0.2

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/dist/lib.cjs.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @danielgindi/selectbox 2.0.1
2
+ * @danielgindi/selectbox 2.0.2
3
3
  * git://github.com/danielgindi/selectbox.git
4
4
  */
5
5
  'use strict';
@@ -61,7 +61,7 @@ const throttle = (func, wait, options) => {
61
61
  return throttled;
62
62
  };
63
63
 
64
- const ItemSymbol$1 = Symbol('item');
64
+ const ItemSymbol = Symbol('item');
65
65
  const DestroyedSymbol$1 = Symbol('destroyed');
66
66
  const GhostSymbol = Symbol('ghost');
67
67
  const NoResultsItemSymbol = Symbol('no_results_items');
@@ -93,6 +93,7 @@ const hasOwnProperty = Object.prototype.hasOwnProperty;
93
93
  * @property {function(item: DropList.ItemBase, itemEl: Element):(*|false)} [renderNoResultsItem]
94
94
  * @property {function(item: DropList.ItemBase, itemEl: Element)} [unrenderNoResultsItem]
95
95
  * @property {function(name: string, data: *)} [on]
96
+ * @property {boolean} [isHeaderVisible=false] show header element
96
97
  * @property {boolean} [searchable=false] include inline search box
97
98
  * @property {string} [noResultsText='No matching results'] text for no results (empty for none)
98
99
  * @property {number} [filterThrottleWindow=300] throttle time (milliseconds) for filtering
@@ -165,6 +166,7 @@ let defaultOptions$1 = {
165
166
 
166
167
  on: null,
167
168
 
169
+ isHeaderVisible: false,
168
170
  searchable: false,
169
171
  noResultsText: 'No matching results',
170
172
  filterThrottleWindow: 300,
@@ -237,6 +239,7 @@ class DropList {
237
239
  positionOptionsProvider: o.positionOptionsProvider ?? null,
238
240
 
239
241
  searchable: o.searchable,
242
+ isHeaderVisible: o.isHeaderVisible,
240
243
 
241
244
  silenceEvents: true,
242
245
  mitt: mitt(),
@@ -284,33 +287,24 @@ class DropList {
284
287
  });
285
288
  }
286
289
 
290
+ p.el = wrapperEl;
291
+
287
292
  let menuEl = Dom.createElement('ul');
288
293
  menuEl.role = 'menu';
294
+ p.menuEl = menuEl;
289
295
 
290
- if (o.searchable) {
291
- p.headerEl = Dom.createElement('div', {
292
- class: p.baseClassName + '_header'
293
- });
294
-
295
- p.searchInput = Dom.createElement('input', {
296
- type: 'search',
297
- role: 'searchbox',
298
- tabindex: '0',
299
- autocorrect: 'off',
300
- autocomplete: 'off',
301
- autocapitalize: 'off',
302
- spellcheck: 'false',
303
- 'aria-autocomplete': 'list'
304
- });
296
+ p.headerEl = Dom.createElement('div', {
297
+ class: p.baseClassName + '_header'
298
+ });
305
299
 
306
- p.headerEl.appendChild(p.searchInput);
307
- wrapperEl.appendChild(p.headerEl);
300
+ if (o.searchable) {
301
+ this.setSearchable(true);
308
302
  }
309
303
 
310
- wrapperEl.appendChild(menuEl);
304
+ if (o.isHeaderVisible)
305
+ this.setHeaderVisible(o.isHeaderVisible);
311
306
 
312
- p.el = wrapperEl;
313
- p.menuEl = menuEl;
307
+ wrapperEl.appendChild(menuEl);
314
308
 
315
309
  p.items = [];
316
310
  p.groupCount = 0; // This will keep state of how many `group` items we have
@@ -337,7 +331,7 @@ class DropList {
337
331
  label: p.lastMeasureLongestLabelText,
338
332
  value: 'Measure',
339
333
 
340
- [ItemSymbol$1]: {
334
+ [ItemSymbol]: {
341
335
  [p.labelProp]: p.lastMeasureLongestLabelText,
342
336
  [p.valueProp]: 'Measure'
343
337
  }
@@ -352,7 +346,7 @@ class DropList {
352
346
  _nointeraction: true,
353
347
  _nocheck: true,
354
348
 
355
- [ItemSymbol$1]: NoResultsItemSymbol
349
+ [ItemSymbol]: NoResultsItemSymbol
356
350
  };
357
351
  } else {
358
352
  item = items[index];
@@ -398,7 +392,7 @@ class DropList {
398
392
 
399
393
  this._renderItemContent(item, itemEl);
400
394
 
401
- itemEl[ItemSymbol$1] = item;
395
+ itemEl[ItemSymbol] = item;
402
396
  }
403
397
  });
404
398
 
@@ -578,7 +572,7 @@ class DropList {
578
572
  const fn = p.unrenderItem;
579
573
  const fnNoResults = p.unrenderNoResultsItem;
580
574
  p.virtualListHelper.setOnItemUnrender((el) => {
581
- const item = el[ItemSymbol$1];
575
+ const item = el[ItemSymbol];
582
576
  if (item === NoResultsItemSymbol) {
583
577
  try {
584
578
  fnNoResults(item, el);
@@ -587,19 +581,19 @@ class DropList {
587
581
  }
588
582
  } else {
589
583
  try {
590
- fn(item[ItemSymbol$1], el);
584
+ fn(item[ItemSymbol], el);
591
585
  } catch (err) {
592
586
  console.error(err); // eslint-disable-line no-console
593
587
  }
594
588
  }
595
- delete el[ItemSymbol$1];
589
+ delete el[ItemSymbol];
596
590
 
597
591
  if (p.focusItemEl === el)
598
592
  p.focusItemEl = null;
599
593
  });
600
594
  } else {
601
595
  p.virtualListHelper.setOnItemUnrender((el) => {
602
- delete el[ItemSymbol$1];
596
+ delete el[ItemSymbol];
603
597
 
604
598
  if (p.focusItemEl === el)
605
599
  p.focusItemEl = null;
@@ -665,7 +659,7 @@ class DropList {
665
659
  this._hideSublist();
666
660
  }
667
661
 
668
- this._trigger('itemblur', { value: item.value, item: item[ItemSymbol$1] ?? item });
662
+ this._trigger('itemblur', { value: item.value, item: item[ItemSymbol] ?? item });
669
663
  }
670
664
 
671
665
  nextPage(event) {
@@ -697,7 +691,7 @@ class DropList {
697
691
  }
698
692
  this._trigger('check', {
699
693
  value: item.value,
700
- item: item[ItemSymbol$1] ?? item,
694
+ item: item[ItemSymbol] ?? item,
701
695
  checked: item._checked,
702
696
  isGroup: item._group,
703
697
  isCheckingGroup: false
@@ -717,7 +711,7 @@ class DropList {
717
711
  if (p.focusItemIndex === undefined)
718
712
  p.focusItemIndex = -1;
719
713
 
720
- item = item ?? p.focusItemEl[ItemSymbol$1];
714
+ item = item ?? p.focusItemEl[ItemSymbol];
721
715
  if (item._nointeraction) {
722
716
  return false;
723
717
  }
@@ -728,7 +722,7 @@ class DropList {
728
722
 
729
723
  this._trigger('select', {
730
724
  value: item ? item.value : undefined,
731
- item: item[ItemSymbol$1] ?? item,
725
+ item: item[ItemSymbol] ?? item,
732
726
  event: event,
733
727
  el: p.focusItemEl
734
728
  });
@@ -769,7 +763,7 @@ class DropList {
769
763
  let oitem = itemsToAdd[i];
770
764
  //noinspection PointlessBooleanExpressionJS
771
765
  let item = {
772
- [ItemSymbol$1]: oitem,
766
+ [ItemSymbol]: oitem,
773
767
  label: oitem[labelProp],
774
768
  value: oitem[valueProp],
775
769
  _nocheck: !!oitem._nocheck,
@@ -856,7 +850,7 @@ class DropList {
856
850
  if (itemIndex === -1) return this;
857
851
 
858
852
  let item = this.itemAtIndex(itemIndex);
859
- item[ItemSymbol$1] = newItem;
853
+ item[ItemSymbol] = newItem;
860
854
 
861
855
  if (hasOwnProperty.call(newItem, p.labelProp))
862
856
  item.label = newItem[p.labelProp];
@@ -982,7 +976,7 @@ class DropList {
982
976
  for (let i = 0, count = p.items.length; i < count; i++) {
983
977
  let item = p.items[i];
984
978
  if (item.value === value) {
985
- return item[ItemSymbol$1];
979
+ return item[ItemSymbol];
986
980
  }
987
981
  }
988
982
 
@@ -1052,7 +1046,7 @@ class DropList {
1052
1046
 
1053
1047
  for (let i = 0, count = items.length; i < count; i++) {
1054
1048
  let it = items[i];
1055
- if (it[ItemSymbol$1] === item) {
1049
+ if (it[ItemSymbol] === item) {
1056
1050
  return i;
1057
1051
  }
1058
1052
  }
@@ -1067,7 +1061,7 @@ class DropList {
1067
1061
 
1068
1062
  for (let i = 0, count = items.length; i < count; i++) {
1069
1063
  let it = items[i];
1070
- if (it[ItemSymbol$1] === item) {
1064
+ if (it[ItemSymbol] === item) {
1071
1065
  return i;
1072
1066
  }
1073
1067
  }
@@ -1076,7 +1070,7 @@ class DropList {
1076
1070
  }
1077
1071
 
1078
1072
  items() {
1079
- return this._p.items.map((x) => x[ItemSymbol$1]);
1073
+ return this._p.items.map((x) => x[ItemSymbol]);
1080
1074
  }
1081
1075
 
1082
1076
  itemsReference() {
@@ -1088,13 +1082,42 @@ class DropList {
1088
1082
  }
1089
1083
 
1090
1084
  itemAtIndex(index) {
1091
- return this._p.items[index]?.[ItemSymbol$1];
1085
+ return this._p.items[index]?.[ItemSymbol];
1092
1086
  }
1093
1087
 
1094
1088
  filteredItemAtIndex(index) {
1095
1089
  const p = this._p;
1096
1090
  const items = p.filteredItems ?? p.items;
1097
- return items[index]?.[ItemSymbol$1];
1091
+ return items[index]?.[ItemSymbol];
1092
+ }
1093
+
1094
+ /**
1095
+ * Return the item element at the given original index, if it exists.
1096
+ * The item may not be currently rendered, and null will be returned
1097
+ * @param index
1098
+ * @returns {HTMLElement|null}
1099
+ */
1100
+ itemElementAtIndex(index) {
1101
+ const p = this._p;
1102
+ if (!p.filteredItems)
1103
+ return this.filteredElementItemAtIndex(index);
1104
+
1105
+ index = p.filteredItems.indexOf(this._p.items[index]);
1106
+
1107
+ const li = p.virtualListHelper.getItemElementAt(index);
1108
+ return li ?? null;
1109
+ }
1110
+
1111
+ /**
1112
+ * Return the item element at the given index, if it exists.
1113
+ * The item may not be currently rendered, and null will be returned
1114
+ * @param index
1115
+ * @returns {HTMLElement|null}
1116
+ */
1117
+ filteredElementItemAtIndex(index) {
1118
+ const p = this._p;
1119
+ const li = p.virtualListHelper.getItemElementAt(index);
1120
+ return li ?? null;
1098
1121
  }
1099
1122
 
1100
1123
  /**
@@ -1162,7 +1185,30 @@ class DropList {
1162
1185
  let filteredItems;
1163
1186
 
1164
1187
  if (typeof fn === 'function') {
1165
- filteredItems = p.filterFn(p.items, term);
1188
+ // Send the original items to the filter function
1189
+ filteredItems = p.filterFn(
1190
+ p.items.map((x) => x[ItemSymbol] ?? x),
1191
+ term);
1192
+
1193
+ if (Array.isArray(filteredItems)) {
1194
+ // And back
1195
+ filteredItems = filteredItems.map((oitem) => {
1196
+ let our = oitem[ItemSymbol];
1197
+ if (!our) {
1198
+ our = {
1199
+ [ItemSymbol]: oitem,
1200
+ label: oitem[p.labelProp],
1201
+ value: oitem[p.valueProp],
1202
+ _nocheck: !!oitem._nocheck,
1203
+ _nointeraction: !!oitem._nointeraction,
1204
+ _subitems: oitem._subitems,
1205
+ _group: !!oitem._group,
1206
+ _checked: !!oitem._checked
1207
+ };
1208
+ }
1209
+ return our;
1210
+ });
1211
+ }
1166
1212
  }
1167
1213
 
1168
1214
  // If there was no filter function, or it gave up on filtering.
@@ -1661,7 +1707,7 @@ class DropList {
1661
1707
  let li = p.virtualListHelper.getItemElementAt(index);
1662
1708
  if (!li) return this;
1663
1709
 
1664
- let item = li[ItemSymbol$1];
1710
+ let item = li[ItemSymbol];
1665
1711
 
1666
1712
  checked = checked && !item._nocheck;
1667
1713
 
@@ -1754,7 +1800,7 @@ class DropList {
1754
1800
  let item = p.items[i];
1755
1801
  if (!item._checked) continue;
1756
1802
  if (excludeGroups && item._group) continue;
1757
- items.push(item[ItemSymbol$1]);
1803
+ items.push(item[ItemSymbol]);
1758
1804
  }
1759
1805
 
1760
1806
  return items;
@@ -1920,6 +1966,72 @@ class DropList {
1920
1966
  return p.el.parentNode && getComputedStyle(p.el).display !== 'none';
1921
1967
  }
1922
1968
 
1969
+ /**
1970
+ * Change visibility of the header element
1971
+ * You should probably call `relayout()` after this.
1972
+ * @param {boolean} visible
1973
+ */
1974
+ setHeaderVisible(visible) {
1975
+ let isVisible = this.isHeaderVisible();
1976
+ if (isVisible === !!visible)
1977
+ return;
1978
+
1979
+ if (visible) {
1980
+ this._p.el.insertBefore(this._p.headerEl, this._p.el.firstChild ?? null);
1981
+ } else {
1982
+ this._p.headerEl.remove();
1983
+ }
1984
+ }
1985
+
1986
+ /**
1987
+ * Is the header element visible?
1988
+ * @returns {boolean}
1989
+ */
1990
+ isHeaderVisible() {
1991
+ return !!this._p.headerEl.parentNode;
1992
+ }
1993
+
1994
+ /**
1995
+ * Get a reference to the header element in order to add custom content.
1996
+ * @returns {Element}
1997
+ */
1998
+ getHeaderElement() {
1999
+ return this._p.headerEl;
2000
+ }
2001
+
2002
+ /**
2003
+ * Set inline search visibility
2004
+ * You should probably call `relayout()` after this.
2005
+ * @param {boolean} searchable
2006
+ */
2007
+ setSearchable(searchable) {
2008
+ const p = this._p;
2009
+
2010
+ if (!!p.searchInput === !!searchable)
2011
+ return;
2012
+
2013
+ if (searchable) {
2014
+ p.searchInput = Dom.createElement('input', {
2015
+ type: 'search',
2016
+ role: 'searchbox',
2017
+ tabindex: '0',
2018
+ autocorrect: 'off',
2019
+ autocomplete: 'off',
2020
+ autocapitalize: 'off',
2021
+ spellcheck: 'false',
2022
+ 'aria-autocomplete': 'list'
2023
+ });
2024
+
2025
+ p.headerEl.appendChild(p.searchInput);
2026
+ } else {
2027
+ if (p.searchInput.parentNode)
2028
+ p.searchInput.remove();
2029
+ p.searchInput = null;
2030
+ }
2031
+
2032
+ this.setHeaderVisible(searchable);
2033
+ }
2034
+
1923
2035
  hasFocusedItem() {
1924
2036
  return this._p.focusItemIndex > -1;
1925
2037
  }
@@ -1962,11 +2074,11 @@ class DropList {
1962
2074
  itemElement.classList.add(`${p.baseClassName}__item_focus`);
1963
2075
  p.focusItemEl = itemElement;
1964
2076
 
1965
- const item = itemElement[ItemSymbol$1];
2077
+ const item = itemElement[ItemSymbol];
1966
2078
 
1967
2079
  this._trigger('itemfocus', {
1968
2080
  value: item.value,
1969
- item: item[ItemSymbol$1] ?? item,
2081
+ item: item[ItemSymbol] ?? item,
1970
2082
  event: null,
1971
2083
  el: itemElement
1972
2084
  });
@@ -2033,7 +2145,7 @@ class DropList {
2033
2145
 
2034
2146
  this._trigger('show_subitems', {
2035
2147
  value: item.value,
2036
- item: item[ItemSymbol$1] ?? item,
2148
+ item: item[ItemSymbol] ?? item,
2037
2149
  el: itemElement,
2038
2150
  droplist: droplist
2039
2151
  });
@@ -2205,7 +2317,7 @@ class DropList {
2205
2317
  const p = this._p;
2206
2318
 
2207
2319
  if (this._hasScroll()) {
2208
- const el = p.el,scrollTop = el.scrollTop;
2320
+ const menuEl = p.menuEl,scrollTop = menuEl.scrollTop;
2209
2321
 
2210
2322
  let itemPos,previousPos = -1;
2211
2323
  let maxIterations = 30; // Some zoom/scroll issues can make it so that it takes almost forever
@@ -2220,12 +2332,12 @@ class DropList {
2220
2332
 
2221
2333
  let itemSize = p.virtualListHelper.getItemSize(itemIndex);
2222
2334
 
2223
- let listHeight = el.clientHeight;
2335
+ let listHeight = menuEl.clientHeight;
2224
2336
 
2225
2337
  if (itemPos < scrollTop) {
2226
- el.scrollTop = itemPos;
2338
+ menuEl.scrollTop = itemPos;
2227
2339
  } else if (itemPos + itemSize > scrollTop + listHeight) {
2228
- el.scrollTop = itemPos + itemSize - listHeight;
2340
+ menuEl.scrollTop = itemPos + itemSize - listHeight;
2229
2341
  }
2230
2342
 
2231
2343
  // force update items, until the positions and sizes are final
@@ -2510,6 +2622,8 @@ class DropList {
2510
2622
  case keycodeJs.VALUE_END:
2511
2623
  case keycodeJs.VALUE_UP:
2512
2624
  case keycodeJs.VALUE_DOWN:
2625
+ p.lastKeyWasChar = false;
2626
+
2513
2627
  event.preventDefault();
2514
2628
 
2515
2629
  switch (event.key) {
@@ -2536,6 +2650,7 @@ class DropList {
2536
2650
 
2537
2651
  case keycodeJs.VALUE_LEFT:
2538
2652
  case keycodeJs.VALUE_RIGHT:
2653
+ p.lastKeyWasChar = false;
2539
2654
  if (event.key === keycodeJs.VALUE_RIGHT && getComputedStyle(event.target).direction !== 'rtl' ||
2540
2655
  event.key === keycodeJs.VALUE_LEFT && getComputedStyle(event.target).direction === 'rtl') {
2541
2656
  const items = p.filteredItems ?? p.items;
@@ -2553,22 +2668,31 @@ class DropList {
2553
2668
  break;
2554
2669
 
2555
2670
  case keycodeJs.VALUE_ENTER:
2671
+ p.lastKeyWasChar = false;
2556
2672
  this.triggerItemSelection(null, event);
2557
2673
  event.preventDefault();
2558
2674
  break;
2559
2675
 
2560
2676
  case keycodeJs.VALUE_SPACE:
2677
+ if (event.target.tagName === 'BUTTON' ||
2678
+ event.target.tagName === 'INPUT' && p.lastKeyWasChar) return;
2679
+
2561
2680
  this.toggleFocusedItem();
2562
2681
  event.preventDefault();
2563
2682
  break;
2564
2683
 
2565
2684
  case keycodeJs.VALUE_ESCAPE:
2685
+ p.lastKeyWasChar = false;
2566
2686
  event.preventDefault();
2567
2687
  this.hide();
2568
2688
  break;
2569
2689
 
2570
2690
  default:{
2571
- if (event.type === 'keydown') return;
2691
+ if (event.target.tagName === 'INPUT' ||
2692
+ event.target.tagName === 'TEXTAREA') {
2693
+ const character = event.key || String.fromCharCode(event.keyCode);
2694
+ p.lastKeyWasChar = character.length === 1 || event.key === keycodeJs.VALUE_BACK_SPACE;
2695
+ }
2572
2696
 
2573
2697
  // Inline search box not available, then support typing to focus by first letters
2574
2698
  if (!p.searchable)
@@ -2583,8 +2707,10 @@ class DropList {
2583
2707
  const p = this._p;
2584
2708
 
2585
2709
  // noinspection JSDeprecatedSymbols
2586
- let character = evt.key || String.fromCharCode(evt.keyCode);
2587
- if (character.length !== 1) return;
2710
+ const character = evt.key || String.fromCharCode(evt.keyCode);
2711
+ const isChar = character.length === 1;
2712
+ p.lastKeyWasChar = isChar || evt.key === keycodeJs.VALUE_BACK_SPACE;
2713
+ if (!isChar) return;
2588
2714
 
2589
2715
  clearTimeout(p.filterTimer);
2590
2716
 
@@ -2664,7 +2790,7 @@ class DropList {
2664
2790
  itemIndex = p.virtualListHelper.getItemIndexFromElement(itemEl);
2665
2791
  }
2666
2792
 
2667
- if (itemIndex > -1 && itemEl?.[ItemSymbol$1]?.[ItemSymbol$1] === NoResultsItemSymbol) {
2793
+ if (itemIndex > -1 && itemEl?.[ItemSymbol]?.[ItemSymbol] === NoResultsItemSymbol) {
2668
2794
  itemIndex = undefined;
2669
2795
  }
2670
2796
 
@@ -2675,7 +2801,7 @@ class DropList {
2675
2801
  }
2676
2802
 
2677
2803
  let focusItemEl = itemEl || p.virtualListHelper.getItemElementAt(itemIndex);
2678
- if (!focusItemEl || focusItemEl[ItemSymbol$1]._nointeraction) {
2804
+ if (!focusItemEl || focusItemEl[ItemSymbol]._nointeraction) {
2679
2805
  p._isFocusingItem = false;
2680
2806
  this.blurFocusedItem();
2681
2807
  return;
@@ -2697,7 +2823,7 @@ class DropList {
2697
2823
  const item = items[itemIndex];
2698
2824
  this._trigger('itemfocus', {
2699
2825
  value: item.value,
2700
- item: item[ItemSymbol$1] ?? item,
2826
+ item: item[ItemSymbol] ?? item,
2701
2827
  event: event,
2702
2828
  el: focusItemEl
2703
2829
  });
@@ -2903,7 +3029,7 @@ class DropList {
2903
3029
  // Fire event
2904
3030
  this._trigger('check', {
2905
3031
  value: next.value,
2906
- item: next[ItemSymbol$1] ?? next,
3032
+ item: next[ItemSymbol] ?? next,
2907
3033
  checked: next._checked,
2908
3034
  isGroup: next._group,
2909
3035
  isCheckingGroup: true
@@ -2914,7 +3040,7 @@ class DropList {
2914
3040
  // Fire event
2915
3041
  this._trigger('groupcheck', {
2916
3042
  value: item.value,
2917
- item: item[ItemSymbol$1] ?? item,
3043
+ item: item[ItemSymbol] ?? item,
2918
3044
  affectedItems: affectedItems
2919
3045
  });
2920
3046
  } else if (p.groupCount > 0 && p.autoCheckGroupChildren) {
@@ -2985,7 +3111,7 @@ class DropList {
2985
3111
  // Fire event
2986
3112
  this._trigger('check', {
2987
3113
  value: groupItem.value,
2988
- item: groupItem[ItemSymbol$1] ?? groupItem,
3114
+ item: groupItem[ItemSymbol] ?? groupItem,
2989
3115
  checked: groupItem._checked,
2990
3116
  isGroup: groupItem._group,
2991
3117
  isCheckingGroup: false
@@ -3090,7 +3216,7 @@ class DropList {
3090
3216
  // NOTE: a "measure" item will not have full data of original item.
3091
3217
  // so for a custom renderer - we try to send original item, and fallback to our private list item.
3092
3218
 
3093
- const originalItem = item[ItemSymbol$1];
3219
+ const originalItem = item[ItemSymbol];
3094
3220
 
3095
3221
  if (originalItem === NoResultsItemSymbol) {
3096
3222
  if (p.renderNoResultsItem && p.renderNoResultsItem(item, itemEl) !== false) {
@@ -3173,7 +3299,6 @@ class DropList {
3173
3299
  }
3174
3300
  }
3175
3301
 
3176
- const ItemSymbol = Symbol('item');
3177
3302
  const DestroyedSymbol = Symbol('destroyed');
3178
3303
  const RestMultiItemsSymbol = Symbol('rest_multi_items');
3179
3304