diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 433d9d8..e2ff00f 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -51,6 +51,7 @@ module.exports = {
'react/jsx-props-no-spreading': 'off',
'react/require-default-props': 'off',
'react/prop-types': 'off',
+ 'consistent-return': 'off',
'@typescript-eslint/no-unsafe-enum-comparison': 'off',
'react/function-component-definition': 'off',
'react/react-in-jsx-scope': 'off',
diff --git a/README.md b/README.md
index 008af69..04eebc2 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,13 @@
# Simple Headless Carousel React
+- Extremely small package size: 2kB gzipped
+- 0 external dependencies
+- Full typescript support
+- Built in with Tailwind, but you can always customize the styles
+- Handling touch/mouse events
+- Lazy image loading (WIP)
+- Responsive support (WIP)
+
### How to use:
```
@@ -25,15 +33,11 @@
### TODO:
- [x] Add beta implementation
-- [ ] Add extra props
+- [ ] Add extra option props
- [ ] Add stable version
-- [ ] Setup CI
-- [ ] DX improvments prettier/eslint
+- [x] Setup CI
+- [x] DX improvments prettier/eslint
- [ ] Add docs
- [ ] Add unit tests
- [ ] Add examples
-- [ ] Add more options
-
----
-
-- [ ] Publish on NPM
+- [x] Publish on NPM
diff --git a/src/App.tsx b/src/App.tsx
index 820cef7..3235bc5 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -19,7 +19,6 @@ function App() {
event.target !== imgRef.current;
@@ -56,11 +58,19 @@ export const Carousel = memo(
[dispatch],
);
- const setTranslateX = useCallback((x: number) => {
- animationRef.current = requestAnimationFrame(() => {
- imgRef.current?.style.setProperty('transform', `translateX(${x}px)`);
- });
- }, []);
+ const setTranslateX = useCallback(
+ (x: number) => {
+ animationRef.current = requestAnimationFrame(() => {
+ const percent = (x * 100) / width / total;
+
+ imgRef.current?.style.setProperty(
+ 'transform',
+ `translateX(${percent}%)`,
+ );
+ });
+ },
+ [width, total],
+ );
const onMoveStart = useCallback((event: SlideEvent) => {
if (cancelWrongTarget(event)) return;
@@ -155,9 +165,8 @@ export const Carousel = memo(
return (
diff --git a/src/lib/simple-headless-carousel/context/CarouselProvider.tsx b/src/lib/simple-headless-carousel/context/CarouselProvider.tsx
index 2cb39cb..9aa86ea 100644
--- a/src/lib/simple-headless-carousel/context/CarouselProvider.tsx
+++ b/src/lib/simple-headless-carousel/context/CarouselProvider.tsx
@@ -12,7 +12,6 @@ import { useMergeConfig } from '../hooks/useMergeConfig';
*
* @param {ReactNode} children - The child components to be wrapped by the Carousel context.
* @param {number} total - The total number of slides in the carousel.
- * @param {number} width - The width of each slide in the carousel.
* @param {boolean} autoPlay - Whether the carousel should automatically play.
* @param {number} autoPlayDelay - The delay between each slide transition in auto play mode.
* @param {number} slidesVisible - The number of slides visible at a time.
diff --git a/src/lib/simple-headless-carousel/hooks/useCarouselReducer.ts b/src/lib/simple-headless-carousel/hooks/useCarouselReducer.ts
index bf45e00..e622729 100644
--- a/src/lib/simple-headless-carousel/hooks/useCarouselReducer.ts
+++ b/src/lib/simple-headless-carousel/hooks/useCarouselReducer.ts
@@ -12,7 +12,6 @@ export type DispatchOpts = {
export type CarouselState = {
currentIndex: number;
total: number;
- width: number;
// optional
slidesVisible: number;
step: number;
@@ -25,7 +24,6 @@ export type CarouselReduceDispatch = Dispatch;
export const stateDefaults: CarouselState = {
currentIndex: 0,
- width: 0,
total: 0,
step: 1,
autoPlayDelay: 2000,
diff --git a/src/lib/simple-headless-carousel/hooks/useResizeObserver.ts b/src/lib/simple-headless-carousel/hooks/useResizeObserver.ts
new file mode 100644
index 0000000..b79aa94
--- /dev/null
+++ b/src/lib/simple-headless-carousel/hooks/useResizeObserver.ts
@@ -0,0 +1,41 @@
+import { useEffect, useState, RefObject } from 'react';
+
+interface Size {
+ width: number;
+ height: number;
+}
+
+type UseResizeObserverProps = {
+ ref: RefObject;
+ refWidth: number | undefined;
+};
+
+export const useResizeObserver = (
+ ref: RefObject,
+): UseResizeObserverProps => {
+ const [size, setSize] = useState();
+
+ useEffect(() => {
+ if (!ref.current) return;
+
+ const handleResize = (entries: ResizeObserverEntry[]) => {
+ for (const entry of entries) {
+ if (entry.target === ref.current) {
+ setSize({
+ width: entry.contentRect.width,
+ height: entry.contentRect.height,
+ });
+ }
+ }
+ };
+
+ const resizeObserver = new ResizeObserver(handleResize);
+ resizeObserver.observe(ref.current);
+
+ return () => {
+ resizeObserver.disconnect();
+ };
+ }, [ref]);
+
+ return { ref, refWidth: size?.width };
+};