Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-compare-slider

Package Overview
Dependencies
Maintainers
1
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-compare-slider - npm Package Compare versions

Comparing version 1.2.1 to 2.0.1

dist/ReactCompareSlider.d.ts

10

dist/index.d.ts

@@ -1,3 +0,7 @@

export { ReactCompareSlider, ReactCompareSliderProps, ReactCompareSliderHandle, ReactCompareSliderHandleProps, } from './react-compare-slider';
export { ReactCompareSliderImage, ReactCompareSliderImageProps, } from './react-compare-slider-image';
export { styleFitContainer, supportsCssObjectFit } from './utils';
export { ReactCompareSlider } from './ReactCompareSlider';
export type { ReactCompareSliderProps } from './ReactCompareSlider';
export { ReactCompareSliderHandle } from './ReactCompareSliderHandle';
export type { ReactCompareSliderHandleProps } from './ReactCompareSliderHandle';
export { ReactCompareSliderImage } from './ReactCompareSliderImage';
export type { ReactCompareSliderImageProps } from './ReactCompareSliderImage';
export { styleFitContainer } from './utils';

@@ -9,77 +9,107 @@ 'use strict';

var React__default = _interopDefault(React);
var resizeObserver = require('resize-observer');
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
const ThisArrow = ({
flip
}) => {
const style = {
width: 0,
height: 0,
borderTop: '8px solid transparent',
borderRight: '10px solid',
borderBottom: '8px solid transparent',
transform: flip ? 'rotate(180deg)' : undefined
};
return React__default.createElement("div", {
style: style
});
};
/** Default `handle`. */
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
const ReactCompareSliderHandle = ({
portrait,
buttonStyle,
linesStyle,
style,
...props
}) => {
const _style = {
display: 'flex',
flexDirection: portrait ? 'row' : 'column',
placeItems: 'center',
height: '100%',
cursor: portrait ? 'ns-resize' : 'ew-resize',
pointerEvents: 'none',
color: '#fff',
...style
};
const _linesStyle = {
flexGrow: 1,
height: portrait ? 2 : '100%',
width: portrait ? '100%' : 2,
backgroundColor: 'currentColor',
pointerEvents: 'auto',
boxShadow: '0 0 7px rgba(0,0,0,.35)',
...linesStyle
};
const _buttonStyle = {
display: 'grid',
gridAutoFlow: 'column',
gap: 8,
placeContent: 'center',
flexShrink: 0,
width: 56,
height: 56,
borderRadius: '50%',
borderStyle: 'solid',
borderWidth: 2,
pointerEvents: 'auto',
backdropFilter: 'blur(7px)',
boxShadow: '0 0 7px rgba(0,0,0,.35)',
transform: portrait ? 'rotate(90deg)' : undefined,
...buttonStyle
};
return React__default.createElement("div", Object.assign({
className: "__rcs-handle-root"
}, props, {
style: _style
}), React__default.createElement("div", {
className: "__rcs-handle-line",
style: _linesStyle
}), React__default.createElement("div", {
className: "__rcs-handle-button",
style: _buttonStyle
}, React__default.createElement(ThisArrow, null), React__default.createElement(ThisArrow, {
flip: true
})), React__default.createElement("div", {
className: "__rcs-handle-line",
style: _linesStyle
}));
};
return _extends.apply(this, arguments);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
/** Whether runtime is client-side. */
var isClient = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
/**
* Whether client supports the CSS `object-fit` property.
* Stand-alone CSS utility to make replaced elements (`img`, `video`, etc.) fit their
* container.
*/
var supportsCssObjectFit = function supportsCssObjectFit() {
// Assume object-fit is supported in SSR - it will be picked up again by the
// client anyway.
if (!isClient) return true;
return typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('object-fit', 'cover');
};
/**
* Stand-alone CSS utility to make replaced elements (`img`, `video`, etc.)
* fit their container and maintain their aspect ratio.
*/
var styleFitContainer = function styleFitContainer(_temp) {
var _ref = _temp === void 0 ? {} : _temp,
_ref$objectFit = _ref.objectFit,
objectFit = _ref$objectFit === void 0 ? 'cover' : _ref$objectFit,
_ref$objectPosition = _ref.objectPosition,
objectPosition = _ref$objectPosition === void 0 ? 'center' : _ref$objectPosition,
props = _objectWithoutPropertiesLoose(_ref, ["objectFit", "objectPosition"]);
return _extends({
display: 'block',
width: '100%',
height: '100%',
maxWidth: '100%',
objectFit: objectFit,
objectPosition: objectPosition
}, props);
};
const styleFitContainer = ({
boxSizing = 'border-box',
objectFit = 'cover',
objectPosition = 'center',
...props
} = {}) => ({
display: 'block',
width: '100%',
height: '100%',
maxWidth: '100%',
boxSizing,
objectFit,
objectPosition,
...props
});
/** Store the previous supplied value. */
var usePrevious = function usePrevious(value) {
var ref = React.useRef(value);
React.useEffect(function () {
const usePrevious = value => {
const ref = React.useRef(value);
React.useEffect(() => {
ref.current = value;

@@ -91,42 +121,31 @@ });

* Event listener binding hook.
* @param eventName - Event to bind to
* @param handler - Callback handler
* @param element - Element to bind to
* @param handlerOptions - Event handler options
* @param eventName - Event to bind to.
* @param handler - Callback handler.
* @param element - Element to bind to.
* @param handlerOptions - Event handler options.
*/
var useEventListener = function useEventListener(eventName, handler, element, handlerOptions) {
// Create a ref that stores handler
var savedHandler = React.useRef(); // Update ref.current value if handler changes.
// This allows our effect below to always get latest handler ...
// ... without us needing to pass it in effect deps array ...
// ... and potentially cause effect to re-run every render.
React.useEffect(function () {
const useEventListener = (eventName, handler, element, handlerOptions) => {
const savedHandler = React.useRef();
React.useEffect(() => {
savedHandler.current = handler;
}, [handler]);
React.useEffect(function () {
// Make sure element supports addEventListener
var isSupported = element && element.addEventListener;
if (!isSupported) return; // Create event listener that calls handler function stored in ref
React.useEffect(() => {
// Make sure element supports addEventListener.
if (!(element && element.addEventListener)) return; // Create event listener that calls handler function stored in ref.
var eventListener = function eventListener(event) {
return savedHandler.current && savedHandler.current(event);
}; // Add event listener
const eventListener = event => savedHandler.current && savedHandler.current(event);
element.addEventListener(eventName, eventListener, handlerOptions); // Remove event listener on cleanup
return function () {
element.addEventListener(eventName, eventListener, handlerOptions);
return () => {
element.removeEventListener(eventName, eventListener, handlerOptions);
};
}, [eventName, element, handlerOptions] // Re-run if eventName or element changes
);
}, [eventName, element, handlerOptions]);
};
/**
* Conditionally use `useLayoutEffect` for client *or* `useEffect` for SSR.
* @see https://github.com/reduxjs/react-redux/blob/c581d480dd675f2645851fb006bef91aeb6ac24d/src/utils/useIsomorphicLayoutEffect.js
* @see <https://github.com/reduxjs/react-redux/blob/c581d480dd675f2645851fb006bef91aeb6ac24d/src/utils/useIsomorphicLayoutEffect.js>
*/
var useIsomorphicLayoutEffect = isClient ? React.useLayoutEffect : React.useEffect;
const useIsomorphicLayoutEffect = typeof window !== 'undefined' && window.document && window.document.createElement ? React.useLayoutEffect : React.useEffect;
/**

@@ -138,29 +157,44 @@ * Bind resize observer callback to element.

var useResizeObserver = function useResizeObserver(ref, handler) {
var observer = React.useRef(new resizeObserver.ResizeObserver(function (_ref2) {
var entry = _ref2[0];
return handler(entry.contentRect);
}));
var observe = React.useCallback(function () {
const useResizeObserver = (ref, handler) => {
const observer = React.useRef(new ResizeObserver(([entry]) => handler(entry.contentRect)));
const observe = React.useCallback(() => {
ref.current && observer.current.observe(ref.current);
}, [ref]); // Bind/rebind observer when `handler` changes.
useIsomorphicLayoutEffect(function () {
observer.current = new resizeObserver.ResizeObserver(function (_ref3) {
var entry = _ref3[0];
return handler(entry.contentRect);
});
useIsomorphicLayoutEffect(() => {
observer.current = new ResizeObserver(([entry]) => handler(entry.contentRect));
observe();
return function () {
return observer.current.disconnect();
};
return () => observer.current.disconnect();
}, [handler, observe]);
};
/** Container for clipped item. */
const ThisClipContainer = /*#__PURE__*/React.forwardRef((props, ref) => {
const style = {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
willChange: 'clip',
userSelect: 'none',
KhtmlUserSelect: 'none',
MozUserSelect: 'none',
WebkitUserSelect: 'none'
};
return React__default.createElement("div", Object.assign({}, props, {
style: style,
"data-rcs": "clip-item",
ref: ref
}));
});
ThisClipContainer.displayName = 'ThisClipContainer';
/** Handle container to control position. */
var ReactCompareSliderHandleContainer = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
var children = _ref.children,
portrait = _ref.portrait;
var style = {
const ThisHandleContainer = /*#__PURE__*/React.forwardRef(({
children,
portrait
}, ref) => {
const style = {
position: 'absolute',

@@ -172,3 +206,3 @@ top: 0,

};
var innerStyle = {
const innerStyle = {
position: 'absolute',

@@ -188,94 +222,49 @@ width: portrait ? '100%' : undefined,

});
ReactCompareSliderHandleContainer.displayName = 'ReactCompareSliderHandleContainer';
/** Overridable handle. */
var ReactCompareSliderHandle = function ReactCompareSliderHandle(_ref2) {
var portrait = _ref2.portrait,
style = _ref2.style,
props = _objectWithoutPropertiesLoose(_ref2, ["portrait", "style"]);
var rootStyle = _extends({
height: portrait ? 4 : '100%',
width: portrait ? '100%' : 4,
backgroundColor: '#fff',
boxShadow: '0 0 .2rem #000',
cursor: portrait ? 'ns-resize' : 'ew-resize'
}, style);
return React__default.createElement("div", Object.assign({}, props, {
style: rootStyle,
"data-rcs": "handle-inner"
}));
ThisHandleContainer.displayName = 'ThisHandleContainer';
const EVENT_PASSIVE_PARAMS = {
passive: true
};
/** Container for items passed to main component. */
var ReactCompareSliderClipContainer = /*#__PURE__*/React.forwardRef(function (props, ref) {
var style = {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
willChange: 'clip',
userSelect: 'none',
KhtmlUserSelect: 'none',
MozUserSelect: 'none',
WebkitUserSelect: 'none'
};
return React__default.createElement("div", Object.assign({}, props, {
style: style,
"data-rcs": "clip-item",
ref: ref
}));
});
ReactCompareSliderClipContainer.displayName = 'ReactCompareSliderClipContainer';
const EVENT_CAPTURE_PARAMS = {
capture: true,
passive: false
};
/** Root Comparison slider. */
var ReactCompareSlider = function ReactCompareSlider(_ref3) {
var handle = _ref3.handle,
itemOne = _ref3.itemOne,
itemTwo = _ref3.itemTwo,
_ref3$onlyHandleDragg = _ref3.onlyHandleDraggable,
onlyHandleDraggable = _ref3$onlyHandleDragg === void 0 ? false : _ref3$onlyHandleDragg,
onPositionChange = _ref3.onPositionChange,
_ref3$portrait = _ref3.portrait,
portrait = _ref3$portrait === void 0 ? false : _ref3$portrait,
_ref3$position = _ref3.position,
position = _ref3$position === void 0 ? 50 : _ref3$position,
_ref3$boundsPadding = _ref3.boundsPadding,
boundsPadding = _ref3$boundsPadding === void 0 ? 0 : _ref3$boundsPadding,
style = _ref3.style,
props = _objectWithoutPropertiesLoose(_ref3, ["handle", "itemOne", "itemTwo", "onlyHandleDraggable", "onPositionChange", "portrait", "position", "boundsPadding", "style"]);
const ReactCompareSlider = ({
handle,
itemOne,
itemTwo,
onlyHandleDraggable = false,
onPositionChange,
portrait = false,
position = 50,
boundsPadding = 0,
style,
...props
}) => {
/** Reference to root container. */
var rootContainerRef = React.useRef(null);
const rootContainerRef = React.useRef(null);
/** Reference to clip container. */
var clipContainerRef = React.useRef(null);
const clipContainerRef = React.useRef(null);
/** Reference to handle container. */
var handleContainerRef = React.useRef(null);
const handleContainerRef = React.useRef(null);
/** Reference to current position as a percentage value. */
var internalPositionPc = React.useRef(position);
const internalPositionPc = React.useRef(position);
/** Previous `position` prop value. */
var prevPropPosition = usePrevious(position);
const prevPropPosition = usePrevious(position);
/** Whether user is currently dragging. */
var _useState = React.useState(false),
isDragging = _useState[0],
setIsDragging = _useState[1];
const [isDragging, setIsDragging] = React.useState(false);
/** Whether component has a `window` event binding. */
var hasWindowBinding = React.useRef(false);
const hasWindowBinding = React.useRef(false);
/** Target container for pointer events. */
var _useState2 = React.useState(),
interactiveTarget = _useState2[0],
setInteractiveTarget = _useState2[1]; // Set target container for pointer events.
const [interactiveTarget, setInteractiveTarget] = React.useState(); // Set target container for pointer events.
React.useEffect(function () {
React.useEffect(() => {
setInteractiveTarget(onlyHandleDraggable ? handleContainerRef.current : rootContainerRef.current);

@@ -285,17 +274,17 @@ }, [onlyHandleDraggable]);

var updateInternalPosition = React.useCallback(function updateInternalCall(_ref4) {
var x = _ref4.x,
y = _ref4.y,
isOffset = _ref4.isOffset,
_portrait = _ref4.portrait,
_boundsPadding = _ref4.boundsPadding;
var _rootContainerRef$cur = rootContainerRef.current.getBoundingClientRect(),
top = _rootContainerRef$cur.top,
left = _rootContainerRef$cur.left,
width = _rootContainerRef$cur.width,
height = _rootContainerRef$cur.height; // Early out if width or height are zero, can't calculate values
const updateInternalPosition = React.useCallback(function updateInternalCall({
x,
y,
isOffset,
portrait: _portrait,
boundsPadding: _boundsPadding
}) {
const {
top,
left,
width,
height
} = rootContainerRef.current.getBoundingClientRect(); // Early out if width or height are zero, can't calculate values
// from zeros.
if (width === 0 || height === 0) return; // Clamp pixel position to always be within the container's bounds.

@@ -305,13 +294,17 @@ // This does *not* take `boundsPadding` into account because we need

var positionPx = Math.min(Math.max( // Determine bounds based on orientation
const positionPx = Math.min(Math.max( // Determine bounds based on orientation
_portrait ? isOffset ? y - top - window.pageYOffset : y : isOffset ? x - left - window.pageXOffset : x, // Min value
0), // Max value
_portrait ? height : width); // Calculate internal position percentage *without* bounds - we always
// want to return 0-100 of the *slideable* bounds.
_portrait ? height : width);
/**
* Internal position percentage *without* bounds.
* @NOTE This uses the entire container bounds **without** `boundsPadding`
* to get the *real* bounds.
*/
var nextInternalPositionPc = positionPx / (_portrait ? height : width) * 100;
const nextInternalPositionPc = positionPx / (_portrait ? height : width) * 100;
/** Determine if the current pixel position meets the min/max bounds. */
var positionMeetsBounds = _portrait ? positionPx === 0 || positionPx === height : positionPx === 0 || positionPx === width;
var canSkipPositionPc = nextInternalPositionPc === internalPositionPc.current && (internalPositionPc.current === 0 || internalPositionPc.current === 100); // Early out if pixel and percentage positions are already at the min/max
const positionMeetsBounds = _portrait ? positionPx === 0 || positionPx === height : positionPx === 0 || positionPx === width;
const canSkipPositionPc = nextInternalPositionPc === internalPositionPc.current && (internalPositionPc.current === 0 || internalPositionPc.current === 100); // Early out if pixel and percentage positions are already at the min/max
// to prevent update spamming when the user is sliding outside of the

@@ -328,23 +321,23 @@ // container.

var clampedPx = Math.min( // Get largest from pixel position *or* bounds padding.
const clampedPx = Math.min( // Get largest from pixel position *or* bounds padding.
Math.max(positionPx, 0 + _boundsPadding), // Use height *or* width based on orientation.
(_portrait ? height : width) - _boundsPadding); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
clipContainerRef.current.style.clip = _portrait ? "rect(auto,auto," + clampedPx + "px,auto)" : "rect(auto," + clampedPx + "px,auto,auto)"; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
clipContainerRef.current.style.clip = _portrait ? `rect(auto,auto,${clampedPx}px,auto)` : `rect(auto,${clampedPx}px,auto,auto)`; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
handleContainerRef.current.style.transform = _portrait ? "translate3d(0," + clampedPx + "px,0)" : "translate3d(" + clampedPx + "px,0,0)";
handleContainerRef.current.style.transform = _portrait ? `translate3d(0,${clampedPx}px,0)` : `translate3d(${clampedPx}px,0,0)`;
if (onPositionChange) onPositionChange(internalPositionPc.current);
}, [onPositionChange]); // Update internal position if `position` prop changes.
}, [onPositionChange]); // Update internal position when other user controllable props change.
React.useEffect(function () {
React.useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
var _rootContainerRef$cur2 = rootContainerRef.current.getBoundingClientRect(),
width = _rootContainerRef$cur2.width,
height = _rootContainerRef$cur2.height; // Use current internal position if `position` hasn't changed.
const {
width,
height
} = rootContainerRef.current.getBoundingClientRect(); // Use current internal position if `position` hasn't changed.
var nextPosition = position === prevPropPosition ? internalPositionPc.current : position;
const nextPosition = position === prevPropPosition ? internalPositionPc.current : position;
updateInternalPosition({
portrait: portrait,
boundsPadding: boundsPadding,
portrait,
boundsPadding,
x: width / 100 * nextPosition,

@@ -356,7 +349,7 @@ y: height / 100 * nextPosition

var handlePointerDown = React.useCallback(function (ev) {
const handlePointerDown = React.useCallback(ev => {
ev.preventDefault();
updateInternalPosition({
portrait: portrait,
boundsPadding: boundsPadding,
portrait,
boundsPadding,
isOffset: true,

@@ -370,7 +363,6 @@ x: ev instanceof MouseEvent ? ev.pageX : ev.touches[0].pageX,

var handlePointerMove = React.useCallback(function moveCall(ev) {
if (!isDragging) return;
const handlePointerMove = React.useCallback(function moveCall(ev) {
updateInternalPosition({
portrait: portrait,
boundsPadding: boundsPadding,
portrait,
boundsPadding,
isOffset: true,

@@ -380,6 +372,6 @@ x: ev instanceof MouseEvent ? ev.pageX : ev.touches[0].pageX,

});
}, [portrait, isDragging, boundsPadding, updateInternalPosition]);
}, [portrait, boundsPadding, updateInternalPosition]);
/** Handle mouse/touch up. */
var handlePointerUp = React.useCallback(function () {
const handlePointerUp = React.useCallback(() => {
setIsDragging(false);

@@ -389,8 +381,9 @@ }, []);

var handleResize = React.useCallback(function (_ref5) {
var width = _ref5.width,
height = _ref5.height;
const handleResize = React.useCallback(({
width,
height
}) => {
updateInternalPosition({
portrait: portrait,
boundsPadding: boundsPadding,
portrait,
boundsPadding,
x: width / 100 * internalPositionPc.current,

@@ -401,20 +394,12 @@ y: height / 100 * internalPositionPc.current

React.useEffect(function () {
React.useEffect(() => {
if (isDragging && !hasWindowBinding.current) {
window.addEventListener('mousemove', handlePointerMove, {
passive: true
});
window.addEventListener('mouseup', handlePointerUp, {
passive: true
});
window.addEventListener('touchmove', handlePointerMove, {
passive: true
});
window.addEventListener('touchend', handlePointerUp, {
passive: true
});
window.addEventListener('mousemove', handlePointerMove, EVENT_PASSIVE_PARAMS);
window.addEventListener('mouseup', handlePointerUp, EVENT_PASSIVE_PARAMS);
window.addEventListener('touchmove', handlePointerMove, EVENT_PASSIVE_PARAMS);
window.addEventListener('touchend', handlePointerUp, EVENT_PASSIVE_PARAMS);
hasWindowBinding.current = true;
}
return function () {
return () => {
if (hasWindowBinding.current) {

@@ -430,19 +415,12 @@ window.removeEventListener('mousemove', handlePointerMove);

useResizeObserver(rootContainerRef, handleResize); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
useResizeObserver(rootContainerRef, handleResize);
useEventListener('mousedown', handlePointerDown, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
interactiveTarget, EVENT_CAPTURE_PARAMS);
useEventListener('touchstart', handlePointerDown, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
interactiveTarget, EVENT_CAPTURE_PARAMS); // Use custom handle if requested.
useEventListener('mousedown', handlePointerDown, interactiveTarget, {
capture: true,
passive: false
}); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
useEventListener('touchstart', handlePointerDown, interactiveTarget, {
capture: true,
passive: false
}); // Use custom handle if requested.
var Handle = handle || React__default.createElement(ReactCompareSliderHandle, {
const Handle = handle || React__default.createElement(ReactCompareSliderHandle, {
portrait: portrait
});
var rootStyle = _extends({
const rootStyle = {
position: 'relative',

@@ -455,5 +433,5 @@ overflow: 'hidden',

MozUserSelect: 'none',
WebkitUserSelect: 'none'
}, style);
WebkitUserSelect: 'none',
...style
};
return React__default.createElement("div", Object.assign({}, props, {

@@ -463,5 +441,5 @@ ref: rootContainerRef,

"data-rcs": "root"
}), itemTwo, React__default.createElement(ReactCompareSliderClipContainer, {
}), itemTwo, React__default.createElement(ThisClipContainer, {
ref: clipContainerRef
}, itemOne), React__default.createElement(ReactCompareSliderHandleContainer, {
}, itemOne), React__default.createElement(ThisHandleContainer, {
portrait: portrait,

@@ -472,40 +450,13 @@ ref: handleContainerRef

/**
* Image with fallback background for browsers that don't support the
* `object-fit` CSS property.
*/
/** Image with defaults from `styleFitContainer` applied. */
var ReactCompareSliderImage = function ReactCompareSliderImage(_ref) {
var className = _ref.className,
_ref$fallbackEnable = _ref.fallbackEnable,
fallbackEnable = _ref$fallbackEnable === void 0 ? true : _ref$fallbackEnable,
style = _ref.style,
props = _objectWithoutPropertiesLoose(_ref, ["className", "fallbackEnable", "style"]);
/** Runtime support for `object-fit`. Ref based to allow updates after SSR. */
var objectFitIsSupported = React.useRef(supportsCssObjectFit());
var innerStyle = styleFitContainer(_extends({}, style));
var containerStyle = {
width: innerStyle.width,
height: innerStyle.height,
boxSizing: 'border-box'
}; // Add fallback background props if requested
if (!objectFitIsSupported.current && fallbackEnable) {
// Set fallback CSS properties, use props from `innerStyle` if defined
containerStyle.backgroundImage = innerStyle.backgroundImage || "url(" + props.src + ")";
containerStyle.backgroundSize = innerStyle.backgroundSize || 'cover';
containerStyle.backgroundPosition = innerStyle.backgroundPosition || 'center'; // Hide inner image
innerStyle.opacity = 0;
}
return React__default.createElement("div", {
className: className,
style: containerStyle,
"data-rcs": "image-root"
}, React__default.createElement("img", Object.assign({}, props, {
style: innerStyle,
"data-rcs": "image-inner"
})));
const ReactCompareSliderImage = ({
style,
...props
}) => {
const rootStyle = styleFitContainer(style);
return React__default.createElement("img", Object.assign({}, props, {
style: rootStyle,
"data-rcs": "image"
}));
};

@@ -517,3 +468,2 @@

exports.styleFitContainer = styleFitContainer;
exports.supportsCssObjectFit = supportsCssObjectFit;
//# sourceMappingURL=react-compare-slider.cjs.development.js.map

@@ -1,2 +0,2 @@

"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=require("react"),n=(e=t)&&"object"==typeof e&&"default"in e?e.default:e,r=require("resize-observer");function o(){return(o=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e}).apply(this,arguments)}function i(e,t){if(null==e)return{};var n,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)t.indexOf(n=i[r])>=0||(o[n]=e[n]);return o}var a=!("undefined"==typeof window||!window.document||!window.document.createElement),s=function(){return!a||"undefined"!=typeof CSS&&"function"==typeof CSS.supports&&CSS.supports("object-fit","cover")},c=function(e){var t=void 0===e?{}:e,n=t.objectFit,r=t.objectPosition;return o({display:"block",width:"100%",height:"100%",maxWidth:"100%",objectFit:void 0===n?"cover":n,objectPosition:void 0===r?"center":r},i(t,["objectFit","objectPosition"]))},u=function(e,n,r,o){var i=t.useRef();t.useEffect((function(){i.current=n}),[n]),t.useEffect((function(){if(r&&r.addEventListener){var t=function(e){return i.current&&i.current(e)};return r.addEventListener(e,t,o),function(){r.removeEventListener(e,t,o)}}}),[e,r,o])},d=a?t.useLayoutEffect:t.useEffect,l=t.forwardRef((function(e,t){var r=e.portrait;return n.createElement("div",{style:{position:"absolute",top:0,width:"100%",height:"100%",pointerEvents:"none"},"data-rcs":"handle-container",ref:t},n.createElement("div",{style:{position:"absolute",width:r?"100%":void 0,height:r?void 0:"100%",transform:r?"translateY(-50%)":"translateX(-50%)",pointerEvents:"all"}},e.children))}));l.displayName="ReactCompareSliderHandleContainer";var f=function(e){var t=e.portrait,r=e.style,a=i(e,["portrait","style"]),s=o({height:t?4:"100%",width:t?"100%":4,backgroundColor:"#fff",boxShadow:"0 0 .2rem #000",cursor:t?"ns-resize":"ew-resize"},r);return n.createElement("div",Object.assign({},a,{style:s,"data-rcs":"handle-inner"}))},p=t.forwardRef((function(e,t){return n.createElement("div",Object.assign({},e,{style:{position:"absolute",top:0,left:0,width:"100%",height:"100%",willChange:"clip",userSelect:"none",KhtmlUserSelect:"none",MozUserSelect:"none",WebkitUserSelect:"none"},"data-rcs":"clip-item",ref:t}))}));p.displayName="ReactCompareSliderClipContainer",exports.ReactCompareSlider=function(e){var a,s,c=e.handle,v=e.itemOne,h=e.itemTwo,g=e.onlyHandleDraggable,m=void 0!==g&&g,b=e.onPositionChange,w=e.portrait,E=void 0!==w&&w,y=e.position,S=void 0===y?50:y,C=e.boundsPadding,x=void 0===C?0:C,R=e.style,O=i(e,["handle","itemOne","itemTwo","onlyHandleDraggable","onPositionChange","portrait","position","boundsPadding","style"]),k=t.useRef(null),j=t.useRef(null),P=t.useRef(null),z=t.useRef(S),L=(s=t.useRef(a=S),t.useEffect((function(){s.current=a})),s.current),M=t.useState(!1),U=M[0],X=M[1],Y=t.useRef(!1),F=t.useState(),N=F[0],H=F[1];t.useEffect((function(){H(m?P.current:k.current)}),[m]);var D=t.useCallback((function(e){var t=e.x,n=e.y,r=e.isOffset,o=e.portrait,i=e.boundsPadding,a=k.current.getBoundingClientRect(),s=a.width,c=a.height;if(0!==s&&0!==c){var u=Math.min(Math.max(o?r?n-a.top-window.pageYOffset:n:r?t-a.left-window.pageXOffset:t,0),o?c:s),d=u/(o?c:s)*100;if(d!==z.current||0!==z.current&&100!==z.current||!(o?0===u||u===c:0===u||u===s)){z.current=d;var l=Math.min(Math.max(u,0+i),(o?c:s)-i);j.current.style.clip=o?"rect(auto,auto,"+l+"px,auto)":"rect(auto,"+l+"px,auto,auto)",P.current.style.transform=o?"translate3d(0,"+l+"px,0)":"translate3d("+l+"px,0,0)",b&&b(z.current)}}}),[b]);t.useEffect((function(){var e=k.current.getBoundingClientRect(),t=S===L?z.current:S;D({portrait:E,boundsPadding:x,x:e.width/100*t,y:e.height/100*t})}),[E,S,L,x,D]);var I=t.useCallback((function(e){e.preventDefault(),D({portrait:E,boundsPadding:x,isOffset:!0,x:e instanceof MouseEvent?e.pageX:e.touches[0].pageX,y:e instanceof MouseEvent?e.pageY:e.touches[0].pageY}),X(!0)}),[E,x,D]),W=t.useCallback((function(e){U&&D({portrait:E,boundsPadding:x,isOffset:!0,x:e instanceof MouseEvent?e.pageX:e.touches[0].pageX,y:e instanceof MouseEvent?e.pageY:e.touches[0].pageY})}),[E,U,x,D]),q=t.useCallback((function(){X(!1)}),[]),B=t.useCallback((function(e){D({portrait:E,boundsPadding:x,x:e.width/100*z.current,y:e.height/100*z.current})}),[E,x,D]);t.useEffect((function(){return U&&!Y.current&&(window.addEventListener("mousemove",W,{passive:!0}),window.addEventListener("mouseup",q,{passive:!0}),window.addEventListener("touchmove",W,{passive:!0}),window.addEventListener("touchend",q,{passive:!0}),Y.current=!0),function(){Y.current&&(window.removeEventListener("mousemove",W),window.removeEventListener("mouseup",q),window.removeEventListener("touchmove",W),window.removeEventListener("touchend",q),Y.current=!1)}}),[W,q,U]),function(e,n){var o=t.useRef(new r.ResizeObserver((function(e){return n(e[0].contentRect)}))),i=t.useCallback((function(){e.current&&o.current.observe(e.current)}),[e]);d((function(){return o.current=new r.ResizeObserver((function(e){return n(e[0].contentRect)})),i(),function(){return o.current.disconnect()}}),[n,i])}(k,B),u("mousedown",I,N,{capture:!0,passive:!1}),u("touchstart",I,N,{capture:!0,passive:!1});var K=c||n.createElement(f,{portrait:E}),T=o({position:"relative",overflow:"hidden",cursor:U?E?"ns-resize":"ew-resize":void 0,userSelect:"none",KhtmlUserSelect:"none",msUserSelect:"none",MozUserSelect:"none",WebkitUserSelect:"none"},R);return n.createElement("div",Object.assign({},O,{ref:k,style:T,"data-rcs":"root"}),h,n.createElement(p,{ref:j},v),n.createElement(l,{portrait:E,ref:P},K))},exports.ReactCompareSliderHandle=f,exports.ReactCompareSliderImage=function(e){var r=e.className,a=e.fallbackEnable,u=void 0===a||a,d=e.style,l=i(e,["className","fallbackEnable","style"]),f=t.useRef(s()),p=c(o({},d)),v={width:p.width,height:p.height,boxSizing:"border-box"};return!f.current&&u&&(v.backgroundImage=p.backgroundImage||"url("+l.src+")",v.backgroundSize=p.backgroundSize||"cover",v.backgroundPosition=p.backgroundPosition||"center",p.opacity=0),n.createElement("div",{className:r,style:v,"data-rcs":"image-root"},n.createElement("img",Object.assign({},l,{style:p,"data-rcs":"image-inner"})))},exports.styleFitContainer=c,exports.supportsCssObjectFit=s;
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=require("react"),n=(e=t)&&"object"==typeof e&&"default"in e?e.default:e;const r=({flip:e})=>n.createElement("div",{style:{width:0,height:0,borderTop:"8px solid transparent",borderRight:"10px solid",borderBottom:"8px solid transparent",transform:e?"rotate(180deg)":void 0}}),o=({portrait:e,buttonStyle:t,linesStyle:o,style:s,...i})=>{const a={display:"flex",flexDirection:e?"row":"column",placeItems:"center",height:"100%",cursor:e?"ns-resize":"ew-resize",pointerEvents:"none",color:"#fff",...s},c={flexGrow:1,height:e?2:"100%",width:e?"100%":2,backgroundColor:"currentColor",pointerEvents:"auto",boxShadow:"0 0 7px rgba(0,0,0,.35)",...o},l={display:"grid",gridAutoFlow:"column",gap:8,placeContent:"center",flexShrink:0,width:56,height:56,borderRadius:"50%",borderStyle:"solid",borderWidth:2,pointerEvents:"auto",backdropFilter:"blur(7px)",boxShadow:"0 0 7px rgba(0,0,0,.35)",transform:e?"rotate(90deg)":void 0,...t};return n.createElement("div",Object.assign({className:"__rcs-handle-root"},i,{style:a}),n.createElement("div",{className:"__rcs-handle-line",style:c}),n.createElement("div",{className:"__rcs-handle-button",style:l},n.createElement(r,null),n.createElement(r,{flip:!0})),n.createElement("div",{className:"__rcs-handle-line",style:c}))},s=({boxSizing:e="border-box",objectFit:t="cover",objectPosition:n="center",...r}={})=>({display:"block",width:"100%",height:"100%",maxWidth:"100%",boxSizing:e,objectFit:t,objectPosition:n,...r}),i=(e,n,r,o)=>{const s=t.useRef();t.useEffect(()=>{s.current=n},[n]),t.useEffect(()=>{if(!r||!r.addEventListener)return;const t=e=>s.current&&s.current(e);return r.addEventListener(e,t,o),()=>{r.removeEventListener(e,t,o)}},[e,r,o])},a="undefined"!=typeof window&&window.document&&window.document.createElement?t.useLayoutEffect:t.useEffect,c=t.forwardRef((e,t)=>n.createElement("div",Object.assign({},e,{style:{position:"absolute",top:0,left:0,width:"100%",height:"100%",willChange:"clip",userSelect:"none",KhtmlUserSelect:"none",MozUserSelect:"none",WebkitUserSelect:"none"},"data-rcs":"clip-item",ref:t})));c.displayName="ThisClipContainer";const l=t.forwardRef(({children:e,portrait:t},r)=>n.createElement("div",{style:{position:"absolute",top:0,width:"100%",height:"100%",pointerEvents:"none"},"data-rcs":"handle-container",ref:r},n.createElement("div",{style:{position:"absolute",width:t?"100%":void 0,height:t?void 0:"100%",transform:t?"translateY(-50%)":"translateX(-50%)",pointerEvents:"all"}},e)));l.displayName="ThisHandleContainer";const d={passive:!0},u={capture:!0,passive:!1};exports.ReactCompareSlider=({handle:e,itemOne:r,itemTwo:s,onlyHandleDraggable:p=!1,onPositionChange:f,portrait:h=!1,position:m=50,boundsPadding:v=0,style:g,...b})=>{const w=t.useRef(null),E=t.useRef(null),y=t.useRef(null),x=t.useRef(m),S=(e=>{const n=t.useRef(e);return t.useEffect(()=>{n.current=e}),n.current})(m),[R,C]=t.useState(!1),O=t.useRef(!1),[k,L]=t.useState();t.useEffect(()=>{L(p?y.current:w.current)},[p]);const M=t.useCallback((function({x:e,y:t,isOffset:n,portrait:r,boundsPadding:o}){const{top:s,left:i,width:a,height:c}=w.current.getBoundingClientRect();if(0===a||0===c)return;const l=Math.min(Math.max(r?n?t-s-window.pageYOffset:t:n?e-i-window.pageXOffset:e,0),r?c:a),d=l/(r?c:a)*100;if(d===x.current&&(0===x.current||100===x.current)&&(r?0===l||l===c:0===l||l===a))return;x.current=d;const u=Math.min(Math.max(l,0+o),(r?c:a)-o);E.current.style.clip=r?`rect(auto,auto,${u}px,auto)`:`rect(auto,${u}px,auto,auto)`,y.current.style.transform=r?`translate3d(0,${u}px,0)`:`translate3d(${u}px,0,0)`,f&&f(x.current)}),[f]);t.useEffect(()=>{const{width:e,height:t}=w.current.getBoundingClientRect(),n=m===S?x.current:m;M({portrait:h,boundsPadding:v,x:e/100*n,y:t/100*n})},[h,m,S,v,M]);const j=t.useCallback(e=>{e.preventDefault(),M({portrait:h,boundsPadding:v,isOffset:!0,x:e instanceof MouseEvent?e.pageX:e.touches[0].pageX,y:e instanceof MouseEvent?e.pageY:e.touches[0].pageY}),C(!0)},[h,v,M]),z=t.useCallback((function(e){M({portrait:h,boundsPadding:v,isOffset:!0,x:e instanceof MouseEvent?e.pageX:e.touches[0].pageX,y:e instanceof MouseEvent?e.pageY:e.touches[0].pageY})}),[h,v,M]),P=t.useCallback(()=>{C(!1)},[]),_=t.useCallback(({width:e,height:t})=>{M({portrait:h,boundsPadding:v,x:e/100*x.current,y:t/100*x.current})},[h,v,M]);t.useEffect(()=>(R&&!O.current&&(window.addEventListener("mousemove",z,d),window.addEventListener("mouseup",P,d),window.addEventListener("touchmove",z,d),window.addEventListener("touchend",P,d),O.current=!0),()=>{O.current&&(window.removeEventListener("mousemove",z),window.removeEventListener("mouseup",P),window.removeEventListener("touchmove",z),window.removeEventListener("touchend",P),O.current=!1)}),[z,P,R]),((e,n)=>{const r=t.useRef(new ResizeObserver(([e])=>n(e.contentRect))),o=t.useCallback(()=>{e.current&&r.current.observe(e.current)},[e]);a(()=>(r.current=new ResizeObserver(([e])=>n(e.contentRect)),o(),()=>r.current.disconnect()),[n,o])})(w,_),i("mousedown",j,k,u),i("touchstart",j,k,u);const U=e||n.createElement(o,{portrait:h}),N={position:"relative",overflow:"hidden",cursor:R?h?"ns-resize":"ew-resize":void 0,userSelect:"none",KhtmlUserSelect:"none",msUserSelect:"none",MozUserSelect:"none",WebkitUserSelect:"none",...g};return n.createElement("div",Object.assign({},b,{ref:w,style:N,"data-rcs":"root"}),s,n.createElement(c,{ref:E},r),n.createElement(l,{portrait:h,ref:y},U))},exports.ReactCompareSliderHandle=o,exports.ReactCompareSliderImage=({style:e,...t})=>{const r=s(e);return n.createElement("img",Object.assign({},t,{style:r,"data-rcs":"image"}))},exports.styleFitContainer=s;
//# sourceMappingURL=react-compare-slider.cjs.production.min.js.map
import React, { useRef, useEffect, useCallback, useLayoutEffect, useState, forwardRef } from 'react';
import { ResizeObserver } from 'resize-observer';
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
const ThisArrow = ({
flip
}) => {
const style = {
width: 0,
height: 0,
borderTop: '8px solid transparent',
borderRight: '10px solid',
borderBottom: '8px solid transparent',
transform: flip ? 'rotate(180deg)' : undefined
};
return React.createElement("div", {
style: style
});
};
/** Default `handle`. */
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
const ReactCompareSliderHandle = ({
portrait,
buttonStyle,
linesStyle,
style,
...props
}) => {
const _style = {
display: 'flex',
flexDirection: portrait ? 'row' : 'column',
placeItems: 'center',
height: '100%',
cursor: portrait ? 'ns-resize' : 'ew-resize',
pointerEvents: 'none',
color: '#fff',
...style
};
const _linesStyle = {
flexGrow: 1,
height: portrait ? 2 : '100%',
width: portrait ? '100%' : 2,
backgroundColor: 'currentColor',
pointerEvents: 'auto',
boxShadow: '0 0 7px rgba(0,0,0,.35)',
...linesStyle
};
const _buttonStyle = {
display: 'grid',
gridAutoFlow: 'column',
gap: 8,
placeContent: 'center',
flexShrink: 0,
width: 56,
height: 56,
borderRadius: '50%',
borderStyle: 'solid',
borderWidth: 2,
pointerEvents: 'auto',
backdropFilter: 'blur(7px)',
boxShadow: '0 0 7px rgba(0,0,0,.35)',
transform: portrait ? 'rotate(90deg)' : undefined,
...buttonStyle
};
return React.createElement("div", Object.assign({
className: "__rcs-handle-root"
}, props, {
style: _style
}), React.createElement("div", {
className: "__rcs-handle-line",
style: _linesStyle
}), React.createElement("div", {
className: "__rcs-handle-button",
style: _buttonStyle
}, React.createElement(ThisArrow, null), React.createElement(ThisArrow, {
flip: true
})), React.createElement("div", {
className: "__rcs-handle-line",
style: _linesStyle
}));
};
return _extends.apply(this, arguments);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
/** Whether runtime is client-side. */
var isClient = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
/**
* Whether client supports the CSS `object-fit` property.
* Stand-alone CSS utility to make replaced elements (`img`, `video`, etc.) fit their
* container.
*/
var supportsCssObjectFit = function supportsCssObjectFit() {
// Assume object-fit is supported in SSR - it will be picked up again by the
// client anyway.
if (!isClient) return true;
return typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('object-fit', 'cover');
};
/**
* Stand-alone CSS utility to make replaced elements (`img`, `video`, etc.)
* fit their container and maintain their aspect ratio.
*/
var styleFitContainer = function styleFitContainer(_temp) {
var _ref = _temp === void 0 ? {} : _temp,
_ref$objectFit = _ref.objectFit,
objectFit = _ref$objectFit === void 0 ? 'cover' : _ref$objectFit,
_ref$objectPosition = _ref.objectPosition,
objectPosition = _ref$objectPosition === void 0 ? 'center' : _ref$objectPosition,
props = _objectWithoutPropertiesLoose(_ref, ["objectFit", "objectPosition"]);
return _extends({
display: 'block',
width: '100%',
height: '100%',
maxWidth: '100%',
objectFit: objectFit,
objectPosition: objectPosition
}, props);
};
const styleFitContainer = ({
boxSizing = 'border-box',
objectFit = 'cover',
objectPosition = 'center',
...props
} = {}) => ({
display: 'block',
width: '100%',
height: '100%',
maxWidth: '100%',
boxSizing,
objectFit,
objectPosition,
...props
});
/** Store the previous supplied value. */
var usePrevious = function usePrevious(value) {
var ref = useRef(value);
useEffect(function () {
const usePrevious = value => {
const ref = useRef(value);
useEffect(() => {
ref.current = value;

@@ -83,42 +113,31 @@ });

* Event listener binding hook.
* @param eventName - Event to bind to
* @param handler - Callback handler
* @param element - Element to bind to
* @param handlerOptions - Event handler options
* @param eventName - Event to bind to.
* @param handler - Callback handler.
* @param element - Element to bind to.
* @param handlerOptions - Event handler options.
*/
var useEventListener = function useEventListener(eventName, handler, element, handlerOptions) {
// Create a ref that stores handler
var savedHandler = useRef(); // Update ref.current value if handler changes.
// This allows our effect below to always get latest handler ...
// ... without us needing to pass it in effect deps array ...
// ... and potentially cause effect to re-run every render.
useEffect(function () {
const useEventListener = (eventName, handler, element, handlerOptions) => {
const savedHandler = useRef();
useEffect(() => {
savedHandler.current = handler;
}, [handler]);
useEffect(function () {
// Make sure element supports addEventListener
var isSupported = element && element.addEventListener;
if (!isSupported) return; // Create event listener that calls handler function stored in ref
useEffect(() => {
// Make sure element supports addEventListener.
if (!(element && element.addEventListener)) return; // Create event listener that calls handler function stored in ref.
var eventListener = function eventListener(event) {
return savedHandler.current && savedHandler.current(event);
}; // Add event listener
const eventListener = event => savedHandler.current && savedHandler.current(event);
element.addEventListener(eventName, eventListener, handlerOptions); // Remove event listener on cleanup
return function () {
element.addEventListener(eventName, eventListener, handlerOptions);
return () => {
element.removeEventListener(eventName, eventListener, handlerOptions);
};
}, [eventName, element, handlerOptions] // Re-run if eventName or element changes
);
}, [eventName, element, handlerOptions]);
};
/**
* Conditionally use `useLayoutEffect` for client *or* `useEffect` for SSR.
* @see https://github.com/reduxjs/react-redux/blob/c581d480dd675f2645851fb006bef91aeb6ac24d/src/utils/useIsomorphicLayoutEffect.js
* @see <https://github.com/reduxjs/react-redux/blob/c581d480dd675f2645851fb006bef91aeb6ac24d/src/utils/useIsomorphicLayoutEffect.js>
*/
var useIsomorphicLayoutEffect = isClient ? useLayoutEffect : useEffect;
const useIsomorphicLayoutEffect = typeof window !== 'undefined' && window.document && window.document.createElement ? useLayoutEffect : useEffect;
/**

@@ -130,29 +149,44 @@ * Bind resize observer callback to element.

var useResizeObserver = function useResizeObserver(ref, handler) {
var observer = useRef(new ResizeObserver(function (_ref2) {
var entry = _ref2[0];
return handler(entry.contentRect);
}));
var observe = useCallback(function () {
const useResizeObserver = (ref, handler) => {
const observer = useRef(new ResizeObserver(([entry]) => handler(entry.contentRect)));
const observe = useCallback(() => {
ref.current && observer.current.observe(ref.current);
}, [ref]); // Bind/rebind observer when `handler` changes.
useIsomorphicLayoutEffect(function () {
observer.current = new ResizeObserver(function (_ref3) {
var entry = _ref3[0];
return handler(entry.contentRect);
});
useIsomorphicLayoutEffect(() => {
observer.current = new ResizeObserver(([entry]) => handler(entry.contentRect));
observe();
return function () {
return observer.current.disconnect();
};
return () => observer.current.disconnect();
}, [handler, observe]);
};
/** Container for clipped item. */
const ThisClipContainer = /*#__PURE__*/forwardRef((props, ref) => {
const style = {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
willChange: 'clip',
userSelect: 'none',
KhtmlUserSelect: 'none',
MozUserSelect: 'none',
WebkitUserSelect: 'none'
};
return React.createElement("div", Object.assign({}, props, {
style: style,
"data-rcs": "clip-item",
ref: ref
}));
});
ThisClipContainer.displayName = 'ThisClipContainer';
/** Handle container to control position. */
var ReactCompareSliderHandleContainer = /*#__PURE__*/forwardRef(function (_ref, ref) {
var children = _ref.children,
portrait = _ref.portrait;
var style = {
const ThisHandleContainer = /*#__PURE__*/forwardRef(({
children,
portrait
}, ref) => {
const style = {
position: 'absolute',

@@ -164,3 +198,3 @@ top: 0,

};
var innerStyle = {
const innerStyle = {
position: 'absolute',

@@ -180,94 +214,49 @@ width: portrait ? '100%' : undefined,

});
ReactCompareSliderHandleContainer.displayName = 'ReactCompareSliderHandleContainer';
/** Overridable handle. */
var ReactCompareSliderHandle = function ReactCompareSliderHandle(_ref2) {
var portrait = _ref2.portrait,
style = _ref2.style,
props = _objectWithoutPropertiesLoose(_ref2, ["portrait", "style"]);
var rootStyle = _extends({
height: portrait ? 4 : '100%',
width: portrait ? '100%' : 4,
backgroundColor: '#fff',
boxShadow: '0 0 .2rem #000',
cursor: portrait ? 'ns-resize' : 'ew-resize'
}, style);
return React.createElement("div", Object.assign({}, props, {
style: rootStyle,
"data-rcs": "handle-inner"
}));
ThisHandleContainer.displayName = 'ThisHandleContainer';
const EVENT_PASSIVE_PARAMS = {
passive: true
};
/** Container for items passed to main component. */
var ReactCompareSliderClipContainer = /*#__PURE__*/forwardRef(function (props, ref) {
var style = {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
willChange: 'clip',
userSelect: 'none',
KhtmlUserSelect: 'none',
MozUserSelect: 'none',
WebkitUserSelect: 'none'
};
return React.createElement("div", Object.assign({}, props, {
style: style,
"data-rcs": "clip-item",
ref: ref
}));
});
ReactCompareSliderClipContainer.displayName = 'ReactCompareSliderClipContainer';
const EVENT_CAPTURE_PARAMS = {
capture: true,
passive: false
};
/** Root Comparison slider. */
var ReactCompareSlider = function ReactCompareSlider(_ref3) {
var handle = _ref3.handle,
itemOne = _ref3.itemOne,
itemTwo = _ref3.itemTwo,
_ref3$onlyHandleDragg = _ref3.onlyHandleDraggable,
onlyHandleDraggable = _ref3$onlyHandleDragg === void 0 ? false : _ref3$onlyHandleDragg,
onPositionChange = _ref3.onPositionChange,
_ref3$portrait = _ref3.portrait,
portrait = _ref3$portrait === void 0 ? false : _ref3$portrait,
_ref3$position = _ref3.position,
position = _ref3$position === void 0 ? 50 : _ref3$position,
_ref3$boundsPadding = _ref3.boundsPadding,
boundsPadding = _ref3$boundsPadding === void 0 ? 0 : _ref3$boundsPadding,
style = _ref3.style,
props = _objectWithoutPropertiesLoose(_ref3, ["handle", "itemOne", "itemTwo", "onlyHandleDraggable", "onPositionChange", "portrait", "position", "boundsPadding", "style"]);
const ReactCompareSlider = ({
handle,
itemOne,
itemTwo,
onlyHandleDraggable = false,
onPositionChange,
portrait = false,
position = 50,
boundsPadding = 0,
style,
...props
}) => {
/** Reference to root container. */
var rootContainerRef = useRef(null);
const rootContainerRef = useRef(null);
/** Reference to clip container. */
var clipContainerRef = useRef(null);
const clipContainerRef = useRef(null);
/** Reference to handle container. */
var handleContainerRef = useRef(null);
const handleContainerRef = useRef(null);
/** Reference to current position as a percentage value. */
var internalPositionPc = useRef(position);
const internalPositionPc = useRef(position);
/** Previous `position` prop value. */
var prevPropPosition = usePrevious(position);
const prevPropPosition = usePrevious(position);
/** Whether user is currently dragging. */
var _useState = useState(false),
isDragging = _useState[0],
setIsDragging = _useState[1];
const [isDragging, setIsDragging] = useState(false);
/** Whether component has a `window` event binding. */
var hasWindowBinding = useRef(false);
const hasWindowBinding = useRef(false);
/** Target container for pointer events. */
var _useState2 = useState(),
interactiveTarget = _useState2[0],
setInteractiveTarget = _useState2[1]; // Set target container for pointer events.
const [interactiveTarget, setInteractiveTarget] = useState(); // Set target container for pointer events.
useEffect(function () {
useEffect(() => {
setInteractiveTarget(onlyHandleDraggable ? handleContainerRef.current : rootContainerRef.current);

@@ -277,17 +266,17 @@ }, [onlyHandleDraggable]);

var updateInternalPosition = useCallback(function updateInternalCall(_ref4) {
var x = _ref4.x,
y = _ref4.y,
isOffset = _ref4.isOffset,
_portrait = _ref4.portrait,
_boundsPadding = _ref4.boundsPadding;
var _rootContainerRef$cur = rootContainerRef.current.getBoundingClientRect(),
top = _rootContainerRef$cur.top,
left = _rootContainerRef$cur.left,
width = _rootContainerRef$cur.width,
height = _rootContainerRef$cur.height; // Early out if width or height are zero, can't calculate values
const updateInternalPosition = useCallback(function updateInternalCall({
x,
y,
isOffset,
portrait: _portrait,
boundsPadding: _boundsPadding
}) {
const {
top,
left,
width,
height
} = rootContainerRef.current.getBoundingClientRect(); // Early out if width or height are zero, can't calculate values
// from zeros.
if (width === 0 || height === 0) return; // Clamp pixel position to always be within the container's bounds.

@@ -297,13 +286,17 @@ // This does *not* take `boundsPadding` into account because we need

var positionPx = Math.min(Math.max( // Determine bounds based on orientation
const positionPx = Math.min(Math.max( // Determine bounds based on orientation
_portrait ? isOffset ? y - top - window.pageYOffset : y : isOffset ? x - left - window.pageXOffset : x, // Min value
0), // Max value
_portrait ? height : width); // Calculate internal position percentage *without* bounds - we always
// want to return 0-100 of the *slideable* bounds.
_portrait ? height : width);
/**
* Internal position percentage *without* bounds.
* @NOTE This uses the entire container bounds **without** `boundsPadding`
* to get the *real* bounds.
*/
var nextInternalPositionPc = positionPx / (_portrait ? height : width) * 100;
const nextInternalPositionPc = positionPx / (_portrait ? height : width) * 100;
/** Determine if the current pixel position meets the min/max bounds. */
var positionMeetsBounds = _portrait ? positionPx === 0 || positionPx === height : positionPx === 0 || positionPx === width;
var canSkipPositionPc = nextInternalPositionPc === internalPositionPc.current && (internalPositionPc.current === 0 || internalPositionPc.current === 100); // Early out if pixel and percentage positions are already at the min/max
const positionMeetsBounds = _portrait ? positionPx === 0 || positionPx === height : positionPx === 0 || positionPx === width;
const canSkipPositionPc = nextInternalPositionPc === internalPositionPc.current && (internalPositionPc.current === 0 || internalPositionPc.current === 100); // Early out if pixel and percentage positions are already at the min/max
// to prevent update spamming when the user is sliding outside of the

@@ -320,23 +313,23 @@ // container.

var clampedPx = Math.min( // Get largest from pixel position *or* bounds padding.
const clampedPx = Math.min( // Get largest from pixel position *or* bounds padding.
Math.max(positionPx, 0 + _boundsPadding), // Use height *or* width based on orientation.
(_portrait ? height : width) - _boundsPadding); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
clipContainerRef.current.style.clip = _portrait ? "rect(auto,auto," + clampedPx + "px,auto)" : "rect(auto," + clampedPx + "px,auto,auto)"; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
clipContainerRef.current.style.clip = _portrait ? `rect(auto,auto,${clampedPx}px,auto)` : `rect(auto,${clampedPx}px,auto,auto)`; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
handleContainerRef.current.style.transform = _portrait ? "translate3d(0," + clampedPx + "px,0)" : "translate3d(" + clampedPx + "px,0,0)";
handleContainerRef.current.style.transform = _portrait ? `translate3d(0,${clampedPx}px,0)` : `translate3d(${clampedPx}px,0,0)`;
if (onPositionChange) onPositionChange(internalPositionPc.current);
}, [onPositionChange]); // Update internal position if `position` prop changes.
}, [onPositionChange]); // Update internal position when other user controllable props change.
useEffect(function () {
useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
var _rootContainerRef$cur2 = rootContainerRef.current.getBoundingClientRect(),
width = _rootContainerRef$cur2.width,
height = _rootContainerRef$cur2.height; // Use current internal position if `position` hasn't changed.
const {
width,
height
} = rootContainerRef.current.getBoundingClientRect(); // Use current internal position if `position` hasn't changed.
var nextPosition = position === prevPropPosition ? internalPositionPc.current : position;
const nextPosition = position === prevPropPosition ? internalPositionPc.current : position;
updateInternalPosition({
portrait: portrait,
boundsPadding: boundsPadding,
portrait,
boundsPadding,
x: width / 100 * nextPosition,

@@ -348,7 +341,7 @@ y: height / 100 * nextPosition

var handlePointerDown = useCallback(function (ev) {
const handlePointerDown = useCallback(ev => {
ev.preventDefault();
updateInternalPosition({
portrait: portrait,
boundsPadding: boundsPadding,
portrait,
boundsPadding,
isOffset: true,

@@ -362,7 +355,6 @@ x: ev instanceof MouseEvent ? ev.pageX : ev.touches[0].pageX,

var handlePointerMove = useCallback(function moveCall(ev) {
if (!isDragging) return;
const handlePointerMove = useCallback(function moveCall(ev) {
updateInternalPosition({
portrait: portrait,
boundsPadding: boundsPadding,
portrait,
boundsPadding,
isOffset: true,

@@ -372,6 +364,6 @@ x: ev instanceof MouseEvent ? ev.pageX : ev.touches[0].pageX,

});
}, [portrait, isDragging, boundsPadding, updateInternalPosition]);
}, [portrait, boundsPadding, updateInternalPosition]);
/** Handle mouse/touch up. */
var handlePointerUp = useCallback(function () {
const handlePointerUp = useCallback(() => {
setIsDragging(false);

@@ -381,8 +373,9 @@ }, []);

var handleResize = useCallback(function (_ref5) {
var width = _ref5.width,
height = _ref5.height;
const handleResize = useCallback(({
width,
height
}) => {
updateInternalPosition({
portrait: portrait,
boundsPadding: boundsPadding,
portrait,
boundsPadding,
x: width / 100 * internalPositionPc.current,

@@ -393,20 +386,12 @@ y: height / 100 * internalPositionPc.current

useEffect(function () {
useEffect(() => {
if (isDragging && !hasWindowBinding.current) {
window.addEventListener('mousemove', handlePointerMove, {
passive: true
});
window.addEventListener('mouseup', handlePointerUp, {
passive: true
});
window.addEventListener('touchmove', handlePointerMove, {
passive: true
});
window.addEventListener('touchend', handlePointerUp, {
passive: true
});
window.addEventListener('mousemove', handlePointerMove, EVENT_PASSIVE_PARAMS);
window.addEventListener('mouseup', handlePointerUp, EVENT_PASSIVE_PARAMS);
window.addEventListener('touchmove', handlePointerMove, EVENT_PASSIVE_PARAMS);
window.addEventListener('touchend', handlePointerUp, EVENT_PASSIVE_PARAMS);
hasWindowBinding.current = true;
}
return function () {
return () => {
if (hasWindowBinding.current) {

@@ -422,19 +407,12 @@ window.removeEventListener('mousemove', handlePointerMove);

useResizeObserver(rootContainerRef, handleResize); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
useResizeObserver(rootContainerRef, handleResize);
useEventListener('mousedown', handlePointerDown, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
interactiveTarget, EVENT_CAPTURE_PARAMS);
useEventListener('touchstart', handlePointerDown, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
interactiveTarget, EVENT_CAPTURE_PARAMS); // Use custom handle if requested.
useEventListener('mousedown', handlePointerDown, interactiveTarget, {
capture: true,
passive: false
}); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
useEventListener('touchstart', handlePointerDown, interactiveTarget, {
capture: true,
passive: false
}); // Use custom handle if requested.
var Handle = handle || React.createElement(ReactCompareSliderHandle, {
const Handle = handle || React.createElement(ReactCompareSliderHandle, {
portrait: portrait
});
var rootStyle = _extends({
const rootStyle = {
position: 'relative',

@@ -447,5 +425,5 @@ overflow: 'hidden',

MozUserSelect: 'none',
WebkitUserSelect: 'none'
}, style);
WebkitUserSelect: 'none',
...style
};
return React.createElement("div", Object.assign({}, props, {

@@ -455,5 +433,5 @@ ref: rootContainerRef,

"data-rcs": "root"
}), itemTwo, React.createElement(ReactCompareSliderClipContainer, {
}), itemTwo, React.createElement(ThisClipContainer, {
ref: clipContainerRef
}, itemOne), React.createElement(ReactCompareSliderHandleContainer, {
}, itemOne), React.createElement(ThisHandleContainer, {
portrait: portrait,

@@ -464,43 +442,16 @@ ref: handleContainerRef

/**
* Image with fallback background for browsers that don't support the
* `object-fit` CSS property.
*/
/** Image with defaults from `styleFitContainer` applied. */
var ReactCompareSliderImage = function ReactCompareSliderImage(_ref) {
var className = _ref.className,
_ref$fallbackEnable = _ref.fallbackEnable,
fallbackEnable = _ref$fallbackEnable === void 0 ? true : _ref$fallbackEnable,
style = _ref.style,
props = _objectWithoutPropertiesLoose(_ref, ["className", "fallbackEnable", "style"]);
/** Runtime support for `object-fit`. Ref based to allow updates after SSR. */
var objectFitIsSupported = useRef(supportsCssObjectFit());
var innerStyle = styleFitContainer(_extends({}, style));
var containerStyle = {
width: innerStyle.width,
height: innerStyle.height,
boxSizing: 'border-box'
}; // Add fallback background props if requested
if (!objectFitIsSupported.current && fallbackEnable) {
// Set fallback CSS properties, use props from `innerStyle` if defined
containerStyle.backgroundImage = innerStyle.backgroundImage || "url(" + props.src + ")";
containerStyle.backgroundSize = innerStyle.backgroundSize || 'cover';
containerStyle.backgroundPosition = innerStyle.backgroundPosition || 'center'; // Hide inner image
innerStyle.opacity = 0;
}
return React.createElement("div", {
className: className,
style: containerStyle,
"data-rcs": "image-root"
}, React.createElement("img", Object.assign({}, props, {
style: innerStyle,
"data-rcs": "image-inner"
})));
const ReactCompareSliderImage = ({
style,
...props
}) => {
const rootStyle = styleFitContainer(style);
return React.createElement("img", Object.assign({}, props, {
style: rootStyle,
"data-rcs": "image"
}));
};
export { ReactCompareSlider, ReactCompareSliderHandle, ReactCompareSliderImage, styleFitContainer, supportsCssObjectFit };
export { ReactCompareSlider, ReactCompareSliderHandle, ReactCompareSliderImage, styleFitContainer };
//# sourceMappingURL=react-compare-slider.esm.js.map

@@ -1,12 +0,7 @@

import { RefObject } from 'react';
import { ContentRect } from 'resize-observer/lib/ContentRect';
import { RefObject, useLayoutEffect } from 'react';
/**
* Whether client supports the CSS `object-fit` property.
* Stand-alone CSS utility to make replaced elements (`img`, `video`, etc.) fit their
* container.
*/
export declare const supportsCssObjectFit: () => boolean;
/**
* Stand-alone CSS utility to make replaced elements (`img`, `video`, etc.)
* fit their container and maintain their aspect ratio.
*/
export declare const styleFitContainer: ({ objectFit, objectPosition, ...props }?: React.CSSProperties) => React.CSSProperties;
export declare const styleFitContainer: ({ boxSizing, objectFit, objectPosition, ...props }?: React.CSSProperties) => React.CSSProperties;
/** Store the previous supplied value. */

@@ -16,10 +11,15 @@ export declare const usePrevious: <T>(value: T) => T;

* Event listener binding hook.
* @param eventName - Event to bind to
* @param handler - Callback handler
* @param element - Element to bind to
* @param handlerOptions - Event handler options
* @param eventName - Event to bind to.
* @param handler - Callback handler.
* @param element - Element to bind to.
* @param handlerOptions - Event handler options.
*/
export declare const useEventListener: (eventName: EventListener['name'], handler: EventListener['caller'], element: EventTarget, handlerOptions: AddEventListenerOptions) => void;
/**
* Conditionally use `useLayoutEffect` for client *or* `useEffect` for SSR.
* @see <https://github.com/reduxjs/react-redux/blob/c581d480dd675f2645851fb006bef91aeb6ac24d/src/utils/useIsomorphicLayoutEffect.js>
*/
export declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
/** Params passed to `useResizeObserver` `handler` function. */
export declare type UseResizeObserverHandlerParams = ContentRect;
export declare type UseResizeObserverHandlerParams = DOMRect;
/**

@@ -26,0 +26,0 @@ * Bind resize observer callback to element.

{
"name": "react-compare-slider",
"version": "1.2.1",
"version": "2.0.1",
"license": "MIT",

@@ -38,3 +38,3 @@ "repository": {

"start": "tsdx watch",
"build": "tsdx build",
"build": "NODE_ENV=production tsdx build",
"dedupe-types": "rm -rf node_modules && yarn remove @types/react && yarn && yarn add --dev @types/react && npx yarn-deduplicate --packages @types/react yarn.lock",

@@ -50,9 +50,29 @@ "release": "yarn build && np --no-2fa",

},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8"
"browserslist": {
"production": [
"last 2 chrome versions",
"last 2 edge versions",
"last 2 firefox versions",
"last 2 safari versions",
"not dead",
"not ie > 0",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"np": {
"yarn": true
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"jest": {
"verbose": true,
"setupFilesAfterEnv": [
"./test/setupTests.ts"
]
},
"lint-staged": {

@@ -65,9 +85,7 @@ "**/*.{js,jsx,ts,tsx}": [

},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
"np": {
"yarn": true
},
"prettier": {
"printWidth": 80,
"printWidth": 90,
"semi": true,

@@ -77,46 +95,53 @@ "singleQuote": true,

},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8"
},
"devDependencies": {
"@emotion/babel-preset-css-prop": "^10.0.27",
"@emotion/css": "^10.0.27",
"@storybook/addon-actions": "^6.0.21",
"@storybook/addon-console": "^1.2.1",
"@storybook/addon-controls": "^6.0.21",
"@storybook/addon-docs": "^6.0.21",
"@storybook/addon-storysource": "^6.0.21",
"@storybook/addon-viewport": "^6.0.21",
"@storybook/addons": "^6.0.21",
"@emotion/babel-preset-css-prop": "^11.0.0",
"@emotion/css": "^11.1.3",
"@emotion/react": "^11.1.4",
"@storybook/addon-actions": "^6.2.0-alpha.10",
"@storybook/addon-console": "^1.2.2",
"@storybook/addon-controls": "^6.2.0-alpha.10",
"@storybook/addon-docs": "^6.2.0-alpha.10",
"@storybook/addon-storysource": "^6.2.0-alpha.10",
"@storybook/addon-viewport": "^6.2.0-alpha.10",
"@storybook/addons": "^6.2.0-alpha.10",
"@storybook/preset-typescript": "3.0.0",
"@storybook/react": "^6.0.21",
"@storybook/theming": "^6.0.21",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.0.2",
"@types/jest": "^26.0.13",
"@types/node": "^12.12.26",
"@types/react": "^16.9.49",
"@types/react-dom": "^16.9.8",
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"babel-loader": "^8.1.0",
"eslint": "^7.8.1",
"eslint-plugin-jest": "^24.0.0",
"eslint-plugin-jest-dom": "^3.2.2",
"eslint-plugin-react": "^7.20.6",
"eslint-plugin-react-hooks": "^4.1.0",
"eslint-plugin-testing-library": "^3.8.0",
"@storybook/react": "^6.2.0-alpha.10",
"@storybook/theming": "^6.2.0-alpha.10",
"@testing-library/jest-dom": "^5.11.8",
"@testing-library/react": "^11.2.2",
"@testing-library/react-hooks": "^3.7.0",
"@types/jest": "^26.0.19",
"@types/node": "^14.14.17",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/resize-observer-browser": "^0.1.4",
"@typescript-eslint/eslint-plugin": "^4.11.1",
"@typescript-eslint/parser": "^4.11.1",
"babel-loader": "^8.2.2",
"eslint": "^7.16.0",
"eslint-plugin-jest": "^24.1.3",
"eslint-plugin-jest-dom": "^3.6.5",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-testing-library": "^3.10.1",
"google-maps-react": "^2.0.6",
"husky": "^4.2.5",
"lint-staged": "^10.3.0",
"np": "^6.5.0",
"prettier": "^2.1.1",
"pretty-quick": "^3.0.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"remark-codesandbox": "^0.6.0",
"tsdx": "^0.13.3",
"tslib": "^2.0.1",
"typescript": "^4.0.2"
"husky": "^4.3.6",
"lint-staged": "^10.5.3",
"np": "^7.2.0",
"prettier": "^2.2.1",
"pretty-quick": "^3.1.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-test-renderer": "^17.0.1",
"remark-codesandbox": "^0.10.0",
"rollup-plugin-analyzer": "^4.0.0",
"tsdx": "^0.14.1",
"tslib": "^2.0.3",
"typescript": "^4.1.3"
},
"dependencies": {
"resize-observer": "^1.0.0"
}
"dependencies": {}
}
<div align="center">
<h1>React Compare Slider</h1>
<p>Compare two components side-by-side or top-to-toe.</p>
<h1>React Compare Slider</h1>
<p>Compare two components side-by-side or top-to-toe.</p>

@@ -8,19 +8,19 @@ [![Example](./example/default-handle-capture.gif)](https://codesandbox.io/s/react-compare-slider-simple-example-9si6l?file=/src/App.jsx)

<a href="https://github.com/nerdyman/react-compare-slider/blob/master/LICENSE">
<img src="https://img.shields.io/npm/l/react-compare-slider.svg" alt="License MIT" />
<img src="https://img.shields.io/npm/l/react-compare-slider.svg" alt="License MIT" />
</a>
<a href="https://npmjs.com/package/react-compare-slider">
<img src="https://img.shields.io/npm/v/react-compare-slider.svg" alt="NPM package" />
<img src="https://img.shields.io/npm/v/react-compare-slider.svg" alt="NPM package" />
</a>
<a href="https://bundlephobia.com/result?p=react-compare-slider">
<img src="https://img.shields.io/bundlephobia/minzip/react-compare-slider.svg" alt="Bundle size" />
<img src="https://img.shields.io/bundlephobia/minzip/react-compare-slider.svg" alt="Bundle size" />
</a>
<br/>
<a href="https://github.com/nerdyman/react-compare-slider/actions?query=workflow%3Abuild">
<img src="https://img.shields.io/github/workflow/status/nerdyman/react-compare-slider/build" alt="Build Status" />
<img src="https://img.shields.io/github/workflow/status/nerdyman/react-compare-slider/build" alt="Build Status" />
</a>
<a href="https://codeclimate.com/github/nerdyman/react-compare-slider">
<img src="https://img.shields.io/codeclimate/coverage/nerdyman/react-compare-slider" alt="Coverage" />
<img src="https://img.shields.io/codeclimate/coverage/nerdyman/react-compare-slider" alt="Coverage" />
</a>
<a href="https://react-compare-slider.vercel.app">
<img src="https://raw.githubusercontent.com/storybookjs/brand/8d28584c89959d7075c237e9345955c895048977/badge/badge-storybook.svg" alt="Demos" />
<img src="https://raw.githubusercontent.com/storybookjs/brand/8d28584c89959d7075c237e9345955c895048977/badge/badge-storybook.svg" alt="Demos" />
</a>

@@ -39,6 +39,8 @@

- Responsive, fluid
- Works in IE11+
- [Teeny-tiny](https://bundlephobia.com/result?p=react-compare-slider), only one ponyfill dependency
- [Teeny-tiny](https://bundlephobia.com/result?p=react-compare-slider)
- Zero dependencies
- Type safe
<br />
## Demo

@@ -104,3 +106,3 @@

[![Custom Handles](./example/custom-handle-capture.gif)](https://codesandbox.io/s/react-compare-slider-simple-example-9si6l?file=/src/App.jsx)
[![Custom Handles](./example/custom-handle-capture.gif)](https://react-compare-slider.vercel.app/?path=/story/demos-handles--individual-styles)

@@ -115,2 +117,2 @@ See the [Handles docs](https://react-compare-slider.vercel.app/?path=/docs/docs-handles--page) for more information.

Bootstrapped with [TSDX](<https://github.com/palmerhq/tsdx>).
Bootstrapped with [TSDX](https://github.com/formium/tsdx).

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc