diff --git a/packages/unity-react-core/package.json b/packages/unity-react-core/package.json
index c0364c0cd1..1ec177afbd 100644
--- a/packages/unity-react-core/package.json
+++ b/packages/unity-react-core/package.json
@@ -104,6 +104,7 @@
},
"dependencies": {
"@glidejs/glide": "^3.6.0",
+ "embla-carousel-react": "^8.6.0",
"react-share": "^5.3"
},
"peerDependencies": {
diff --git a/packages/unity-react-core/src/components/ComponentCarousel/components/ImageGalleryCarousel/EmblaImageGalleryPrototype.jsx b/packages/unity-react-core/src/components/ComponentCarousel/components/ImageGalleryCarousel/EmblaImageGalleryPrototype.jsx
new file mode 100644
index 0000000000..110319ec5f
--- /dev/null
+++ b/packages/unity-react-core/src/components/ComponentCarousel/components/ImageGalleryCarousel/EmblaImageGalleryPrototype.jsx
@@ -0,0 +1,134 @@
+//@ts-check
+import React, { useState, useEffect, useCallback } from "react";
+import useEmblaCarousel from "embla-carousel-react";
+import PropTypes from "prop-types";
+
+const EmblaImageGalleryPrototype = ({
+ imageItems = [],
+ hasContent = false,
+ maxWidth = "996px"
+}) => {
+ //Initializing Embla
+ const [emblaRef, emblaApi] = useEmblaCarousel({ loop: false, align: "start" });
+
+ //React state to track the active slide
+ const [selectedIndex, setSelectedIndex] = useState(0);
+
+ //Navigation controls
+ const scrollPrev = useCallback(() => emblaApi && emblaApi.scrollPrev(), [emblaApi]);
+ const scrollNext = useCallback(() => emblaApi && emblaApi.scrollNext(), [emblaApi]);
+ const scrollTo = useCallback((index) => emblaApi && emblaApi.scrollTo(index), [emblaApi]);
+
+ const onSelect = useCallback(() => {
+ if (!emblaApi) return;
+ setSelectedIndex(emblaApi.selectedScrollSnap()); //save number to react state
+ }, [emblaApi]);
+
+ //Use direct react callback to update uI
+ useEffect(() => {
+ if (!emblaApi) return;
+ emblaApi.on("select", onSelect);
+ emblaApi.on("reInit", onSelect);
+ onSelect(); //Set initial state on load
+ }, [emblaApi, onSelect]);
+
+ if (!imageItems || imageItems.length === 0) return null; //prevent website from crashing if empty data
+
+ const currentItem = imageItems[selectedIndex];
+
+ return (
+ //600px so it matches storybook wrapper limit (temperory)
+
+
+
{/* force images to shrink and fit */}
+
+
+ {imageItems.map((item) => ( //iterate and render every image inside contatiner
+
+

+
+ ))}
+
+
+
+ {/* prevent nav bar from getting reduced in size */}
+
+
+ {/* Arrows */}
+
+
+
+
+ {/* thumbnails in nav bar */}
+
{/* allow scrolling images if too many */}
+ {/* clickable thumbnail images */}
+ {imageItems.map((item, index) => (
+
+ ))}
+
+
+
+
+
+ {/* Captions */}
+ {hasContent && (currentItem.title || currentItem.content) && ( //hide if no text caption
+
+
+ {currentItem.title &&
{currentItem.title}
}
+
+
+
+ )}
+
+
+ );
+};
+
+EmblaImageGalleryPrototype.propTypes = {
+ imageItems: PropTypes.array.isRequired,
+ hasContent: PropTypes.bool,
+ maxWidth: PropTypes.string,
+};
+
+export { EmblaImageGalleryPrototype };
+
diff --git a/packages/unity-react-core/src/components/ComponentCarousel/components/ImageGalleryCarousel/ImageGalleryCarousel.stories.jsx b/packages/unity-react-core/src/components/ComponentCarousel/components/ImageGalleryCarousel/ImageGalleryCarousel.stories.jsx
index b6122c462e..113df4ea12 100644
--- a/packages/unity-react-core/src/components/ComponentCarousel/components/ImageGalleryCarousel/ImageGalleryCarousel.stories.jsx
+++ b/packages/unity-react-core/src/components/ComponentCarousel/components/ImageGalleryCarousel/ImageGalleryCarousel.stories.jsx
@@ -121,3 +121,15 @@ export const ImageCarouselWithMoreContent = () => (
/>
);
+
+import { EmblaImageGalleryPrototype } from "./EmblaImageGalleryPrototype";
+
+export const EmblaPrototype = () => (
+
+
+
+);
diff --git a/yarn.lock b/yarn.lock
index a270a21578..35100528e7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -517,6 +517,7 @@ __metadata:
chromium-bidi: "npm:^3.0.0"
classnames: "npm:^2.2.6"
css-loader: "npm:^5.2.0"
+ embla-carousel-react: "npm:^8.6.0"
file-loader: "npm:^6.2.0"
glob: "npm:^7.1.6"
html-entities: "npm:^2.3.1"
@@ -14359,6 +14360,34 @@ __metadata:
languageName: node
linkType: hard
+"embla-carousel-react@npm:^8.6.0":
+ version: 8.6.0
+ resolution: "embla-carousel-react@npm:8.6.0"
+ dependencies:
+ embla-carousel: "npm:8.6.0"
+ embla-carousel-reactive-utils: "npm:8.6.0"
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc
+ checksum: 10c0/461b0c427a6fca62e730c7b39d08e9c55b01a2138c173d5b9ebf77ec92092a900b45ac384731c77382b48d5d65946994d3abba6e9899a66d6e16f8ddf191ed1c
+ languageName: node
+ linkType: hard
+
+"embla-carousel-reactive-utils@npm:8.6.0":
+ version: 8.6.0
+ resolution: "embla-carousel-reactive-utils@npm:8.6.0"
+ peerDependencies:
+ embla-carousel: 8.6.0
+ checksum: 10c0/33d07e6df4d8dec9b4fc95858838ea2d5e5df078039c05b2a342c05ba4979d8d18564a1c607da445fed744daf969a0b5a90124ce487a854e86ced6f0458b51e9
+ languageName: node
+ linkType: hard
+
+"embla-carousel@npm:8.6.0":
+ version: 8.6.0
+ resolution: "embla-carousel@npm:8.6.0"
+ checksum: 10c0/f4c598e7be28b70340d31ffd2bebb2472db370b0c81d9b089bf9555cf618695f35dc4a0694565c994c9ab972731123063f945aa09ff485df0df761d79c6a08ef
+ languageName: node
+ linkType: hard
+
"emittery@npm:^0.13.1":
version: 0.13.1
resolution: "emittery@npm:0.13.1"