overlapping-cards-scroll 0.1.3 → 0.1.5

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/README.md CHANGED
@@ -18,15 +18,19 @@ Peer dependencies:
18
18
  ## Web Usage
19
19
 
20
20
  ```tsx
21
- import 'overlapping-cards-scroll/styles.css'
21
+ import "overlapping-cards-scroll/styles.css";
22
22
  import {
23
23
  OverlappingCardsScroll,
24
24
  OverlappingCardsScrollFocusTrigger,
25
- } from 'overlapping-cards-scroll'
25
+ } from "overlapping-cards-scroll";
26
26
 
27
27
  export function Example({ cards }) {
28
28
  return (
29
- <OverlappingCardsScroll cardHeight={280} showPageDots pageDotsPosition="below">
29
+ <OverlappingCardsScroll
30
+ cardHeight={280}
31
+ showPageDots
32
+ pageDotsPosition="below"
33
+ >
30
34
  {cards.map((card) => (
31
35
  <article key={card.id}>
32
36
  <h3>{card.title}</h3>
@@ -36,7 +40,7 @@ export function Example({ cards }) {
36
40
  </article>
37
41
  ))}
38
42
  </OverlappingCardsScroll>
39
- )
43
+ );
40
44
  }
41
45
  ```
42
46
 
@@ -46,7 +50,7 @@ export function Example({ cards }) {
46
50
  import {
47
51
  OverlappingCardsScrollRN,
48
52
  OverlappingCardsScrollRNFocusTrigger,
49
- } from 'overlapping-cards-scroll/react-native'
53
+ } from "overlapping-cards-scroll/react-native";
50
54
  ```
51
55
 
52
56
  `/react-native` resolves to:
@@ -62,7 +66,7 @@ You can also target explicit builds:
62
66
  For web adapter usage, import package styles:
63
67
 
64
68
  ```tsx
65
- import 'overlapping-cards-scroll/styles.css'
69
+ import "overlapping-cards-scroll/styles.css";
66
70
  ```
67
71
 
68
72
  ## Props
package/dist/index.cjs CHANGED
@@ -33,6 +33,7 @@ var PAGE_DOT_POSITIONS = /* @__PURE__ */ new Set(["above", "below", "overlay"]);
33
33
  var normalizePageDotsPosition = (value) => PAGE_DOT_POSITIONS.has(value) ? value : "below";
34
34
  var TAB_POSITIONS = /* @__PURE__ */ new Set(["above", "below"]);
35
35
  var normalizeTabsPosition = (value) => TAB_POSITIONS.has(value) ? value : "above";
36
+ var lastKnownViewportWidth = 1;
36
37
  function DefaultTabsContainerComponent({
37
38
  children,
38
39
  className,
@@ -109,7 +110,17 @@ function OverlappingCardsScrollFocusTrigger({
109
110
  }
110
111
  };
111
112
  const buttonClassName = className ? `ocs-focus-trigger ${className}` : "ocs-focus-trigger";
112
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: buttonClassName, disabled: !canFocus, onClick: handleClick, ...buttonProps, children });
113
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
114
+ "button",
115
+ {
116
+ type: "button",
117
+ className: buttonClassName,
118
+ disabled: !canFocus,
119
+ onClick: handleClick,
120
+ ...buttonProps,
121
+ children
122
+ }
123
+ );
113
124
  }
114
125
  var resolveCardWidth = (cardWidth, viewportWidth, fallbackRatio) => {
115
126
  if (typeof cardWidth === "number" && Number.isFinite(cardWidth) && cardWidth > 0) {
@@ -188,7 +199,7 @@ function OverlappingCardsScroll(props) {
188
199
  const snapTimeoutRef = (0, import_react.useRef)(null);
189
200
  const shouldSnapOnMouseMoveRef = (0, import_react.useRef)(false);
190
201
  const focusTransitionTimeoutRef = (0, import_react.useRef)(null);
191
- const [viewportWidth, setViewportWidth] = (0, import_react.useState)(1);
202
+ const [viewportWidth, setViewportWidth] = (0, import_react.useState)(lastKnownViewportWidth);
192
203
  const [scrollLeft, setScrollLeft] = (0, import_react.useState)(0);
193
204
  const [focusTransition, setFocusTransition] = (0, import_react.useState)(null);
194
205
  const clearSnapTimeout = (0, import_react.useCallback)(() => {
@@ -208,6 +219,7 @@ function OverlappingCardsScroll(props) {
208
219
  setFocusTransition(null);
209
220
  }, [clearFocusTransitionTimeout]);
210
221
  (0, import_react.useEffect)(() => {
222
+ var _a;
211
223
  const containerElement = containerRef.current;
212
224
  const scrollElement = scrollRef.current;
213
225
  if (!containerElement || !scrollElement) {
@@ -216,15 +228,22 @@ function OverlappingCardsScroll(props) {
216
228
  const syncScroll = () => {
217
229
  setScrollLeft(scrollElement.scrollLeft);
218
230
  };
231
+ const applyWidth = (width) => {
232
+ const w = Math.max(0, width);
233
+ if (w > 10) {
234
+ lastKnownViewportWidth = w;
235
+ setViewportWidth(w);
236
+ }
237
+ };
219
238
  const resizeObserver = new ResizeObserver((entries) => {
220
- var _a, _b;
239
+ var _a2, _b;
221
240
  const entry = entries[0];
222
- const width = (_b = (_a = entry == null ? void 0 : entry.contentRect) == null ? void 0 : _a.width) != null ? _b : 1;
223
- setViewportWidth(Math.max(1, width));
241
+ const width = (_b = (_a2 = entry == null ? void 0 : entry.contentRect) == null ? void 0 : _a2.width) != null ? _b : 0;
242
+ applyWidth(width);
224
243
  syncScroll();
225
244
  });
226
245
  resizeObserver.observe(containerElement);
227
- setViewportWidth(Math.max(1, containerElement.getBoundingClientRect().width || 1));
246
+ applyWidth((_a = containerElement.getBoundingClientRect().width) != null ? _a : 0);
228
247
  syncScroll();
229
248
  scrollElement.addEventListener("scroll", syncScroll, { passive: true });
230
249
  return () => {
@@ -233,7 +252,10 @@ function OverlappingCardsScroll(props) {
233
252
  };
234
253
  }, []);
235
254
  (0, import_react.useEffect)(() => () => clearSnapTimeout(), [clearSnapTimeout]);
236
- (0, import_react.useEffect)(() => () => clearFocusTransitionTimeout(), [clearFocusTransitionTimeout]);
255
+ (0, import_react.useEffect)(
256
+ () => () => clearFocusTransitionTimeout(),
257
+ [clearFocusTransitionTimeout]
258
+ );
237
259
  (0, import_react.useEffect)(() => {
238
260
  if (snapToCardOnRelease && cardCount > 1) {
239
261
  return;
@@ -251,7 +273,10 @@ function OverlappingCardsScroll(props) {
251
273
  const layout = (0, import_react.useMemo)(() => {
252
274
  const safeWidth = Math.max(1, viewportWidth);
253
275
  const safeRatio = clamp(cardWidthRatio, 0.2, 0.95);
254
- const width = Math.max(1, resolveCardWidth(cardWidth, safeWidth, safeRatio));
276
+ const width = Math.max(
277
+ 1,
278
+ resolveCardWidth(cardWidth, safeWidth, safeRatio)
279
+ );
255
280
  if (cardCount < 2) {
256
281
  return {
257
282
  cardWidth: width,
@@ -275,7 +300,15 @@ function OverlappingCardsScroll(props) {
275
300
  scrollRange,
276
301
  trackWidth
277
302
  };
278
- }, [basePeek, cardCount, cardWidth, cardWidthRatio, maxPeek, minPeek, viewportWidth]);
303
+ }, [
304
+ basePeek,
305
+ cardCount,
306
+ cardWidth,
307
+ cardWidthRatio,
308
+ maxPeek,
309
+ minPeek,
310
+ viewportWidth
311
+ ]);
279
312
  (0, import_react.useEffect)(() => {
280
313
  const scrollElement = scrollRef.current;
281
314
  if (!scrollElement) {
@@ -299,7 +332,11 @@ function OverlappingCardsScroll(props) {
299
332
  if (!scrollElement) {
300
333
  return;
301
334
  }
302
- const currentScrollLeft = clamp(scrollElement.scrollLeft, 0, layout.scrollRange);
335
+ const currentScrollLeft = clamp(
336
+ scrollElement.scrollLeft,
337
+ 0,
338
+ layout.scrollRange
339
+ );
303
340
  const nearestIndex = clamp(
304
341
  Math.round(currentScrollLeft / layout.stepDistance),
305
342
  0,
@@ -341,7 +378,13 @@ function OverlappingCardsScroll(props) {
341
378
  snapToNearestCard({ behavior: "smooth" });
342
379
  }, safeDelay);
343
380
  },
344
- [cardCount, clearSnapTimeout, snapReleaseDelay, snapToCardOnRelease, snapToNearestCard]
381
+ [
382
+ cardCount,
383
+ clearSnapTimeout,
384
+ snapReleaseDelay,
385
+ snapToCardOnRelease,
386
+ snapToNearestCard
387
+ ]
345
388
  );
346
389
  const markSnapCandidateFromScroll = (0, import_react.useCallback)(() => {
347
390
  if (!snapToCardOnRelease || cardCount < 2) {
@@ -378,7 +421,11 @@ function OverlappingCardsScroll(props) {
378
421
  shouldSnapOnMouseMoveRef.current = false;
379
422
  cancelFocusTransition();
380
423
  const safeIndex = clamp(Math.round(targetIndex), 0, cardCount - 1);
381
- const nextScrollLeft = clamp(safeIndex * layout.stepDistance, 0, layout.scrollRange);
424
+ const nextScrollLeft = clamp(
425
+ safeIndex * layout.stepDistance,
426
+ 0,
427
+ layout.scrollRange
428
+ );
382
429
  const transitionMode = (_a = options.transitionMode) != null ? _a : "swoop";
383
430
  if (transitionMode === "swoop") {
384
431
  const duration = Number.isFinite(options.duration) ? Math.max(0, options.duration) : focusTransitionDuration;
@@ -466,7 +513,12 @@ function OverlappingCardsScroll(props) {
466
513
  applyScrollDelta(event.deltaX);
467
514
  markSnapCandidateFromScroll();
468
515
  },
469
- [cardCount, cancelFocusTransition, applyScrollDelta, markSnapCandidateFromScroll]
516
+ [
517
+ cardCount,
518
+ cancelFocusTransition,
519
+ applyScrollDelta,
520
+ markSnapCandidateFromScroll
521
+ ]
470
522
  );
471
523
  const handleTouchStart = (event) => {
472
524
  if (cardCount < 2) {
@@ -574,143 +626,172 @@ function OverlappingCardsScroll(props) {
574
626
  }
575
627
  );
576
628
  };
577
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OverlappingCardsScrollControllerContext.Provider, { value: controllerContextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: containerClassName, "aria-label": ariaLabel, ref: containerRef, children: [
578
- resolvedTabsPosition === "above" ? renderTabs("above") : null,
579
- showNavigationDots && resolvedPageDotsPosition === "above" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
580
- "nav",
581
- {
582
- className: pageDotsClassName ? `ocs-page-dots ocs-page-dots--above ${pageDotsClassName}` : "ocs-page-dots ocs-page-dots--above",
583
- style: { marginBottom: toCssDimension(pageDotsOffset) },
584
- "aria-label": "Card pages",
585
- children: cards.map((_, index) => {
586
- const influence = clamp(1 - Math.abs(progress - index), 0, 1);
587
- const opacity = 0.25 + influence * 0.75;
588
- const scale = 0.9 + influence * 0.22;
589
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
590
- "button",
591
- {
592
- type: "button",
593
- className: "ocs-page-dot",
594
- "aria-label": `Go to card ${index + 1}`,
595
- "aria-current": influence > 0.98 ? "page" : void 0,
596
- onClick: () => focusCard(index, {
597
- behavior: pageDotsBehavior,
598
- transitionMode: "swoop"
599
- }),
600
- style: { opacity, transform: `scale(${scale})` }
601
- },
602
- `ocs-page-dot-above-${index}`
603
- );
604
- })
605
- }
606
- ) : null,
607
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ocs-stage-frame", children: [
608
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
609
- "div",
629
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
630
+ OverlappingCardsScrollControllerContext.Provider,
631
+ {
632
+ value: controllerContextValue,
633
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
634
+ "section",
610
635
  {
611
- className: "ocs-stage",
612
- ref: stageRef,
613
- style: {
614
- minHeight: toCssDimension(cardHeight)
615
- },
616
- onTouchStart: handleTouchStart,
617
- onTouchMove: handleTouchMove,
618
- onTouchEnd: handleTouchEnd,
619
- onTouchCancel: handleTouchEnd,
636
+ className: containerClassName,
637
+ "aria-label": ariaLabel,
638
+ ref: containerRef,
620
639
  children: [
621
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
622
- "div",
640
+ resolvedTabsPosition === "above" ? renderTabs("above") : null,
641
+ showNavigationDots && resolvedPageDotsPosition === "above" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
642
+ "nav",
623
643
  {
624
- className: "ocs-track",
625
- children: cards.map((card, index) => {
626
- var _a;
627
- const cardX = resolveCardX(index, activeIndex, transitionProgress, layout);
644
+ className: pageDotsClassName ? `ocs-page-dots ocs-page-dots--above ${pageDotsClassName}` : "ocs-page-dots ocs-page-dots--above",
645
+ style: { marginBottom: toCssDimension(pageDotsOffset) },
646
+ "aria-label": "Card pages",
647
+ children: cards.map((_, index) => {
648
+ const influence = clamp(1 - Math.abs(progress - index), 0, 1);
649
+ const opacity = 0.25 + influence * 0.75;
650
+ const scale = 0.9 + influence * 0.22;
628
651
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
629
- "div",
652
+ "button",
630
653
  {
631
- className: cardContainerClassName ? `${focusTransition ? "ocs-card ocs-card--focus-transition" : "ocs-card"} ${cardContainerClassName}` : focusTransition ? "ocs-card ocs-card--focus-transition" : "ocs-card",
632
- style: {
633
- width: `${layout.cardWidth}px`,
634
- transform: `translate3d(${cardX}px, 0, 0)`,
635
- transitionDuration: focusTransition ? `${focusTransition.duration}ms` : void 0,
636
- ...cardContainerStyle
637
- },
638
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OverlappingCardsScrollCardIndexContext.Provider, { value: index, children: card })
654
+ type: "button",
655
+ className: "ocs-page-dot",
656
+ "aria-label": `Go to card ${index + 1}`,
657
+ "aria-current": influence > 0.98 ? "page" : void 0,
658
+ onClick: () => focusCard(index, {
659
+ behavior: pageDotsBehavior,
660
+ transitionMode: "swoop"
661
+ }),
662
+ style: { opacity, transform: `scale(${scale})` }
639
663
  },
640
- (_a = card.key) != null ? _a : `ocs-card-${index}`
664
+ `ocs-page-dot-above-${index}`
641
665
  );
642
666
  })
643
667
  }
644
- ),
645
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "ocs-scroll-region", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
646
- "div",
647
- {
648
- className: "ocs-scroll-spacer",
649
- style: {
650
- width: `${layout.trackWidth}px`
668
+ ) : null,
669
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "ocs-stage-frame", children: [
670
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
671
+ "div",
672
+ {
673
+ className: "ocs-stage",
674
+ ref: stageRef,
675
+ style: {
676
+ minHeight: toCssDimension(cardHeight)
677
+ },
678
+ onTouchStart: handleTouchStart,
679
+ onTouchMove: handleTouchMove,
680
+ onTouchEnd: handleTouchEnd,
681
+ onTouchCancel: handleTouchEnd,
682
+ children: [
683
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "ocs-track", children: cards.map((card, index) => {
684
+ var _a;
685
+ const cardX = resolveCardX(
686
+ index,
687
+ activeIndex,
688
+ transitionProgress,
689
+ layout
690
+ );
691
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
692
+ "div",
693
+ {
694
+ className: cardContainerClassName ? `${focusTransition ? "ocs-card ocs-card--focus-transition" : "ocs-card"} ${cardContainerClassName}` : focusTransition ? "ocs-card ocs-card--focus-transition" : "ocs-card",
695
+ style: {
696
+ width: `${layout.cardWidth}px`,
697
+ transform: `translate3d(${cardX}px, 0, 0)`,
698
+ transitionDuration: focusTransition ? `${focusTransition.duration}ms` : void 0,
699
+ ...cardContainerStyle,
700
+ pointerEvents: "none"
701
+ },
702
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
703
+ "div",
704
+ {
705
+ style: {
706
+ pointerEvents: "auto",
707
+ display: "flex"
708
+ },
709
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
710
+ OverlappingCardsScrollCardIndexContext.Provider,
711
+ {
712
+ value: index,
713
+ children: card
714
+ }
715
+ )
716
+ }
717
+ )
718
+ },
719
+ (_a = card.key) != null ? _a : `ocs-card-${index}`
720
+ );
721
+ }) }),
722
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "ocs-scroll-region", ref: scrollRef, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
723
+ "div",
724
+ {
725
+ className: "ocs-scroll-spacer",
726
+ style: {
727
+ width: `${layout.trackWidth}px`
728
+ }
729
+ }
730
+ ) })
731
+ ]
651
732
  }
733
+ ),
734
+ showNavigationDots && resolvedPageDotsPosition === "overlay" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
735
+ "nav",
736
+ {
737
+ className: pageDotsClassName ? `ocs-page-dots ocs-page-dots--overlay ${pageDotsClassName}` : "ocs-page-dots ocs-page-dots--overlay",
738
+ style: { bottom: toCssDimension(pageDotsOffset) },
739
+ "aria-label": "Card pages",
740
+ children: cards.map((_, index) => {
741
+ const influence = clamp(1 - Math.abs(progress - index), 0, 1);
742
+ const opacity = 0.25 + influence * 0.75;
743
+ const scale = 0.9 + influence * 0.22;
744
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
745
+ "button",
746
+ {
747
+ type: "button",
748
+ className: "ocs-page-dot",
749
+ "aria-label": `Go to card ${index + 1}`,
750
+ "aria-current": influence > 0.98 ? "page" : void 0,
751
+ onClick: () => focusCard(index, {
752
+ behavior: pageDotsBehavior,
753
+ transitionMode: "swoop"
754
+ }),
755
+ style: { opacity, transform: `scale(${scale})` }
756
+ },
757
+ `ocs-page-dot-overlay-${index}`
758
+ );
759
+ })
760
+ }
761
+ ) : null
762
+ ] }),
763
+ showNavigationDots && resolvedPageDotsPosition === "below" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
764
+ "nav",
765
+ {
766
+ className: pageDotsClassName ? `ocs-page-dots ocs-page-dots--below ${pageDotsClassName}` : "ocs-page-dots ocs-page-dots--below",
767
+ style: { marginTop: toCssDimension(pageDotsOffset) },
768
+ "aria-label": "Card pages",
769
+ children: cards.map((_, index) => {
770
+ const influence = clamp(1 - Math.abs(progress - index), 0, 1);
771
+ const opacity = 0.25 + influence * 0.75;
772
+ const scale = 0.9 + influence * 0.22;
773
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
774
+ "button",
775
+ {
776
+ type: "button",
777
+ className: "ocs-page-dot",
778
+ "aria-label": `Go to card ${index + 1}`,
779
+ "aria-current": influence > 0.98 ? "page" : void 0,
780
+ onClick: () => focusCard(index, {
781
+ behavior: pageDotsBehavior,
782
+ transitionMode: "swoop"
783
+ }),
784
+ style: { opacity, transform: `scale(${scale})` }
785
+ },
786
+ `ocs-page-dot-below-${index}`
787
+ );
788
+ })
652
789
  }
653
- ) })
790
+ ) : null,
791
+ resolvedTabsPosition === "below" ? renderTabs("below") : null
654
792
  ]
655
793
  }
656
- ),
657
- showNavigationDots && resolvedPageDotsPosition === "overlay" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
658
- "nav",
659
- {
660
- className: pageDotsClassName ? `ocs-page-dots ocs-page-dots--overlay ${pageDotsClassName}` : "ocs-page-dots ocs-page-dots--overlay",
661
- style: { bottom: toCssDimension(pageDotsOffset) },
662
- "aria-label": "Card pages",
663
- children: cards.map((_, index) => {
664
- const influence = clamp(1 - Math.abs(progress - index), 0, 1);
665
- const opacity = 0.25 + influence * 0.75;
666
- const scale = 0.9 + influence * 0.22;
667
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
668
- "button",
669
- {
670
- type: "button",
671
- className: "ocs-page-dot",
672
- "aria-label": `Go to card ${index + 1}`,
673
- "aria-current": influence > 0.98 ? "page" : void 0,
674
- onClick: () => focusCard(index, {
675
- behavior: pageDotsBehavior,
676
- transitionMode: "swoop"
677
- }),
678
- style: { opacity, transform: `scale(${scale})` }
679
- },
680
- `ocs-page-dot-overlay-${index}`
681
- );
682
- })
683
- }
684
- ) : null
685
- ] }),
686
- showNavigationDots && resolvedPageDotsPosition === "below" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
687
- "nav",
688
- {
689
- className: pageDotsClassName ? `ocs-page-dots ocs-page-dots--below ${pageDotsClassName}` : "ocs-page-dots ocs-page-dots--below",
690
- style: { marginTop: toCssDimension(pageDotsOffset) },
691
- "aria-label": "Card pages",
692
- children: cards.map((_, index) => {
693
- const influence = clamp(1 - Math.abs(progress - index), 0, 1);
694
- const opacity = 0.25 + influence * 0.75;
695
- const scale = 0.9 + influence * 0.22;
696
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
697
- "button",
698
- {
699
- type: "button",
700
- className: "ocs-page-dot",
701
- "aria-label": `Go to card ${index + 1}`,
702
- "aria-current": influence > 0.98 ? "page" : void 0,
703
- onClick: () => focusCard(index, {
704
- behavior: pageDotsBehavior,
705
- transitionMode: "swoop"
706
- }),
707
- style: { opacity, transform: `scale(${scale})` }
708
- },
709
- `ocs-page-dot-below-${index}`
710
- );
711
- })
712
- }
713
- ) : null,
714
- resolvedTabsPosition === "below" ? renderTabs("below") : null
715
- ] }) });
794
+ )
795
+ }
796
+ );
716
797
  }