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 0.1.4 to 1.0.0

dist/utils.d.ts

1

dist/index.d.ts
export * from './react-compare-slider-image';
export * from './react-compare-slider';
export { styleFitContainer } from './utils';

536

dist/react-compare-slider.cjs.development.js
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var tslib = require('tslib');
var React = require('react');

@@ -9,35 +12,2 @@ var React__default = _interopDefault(React);

function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
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;
}
/**

@@ -47,9 +17,12 @@ * CSS style util for child to fit container

var styleFitContainer = function styleFitContainer(_temp) {
var _ref = _temp === void 0 ? {} : _temp,
_ref$objectFit = _ref.objectFit,
objectFit = _ref$objectFit === void 0 ? 'cover' : _ref$objectFit,
props = _objectWithoutPropertiesLoose(_ref, ["objectFit"]);
var styleFitContainer = function styleFitContainer(_a) {
if (_a === void 0) {
_a = {};
}
return _extends({
var _b = _a.objectFit,
objectFit = _b === void 0 ? 'cover' : _b,
props = tslib.__rest(_a, ["objectFit"]);
return tslib.__assign({
display: 'block',

@@ -63,9 +36,118 @@ width: '100%',

/**
* Handle container to control position
* Event listener binding hook
* @param eventName - Event to bind to
* @param handler - Callback handler
* @param element - Element to bind to
* @see https://usehooks.com/useEventListener/
*/
var ReactCompareSliderHandleContainer = function ReactCompareSliderHandleContainer(_ref2) {
var children = _ref2.children,
position = _ref2.position,
portrait = _ref2.portrait;
var useEventListener = function useEventListener(eventName, handler, element, handlerOptions) {
if (element === void 0) {
element = window;
} // 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 () {
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
var eventListener = function eventListener(event) {
return savedHandler.current && savedHandler.current(event);
}; // Add event listener
element.addEventListener(eventName, eventListener, handlerOptions); // Remove event listener on cleanup
return function () {
element.removeEventListener(eventName, eventListener, handlerOptions);
};
}, [eventName, element, handlerOptions] // Re-run if eventName or element changes
);
};
/**
* Bind resize observer to ref
* @param ref - Ref to bind to
* @param handler - Callback for handling entry's bounding rect
* @see https://tobbelindstrom.com/blog/resize-observer-hook/ https://codesandbox.io/s/zw8kylol8m
*/
var useResizeObserver = function useResizeObserver(ref, handler) {
var observer = React.useRef(new resizeObserver.ResizeObserver(function (_a) {
var entry = _a[0];
handler && handler(entry.contentRect);
}));
var disconnect = React.useCallback(function () {
var current = observer.current;
current && current.disconnect();
}, []);
var observe = React.useCallback(function () {
ref.current && observer.current.observe(ref.current);
}, [ref]);
React.useLayoutEffect(function () {
observe();
return function () {
return disconnect();
};
}, [disconnect, observe]);
};
/**
* Whether client supports the CSS `object-fit` property
*/
var CLIENT_SUPPORTS_CSS_OBJECT_FIT = typeof CSS !== 'undefined' && CSS.supports &&
/*#__PURE__*/
CSS.supports('object-fit', 'cover');
/**
* Image with fallback background for browsers that don't support the
* `object-fit` CSS property
*/
var ReactCompareSliderImage = function ReactCompareSliderImage(_a) {
var className = _a.className,
_b = _a.fallbackEnable,
fallbackEnable = _b === void 0 ? true : _b,
style = _a.style,
props = tslib.__rest(_a, ["className", "fallbackEnable", "style"]);
var innerStyle = styleFitContainer(tslib.__assign({}, style));
var containerStyle = {
width: innerStyle.width,
height: innerStyle.height
}; // Add fallback background props if requested
if (!CLIENT_SUPPORTS_CSS_OBJECT_FIT && 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", tslib.__assign({}, props, {
style: innerStyle,
"data-rcs": "image-inner"
})));
};
/** Handle container to control position */
var ReactCompareSliderHandleContainer = function ReactCompareSliderHandleContainer(_a) {
var children = _a.children,
position = _a.position,
portrait = _a.portrait;
var style = {

@@ -94,10 +176,8 @@ position: 'absolute',

};
/**
* Overridable handle
*/
/** Overridable handle */
var ReactCompareSliderHandle = function ReactCompareSliderHandle(_ref3) {
var portrait = _ref3.portrait,
props = _objectWithoutPropertiesLoose(_ref3, ["portrait"]);
var ReactCompareSliderHandle = function ReactCompareSliderHandle(_a) {
var portrait = _a.portrait,
props = tslib.__rest(_a, ["portrait"]);

@@ -111,3 +191,3 @@ var style = {

};
return React__default.createElement("div", Object.assign({}, props, {
return React__default.createElement("div", tslib.__assign({}, props, {
style: style,

@@ -117,10 +197,8 @@ "data-rcs": "main-handle-inner"

};
/**
* Container for items passed to main component
*/
/** Container for items passed to main component */
var ReactCompareSliderItem = function ReactCompareSliderItem(_ref4) {
var portrait = _ref4.portrait,
position = _ref4.position,
props = _objectWithoutPropertiesLoose(_ref4, ["portrait", "position"]);
var ReactCompareSliderItem = function ReactCompareSliderItem(_a) {
var portrait = _a.portrait,
position = _a.position,
props = tslib.__rest(_a, ["portrait", "position"]);

@@ -140,3 +218,3 @@ var style = {

};
return React__default.createElement("div", Object.assign({}, props, {
return React__default.createElement("div", tslib.__assign({}, props, {
style: style,

@@ -146,208 +224,141 @@ "data-rcs": "clip-item"

};
/**
* Root component
*/
/** Comparison slider */
var ReactCompareSlider = function ReactCompareSlider(_ref5) {
var handle = _ref5.handle,
itemOne = _ref5.itemOne,
itemTwo = _ref5.itemTwo,
onChange = _ref5.onChange,
portrait = _ref5.portrait,
_ref5$position = _ref5.position,
position = _ref5$position === void 0 ? 50 : _ref5$position,
props = _objectWithoutPropertiesLoose(_ref5, ["handle", "itemOne", "itemTwo", "onChange", "portrait", "position"]);
var ReactCompareSlider = function ReactCompareSlider(_a) {
var handle = _a.handle,
itemOne = _a.itemOne,
itemTwo = _a.itemTwo,
onPositionChange = _a.onPositionChange,
portrait = _a.portrait,
_b = _a.position,
position = _b === void 0 ? 50 : _b,
style = _a.style,
props = tslib.__rest(_a, ["handle", "itemOne", "itemTwo", "onPositionChange", "portrait", "position", "style"]);
var containerRef = React.useRef(document.createElement('div'));
var _useState = React.useState(false),
isDragging = _useState[0],
setIsDragging = _useState[1]; // const [containerDimensions, setContainerDimensions] = useState({
// width: 0,
// height: 0,
// });
var _useState2 = React.useState({
pc: position,
px: 0
var _c = React.useState({
width: 0,
height: 0
}),
internalPosition = _useState2[0],
setInternalPosition = _useState2[1];
/**
* Update internal position state from `x` and `y` coordinate *or* a
* `percentage` value
*/
containerBounds = _c[0],
setContainerBounds = _c[1];
var containerRef = React.useRef(document.createElement('div'));
var internalPositionPc = React.useRef(position);
var updateInternalPosition = React.useCallback(function (_ref6) {
var percentage = _ref6.percentage,
pointerX = _ref6.pointerX,
pointerY = _ref6.pointerY;
var _d = React.useState(0),
internalPositionPx = _d[0],
setInternalPositionPx = _d[1];
var _containerRef$current = containerRef.current.getBoundingClientRect(),
top = _containerRef$current.top,
left = _containerRef$current.left,
width = _containerRef$current.width,
height = _containerRef$current.height;
var _e = React.useState(false),
isDragging = _e[0],
setIsDragging = _e[1];
var x = 0;
var y = 0; // Use pointer positions if defined
var hasWindowBinding = React.useRef(false);
var updateInternalPosition = React.useCallback(function (_a) {
var x = _a.x,
y = _a.y;
if (pointerX && pointerY) {
x = pointerX - left - window.scrollX;
y = pointerY - top - window.scrollY; // Use percentage if defined
} else if (percentage) {
x = width / 100 * percentage;
y = height / 100 * percentage;
}
var _b = containerRef.current.getBoundingClientRect(),
top = _b.top,
left = _b.left;
var px = portrait ? y : x;
var pc = portrait ? y / height * 100 : x / width * 100;
setInternalPosition({
pc: pc,
px: px
});
var positionPx = portrait ? y - top - window.pageYOffset : x - left - window.pageXOffset;
setInternalPositionPx(positionPx); // Calculate percentage with bounds checking
if (onChange) {
onChange(pc);
}
}, [onChange, portrait]); // Update internal position if position prop changes
internalPositionPc.current = Math.min(Math.max(positionPx / (portrait ? containerBounds.height : containerBounds.width) * 100, 0), 100);
if (onPositionChange) onPositionChange(internalPositionPc.current);
}, [containerBounds.height, containerBounds.width, onPositionChange, portrait]); // Update internal position if `position` prop changes
React.useEffect(function () {
var _a = containerRef.current.getBoundingClientRect(),
top = _a.top,
left = _a.left,
width = _a.width,
height = _a.height;
updateInternalPosition({
percentage: position
x: width / 100 * position + left,
y: height / 100 * position + top
});
}, [position, updateInternalPosition]);
/**
* Handle element resize event
*/
var handleResize = React.useCallback(function () {
var _containerRef$current2 = containerRef.current.getBoundingClientRect(),
width = _containerRef$current2.width,
height = _containerRef$current2.height;
setInternalPosition(function (state) {
return _extends({}, state, {
px: portrait ? height / 100 * state.pc : width / 100 * state.pc
var handlePointerDown = React.useCallback(function (ev) {
ev.preventDefault();
updateInternalPosition({
x: ev instanceof MouseEvent ? ev.pageX : ev.touches[0].pageX,
y: ev instanceof MouseEvent ? ev.pageY : ev.touches[0].pageY
});
setIsDragging(true);
}, [updateInternalPosition]);
var handlePointerMove = React.useCallback(function (ev) {
if (!isDragging) return;
requestAnimationFrame(function () {
updateInternalPosition({
x: ev instanceof MouseEvent ? ev.pageX : ev.touches[0].pageX,
y: ev instanceof MouseEvent ? ev.pageY : ev.touches[0].pageY
});
});
}, [portrait]); // Update internal position on resize
}, [isDragging, updateInternalPosition]);
var handlePointerUp = React.useCallback(function () {
setIsDragging(false);
}, []);
var handleResize = React.useCallback(function (_a) {
var width = _a.width,
height = _a.height;
setContainerBounds({
width: width,
height: height
});
setInternalPositionPx((portrait ? height : width) / 100 * internalPositionPc.current);
}, [portrait]); // Allow drag outside of container while pointer is still down
React.useEffect(function () {
var ro = new resizeObserver.ResizeObserver(function () {
handleResize();
}); // Bind observer
var el = containerRef.current;
ro.observe(el);
return function () {
return ro.unobserve(el);
};
}, [handleResize]); // Bind and handle events
React.useEffect(function () {
var containerRefCurrent = containerRef.current;
var handleMouseDown = function handleMouseDown(ev) {
ev.preventDefault();
if (!isDragging) setIsDragging(true);
updateInternalPosition({
pointerX: ev.pageX,
pointerY: ev.pageY
if (isDragging && !hasWindowBinding.current) {
window.addEventListener('mousemove', handlePointerMove, {
passive: true
});
};
var handleMouseMove = function handleMouseMove(ev) {
if (isDragging) {
requestAnimationFrame(function () {
updateInternalPosition({
pointerX: ev.pageX,
pointerY: ev.pageY
});
});
}
};
var handleTouchStart = function handleTouchStart(ev) {
ev.preventDefault();
if (!isDragging) setIsDragging(true);
updateInternalPosition({
pointerX: ev.touches[0].pageX,
pointerY: ev.touches[0].pageY
document.addEventListener('mouseup', handlePointerUp, {
passive: true
});
};
window.addEventListener('touchmove', handlePointerMove, {
passive: true
});
window.addEventListener('touchend', handlePointerUp, {
passive: true
});
hasWindowBinding.current = true;
}
var handleTouchMove = function handleTouchMove(ev) {
if (isDragging) {
requestAnimationFrame(function () {
updateInternalPosition({
pointerX: ev.touches[0].pageX,
pointerY: ev.touches[0].pageY
});
});
return function () {
if (hasWindowBinding.current) {
window.removeEventListener('mousemove', handlePointerMove);
window.removeEventListener('mouseup', handlePointerUp);
hasWindowBinding.current = false;
}
};
}, [handlePointerMove, handlePointerUp, isDragging]); // Bind resize observer to container
var handleFinish = function handleFinish() {
if (isDragging) setIsDragging(false);
}; // Mouse event bindings
useResizeObserver(containerRef, handleResize);
useEventListener('mousedown', handlePointerDown, containerRef.current, {
capture: true,
passive: false
});
useEventListener('touchmove', handlePointerMove, containerRef.current, {
capture: false,
passive: true
});
useEventListener('touchend', handlePointerUp, containerRef.current, {
capture: false,
passive: true
});
useEventListener('touchstart', handlePointerDown, containerRef.current, {
capture: true,
passive: false
}); // Use custom handle if requested
containerRefCurrent.addEventListener('mousedown', handleMouseDown, {
capture: false,
passive: false
});
containerRefCurrent.addEventListener('mouseleave', handleFinish, {
capture: false,
passive: true
});
containerRefCurrent.addEventListener('mousemove', handleMouseMove, {
capture: false,
passive: true
});
containerRefCurrent.addEventListener('mouseup', handleFinish, {
capture: false,
passive: true
}); // Touch event bindings
containerRefCurrent.addEventListener('touchstart', handleTouchStart, {
capture: false,
passive: false
});
containerRefCurrent.addEventListener('touchend', handleFinish, {
capture: false,
passive: true
});
containerRefCurrent.addEventListener('touchmove', handleTouchMove, {
capture: false,
passive: true
});
containerRefCurrent.addEventListener('touchcancel', handleFinish, {
capture: false,
passive: true
});
return function () {
// Mouse event bindings
containerRefCurrent.removeEventListener('mousedown', handleMouseDown);
containerRefCurrent.removeEventListener('mouseleave', handleFinish);
containerRefCurrent.removeEventListener('mousemove', handleMouseMove);
containerRefCurrent.removeEventListener('mouseup', handleFinish); // Touch events bindings
containerRefCurrent.removeEventListener('touchstart', handleTouchStart);
containerRefCurrent.removeEventListener('touchend', handleFinish);
containerRefCurrent.removeEventListener('touchmove', handleTouchMove);
containerRefCurrent.removeEventListener('touchcancel', handleFinish);
};
}, [isDragging, portrait, updateInternalPosition]); // Use custom handle if requested
var Handle = handle || React__default.createElement(ReactCompareSliderHandle, {
portrait: portrait
});
var style = {
// @NOTE using `flex` to ensure Firefox will calculate the correct width
// of bounding box, it will return `0` otherwise
flex: 1,
var rootStyle = tslib.__assign({
position: 'relative',

@@ -360,12 +371,13 @@ overflow: 'hidden',

WebkitUserSelect: 'none'
};
return React__default.createElement("div", Object.assign({}, props, {
}, style);
return React__default.createElement("div", tslib.__assign({}, props, {
ref: containerRef,
style: style,
style: rootStyle,
"data-rcs": "root"
}), itemTwo, React__default.createElement(ReactCompareSliderItem, {
position: internalPosition.px,
position: internalPositionPx,
portrait: portrait
}, itemOne), React__default.createElement(ReactCompareSliderHandleContainer, {
position: internalPosition.px,
position: internalPositionPx,
portrait: portrait

@@ -375,46 +387,2 @@ }, Handle));

/**
* Whether client supports the CSS `object-fit` property
*/
var CLIENT_SUPPORTS_CSS_OBJECT_FIT = typeof CSS !== 'undefined' && CSS.supports &&
/*#__PURE__*/
CSS.supports('object-fit', 'cover');
/**
* Image with fallback background for browsers that don't support the
* `object-fit` CSS property
*/
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"]);
var innerStyle = styleFitContainer(_extends({}, style));
var containerStyle = {
width: innerStyle.width,
height: innerStyle.height
}; // Add fallback background props if requested
if (!CLIENT_SUPPORTS_CSS_OBJECT_FIT && 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"
})));
};
exports.CLIENT_SUPPORTS_CSS_OBJECT_FIT = CLIENT_SUPPORTS_CSS_OBJECT_FIT;

@@ -421,0 +389,0 @@ exports.ReactCompareSlider = ReactCompareSlider;

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

"use strict";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=function(e){var t=void 0===e?{}:e,n=t.objectFit;return o({display:"block",width:"100%",height:"100%",maxWidth:"100%",objectFit:void 0===n?"cover":n},i(t,["objectFit"]))},s=function(e){var t=e.position,r=e.portrait;return n.createElement("div",{style:{position:"absolute",top:0,width:"100%",height:"100%",transform:r?"translateY("+t+"px)":"translateX("+t+"px)",pointerEvents:"none"},"data-rcs":"main-handle-container"},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))},c=function(e){var t=e.portrait,r=i(e,["portrait"]);return n.createElement("div",Object.assign({},r,{style:{height:t?3:"100%",width:t?"100%":3,backgroundColor:"#ffffff",boxShadow:"0 0 .2rem #000000",cursor:t?"ns-resize":"ew-resize"},"data-rcs":"main-handle-inner"}))},u=function(e){var t=e.portrait,r=e.position,o=i(e,["portrait","position"]);return n.createElement("div",Object.assign({},o,{style:{position:"absolute",top:0,left:0,width:"100%",height:"100%",clip:t?"rect(auto,auto,"+r+"px,auto)":"rect(auto,"+r+"px,auto,auto)",willChange:"clip",userSelect:"none",KhtmlUserSelect:"none",MozUserSelect:"none",WebkitUserSelect:"none"},"data-rcs":"clip-item"}))},p="undefined"!=typeof CSS&&CSS.supports&&CSS.supports("object-fit","cover");exports.CLIENT_SUPPORTS_CSS_OBJECT_FIT=p,exports.ReactCompareSlider=function(e){var a=e.handle,p=e.itemOne,l=e.itemTwo,v=e.onChange,d=e.portrait,m=e.position,f=void 0===m?50:m,h=i(e,["handle","itemOne","itemTwo","onChange","portrait","position"]),g=t.useRef(document.createElement("div")),b=t.useState(!1),E=b[0],S=b[1],w=t.useState({pc:f,px:0}),x=w[0],y=w[1],C=t.useCallback(function(e){var t=e.percentage,n=e.pointerX,r=e.pointerY,o=g.current.getBoundingClientRect(),i=o.width,a=o.height,s=0,c=0;n&&r?(s=n-o.left-window.scrollX,c=r-o.top-window.scrollY):t&&(s=i/100*t,c=a/100*t);var u=d?c/a*100:s/i*100;y({pc:u,px:d?c:s}),v&&v(u)},[v,d]);t.useEffect(function(){C({percentage:f})},[f,C]);var L=t.useCallback(function(){var e=g.current.getBoundingClientRect(),t=e.width,n=e.height;y(function(e){return o({},e,{px:d?n/100*e.pc:t/100*e.pc})})},[d]);t.useEffect(function(){var e=new r.ResizeObserver(function(){L()}),t=g.current;return e.observe(t),function(){return e.unobserve(t)}},[L]),t.useEffect(function(){var e=g.current,t=function(e){e.preventDefault(),E||S(!0),C({pointerX:e.pageX,pointerY:e.pageY})},n=function(e){E&&requestAnimationFrame(function(){C({pointerX:e.pageX,pointerY:e.pageY})})},r=function(e){e.preventDefault(),E||S(!0),C({pointerX:e.touches[0].pageX,pointerY:e.touches[0].pageY})},o=function(e){E&&requestAnimationFrame(function(){C({pointerX:e.touches[0].pageX,pointerY:e.touches[0].pageY})})},i=function(){E&&S(!1)};return e.addEventListener("mousedown",t,{capture:!1,passive:!1}),e.addEventListener("mouseleave",i,{capture:!1,passive:!0}),e.addEventListener("mousemove",n,{capture:!1,passive:!0}),e.addEventListener("mouseup",i,{capture:!1,passive:!0}),e.addEventListener("touchstart",r,{capture:!1,passive:!1}),e.addEventListener("touchend",i,{capture:!1,passive:!0}),e.addEventListener("touchmove",o,{capture:!1,passive:!0}),e.addEventListener("touchcancel",i,{capture:!1,passive:!0}),function(){e.removeEventListener("mousedown",t),e.removeEventListener("mouseleave",i),e.removeEventListener("mousemove",n),e.removeEventListener("mouseup",i),e.removeEventListener("touchstart",r),e.removeEventListener("touchend",i),e.removeEventListener("touchmove",o),e.removeEventListener("touchcancel",i)}},[E,d,C]);var k=a||n.createElement(c,{portrait:d});return n.createElement("div",Object.assign({},h,{ref:g,style:{flex:1,position:"relative",overflow:"hidden",cursor:E?d?"ns-resize":"ew-resize":void 0,userSelect:"none",KhtmlUserSelect:"none",MozUserSelect:"none",WebkitUserSelect:"none"},"data-rcs":"root"}),l,n.createElement(u,{position:x.px,portrait:d},p),n.createElement(s,{position:x.px,portrait:d},k))},exports.ReactCompareSliderHandle=c,exports.ReactCompareSliderImage=function(e){var t=e.className,r=e.fallbackEnable,s=void 0===r||r,c=e.style,u=i(e,["className","fallbackEnable","style"]),l=a(o({},c)),v={width:l.width,height:l.height};return!p&&s&&(v.backgroundImage=l.backgroundImage||"url("+u.src+")",v.backgroundSize=l.backgroundSize||"cover",v.backgroundPosition=l.backgroundPosition||"center",l.opacity=0),n.createElement("div",{className:t,style:v,"data-rcs":"image-root"},n.createElement("img",Object.assign({},u,{style:l,"data-rcs":"image-inner"})))},exports.styleFitContainer=a;
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=require("tslib"),n=require("react"),r=(e=n)&&"object"==typeof e&&"default"in e?e.default:e,i=require("resize-observer"),o=function(e){void 0===e&&(e={});var n=e.objectFit,r=void 0===n?"cover":n,i=t.__rest(e,["objectFit"]);return t.__assign({display:"block",width:"100%",height:"100%",maxWidth:"100%",objectFit:r},i)},a=function(e,t,r,i){void 0===r&&(r=window);var o=n.useRef();n.useEffect((function(){o.current=t}),[t]),n.useEffect((function(){if(r&&r.addEventListener){var t=function(e){return o.current&&o.current(e)};return r.addEventListener(e,t,i),function(){r.removeEventListener(e,t,i)}}}),[e,r,i])},s="undefined"!=typeof CSS&&CSS.supports&&CSS.supports("object-fit","cover"),c=function(e){var t=e.position,n=e.portrait;return r.createElement("div",{style:{position:"absolute",top:0,width:"100%",height:"100%",transform:n?"translateY("+t+"px)":"translateX("+t+"px)",pointerEvents:"none"},"data-rcs":"main-handle-container"},r.createElement("div",{style:{position:"absolute",width:n?"100%":void 0,height:n?void 0:"100%",transform:n?"translateY(-50%)":"translateX(-50%)",pointerEvents:"all"}},e.children))},u=function(e){var n=e.portrait,i=t.__rest(e,["portrait"]);return r.createElement("div",t.__assign({},i,{style:{height:n?3:"100%",width:n?"100%":3,backgroundColor:"#ffffff",boxShadow:"0 0 .2rem #000000",cursor:n?"ns-resize":"ew-resize"},"data-rcs":"main-handle-inner"}))},l=function(e){var n=e.portrait,i=e.position,o=t.__rest(e,["portrait","position"]);return r.createElement("div",t.__assign({},o,{style:{position:"absolute",top:0,left:0,width:"100%",height:"100%",clip:n?"rect(auto,auto,"+i+"px,auto)":"rect(auto,"+i+"px,auto,auto)",willChange:"clip",userSelect:"none",KhtmlUserSelect:"none",MozUserSelect:"none",WebkitUserSelect:"none"},"data-rcs":"clip-item"}))};exports.CLIENT_SUPPORTS_CSS_OBJECT_FIT=s,exports.ReactCompareSlider=function(e){var o=e.handle,s=e.itemOne,d=e.itemTwo,p=e.onPositionChange,f=e.portrait,v=e.position,h=void 0===v?50:v,m=e.style,g=t.__rest(e,["handle","itemOne","itemTwo","onPositionChange","portrait","position","style"]),w=n.useState({width:0,height:0}),b=w[0],E=w[1],_=n.useRef(document.createElement("div")),S=n.useRef(h),C=n.useState(0),y=C[0],k=C[1],x=n.useState(!1),R=x[0],L=x[1],z=n.useRef(!1),M=n.useCallback((function(e){var t=e.x,n=e.y,r=_.current.getBoundingClientRect(),i=f?n-r.top-window.pageYOffset:t-r.left-window.pageXOffset;k(i),S.current=Math.min(Math.max(i/(f?b.height:b.width)*100,0),100),p&&p(S.current)}),[b.height,b.width,p,f]);n.useEffect((function(){var e=_.current.getBoundingClientRect();M({x:e.width/100*h+e.left,y:e.height/100*h+e.top})}),[h,M]);var O,P,U,X,Y,j=n.useCallback((function(e){e.preventDefault(),M({x:e instanceof MouseEvent?e.pageX:e.touches[0].pageX,y:e instanceof MouseEvent?e.pageY:e.touches[0].pageY}),L(!0)}),[M]),F=n.useCallback((function(e){R&&requestAnimationFrame((function(){M({x:e instanceof MouseEvent?e.pageX:e.touches[0].pageX,y:e instanceof MouseEvent?e.pageY:e.touches[0].pageY})}))}),[R,M]),T=n.useCallback((function(){L(!1)}),[]),I=n.useCallback((function(e){var t=e.width,n=e.height;E({width:t,height:n}),k((f?n:t)/100*S.current)}),[f]);n.useEffect((function(){return R&&!z.current&&(window.addEventListener("mousemove",F,{passive:!0}),document.addEventListener("mouseup",T,{passive:!0}),window.addEventListener("touchmove",F,{passive:!0}),window.addEventListener("touchend",T,{passive:!0}),z.current=!0),function(){z.current&&(window.removeEventListener("mousemove",F),window.removeEventListener("mouseup",T),z.current=!1)}}),[F,T,R]),O=_,P=I,U=n.useRef(new i.ResizeObserver((function(e){P&&P(e[0].contentRect)}))),X=n.useCallback((function(){var e=U.current;e&&e.disconnect()}),[]),Y=n.useCallback((function(){O.current&&U.current.observe(O.current)}),[O]),n.useLayoutEffect((function(){return Y(),function(){return X()}}),[X,Y]),a("mousedown",j,_.current,{capture:!0,passive:!1}),a("touchmove",F,_.current,{capture:!1,passive:!0}),a("touchend",T,_.current,{capture:!1,passive:!0}),a("touchstart",j,_.current,{capture:!0,passive:!1});var q=o||r.createElement(u,{portrait:f}),N=t.__assign({position:"relative",overflow:"hidden",cursor:R?f?"ns-resize":"ew-resize":void 0,userSelect:"none",KhtmlUserSelect:"none",MozUserSelect:"none",WebkitUserSelect:"none"},m);return r.createElement("div",t.__assign({},g,{ref:_,style:N,"data-rcs":"root"}),d,r.createElement(l,{position:y,portrait:f},s),r.createElement(c,{position:y,portrait:f},q))},exports.ReactCompareSliderHandle=u,exports.ReactCompareSliderImage=function(e){var n=e.className,i=e.fallbackEnable,a=void 0===i||i,c=e.style,u=t.__rest(e,["className","fallbackEnable","style"]),l=o(t.__assign({},c)),d={width:l.width,height:l.height};return!s&&a&&(d.backgroundImage=l.backgroundImage||"url("+u.src+")",d.backgroundSize=l.backgroundSize||"cover",d.backgroundPosition=l.backgroundPosition||"center",l.opacity=0),r.createElement("div",{className:n,style:d,"data-rcs":"image-root"},r.createElement("img",t.__assign({},u,{style:l,"data-rcs":"image-inner"})))},exports.styleFitContainer=o;
//# sourceMappingURL=react-compare-slider.cjs.production.min.js.map
import React from 'react';
/**
* CSS style util for child to fit container
*/
export declare const styleFitContainer: ({ objectFit, ...props }?: React.CSSProperties) => Partial<React.CSSProperties>;
/** Slider position prop */
declare type ReactCompareSliderPropPosition = number;
/**
* Common props shared between child components
*/
/** Common props shared between child components */
interface ReactCompareSliderCommonProps {

@@ -14,11 +9,7 @@ portrait?: boolean;

}
/**
* Overridable handle
*/
/** Overridable handle */
export declare const ReactCompareSliderHandle: React.FC<Pick<ReactCompareSliderCommonProps, 'portrait'>>;
/**
* Props for main component
*/
/** Comparison slider props */
export interface ReactCompareSliderProps {
/** Handle component for dragging between comparisons */
/** Custom handle component */
handle?: React.ReactNode;

@@ -30,3 +21,3 @@ /** First item to show */

/** Callback on position change */
onChange?: (position: ReactCompareSliderPropPosition) => void;
onPositionChange?: (position: ReactCompareSliderPropPosition) => void;
/** Orientation */

@@ -37,6 +28,4 @@ portrait?: boolean;

}
/**
* Root component
*/
/** Comparison slider */
export declare const ReactCompareSlider: React.FC<ReactCompareSliderProps & React.HtmlHTMLAttributes<HTMLDivElement>>;
export {};

@@ -1,37 +0,5 @@

import React, { useRef, useState, useCallback, useEffect } from 'react';
import { __rest, __assign } from 'tslib';
import React, { useRef, useEffect, useCallback, useLayoutEffect, useState } 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];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
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;
}
/**

@@ -41,9 +9,12 @@ * CSS style util for child to fit container

var styleFitContainer = function styleFitContainer(_temp) {
var _ref = _temp === void 0 ? {} : _temp,
_ref$objectFit = _ref.objectFit,
objectFit = _ref$objectFit === void 0 ? 'cover' : _ref$objectFit,
props = _objectWithoutPropertiesLoose(_ref, ["objectFit"]);
var styleFitContainer = function styleFitContainer(_a) {
if (_a === void 0) {
_a = {};
}
return _extends({
var _b = _a.objectFit,
objectFit = _b === void 0 ? 'cover' : _b,
props = __rest(_a, ["objectFit"]);
return __assign({
display: 'block',

@@ -57,9 +28,118 @@ width: '100%',

/**
* Handle container to control position
* Event listener binding hook
* @param eventName - Event to bind to
* @param handler - Callback handler
* @param element - Element to bind to
* @see https://usehooks.com/useEventListener/
*/
var ReactCompareSliderHandleContainer = function ReactCompareSliderHandleContainer(_ref2) {
var children = _ref2.children,
position = _ref2.position,
portrait = _ref2.portrait;
var useEventListener = function useEventListener(eventName, handler, element, handlerOptions) {
if (element === void 0) {
element = window;
} // 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 () {
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
var eventListener = function eventListener(event) {
return savedHandler.current && savedHandler.current(event);
}; // Add event listener
element.addEventListener(eventName, eventListener, handlerOptions); // Remove event listener on cleanup
return function () {
element.removeEventListener(eventName, eventListener, handlerOptions);
};
}, [eventName, element, handlerOptions] // Re-run if eventName or element changes
);
};
/**
* Bind resize observer to ref
* @param ref - Ref to bind to
* @param handler - Callback for handling entry's bounding rect
* @see https://tobbelindstrom.com/blog/resize-observer-hook/ https://codesandbox.io/s/zw8kylol8m
*/
var useResizeObserver = function useResizeObserver(ref, handler) {
var observer = useRef(new ResizeObserver(function (_a) {
var entry = _a[0];
handler && handler(entry.contentRect);
}));
var disconnect = useCallback(function () {
var current = observer.current;
current && current.disconnect();
}, []);
var observe = useCallback(function () {
ref.current && observer.current.observe(ref.current);
}, [ref]);
useLayoutEffect(function () {
observe();
return function () {
return disconnect();
};
}, [disconnect, observe]);
};
/**
* Whether client supports the CSS `object-fit` property
*/
var CLIENT_SUPPORTS_CSS_OBJECT_FIT = typeof CSS !== 'undefined' && CSS.supports &&
/*#__PURE__*/
CSS.supports('object-fit', 'cover');
/**
* Image with fallback background for browsers that don't support the
* `object-fit` CSS property
*/
var ReactCompareSliderImage = function ReactCompareSliderImage(_a) {
var className = _a.className,
_b = _a.fallbackEnable,
fallbackEnable = _b === void 0 ? true : _b,
style = _a.style,
props = __rest(_a, ["className", "fallbackEnable", "style"]);
var innerStyle = styleFitContainer(__assign({}, style));
var containerStyle = {
width: innerStyle.width,
height: innerStyle.height
}; // Add fallback background props if requested
if (!CLIENT_SUPPORTS_CSS_OBJECT_FIT && 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", __assign({}, props, {
style: innerStyle,
"data-rcs": "image-inner"
})));
};
/** Handle container to control position */
var ReactCompareSliderHandleContainer = function ReactCompareSliderHandleContainer(_a) {
var children = _a.children,
position = _a.position,
portrait = _a.portrait;
var style = {

@@ -88,10 +168,8 @@ position: 'absolute',

};
/**
* Overridable handle
*/
/** Overridable handle */
var ReactCompareSliderHandle = function ReactCompareSliderHandle(_ref3) {
var portrait = _ref3.portrait,
props = _objectWithoutPropertiesLoose(_ref3, ["portrait"]);
var ReactCompareSliderHandle = function ReactCompareSliderHandle(_a) {
var portrait = _a.portrait,
props = __rest(_a, ["portrait"]);

@@ -105,3 +183,3 @@ var style = {

};
return React.createElement("div", Object.assign({}, props, {
return React.createElement("div", __assign({}, props, {
style: style,

@@ -111,10 +189,8 @@ "data-rcs": "main-handle-inner"

};
/**
* Container for items passed to main component
*/
/** Container for items passed to main component */
var ReactCompareSliderItem = function ReactCompareSliderItem(_ref4) {
var portrait = _ref4.portrait,
position = _ref4.position,
props = _objectWithoutPropertiesLoose(_ref4, ["portrait", "position"]);
var ReactCompareSliderItem = function ReactCompareSliderItem(_a) {
var portrait = _a.portrait,
position = _a.position,
props = __rest(_a, ["portrait", "position"]);

@@ -134,3 +210,3 @@ var style = {

};
return React.createElement("div", Object.assign({}, props, {
return React.createElement("div", __assign({}, props, {
style: style,

@@ -140,208 +216,141 @@ "data-rcs": "clip-item"

};
/**
* Root component
*/
/** Comparison slider */
var ReactCompareSlider = function ReactCompareSlider(_ref5) {
var handle = _ref5.handle,
itemOne = _ref5.itemOne,
itemTwo = _ref5.itemTwo,
onChange = _ref5.onChange,
portrait = _ref5.portrait,
_ref5$position = _ref5.position,
position = _ref5$position === void 0 ? 50 : _ref5$position,
props = _objectWithoutPropertiesLoose(_ref5, ["handle", "itemOne", "itemTwo", "onChange", "portrait", "position"]);
var ReactCompareSlider = function ReactCompareSlider(_a) {
var handle = _a.handle,
itemOne = _a.itemOne,
itemTwo = _a.itemTwo,
onPositionChange = _a.onPositionChange,
portrait = _a.portrait,
_b = _a.position,
position = _b === void 0 ? 50 : _b,
style = _a.style,
props = __rest(_a, ["handle", "itemOne", "itemTwo", "onPositionChange", "portrait", "position", "style"]);
var containerRef = useRef(document.createElement('div'));
var _useState = useState(false),
isDragging = _useState[0],
setIsDragging = _useState[1]; // const [containerDimensions, setContainerDimensions] = useState({
// width: 0,
// height: 0,
// });
var _useState2 = useState({
pc: position,
px: 0
var _c = useState({
width: 0,
height: 0
}),
internalPosition = _useState2[0],
setInternalPosition = _useState2[1];
/**
* Update internal position state from `x` and `y` coordinate *or* a
* `percentage` value
*/
containerBounds = _c[0],
setContainerBounds = _c[1];
var containerRef = useRef(document.createElement('div'));
var internalPositionPc = useRef(position);
var updateInternalPosition = useCallback(function (_ref6) {
var percentage = _ref6.percentage,
pointerX = _ref6.pointerX,
pointerY = _ref6.pointerY;
var _d = useState(0),
internalPositionPx = _d[0],
setInternalPositionPx = _d[1];
var _containerRef$current = containerRef.current.getBoundingClientRect(),
top = _containerRef$current.top,
left = _containerRef$current.left,
width = _containerRef$current.width,
height = _containerRef$current.height;
var _e = useState(false),
isDragging = _e[0],
setIsDragging = _e[1];
var x = 0;
var y = 0; // Use pointer positions if defined
var hasWindowBinding = useRef(false);
var updateInternalPosition = useCallback(function (_a) {
var x = _a.x,
y = _a.y;
if (pointerX && pointerY) {
x = pointerX - left - window.scrollX;
y = pointerY - top - window.scrollY; // Use percentage if defined
} else if (percentage) {
x = width / 100 * percentage;
y = height / 100 * percentage;
}
var _b = containerRef.current.getBoundingClientRect(),
top = _b.top,
left = _b.left;
var px = portrait ? y : x;
var pc = portrait ? y / height * 100 : x / width * 100;
setInternalPosition({
pc: pc,
px: px
});
var positionPx = portrait ? y - top - window.pageYOffset : x - left - window.pageXOffset;
setInternalPositionPx(positionPx); // Calculate percentage with bounds checking
if (onChange) {
onChange(pc);
}
}, [onChange, portrait]); // Update internal position if position prop changes
internalPositionPc.current = Math.min(Math.max(positionPx / (portrait ? containerBounds.height : containerBounds.width) * 100, 0), 100);
if (onPositionChange) onPositionChange(internalPositionPc.current);
}, [containerBounds.height, containerBounds.width, onPositionChange, portrait]); // Update internal position if `position` prop changes
useEffect(function () {
var _a = containerRef.current.getBoundingClientRect(),
top = _a.top,
left = _a.left,
width = _a.width,
height = _a.height;
updateInternalPosition({
percentage: position
x: width / 100 * position + left,
y: height / 100 * position + top
});
}, [position, updateInternalPosition]);
/**
* Handle element resize event
*/
var handleResize = useCallback(function () {
var _containerRef$current2 = containerRef.current.getBoundingClientRect(),
width = _containerRef$current2.width,
height = _containerRef$current2.height;
setInternalPosition(function (state) {
return _extends({}, state, {
px: portrait ? height / 100 * state.pc : width / 100 * state.pc
var handlePointerDown = useCallback(function (ev) {
ev.preventDefault();
updateInternalPosition({
x: ev instanceof MouseEvent ? ev.pageX : ev.touches[0].pageX,
y: ev instanceof MouseEvent ? ev.pageY : ev.touches[0].pageY
});
setIsDragging(true);
}, [updateInternalPosition]);
var handlePointerMove = useCallback(function (ev) {
if (!isDragging) return;
requestAnimationFrame(function () {
updateInternalPosition({
x: ev instanceof MouseEvent ? ev.pageX : ev.touches[0].pageX,
y: ev instanceof MouseEvent ? ev.pageY : ev.touches[0].pageY
});
});
}, [portrait]); // Update internal position on resize
}, [isDragging, updateInternalPosition]);
var handlePointerUp = useCallback(function () {
setIsDragging(false);
}, []);
var handleResize = useCallback(function (_a) {
var width = _a.width,
height = _a.height;
setContainerBounds({
width: width,
height: height
});
setInternalPositionPx((portrait ? height : width) / 100 * internalPositionPc.current);
}, [portrait]); // Allow drag outside of container while pointer is still down
useEffect(function () {
var ro = new ResizeObserver(function () {
handleResize();
}); // Bind observer
var el = containerRef.current;
ro.observe(el);
return function () {
return ro.unobserve(el);
};
}, [handleResize]); // Bind and handle events
useEffect(function () {
var containerRefCurrent = containerRef.current;
var handleMouseDown = function handleMouseDown(ev) {
ev.preventDefault();
if (!isDragging) setIsDragging(true);
updateInternalPosition({
pointerX: ev.pageX,
pointerY: ev.pageY
if (isDragging && !hasWindowBinding.current) {
window.addEventListener('mousemove', handlePointerMove, {
passive: true
});
};
var handleMouseMove = function handleMouseMove(ev) {
if (isDragging) {
requestAnimationFrame(function () {
updateInternalPosition({
pointerX: ev.pageX,
pointerY: ev.pageY
});
});
}
};
var handleTouchStart = function handleTouchStart(ev) {
ev.preventDefault();
if (!isDragging) setIsDragging(true);
updateInternalPosition({
pointerX: ev.touches[0].pageX,
pointerY: ev.touches[0].pageY
document.addEventListener('mouseup', handlePointerUp, {
passive: true
});
};
window.addEventListener('touchmove', handlePointerMove, {
passive: true
});
window.addEventListener('touchend', handlePointerUp, {
passive: true
});
hasWindowBinding.current = true;
}
var handleTouchMove = function handleTouchMove(ev) {
if (isDragging) {
requestAnimationFrame(function () {
updateInternalPosition({
pointerX: ev.touches[0].pageX,
pointerY: ev.touches[0].pageY
});
});
return function () {
if (hasWindowBinding.current) {
window.removeEventListener('mousemove', handlePointerMove);
window.removeEventListener('mouseup', handlePointerUp);
hasWindowBinding.current = false;
}
};
}, [handlePointerMove, handlePointerUp, isDragging]); // Bind resize observer to container
var handleFinish = function handleFinish() {
if (isDragging) setIsDragging(false);
}; // Mouse event bindings
useResizeObserver(containerRef, handleResize);
useEventListener('mousedown', handlePointerDown, containerRef.current, {
capture: true,
passive: false
});
useEventListener('touchmove', handlePointerMove, containerRef.current, {
capture: false,
passive: true
});
useEventListener('touchend', handlePointerUp, containerRef.current, {
capture: false,
passive: true
});
useEventListener('touchstart', handlePointerDown, containerRef.current, {
capture: true,
passive: false
}); // Use custom handle if requested
containerRefCurrent.addEventListener('mousedown', handleMouseDown, {
capture: false,
passive: false
});
containerRefCurrent.addEventListener('mouseleave', handleFinish, {
capture: false,
passive: true
});
containerRefCurrent.addEventListener('mousemove', handleMouseMove, {
capture: false,
passive: true
});
containerRefCurrent.addEventListener('mouseup', handleFinish, {
capture: false,
passive: true
}); // Touch event bindings
containerRefCurrent.addEventListener('touchstart', handleTouchStart, {
capture: false,
passive: false
});
containerRefCurrent.addEventListener('touchend', handleFinish, {
capture: false,
passive: true
});
containerRefCurrent.addEventListener('touchmove', handleTouchMove, {
capture: false,
passive: true
});
containerRefCurrent.addEventListener('touchcancel', handleFinish, {
capture: false,
passive: true
});
return function () {
// Mouse event bindings
containerRefCurrent.removeEventListener('mousedown', handleMouseDown);
containerRefCurrent.removeEventListener('mouseleave', handleFinish);
containerRefCurrent.removeEventListener('mousemove', handleMouseMove);
containerRefCurrent.removeEventListener('mouseup', handleFinish); // Touch events bindings
containerRefCurrent.removeEventListener('touchstart', handleTouchStart);
containerRefCurrent.removeEventListener('touchend', handleFinish);
containerRefCurrent.removeEventListener('touchmove', handleTouchMove);
containerRefCurrent.removeEventListener('touchcancel', handleFinish);
};
}, [isDragging, portrait, updateInternalPosition]); // Use custom handle if requested
var Handle = handle || React.createElement(ReactCompareSliderHandle, {
portrait: portrait
});
var style = {
// @NOTE using `flex` to ensure Firefox will calculate the correct width
// of bounding box, it will return `0` otherwise
flex: 1,
var rootStyle = __assign({
position: 'relative',

@@ -354,12 +363,13 @@ overflow: 'hidden',

WebkitUserSelect: 'none'
};
return React.createElement("div", Object.assign({}, props, {
}, style);
return React.createElement("div", __assign({}, props, {
ref: containerRef,
style: style,
style: rootStyle,
"data-rcs": "root"
}), itemTwo, React.createElement(ReactCompareSliderItem, {
position: internalPosition.px,
position: internalPositionPx,
portrait: portrait
}, itemOne), React.createElement(ReactCompareSliderHandleContainer, {
position: internalPosition.px,
position: internalPositionPx,
portrait: portrait

@@ -369,47 +379,3 @@ }, Handle));

/**
* Whether client supports the CSS `object-fit` property
*/
var CLIENT_SUPPORTS_CSS_OBJECT_FIT = typeof CSS !== 'undefined' && CSS.supports &&
/*#__PURE__*/
CSS.supports('object-fit', 'cover');
/**
* Image with fallback background for browsers that don't support the
* `object-fit` CSS property
*/
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"]);
var innerStyle = styleFitContainer(_extends({}, style));
var containerStyle = {
width: innerStyle.width,
height: innerStyle.height
}; // Add fallback background props if requested
if (!CLIENT_SUPPORTS_CSS_OBJECT_FIT && 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"
})));
};
export { CLIENT_SUPPORTS_CSS_OBJECT_FIT, ReactCompareSlider, ReactCompareSliderHandle, ReactCompareSliderImage, styleFitContainer };
//# sourceMappingURL=react-compare-slider.esm.js.map
{
"name": "react-compare-slider",
"version": "0.1.4",
"version": "1.0.0",
"license": "MIT",

@@ -36,6 +36,9 @@ "repository": {

"release": "np",
"test": "tsdx test --env=jsdom",
"test:watch": "yarn test --coverage --watch",
"test": "CI=true tsdx test --color",
"test:watch": "tsdx test",
"test:coverage": "CI=true tsdx test --color --coverage",
"lint": "tsdx lint",
"lint-staged": "lint-staged"
"lint-staged": "lint-staged",
"storybook": "start-storybook -p 6006 --ci",
"storybook:build": "build-storybook"
},

@@ -52,3 +55,3 @@ "peerDependencies": {

"pretty-quick",
"eslint --fix",
"eslint --config ./.eslintrc.precommit.js --fix",
"git add",

@@ -70,22 +73,37 @@ "yarn test --bail --findRelatedTests"

"devDependencies": {
"@testing-library/react": "^9.3.0",
"@types/jest": "^24.0.18",
"@types/react": "^16.9.5",
"@types/react-dom": "^16.9.1",
"@typescript-eslint/eslint-plugin": "^2.3.2",
"@typescript-eslint/parser": "^2.3.2",
"eslint": "^6.5.1",
"eslint-plugin-jest": "^22.17.0",
"eslint-plugin-react": "^7.16.0",
"eslint-plugin-react-hooks": "^2.1.2",
"husky": "^3.0.8",
"lint-staged": "^9.4.1",
"np": "^5.1.0",
"prettier": "^1.18.2",
"pretty-quick": "^1.11.1",
"react": "^16.10.2",
"react-dom": "^16.10.2",
"tsdx": "^0.9.3",
"@storybook/addon-actions": "^5.3.0-rc.6",
"@storybook/addon-docs": "^5.3.0-rc.6",
"@storybook/addon-info": "^5.3.0-rc.6",
"@storybook/addon-knobs": "^5.3.0-rc.6",
"@storybook/addon-links": "^5.3.0-rc.6",
"@storybook/addon-viewport": "^5.3.0-rc.6",
"@storybook/addons": "^5.3.0-rc.6",
"@storybook/preset-typescript": "^1.2.0",
"@storybook/react": "^5.3.0-rc.6",
"@storybook/theming": "^5.3.0-rc.6",
"@testing-library/react": "^9.4.0",
"@types/jest": "^24.0.25",
"@types/node": "12.11.7",
"@types/react": "^16.9.17",
"@types/react-dom": "^16.9.4",
"@types/storybook__react": "^4.0.2",
"@typescript-eslint/eslint-plugin": "^2.14.0",
"@typescript-eslint/parser": "^2.14.0",
"babel-loader": "^8.0.6",
"eslint": "^6.8.0",
"eslint-plugin-jest": "^23.2.0",
"eslint-plugin-react": "^7.17.0",
"eslint-plugin-react-hooks": "^2.3.0",
"husky": "^3.1.0",
"lint-staged": "^9.5.0",
"np": "^5.2.1",
"prettier": "^1.19.1",
"pretty-quick": "^2.0.1",
"react": "^16.12.0",
"react-docgen-typescript-loader": "^3.6.0",
"react-dom": "^16.12.0",
"ts-loader": "^6.2.1",
"tsdx": "^0.12.1",
"tslib": "^1.10.0",
"typescript": "^3.6.3"
"typescript": "^3.7.4"
},

@@ -92,0 +110,0 @@ "dependencies": {

@@ -1,7 +0,23 @@

![License](https://img.shields.io/npm/l/react-compare-slider) ![npm](https://img.shields.io/npm/v/react-compare-slider) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/react-compare-slider)
[![Build Status](https://github.com/nerdyman/react-compare-slider/workflows/node-ci/badge.svg)](https://github.com/nerdyman/react-compare-slider/workflows/node-ci)
<div align="center">
<h1>React Compare Slider</h1>
<p>Compare two components, side-by-side or top-to-toe.</p>
# React Compare Slider
<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">
</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">
</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">
</a>
<a href="https://github.com/nerdyman/react-compare-slider/actions?query=workflow%3Abuild">
<img src="https://github.com/nerdyman/react-compare-slider/workflows/build/badge.svg" alt="Build Status">
</a>
<a href="https://festive-darwin-fab443.netlify.com/">
<img src="https://img.shields.io/badge/demos-🚀-blue.svg" alt="Demos" />
</a>
</div>
Compare two components, side-by-side or top-to-toe.
---

@@ -13,6 +29,6 @@ ## Features

- Simple API
- Unopinionated & fully customizable &ndash; optionally use your own components and styles
- Responsive, fluid
- Fully customisable
- Works in IE11+
- Teeny-tiny, only one ponyfill dependency
- [Teeny-tiny](https://bundlephobia.com/result?p=react-compare-slider), only one ponyfill dependency
- Type safe

@@ -22,10 +38,4 @@

### CodeSandbox
See Storybook for [documentation](https://festive-darwin-fab443.netlify.com/?path=/docs/docs-intro--page) and [demos](https://festive-darwin-fab443.netlify.com/?path=/docs/demos-images--default).
**Note**: The CodeSandbox code view degrades performance slightly, see _Demo_ links for real-world performance.
- Landscape, Portrait with custom handle
- [Demo](<https://9si6l.codesandbox.io/>)
- [Code](<https://codesandbox.io/s/react-compare-slider-simple-example-9si6l>)
## Usage

@@ -41,17 +51,22 @@

### Use it!
### Basic Image Usage
You *may* use `ReactCompareSliderImage` to render images or use your own custom
components.
```jsx
import { ReactCompareSlider } from 'react-compare-slider';
import { ReactCompareSlider, ReactCompareSliderImage } from 'react-compare-slider';
<ReactCompareSlider
itemOne={<img src="..." alt="Image one" />}
itemTwo={<img src="..." alt="Image two" />}
itemOne={<ReactCompareSliderImage src="..." srcSet="..." alt="Image one" />}
itemTwo={<ReactCompareSliderImage src="..." srcSet="..." alt="Image two" />}
/>
```
## Props & docs
### Advanced Usage
### Props
See the [docs](https://festive-darwin-fab443.netlify.com/?path=/docs/docs-intro--page) for advanced examples.
## Props
| Prop | Type | Required | Default value | Description |

@@ -62,11 +77,15 @@ |------|------|:--------:|---------------|-------------|

| `itemTwo` | `ReactNode` | ✓ | `undefined` | Second component to show in slider |
| `onChange` | `function` | | `undefined` | Callback on position change, returns current position as argument `(position) => { ... }` |
| `onPositionChange` | `function` | | `undefined` | Callback on position change, returns current position as argument `(position) => { ... }` |
| `position` | `number` | | `50` | Initial percentage position of divide (`0-100`) |
| `portrait` | `boolean` | | `undefined` | Whether to use portrait orientation |
See the [API docs](https://festive-darwin-fab443.netlify.com/?path=/docs/docs-api--page) for detailed information.
## Extending
### `ReactCompareSliderImage`
`ReactCompareSliderImage` is a standalone image component that detects whether the browser supports the `object-fit` CSS property, if not it will apply a background image to achieve the same effect. It calls `styleFitContainer` internally and will set `background-size`, `background-position` and `background-image` if they have not already been defined in a passed `style` prop.
`ReactCompareSliderImage` is a standalone image component that detects whether the browser supports the `object-fit` CSS property, if not it will apply a background image to achieve the same effect. It will set `background-size`, `background-position` and `background-image` if they have not already been defined in a passed `style` prop.
#### Props
#### `ReactCompareSliderImage` Props

@@ -93,13 +112,2 @@ `ReactCompareSliderImage` supports all attributes assignable to an `img` component, in addition to the following:

Within slider:
```jsx
import { ReactCompareSlider, ReactCompareSliderImage } from 'react-compare-slider';
<ReactCompareSlider
itemOne={<ReactCompareSliderImage src="..." alt="Image one" />}
itemTwo={<ReactCompareSliderImage src="..." alt="Image two" />}
/>
```
### `styleFitContainer`

@@ -117,4 +125,2 @@

// ...
<div style={{ width: '100vw', height: '100vh' }}>

@@ -128,3 +134,2 @@ <video

}}
// ...
/>

@@ -134,4 +139,8 @@ </div>

## Requirements
- React 16.8+
## Notes
Bootstrapped with [TSDX](<https://github.com/palmerhq/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