@deriv-web-design/ui 0.1.17 → 0.1.18

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.
@@ -891,7 +891,7 @@
891
891
  "name": "DotLottieInView",
892
892
  "source": "components/DotLottieInView/DotLottieInView.tsx",
893
893
  "props": {},
894
- "description": "Plays a .lottie once when it scrolls into view. Stops and resets when it leaves view. When it enters view again, it plays once more. Set `enabled={false}` to force stop (e.g. hidden slides) without relying on geometry alone."
894
+ "description": "Plays a .lottie once when it scrolls into view. Stops and resets when it leaves view. When it enters view again, it plays once more. Set `enabled={false}` to force stop (e.g. hidden slides) without relying on geometry alone. The player itself is fetched lazily, the first time this instance is both enabled and in view — so a page with no animation never downloads it, and a below-the-fold band does not pay for it during initial load."
895
895
  },
896
896
  "DownloadBadge": {
897
897
  "name": "DownloadBadge",
@@ -1836,6 +1836,11 @@
1836
1836
  "required": true,
1837
1837
  "description": "URL to the .lottie file or any image asset (png, jpg, svg, webp…)"
1838
1838
  },
1839
+ "posterUrl": {
1840
+ "type": "string",
1841
+ "required": false,
1842
+ "description": "Still frame painted while an animation's player and engine are loading. Only used when the item resolves to `\"lottie\"`. The WebAssembly engine is ~630 KB compressed and one engine serves every animation on the page, so on a cold visit over a slow connection the first animated band can sit empty for seconds. A poster turns that into a progressive load instead of a hole in the layout. Ignored once the animation is playing."
1843
+ },
1839
1844
  "title": {
1840
1845
  "type": "string",
1841
1846
  "required": true,
@@ -1843,6 +1848,16 @@
1843
1848
  }
1844
1849
  }
1845
1850
  },
1851
+ "mediaRootMargin": {
1852
+ "type": "string",
1853
+ "required": false,
1854
+ "description": "`rootMargin` for the observer that decides when an animation's player may load and play. Forwarded to `DotLottieInView`. The default starts the work only once a band is actually on screen, which is the safe choice: the engine is large, and fetching it earlier competes with whatever the visitor is currently looking at — including the LCP image. Widen it (e.g. `\"600px 0px\"`) on pages where the animated band sits well below the fold and you would rather it were ready on arrival."
1855
+ },
1856
+ "mediaThreshold": {
1857
+ "type": "number | number[]",
1858
+ "required": false,
1859
+ "description": "`threshold` for that same observer. Forwarded to `DotLottieInView`."
1860
+ },
1846
1861
  "variant": {
1847
1862
  "type": "\"media-left\" | \"media-right\"",
1848
1863
  "required": false,
package/dist/index.d.mts CHANGED
@@ -750,6 +750,16 @@ interface FeatureScrollItem {
750
750
  mediaType?: "lottie" | "image";
751
751
  /** URL to the .lottie file or any image asset (png, jpg, svg, webp…) */
752
752
  mediaUrl: string;
753
+ /**
754
+ * Still frame painted while an animation's player and engine are loading.
755
+ *
756
+ * Only used when the item resolves to `"lottie"`. The WebAssembly engine is
757
+ * ~630 KB compressed and one engine serves every animation on the page, so
758
+ * on a cold visit over a slow connection the first animated band can sit
759
+ * empty for seconds. A poster turns that into a progressive load instead of
760
+ * a hole in the layout. Ignored once the animation is playing.
761
+ */
762
+ posterUrl?: string;
753
763
  }
754
764
  interface FeatureScrollProps extends HTMLAttributes<HTMLElement> {
755
765
  /** Section heading rendered as an H2 */
@@ -764,10 +774,27 @@ interface FeatureScrollProps extends HTMLAttributes<HTMLElement> {
764
774
  * @default "media-right"
765
775
  */
766
776
  variant?: "media-left" | "media-right";
777
+ /**
778
+ * `rootMargin` for the observer that decides when an animation's player may
779
+ * load and play. Forwarded to `DotLottieInView`.
780
+ *
781
+ * The default starts the work only once a band is actually on screen, which
782
+ * is the safe choice: the engine is large, and fetching it earlier competes
783
+ * with whatever the visitor is currently looking at — including the LCP
784
+ * image. Widen it (e.g. `"600px 0px"`) on pages where the animated band sits
785
+ * well below the fold and you would rather it were ready on arrival.
786
+ * @default "0px"
787
+ */
788
+ mediaRootMargin?: string;
789
+ /**
790
+ * `threshold` for that same observer. Forwarded to `DotLottieInView`.
791
+ * @default 0.2
792
+ */
793
+ mediaThreshold?: number | number[];
767
794
  }
768
795
 
769
796
  declare const FEATURE_SCROLL_DATA: FeatureScrollItem[];
770
- declare const FeatureScroll: ({ header, items, variant, className, ...props }: FeatureScrollProps) => react_jsx_runtime.JSX.Element;
797
+ declare const FeatureScroll: ({ header, items, variant, className, mediaRootMargin, mediaThreshold, ...props }: FeatureScrollProps) => react_jsx_runtime.JSX.Element;
771
798
 
772
799
  type FeatureSplitImagePosition = "left" | "right";
773
800
  interface FeatureSplitProps {
@@ -799,13 +826,29 @@ type DotLottieInViewProps = Omit<ComponentProps<typeof DotLottieReact>, "autopla
799
826
  enabled?: boolean;
800
827
  rootMargin?: string;
801
828
  threshold?: number | number[];
829
+ /**
830
+ * Painted in place of the player until the animation is ready, and as the
831
+ * Suspense fallback while the player chunk loads.
832
+ *
833
+ * Worth supplying on anything a visitor meets early on a slow connection:
834
+ * the WebAssembly engine is ~630 KB compressed and one engine serves every
835
+ * animation on the page, so the first animated band on a cold visit can sit
836
+ * empty for seconds. A still frame makes that a progressive load rather than
837
+ * a hole in the layout. A `ReactNode` rather than a URL so the consumer can
838
+ * pass a properly sized, responsive `<img>` rather than a bare `src`.
839
+ */
840
+ poster?: ReactNode;
802
841
  };
803
842
  /**
804
843
  * Plays a .lottie once when it scrolls into view. Stops and resets when it leaves view.
805
844
  * When it enters view again, it plays once more. Set `enabled={false}` to force stop
806
845
  * (e.g. hidden slides) without relying on geometry alone.
846
+ *
847
+ * The player itself is fetched lazily, the first time this instance is both
848
+ * enabled and in view — so a page with no animation never downloads it, and a
849
+ * below-the-fold band does not pay for it during initial load.
807
850
  */
808
- declare function DotLottieInView({ enabled, rootMargin, threshold, className, style, ...dotProps }: DotLottieInViewProps): react_jsx_runtime.JSX.Element;
851
+ declare function DotLottieInView({ enabled, rootMargin, threshold, className, style, poster, ...dotProps }: DotLottieInViewProps): react_jsx_runtime.JSX.Element;
809
852
 
810
853
  /** Visual colour theme for each card — matches the Figma palette. */
811
854
  type StickyCardTheme = "light" | "coral" | "dark";
package/dist/index.d.ts CHANGED
@@ -750,6 +750,16 @@ interface FeatureScrollItem {
750
750
  mediaType?: "lottie" | "image";
751
751
  /** URL to the .lottie file or any image asset (png, jpg, svg, webp…) */
752
752
  mediaUrl: string;
753
+ /**
754
+ * Still frame painted while an animation's player and engine are loading.
755
+ *
756
+ * Only used when the item resolves to `"lottie"`. The WebAssembly engine is
757
+ * ~630 KB compressed and one engine serves every animation on the page, so
758
+ * on a cold visit over a slow connection the first animated band can sit
759
+ * empty for seconds. A poster turns that into a progressive load instead of
760
+ * a hole in the layout. Ignored once the animation is playing.
761
+ */
762
+ posterUrl?: string;
753
763
  }
754
764
  interface FeatureScrollProps extends HTMLAttributes<HTMLElement> {
755
765
  /** Section heading rendered as an H2 */
@@ -764,10 +774,27 @@ interface FeatureScrollProps extends HTMLAttributes<HTMLElement> {
764
774
  * @default "media-right"
765
775
  */
766
776
  variant?: "media-left" | "media-right";
777
+ /**
778
+ * `rootMargin` for the observer that decides when an animation's player may
779
+ * load and play. Forwarded to `DotLottieInView`.
780
+ *
781
+ * The default starts the work only once a band is actually on screen, which
782
+ * is the safe choice: the engine is large, and fetching it earlier competes
783
+ * with whatever the visitor is currently looking at — including the LCP
784
+ * image. Widen it (e.g. `"600px 0px"`) on pages where the animated band sits
785
+ * well below the fold and you would rather it were ready on arrival.
786
+ * @default "0px"
787
+ */
788
+ mediaRootMargin?: string;
789
+ /**
790
+ * `threshold` for that same observer. Forwarded to `DotLottieInView`.
791
+ * @default 0.2
792
+ */
793
+ mediaThreshold?: number | number[];
767
794
  }
768
795
 
769
796
  declare const FEATURE_SCROLL_DATA: FeatureScrollItem[];
770
- declare const FeatureScroll: ({ header, items, variant, className, ...props }: FeatureScrollProps) => react_jsx_runtime.JSX.Element;
797
+ declare const FeatureScroll: ({ header, items, variant, className, mediaRootMargin, mediaThreshold, ...props }: FeatureScrollProps) => react_jsx_runtime.JSX.Element;
771
798
 
772
799
  type FeatureSplitImagePosition = "left" | "right";
773
800
  interface FeatureSplitProps {
@@ -799,13 +826,29 @@ type DotLottieInViewProps = Omit<ComponentProps<typeof DotLottieReact>, "autopla
799
826
  enabled?: boolean;
800
827
  rootMargin?: string;
801
828
  threshold?: number | number[];
829
+ /**
830
+ * Painted in place of the player until the animation is ready, and as the
831
+ * Suspense fallback while the player chunk loads.
832
+ *
833
+ * Worth supplying on anything a visitor meets early on a slow connection:
834
+ * the WebAssembly engine is ~630 KB compressed and one engine serves every
835
+ * animation on the page, so the first animated band on a cold visit can sit
836
+ * empty for seconds. A still frame makes that a progressive load rather than
837
+ * a hole in the layout. A `ReactNode` rather than a URL so the consumer can
838
+ * pass a properly sized, responsive `<img>` rather than a bare `src`.
839
+ */
840
+ poster?: ReactNode;
802
841
  };
803
842
  /**
804
843
  * Plays a .lottie once when it scrolls into view. Stops and resets when it leaves view.
805
844
  * When it enters view again, it plays once more. Set `enabled={false}` to force stop
806
845
  * (e.g. hidden slides) without relying on geometry alone.
846
+ *
847
+ * The player itself is fetched lazily, the first time this instance is both
848
+ * enabled and in view — so a page with no animation never downloads it, and a
849
+ * below-the-fold band does not pay for it during initial load.
807
850
  */
808
- declare function DotLottieInView({ enabled, rootMargin, threshold, className, style, ...dotProps }: DotLottieInViewProps): react_jsx_runtime.JSX.Element;
851
+ declare function DotLottieInView({ enabled, rootMargin, threshold, className, style, poster, ...dotProps }: DotLottieInViewProps): react_jsx_runtime.JSX.Element;
809
852
 
810
853
  /** Visual colour theme for each card — matches the Figma palette. */
811
854
  type StickyCardTheme = "light" | "coral" | "dark";
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // index.ts
@@ -2635,18 +2645,22 @@ var import_react13 = require("react");
2635
2645
 
2636
2646
  // components/DotLottieInView/DotLottieInView.tsx
2637
2647
  var import_react12 = require("react");
2638
- var import_dotlottie_react = require("@lottiefiles/dotlottie-react");
2639
2648
  var import_jsx_runtime27 = require("react/jsx-runtime");
2649
+ var DotLottiePlayer = (0, import_react12.lazy)(
2650
+ () => import("@lottiefiles/dotlottie-react").then((m) => ({ default: m.DotLottieReact }))
2651
+ );
2640
2652
  function DotLottieInView({
2641
2653
  enabled = true,
2642
2654
  rootMargin = "0px",
2643
2655
  threshold = 0.2,
2644
2656
  className,
2645
2657
  style,
2658
+ poster,
2646
2659
  ...dotProps
2647
2660
  }) {
2648
2661
  const wrapRef = (0, import_react12.useRef)(null);
2649
2662
  const [inView, setInView] = (0, import_react12.useState)(false);
2663
+ const [mounted, setMounted] = (0, import_react12.useState)(false);
2650
2664
  const [dotLottie, setDotLottie] = (0, import_react12.useState)(null);
2651
2665
  (0, import_react12.useEffect)(() => {
2652
2666
  const el = wrapRef.current;
@@ -2660,6 +2674,24 @@ function DotLottieInView({
2660
2674
  observer.observe(el);
2661
2675
  return () => observer.disconnect();
2662
2676
  }, [rootMargin, threshold]);
2677
+ (0, import_react12.useEffect)(() => {
2678
+ if (mounted) return;
2679
+ if (!(inView && enabled)) return;
2680
+ if (typeof window === "undefined") return;
2681
+ let cancelled = false;
2682
+ const commit = () => {
2683
+ if (!cancelled) setMounted(true);
2684
+ };
2685
+ const idleId = typeof window.requestIdleCallback === "function" ? window.requestIdleCallback(commit, { timeout: 400 }) : null;
2686
+ const timerId = idleId === null ? window.setTimeout(commit, 0) : null;
2687
+ return () => {
2688
+ cancelled = true;
2689
+ if (idleId !== null && typeof window.cancelIdleCallback === "function") {
2690
+ window.cancelIdleCallback(idleId);
2691
+ }
2692
+ if (timerId !== null) window.clearTimeout(timerId);
2693
+ };
2694
+ }, [inView, enabled, mounted]);
2663
2695
  (0, import_react12.useEffect)(() => {
2664
2696
  if (!dotLottie) return;
2665
2697
  if (!enabled || !inView) {
@@ -2684,15 +2716,15 @@ function DotLottieInView({
2684
2716
  backgroundColor: "transparent",
2685
2717
  ...style
2686
2718
  },
2687
- children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2688
- import_dotlottie_react.DotLottieReact,
2719
+ children: mounted ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react12.Suspense, { fallback: poster ?? null, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2720
+ DotLottiePlayer,
2689
2721
  {
2690
2722
  ...dotProps,
2691
2723
  loop: false,
2692
2724
  autoplay: false,
2693
2725
  dotLottieRefCallback: setDotLottie
2694
2726
  }
2695
- )
2727
+ ) }) : poster ?? null
2696
2728
  }
2697
2729
  );
2698
2730
  }
@@ -2764,26 +2796,45 @@ var ChevronRight2 = () => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2764
2796
  )
2765
2797
  }
2766
2798
  );
2799
+ function mediaSrc(item) {
2800
+ return typeof item.mediaUrl === "string" && item.mediaUrl !== "" ? item.mediaUrl : null;
2801
+ }
2767
2802
  function resolveMediaType(item) {
2768
2803
  if (item.mediaType) return item.mediaType;
2769
- return item.mediaUrl.split("?")[0].endsWith(".lottie") ? "lottie" : "image";
2804
+ const src = mediaSrc(item);
2805
+ return src?.split("?")[0].endsWith(".lottie") ? "lottie" : "image";
2770
2806
  }
2771
- var MediaRenderer = ({ item, active }) => {
2807
+ var MediaRenderer = ({ item, active, rootMargin, threshold }) => {
2808
+ const src = mediaSrc(item);
2809
+ if (!src) return null;
2772
2810
  if (resolveMediaType(item) === "lottie") {
2773
2811
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2774
2812
  DotLottieInView,
2775
2813
  {
2776
- src: item.mediaUrl,
2777
- enabled: active
2814
+ src,
2815
+ enabled: active,
2816
+ rootMargin,
2817
+ threshold,
2818
+ poster: item.posterUrl ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2819
+ "img",
2820
+ {
2821
+ src: item.posterUrl,
2822
+ alt: "",
2823
+ "aria-hidden": "true",
2824
+ loading: "lazy",
2825
+ decoding: "async"
2826
+ }
2827
+ ) : void 0
2778
2828
  }
2779
2829
  );
2780
2830
  }
2781
2831
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2782
2832
  "img",
2783
2833
  {
2784
- src: item.mediaUrl,
2834
+ src,
2785
2835
  alt: item.title,
2786
- loading: "lazy"
2836
+ loading: "lazy",
2837
+ decoding: "async"
2787
2838
  }
2788
2839
  );
2789
2840
  };
@@ -2792,10 +2843,16 @@ var FeatureScroll = ({
2792
2843
  items,
2793
2844
  variant = "media-right",
2794
2845
  className,
2846
+ // Destructured, not spread: `...props` lands on the <section>, and an
2847
+ // unknown attribute there is a React DOM warning at best.
2848
+ mediaRootMargin,
2849
+ mediaThreshold,
2795
2850
  ...props
2796
2851
  }) => {
2797
2852
  const [activeIndex, setActiveIndex] = (0, import_react13.useState)(0);
2853
+ const [mobileActiveIndex, setMobileActiveIndex] = (0, import_react13.useState)(0);
2798
2854
  const titleRefs = (0, import_react13.useRef)([]);
2855
+ const mobileItemRefs = (0, import_react13.useRef)([]);
2799
2856
  const mediaColRef = (0, import_react13.useRef)(null);
2800
2857
  (0, import_react13.useLayoutEffect)(() => {
2801
2858
  if (items.length === 0) return;
@@ -2843,6 +2900,40 @@ var FeatureScroll = ({
2843
2900
  if (rafId !== 0) window.cancelAnimationFrame(rafId);
2844
2901
  };
2845
2902
  }, [items.length]);
2903
+ (0, import_react13.useEffect)(() => {
2904
+ if (items.length === 0) return;
2905
+ if (typeof window === "undefined") return;
2906
+ const ratios = /* @__PURE__ */ new Map();
2907
+ const observer = new IntersectionObserver(
2908
+ (entries) => {
2909
+ if (window.matchMedia("(min-width: 992px)").matches) return;
2910
+ for (const entry of entries) {
2911
+ const idx = Number(entry.target.getAttribute("data-fs-mobile-idx"));
2912
+ if (!Number.isFinite(idx)) continue;
2913
+ ratios.set(idx, entry.isIntersecting ? entry.intersectionRatio : 0);
2914
+ }
2915
+ let best = 0;
2916
+ let bestRatio = -1;
2917
+ for (const [idx, ratio] of ratios) {
2918
+ if (ratio > bestRatio) {
2919
+ bestRatio = ratio;
2920
+ best = idx;
2921
+ }
2922
+ }
2923
+ if (bestRatio <= 0) return;
2924
+ setMobileActiveIndex((prev) => prev === best ? prev : best);
2925
+ },
2926
+ {
2927
+ root: null,
2928
+ rootMargin: "-28% 0px -28% 0px",
2929
+ threshold: [0, 0.15, 0.3, 0.5, 0.75, 1]
2930
+ }
2931
+ );
2932
+ for (const el of mobileItemRefs.current) {
2933
+ if (el) observer.observe(el);
2934
+ }
2935
+ return () => observer.disconnect();
2936
+ }, [items.length]);
2846
2937
  const rootClass = [
2847
2938
  "fs",
2848
2939
  `fs--${variant}`,
@@ -2870,7 +2961,9 @@ var FeatureScroll = ({
2870
2961
  MediaRenderer,
2871
2962
  {
2872
2963
  item,
2873
- active: i === activeIndex
2964
+ active: i === activeIndex,
2965
+ rootMargin: mediaRootMargin,
2966
+ threshold: mediaThreshold
2874
2967
  }
2875
2968
  )
2876
2969
  },
@@ -2910,22 +3003,41 @@ var FeatureScroll = ({
2910
3003
  i
2911
3004
  )) })
2912
3005
  ] }),
2913
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "fs__mobile-list", children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "fs__mobile-item", children: [
2914
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h3", { className: "fs__item-title", children: item.title }),
2915
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "fs__mobile-media", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(MediaRenderer, { item, active: true }) }),
2916
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "fs__item-desc", children: item.description }),
2917
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
2918
- "a",
2919
- {
2920
- href: item.link,
2921
- className: "fs__item-link",
2922
- children: [
2923
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { children: item.linkLabel }),
2924
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChevronRight2, {})
2925
- ]
2926
- }
2927
- )
2928
- ] }, i)) })
3006
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "fs__mobile-list", children: items.map((item, i) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3007
+ "div",
3008
+ {
3009
+ className: "fs__mobile-item",
3010
+ "data-fs-mobile-idx": i,
3011
+ ref: (el) => {
3012
+ mobileItemRefs.current[i] = el;
3013
+ },
3014
+ children: [
3015
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h3", { className: "fs__item-title", children: item.title }),
3016
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "fs__mobile-media", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
3017
+ MediaRenderer,
3018
+ {
3019
+ item,
3020
+ active: i === mobileActiveIndex,
3021
+ rootMargin: mediaRootMargin,
3022
+ threshold: mediaThreshold
3023
+ }
3024
+ ) }),
3025
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "fs__item-desc", children: item.description }),
3026
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
3027
+ "a",
3028
+ {
3029
+ href: item.link,
3030
+ className: "fs__item-link",
3031
+ children: [
3032
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { children: item.linkLabel }),
3033
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChevronRight2, {})
3034
+ ]
3035
+ }
3036
+ )
3037
+ ]
3038
+ },
3039
+ i
3040
+ )) })
2929
3041
  ] }) });
2930
3042
  };
2931
3043