@vueuse/components 10.0.0-beta.2 → 10.0.0-beta.3

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/index.cjs CHANGED
@@ -54,14 +54,20 @@ function useEventListener(...args) {
54
54
  el.addEventListener(event, listener, options2);
55
55
  return () => el.removeEventListener(event, listener, options2);
56
56
  };
57
- const stopWatch = vueDemi.watch(() => [unrefElement(target), shared.resolveUnref(options)], ([el, options2]) => {
58
- cleanup();
59
- if (!el)
60
- return;
61
- cleanups.push(...events.flatMap((event) => {
62
- return listeners.map((listener) => register(el, event, listener, options2));
63
- }));
64
- }, { immediate: true, flush: "post" });
57
+ const stopWatch = vueDemi.watch(
58
+ () => [unrefElement(target), shared.resolveUnref(options)],
59
+ ([el, options2]) => {
60
+ cleanup();
61
+ if (!el)
62
+ return;
63
+ cleanups.push(
64
+ ...events.flatMap((event) => {
65
+ return listeners.map((listener) => register(el, event, listener, options2));
66
+ })
67
+ );
68
+ },
69
+ { immediate: true, flush: "post" }
70
+ );
65
71
  const stop = () => {
66
72
  stopWatch();
67
73
  cleanup();
@@ -135,7 +141,7 @@ const vOnClickOutside = {
135
141
  }
136
142
  };
137
143
 
138
- const createKeyPredicate = (keyFilter) => {
144
+ function createKeyPredicate(keyFilter) {
139
145
  if (typeof keyFilter === "function")
140
146
  return keyFilter;
141
147
  else if (typeof keyFilter === "string")
@@ -143,7 +149,7 @@ const createKeyPredicate = (keyFilter) => {
143
149
  else if (Array.isArray(keyFilter))
144
150
  return (event) => keyFilter.includes(event.key);
145
151
  return () => true;
146
- };
152
+ }
147
153
  function onKeyStroke(...args) {
148
154
  let key;
149
155
  let handler;
@@ -234,7 +240,10 @@ function onLongPress(target, handler, options) {
234
240
  ev.preventDefault();
235
241
  if ((_c = options == null ? void 0 : options.modifiers) == null ? void 0 : _c.stop)
236
242
  ev.stopPropagation();
237
- timeout = setTimeout(() => handler(ev), (_d = options == null ? void 0 : options.delay) != null ? _d : DEFAULT_DELAY);
243
+ timeout = setTimeout(
244
+ () => handler(ev),
245
+ (_d = options == null ? void 0 : options.delay) != null ? _d : DEFAULT_DELAY
246
+ );
238
247
  }
239
248
  const listenerOptions = {
240
249
  capture: (_a = options == null ? void 0 : options.modifiers) == null ? void 0 : _a.capture,
@@ -251,9 +260,13 @@ const OnLongPress = /* @__PURE__ */ /* #__PURE__ */ vueDemi.defineComponent({
251
260
  emits: ["trigger"],
252
261
  setup(props, { slots, emit }) {
253
262
  const target = vueDemi.ref();
254
- onLongPress(target, (e) => {
255
- emit("trigger", e);
256
- }, props.options);
263
+ onLongPress(
264
+ target,
265
+ (e) => {
266
+ emit("trigger", e);
267
+ },
268
+ props.options
269
+ );
257
270
  return () => {
258
271
  if (slots.default)
259
272
  return vueDemi.h(props.as || "div", { ref: target }, slots.default());
@@ -399,7 +412,11 @@ function useStorage(key, defaults, storage, options = {}) {
399
412
  const rawInit = shared.resolveUnref(defaults);
400
413
  const type = guessSerializerType(rawInit);
401
414
  const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type];
402
- const { pause: pauseWatch, resume: resumeWatch } = shared.pausableWatch(data, () => write(data.value), { flush, deep, eventFilter });
415
+ const { pause: pauseWatch, resume: resumeWatch } = shared.pausableWatch(
416
+ data,
417
+ () => write(data.value),
418
+ { flush, deep, eventFilter }
419
+ );
403
420
  if (window && listenToStorageChanges) {
404
421
  useEventListener(window, "storage", update);
405
422
  useEventListener(window, customStorageEventName, updateFromCustomEvent);
@@ -478,9 +495,11 @@ function useStorage(key, defaults, storage, options = {}) {
478
495
 
479
496
  function useMounted() {
480
497
  const isMounted = vueDemi.ref(false);
481
- vueDemi.onMounted(() => {
482
- isMounted.value = true;
483
- });
498
+ if (vueDemi.getCurrentInstance()) {
499
+ vueDemi.onMounted(() => {
500
+ isMounted.value = true;
501
+ });
502
+ }
484
503
  return isMounted;
485
504
  }
486
505
 
@@ -510,7 +529,9 @@ function useMediaQuery(query, options = {}) {
510
529
  return;
511
530
  cleanup();
512
531
  mediaQuery = window.matchMedia(shared.resolveRef(query).value);
513
- matches.value = mediaQuery.matches;
532
+ matches.value = !!(mediaQuery == null ? void 0 : mediaQuery.matches);
533
+ if (!mediaQuery)
534
+ return;
514
535
  if ("addEventListener" in mediaQuery)
515
536
  mediaQuery.addEventListener("change", update);
516
537
  else
@@ -552,6 +573,7 @@ function useColorMode(options = {}) {
552
573
  listenToStorageChanges = true,
553
574
  storageRef,
554
575
  emitAuto,
576
+ // TODO: switch to true in v10
555
577
  disableTransition = false
556
578
  } = options;
557
579
  const modes = __spreadValues$b({
@@ -570,33 +592,36 @@ function useColorMode(options = {}) {
570
592
  store.value = v;
571
593
  }
572
594
  });
573
- const updateHTMLAttrs = getSSRHandler("updateHTMLAttrs", (selector2, attribute2, value) => {
574
- const el = window == null ? void 0 : window.document.querySelector(selector2);
575
- if (!el)
576
- return;
577
- let style;
578
- if (disableTransition) {
579
- style = window.document.createElement("style");
580
- style.type = "text/css";
581
- style.appendChild(document.createTextNode("*{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}"));
582
- window.document.head.appendChild(style);
583
- }
584
- if (attribute2 === "class") {
585
- const current = value.split(/\s/g);
586
- Object.values(modes).flatMap((i) => (i || "").split(/\s/g)).filter(Boolean).forEach((v) => {
587
- if (current.includes(v))
588
- el.classList.add(v);
589
- else
590
- el.classList.remove(v);
591
- });
592
- } else {
593
- el.setAttribute(attribute2, value);
594
- }
595
- if (disableTransition) {
596
- window.getComputedStyle(style).opacity;
597
- document.head.removeChild(style);
595
+ const updateHTMLAttrs = getSSRHandler(
596
+ "updateHTMLAttrs",
597
+ (selector2, attribute2, value) => {
598
+ const el = window == null ? void 0 : window.document.querySelector(selector2);
599
+ if (!el)
600
+ return;
601
+ let style;
602
+ if (disableTransition) {
603
+ style = window.document.createElement("style");
604
+ style.type = "text/css";
605
+ style.appendChild(document.createTextNode("*{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}"));
606
+ window.document.head.appendChild(style);
607
+ }
608
+ if (attribute2 === "class") {
609
+ const current = value.split(/\s/g);
610
+ Object.values(modes).flatMap((i) => (i || "").split(/\s/g)).filter(Boolean).forEach((v) => {
611
+ if (current.includes(v))
612
+ el.classList.add(v);
613
+ else
614
+ el.classList.remove(v);
615
+ });
616
+ } else {
617
+ el.setAttribute(attribute2, value);
618
+ }
619
+ if (disableTransition) {
620
+ window.getComputedStyle(style).opacity;
621
+ document.head.removeChild(style);
622
+ }
598
623
  }
599
- });
624
+ );
600
625
  function defaultOnChanged(mode) {
601
626
  var _a;
602
627
  const resolvedMode = mode === "auto" ? preferredMode.value : mode;
@@ -736,7 +761,8 @@ const UseDraggable = /* @__PURE__ */ /* #__PURE__ */ vueDemi.defineComponent({
736
761
  "stopPropagation",
737
762
  "pointerTypes",
738
763
  "as",
739
- "handle"
764
+ "handle",
765
+ "axis"
740
766
  ],
741
767
  setup(props, { slots }) {
742
768
  const target = vueDemi.ref();
@@ -744,7 +770,11 @@ const UseDraggable = /* @__PURE__ */ /* #__PURE__ */ vueDemi.defineComponent({
744
770
  var _a;
745
771
  return (_a = props.handle) != null ? _a : target.value;
746
772
  });
747
- const storageValue = props.storageKey && core.useStorage(props.storageKey, shared.resolveUnref(props.initialValue) || { x: 0, y: 0 }, core.isClient ? props.storageType === "session" ? sessionStorage : localStorage : void 0);
773
+ const storageValue = props.storageKey && core.useStorage(
774
+ props.storageKey,
775
+ shared.resolveUnref(props.initialValue) || { x: 0, y: 0 },
776
+ core.isClient ? props.storageType === "session" ? sessionStorage : localStorage : void 0
777
+ );
748
778
  const initialValue = storageValue || props.initialValue || { x: 0, y: 0 };
749
779
  const onEnd = (position) => {
750
780
  if (!storageValue)
@@ -850,15 +880,21 @@ function useResizeObserver(target, callback, options = {}) {
850
880
  observer = void 0;
851
881
  }
852
882
  };
853
- const targets = vueDemi.computed(() => Array.isArray(target) ? target.map((el) => unrefElement(el)) : [unrefElement(target)]);
854
- const stopWatch = vueDemi.watch(targets, (els) => {
855
- cleanup();
856
- if (isSupported.value && window) {
857
- observer = new ResizeObserver(callback);
858
- for (const _el of els)
859
- _el && observer.observe(_el, observerOptions);
860
- }
861
- }, { immediate: true, flush: "post", deep: true });
883
+ const targets = vueDemi.computed(
884
+ () => Array.isArray(target) ? target.map((el) => unrefElement(el)) : [unrefElement(target)]
885
+ );
886
+ const stopWatch = vueDemi.watch(
887
+ targets,
888
+ (els) => {
889
+ cleanup();
890
+ if (isSupported.value && window) {
891
+ observer = new ResizeObserver(callback);
892
+ for (const _el of els)
893
+ _el && observer.observe(_el, observerOptions);
894
+ }
895
+ },
896
+ { immediate: true, flush: "post", deep: true }
897
+ );
862
898
  const stop = () => {
863
899
  cleanup();
864
900
  stopWatch();
@@ -878,30 +914,37 @@ function useElementSize(target, initialSize = { width: 0, height: 0 }, options =
878
914
  });
879
915
  const width = vueDemi.ref(initialSize.width);
880
916
  const height = vueDemi.ref(initialSize.height);
881
- useResizeObserver(target, ([entry]) => {
882
- const boxSize = box === "border-box" ? entry.borderBoxSize : box === "content-box" ? entry.contentBoxSize : entry.devicePixelContentBoxSize;
883
- if (window && isSVG.value) {
884
- const $elem = unrefElement(target);
885
- if ($elem) {
886
- const styles = window.getComputedStyle($elem);
887
- width.value = parseFloat(styles.width);
888
- height.value = parseFloat(styles.height);
889
- }
890
- } else {
891
- if (boxSize) {
892
- const formatBoxSize = Array.isArray(boxSize) ? boxSize : [boxSize];
893
- width.value = formatBoxSize.reduce((acc, { inlineSize }) => acc + inlineSize, 0);
894
- height.value = formatBoxSize.reduce((acc, { blockSize }) => acc + blockSize, 0);
917
+ useResizeObserver(
918
+ target,
919
+ ([entry]) => {
920
+ const boxSize = box === "border-box" ? entry.borderBoxSize : box === "content-box" ? entry.contentBoxSize : entry.devicePixelContentBoxSize;
921
+ if (window && isSVG.value) {
922
+ const $elem = unrefElement(target);
923
+ if ($elem) {
924
+ const styles = window.getComputedStyle($elem);
925
+ width.value = parseFloat(styles.width);
926
+ height.value = parseFloat(styles.height);
927
+ }
895
928
  } else {
896
- width.value = entry.contentRect.width;
897
- height.value = entry.contentRect.height;
929
+ if (boxSize) {
930
+ const formatBoxSize = Array.isArray(boxSize) ? boxSize : [boxSize];
931
+ width.value = formatBoxSize.reduce((acc, { inlineSize }) => acc + inlineSize, 0);
932
+ height.value = formatBoxSize.reduce((acc, { blockSize }) => acc + blockSize, 0);
933
+ } else {
934
+ width.value = entry.contentRect.width;
935
+ height.value = entry.contentRect.height;
936
+ }
898
937
  }
938
+ },
939
+ options
940
+ );
941
+ vueDemi.watch(
942
+ () => unrefElement(target),
943
+ (ele) => {
944
+ width.value = ele ? initialSize.width : 0;
945
+ height.value = ele ? initialSize.height : 0;
899
946
  }
900
- }, options);
901
- vueDemi.watch(() => unrefElement(target), (ele) => {
902
- width.value = ele ? initialSize.width : 0;
903
- height.value = ele ? initialSize.height : 0;
904
- });
947
+ );
905
948
  return {
906
949
  width,
907
950
  height
@@ -942,24 +985,31 @@ function useIntersectionObserver(target, callback, options = {}) {
942
985
  } = options;
943
986
  const isSupported = useSupported(() => window && "IntersectionObserver" in window);
944
987
  let cleanup = shared.noop;
945
- const stopWatch = isSupported.value ? vueDemi.watch(() => ({
946
- el: unrefElement(target),
947
- root: unrefElement(root)
948
- }), ({ el, root: root2 }) => {
949
- cleanup();
950
- if (!el)
951
- return;
952
- const observer = new IntersectionObserver(callback, {
953
- root: root2,
954
- rootMargin,
955
- threshold
956
- });
957
- observer.observe(el);
958
- cleanup = () => {
959
- observer.disconnect();
960
- cleanup = shared.noop;
961
- };
962
- }, { immediate: true, flush: "post" }) : shared.noop;
988
+ const stopWatch = isSupported.value ? vueDemi.watch(
989
+ () => ({
990
+ el: unrefElement(target),
991
+ root: unrefElement(root)
992
+ }),
993
+ ({ el, root: root2 }) => {
994
+ cleanup();
995
+ if (!el)
996
+ return;
997
+ const observer = new IntersectionObserver(
998
+ callback,
999
+ {
1000
+ root: root2,
1001
+ rootMargin,
1002
+ threshold
1003
+ }
1004
+ );
1005
+ observer.observe(el);
1006
+ cleanup = () => {
1007
+ observer.disconnect();
1008
+ cleanup = shared.noop;
1009
+ };
1010
+ },
1011
+ { immediate: true, flush: "post" }
1012
+ ) : shared.noop;
963
1013
  const stop = () => {
964
1014
  cleanup();
965
1015
  stopWatch();
@@ -973,12 +1023,16 @@ function useIntersectionObserver(target, callback, options = {}) {
973
1023
 
974
1024
  function useElementVisibility(element, { window = defaultWindow, scrollTarget } = {}) {
975
1025
  const elementIsVisible = vueDemi.ref(false);
976
- useIntersectionObserver(element, ([{ isIntersecting }]) => {
977
- elementIsVisible.value = isIntersecting;
978
- }, {
979
- root: scrollTarget,
980
- window
981
- });
1026
+ useIntersectionObserver(
1027
+ element,
1028
+ ([{ isIntersecting }]) => {
1029
+ elementIsVisible.value = isIntersecting;
1030
+ },
1031
+ {
1032
+ root: scrollTarget,
1033
+ window
1034
+ }
1035
+ );
982
1036
  return elementIsVisible;
983
1037
  }
984
1038
 
@@ -1125,13 +1179,21 @@ async function loadImage(options) {
1125
1179
  img.onerror = reject;
1126
1180
  });
1127
1181
  }
1128
- const useImage = (options, asyncStateOptions = {}) => {
1129
- const state = useAsyncState(() => loadImage(shared.resolveUnref(options)), void 0, __spreadValues$9({
1130
- resetOnExecute: true
1131
- }, asyncStateOptions));
1132
- vueDemi.watch(() => shared.resolveUnref(options), () => state.execute(asyncStateOptions.delay), { deep: true });
1182
+ function useImage(options, asyncStateOptions = {}) {
1183
+ const state = useAsyncState(
1184
+ () => loadImage(shared.resolveUnref(options)),
1185
+ void 0,
1186
+ __spreadValues$9({
1187
+ resetOnExecute: true
1188
+ }, asyncStateOptions)
1189
+ );
1190
+ vueDemi.watch(
1191
+ () => shared.resolveUnref(options),
1192
+ () => state.execute(asyncStateOptions.delay),
1193
+ { deep: true }
1194
+ );
1133
1195
  return state;
1134
- };
1196
+ }
1135
1197
 
1136
1198
  const UseImage = /* @__PURE__ */ /* #__PURE__ */ vueDemi.defineComponent({
1137
1199
  name: "UseImage",
@@ -1247,8 +1309,18 @@ function useScroll(element, options = {}) {
1247
1309
  onScrollEndDebounced(e);
1248
1310
  onScroll(e);
1249
1311
  };
1250
- useEventListener(element, "scroll", throttle ? shared.useThrottleFn(onScrollHandler, throttle, true, false) : onScrollHandler, eventListenerOptions);
1251
- useEventListener(element, "scrollend", onScrollEnd, eventListenerOptions);
1312
+ useEventListener(
1313
+ element,
1314
+ "scroll",
1315
+ throttle ? shared.useThrottleFn(onScrollHandler, throttle, true, false) : onScrollHandler,
1316
+ eventListenerOptions
1317
+ );
1318
+ useEventListener(
1319
+ element,
1320
+ "scrollend",
1321
+ onScrollEnd,
1322
+ eventListenerOptions
1323
+ );
1252
1324
  return {
1253
1325
  x,
1254
1326
  y,
@@ -1280,30 +1352,36 @@ var __spreadProps$7 = (a, b) => __defProps$7(a, __getOwnPropDescs$7(b));
1280
1352
  function useInfiniteScroll(element, onLoadMore, options = {}) {
1281
1353
  var _a, _b;
1282
1354
  const direction = (_a = options.direction) != null ? _a : "bottom";
1283
- const state = vueDemi.reactive(useScroll(element, __spreadProps$7(__spreadValues$8({}, options), {
1284
- offset: __spreadValues$8({
1285
- [direction]: (_b = options.distance) != null ? _b : 0
1286
- }, options.offset)
1287
- })));
1288
- vueDemi.watch(() => state.arrivedState[direction], async (v) => {
1289
- var _a2, _b2;
1290
- if (v) {
1291
- const elem = shared.resolveUnref(element);
1292
- const previous = {
1293
- height: (_a2 = elem == null ? void 0 : elem.scrollHeight) != null ? _a2 : 0,
1294
- width: (_b2 = elem == null ? void 0 : elem.scrollWidth) != null ? _b2 : 0
1295
- };
1296
- await onLoadMore(state);
1297
- if (options.preserveScrollPosition && elem) {
1298
- vueDemi.nextTick(() => {
1299
- elem.scrollTo({
1300
- top: elem.scrollHeight - previous.height,
1301
- left: elem.scrollWidth - previous.width
1355
+ const state = vueDemi.reactive(useScroll(
1356
+ element,
1357
+ __spreadProps$7(__spreadValues$8({}, options), {
1358
+ offset: __spreadValues$8({
1359
+ [direction]: (_b = options.distance) != null ? _b : 0
1360
+ }, options.offset)
1361
+ })
1362
+ ));
1363
+ vueDemi.watch(
1364
+ () => state.arrivedState[direction],
1365
+ async (v) => {
1366
+ var _a2, _b2;
1367
+ if (v) {
1368
+ const elem = shared.resolveUnref(element);
1369
+ const previous = {
1370
+ height: (_a2 = elem == null ? void 0 : elem.scrollHeight) != null ? _a2 : 0,
1371
+ width: (_b2 = elem == null ? void 0 : elem.scrollWidth) != null ? _b2 : 0
1372
+ };
1373
+ await onLoadMore(state);
1374
+ if (options.preserveScrollPosition && elem) {
1375
+ vueDemi.nextTick(() => {
1376
+ elem.scrollTo({
1377
+ top: elem.scrollHeight - previous.height,
1378
+ left: elem.scrollWidth - previous.width
1379
+ });
1302
1380
  });
1303
- });
1381
+ }
1304
1382
  }
1305
1383
  }
1306
- });
1384
+ );
1307
1385
  }
1308
1386
 
1309
1387
  const vInfiniteScroll = {
@@ -1661,12 +1739,19 @@ function useCssVar(prop, target, options = {}) {
1661
1739
  window
1662
1740
  });
1663
1741
  }
1664
- vueDemi.watch([elRef, () => shared.resolveUnref(prop)], updateCssVar, { immediate: true });
1665
- vueDemi.watch(variable, (val) => {
1666
- var _a;
1667
- if ((_a = elRef.value) == null ? void 0 : _a.style)
1668
- elRef.value.style.setProperty(shared.resolveUnref(prop), val);
1669
- });
1742
+ vueDemi.watch(
1743
+ [elRef, () => shared.resolveUnref(prop)],
1744
+ updateCssVar,
1745
+ { immediate: true }
1746
+ );
1747
+ vueDemi.watch(
1748
+ variable,
1749
+ (val) => {
1750
+ var _a;
1751
+ if ((_a = elRef.value) == null ? void 0 : _a.style)
1752
+ elRef.value.style.setProperty(shared.resolveUnref(prop), val);
1753
+ }
1754
+ );
1670
1755
  return variable;
1671
1756
  }
1672
1757
 
@@ -1833,9 +1918,14 @@ function useScrollLock(element, initialState = false) {
1833
1918
  if (!ele || isLocked.value)
1834
1919
  return;
1835
1920
  if (shared.isIOS) {
1836
- stopTouchMoveListener = useEventListener(ele, "touchmove", (e) => {
1837
- preventDefault(e);
1838
- }, { passive: false });
1921
+ stopTouchMoveListener = useEventListener(
1922
+ ele,
1923
+ "touchmove",
1924
+ (e) => {
1925
+ preventDefault(e);
1926
+ },
1927
+ { passive: false }
1928
+ );
1839
1929
  }
1840
1930
  ele.style.overflow = "hidden";
1841
1931
  isLocked.value = true;
@@ -1862,7 +1952,7 @@ function useScrollLock(element, initialState = false) {
1862
1952
  });
1863
1953
  }
1864
1954
 
1865
- const onScrollLock = () => {
1955
+ function onScrollLock() {
1866
1956
  let isMounted = false;
1867
1957
  const state = vueDemi.ref(false);
1868
1958
  return (el, binding) => {
@@ -1873,7 +1963,7 @@ const onScrollLock = () => {
1873
1963
  const isLocked = useScrollLock(el, binding.value);
1874
1964
  vueDemi.watch(state, (v) => isLocked.value = v);
1875
1965
  };
1876
- };
1966
+ }
1877
1967
  const vScrollLock = onScrollLock();
1878
1968
 
1879
1969
  var __defProp$2 = Object.defineProperty;
@@ -1966,9 +2056,21 @@ const UseVirtualList = /* @__PURE__ */ /* #__PURE__ */ vueDemi.defineComponent({
1966
2056
  const { list, containerProps, wrapperProps, scrollTo } = core.useVirtualList(listRef, props.options);
1967
2057
  expose({ scrollTo });
1968
2058
  typeof containerProps.style === "object" && !Array.isArray(containerProps.style) && (containerProps.style.height = props.height || "300px");
1969
- return () => vueDemi.h("div", __spreadValues({}, containerProps), [
1970
- vueDemi.h("div", __spreadValues({}, wrapperProps.value), list.value.map((item) => vueDemi.h("div", { style: { overFlow: "hidden", height: item.height } }, slots.default ? slots.default(item) : "Please set content!")))
1971
- ]);
2059
+ return () => vueDemi.h(
2060
+ "div",
2061
+ __spreadValues({}, containerProps),
2062
+ [
2063
+ vueDemi.h(
2064
+ "div",
2065
+ __spreadValues({}, wrapperProps.value),
2066
+ list.value.map((item) => vueDemi.h(
2067
+ "div",
2068
+ { style: { overFlow: "hidden", height: item.height } },
2069
+ slots.default ? slots.default(item) : "Please set content!"
2070
+ ))
2071
+ )
2072
+ ]
2073
+ );
1972
2074
  }
1973
2075
  });
1974
2076