@onesy/ui-react
Version:
UI for React
1,016 lines (1,004 loc) • 43.8 kB
JavaScript
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
const _excluded = ["ref", "tonal", "color", "version", "valueDefault", "value", "onChange", "id", "items", "orientation", "itemSize", "gap", "move", "moveValue", "moveItems", "moveBeyondEdge", "free", "swipe", "background", "index", "autoPlay", "autoHeight", "autoHeightDelay", "autoPlayInterval", "pauseOnHover", "round", "arrows", "mouseScroll", "momentum", "previousSub", "nextSub", "updateSub", "arrowsVisibility", "arrowHideOnStartEnd", "renderProgress", "renderArrowPrevious", "renderArrowNext", "progress", "progressVisibility", "start", "end", "noTransition", "onUpdatePosition", "onInit", "onUpdateItems", "onBlur", "onFocus", "onMouseEnter", "onMouseLeave", "TransitionComponent", "ProgressTransitionComponent", "ArrowTransitionComponent", "ArrowPreviousTransitionComponent", "ArrowNextTransitionComponent", "IconButtonPrevious", "IconButtonNext", "IconPrevious", "IconNext", "ArrowProps", "ArrowPreviousProps", "ArrowNextProps", "CarouselProps", "TransitionsProps", "TransitionComponentProps", "ArrowTransitionComponentProps", "ArrowPreviousTransitionComponentProps", "ArrowNextTransitionComponentProps", "ProgressTransitionComponentProps", "ItemWrapperProps", "Component", "className", "children"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import React from 'react';
import { is, unique, clamp, debounce, equalDeep, isEnvironment } from '@onesy/utils';
import { classNames, style as styleMethod, useOnesyTheme } from '@onesy/style-react';
import IconMaterialNavigateBefore from '@onesy/icons-material-rounded-react/IconMaterialNavigateBeforeW100';
import IconMaterialNavigateNext from '@onesy/icons-material-rounded-react/IconMaterialNavigateNextW100';
import LineElement from '../Line';
import FadeElement from '../Fade';
import IconButtonElement from '../IconButton';
import TransitionsElement from '../Transitions';
import SurfaceElement from '../Surface';
import useMediaQuery from '../useMediaQuery';
import { valueBreakpoints, staticClassName } from '../utils';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const useStyle = styleMethod(theme => ({
root: {
position: 'relative',
width: '100%',
height: '540px',
overflow: 'hidden'
},
autoHeight: {
transition: theme.methods.transitions.make('height')
},
item: {
width: '100%',
height: '100%',
flex: '0 0 auto',
'& img': {
width: 'auto',
maxHeight: '100%'
}
},
item_transition: {
position: 'absolute',
width: '100%',
height: '100%',
'& img': {
width: 'auto',
maxHeight: '100%'
}
},
item_version_regular_autoHeight: {
width: '100%',
height: 'unset'
},
item_version_transition_autoHeight: {
width: '100%',
height: 'unset'
},
item_itemSize_auto: {
width: 'auto',
height: 'auto'
},
background: {
width: '100%',
height: '100%',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center',
backgroundSize: 'cover'
},
carousel: {
position: 'relative',
width: '100%',
height: '100%',
touchAction: 'none'
},
carousel_version_regular: {
transition: theme.methods.transitions.make('transform')
},
progress: {
position: 'absolute'
},
progress_orientation_horizontal: {
width: '100%',
left: '50%',
transform: 'translateX(-50%)',
bottom: '24px'
},
progress_orientation_vertical: {
height: '100%',
top: '50%',
transform: 'translateY(-50%)',
right: '24px'
},
progress_item: {
width: '5px',
height: '5px',
backgroundColor: 'currentColor',
borderRadius: theme.methods.shape.radius.value(40, 'px'),
cursor: 'pointer',
transition: theme.methods.transitions.make('transform'),
'&:hover': {
transform: 'scale(1.4)'
}
},
progress_item_active: {
transform: 'scale(1.7)'
},
arrow: {
position: 'absolute !important'
},
arrow_previous: {},
arrow_previous_orientation_horizontal: {
top: '50%',
transform: 'translateY(-50%)',
left: '24px'
},
arrow_previous_orientation_vertical: {
left: '50%',
transform: 'translateX(-50%)',
top: '24px'
},
arrow_next: {},
arrow_next_orientation_horizontal: {
top: '50%',
transform: 'translateY(-50%)',
right: '24px'
},
arrow_next_orientation_vertical: {
left: '50%',
transform: 'translateX(-50%)',
bottom: '24px'
},
icon_previous_orientation_vertical: {
transform: 'rotate(90deg)'
},
icon_next_orientation_vertical: {
transform: 'rotate(90deg)'
}
}), {
name: 'onesy-Carousel'
});
const Carousel = props_ => {
const theme = useOnesyTheme();
const props = _objectSpread(_objectSpread(_objectSpread({}, theme?.ui?.elements?.all?.props?.default), theme?.ui?.elements?.onesyCarousel?.props?.default), props_);
const Line = theme?.elements?.Line || LineElement;
const IconButton = theme?.elements?.IconButton || IconButtonElement;
const Fade = theme?.elements?.Fade || FadeElement;
const Surface = theme?.elements?.Surface || SurfaceElement;
const Transitions = theme?.elements?.Transitions || TransitionsElement;
const {
ref,
tonal = true,
color = 'default',
version: version_,
valueDefault,
value: value_,
onChange,
// id if it updates
// update items
id,
// Array of string or object
// object having element as a string or element
// and a transition element
items: items_,
orientation: orientation_,
itemSize: itemSize_,
gap: gap_,
move: move_,
moveValue: moveValue_,
moveItems: moveItems_,
moveBeyondEdge: moveBeyondEdge_,
free: free_,
swipe: swipe_,
background: background_,
index: index_,
autoPlay: autoPlay_,
autoHeight: autoHeight_,
autoHeightDelay = theme.transitions.duration.rg + 14,
autoPlayInterval = 4000,
pauseOnHover = true,
round: round_,
arrows: arrows_,
mouseScroll,
momentum: momentum_,
// OnesySubscription methods
previousSub,
nextSub,
updateSub,
// on mobile visible
arrowsVisibility: arrowsVisibility_,
arrowHideOnStartEnd: arrowHideOnStartEnd_,
renderProgress,
renderArrowPrevious,
renderArrowNext,
progress: progress_,
// on mobile visible
progressVisibility: progressVisibility_,
start: start_,
end: end_,
noTransition: noTransition_,
onUpdatePosition: onUpdatePosition_,
onInit,
onUpdateItems,
onBlur: onBlur_,
onFocus: onFocus_,
onMouseEnter: onMouseEnter_,
onMouseLeave: onMouseLeave_,
TransitionComponent: TransitionComponent_ = Fade,
ProgressTransitionComponent = Fade,
ArrowTransitionComponent = Fade,
ArrowPreviousTransitionComponent,
ArrowNextTransitionComponent,
IconButtonPrevious,
IconButtonNext,
IconPrevious = IconMaterialNavigateBefore,
IconNext = IconMaterialNavigateNext,
ArrowProps,
ArrowPreviousProps: ArrowPreviousProps_,
ArrowNextProps: ArrowNextProps_,
CarouselProps,
TransitionsProps,
TransitionComponentProps,
ArrowTransitionComponentProps,
ArrowPreviousTransitionComponentProps,
ArrowNextTransitionComponentProps,
ProgressTransitionComponentProps,
ItemWrapperProps,
Component = 'div',
className,
children
} = props,
other = _objectWithoutProperties(props, _excluded);
const {
classes
} = useStyle();
const refs = {
root: React.useRef(undefined),
item: React.useRef(undefined),
items: React.useRef(undefined),
value: React.useRef(undefined),
autoPlayTimeout: React.useRef(undefined),
autoPlay: React.useRef(undefined),
carousel: React.useRef(undefined),
mouseDown: React.useRef(undefined),
focus: React.useRef(undefined),
gap: React.useRef(undefined),
previousMouseEvent: React.useRef(undefined),
move: React.useRef(undefined),
moveValue: React.useRef(undefined),
moveItems: React.useRef(undefined),
moveBeyondEdge: React.useRef(undefined),
free: React.useRef(undefined),
swipe: React.useRef(undefined),
mouseDownPosition: React.useRef(undefined),
mouseDownStart: React.useRef(undefined),
mouseDownDuration: React.useRef(undefined),
orientation: React.useRef(undefined),
version: React.useRef(undefined),
itemSize: React.useRef(undefined),
itemsLength: React.useRef(undefined),
momentum: React.useRef(undefined),
round: React.useRef(undefined),
velocity: React.useRef(undefined),
momentumID: React.useRef(undefined),
width: React.useRef(undefined),
onInit: React.useRef(undefined),
ids: {
items: React.useId()
}
};
const keys = React.useMemo(() => {
const result = [];
const properties = [version_, orientation_, itemSize_, gap_, move_, moveValue_, moveItems_, moveBeyondEdge_, swipe_, background_, autoPlay_, autoHeight_, round_, arrows_, arrowsVisibility_, arrowHideOnStartEnd_, progress_, progressVisibility_, noTransition_];
properties.forEach(item => {
if (is('object', item)) Object.keys(item).filter(key => theme.breakpoints.media[key]).forEach(key_0 => result.push(key_0));
});
return unique(result);
}, [version_, orientation_, itemSize_, gap_, move_, moveValue_, moveItems_, moveBeyondEdge_, swipe_, background_, autoPlay_, autoHeight_, round_, arrows_, arrowsVisibility_, arrowHideOnStartEnd_, progress_, progressVisibility_, noTransition_]);
const breakpoints = {};
keys.forEach(key_1 => {
breakpoints[key_1] = useMediaQuery(theme.breakpoints.media[key_1], {
element: refs.root.current
});
});
const version = valueBreakpoints(version_, 'regular', breakpoints, theme);
const orientation = valueBreakpoints(orientation_, 'horizontal', breakpoints, theme);
const itemSize = valueBreakpoints(itemSize_, undefined, breakpoints, theme);
const gap = valueBreakpoints(gap_, 4, breakpoints, theme);
const move = valueBreakpoints(move_, true, breakpoints, theme);
const moveValue = valueBreakpoints(moveValue_, undefined, breakpoints, theme);
const moveItems = valueBreakpoints(moveItems_, undefined, breakpoints, theme);
const moveBeyondEdge = valueBreakpoints(moveBeyondEdge_, true, breakpoints, theme);
const swipe = valueBreakpoints(swipe_, true, breakpoints, theme);
const background = valueBreakpoints(background_, true, breakpoints, theme);
const autoPlay = valueBreakpoints(autoPlay_, undefined, breakpoints, theme);
const autoHeight = valueBreakpoints(autoHeight_, undefined, breakpoints, theme);
const round = valueBreakpoints(round_, true, breakpoints, theme);
const arrows = valueBreakpoints(arrows_, true, breakpoints, theme);
const arrowsVisibility = valueBreakpoints(arrowsVisibility_, 'hover', breakpoints, theme);
const arrowHideOnStartEnd = valueBreakpoints(arrowHideOnStartEnd_, undefined, breakpoints, theme);
const progress = valueBreakpoints(progress_, true, breakpoints, theme);
const progressVisibility = valueBreakpoints(progressVisibility_, 'hover', breakpoints, theme);
const noTransition = valueBreakpoints(noTransition_, undefined, breakpoints, theme);
let free = valueBreakpoints(free_, undefined, breakpoints, theme);
let momentum = valueBreakpoints(momentum_, undefined, breakpoints, theme);
if (momentum && version !== 'regular') momentum = false;
if (momentum) free = true;
if (free && momentum === undefined) momentum = true;
const [init, setInit] = React.useState();
const [items, setItems] = React.useState(items_ || []);
const [value, setValue] = React.useState(valueDefault !== undefined ? valueDefault : value_);
const [hover, setHover] = React.useState();
const [mouseDown, setMouseDown] = React.useState();
const [focus, setFocus] = React.useState();
const styles = {
carousel: {}
};
refs.items.current = items;
refs.value.current = value;
refs.gap.current = gap;
refs.mouseDown.current = mouseDown;
refs.focus.current = focus;
refs.move.current = move;
refs.moveValue.current = moveValue;
refs.moveItems.current = moveItems;
refs.moveBeyondEdge.current = moveBeyondEdge;
refs.free.current = free;
refs.swipe.current = swipe;
refs.orientation.current = orientation;
refs.version.current = version;
refs.itemSize.current = itemSize;
refs.momentum.current = momentum;
refs.round.current = round;
refs.onInit.current = onInit;
const {
scrollWidth,
scrollHeight
} = refs.carousel.current || {};
const {
width,
height
} = refs.carousel.current?.getBoundingClientRect() || {};
refs.width.current = width;
refs.itemsLength.current = items.length;
if (itemSize === 'auto') {
if (moveValue) refs.itemsLength.current = orientation === 'horizontal' ? Math.ceil(scrollWidth / moveValue) : Math.ceil(scrollHeight / moveValue);
if (moveItems) refs.itemsLength.current = Math.ceil(items.length / clamp(moveItems, 1, items.length));
}
const updateValue = valueNew => {
setValue(valueNew);
if (is('function', onChange)) onChange(valueNew);
};
const momentumClear = () => {
cancelAnimationFrame(refs.momentumID.current);
};
const momentumMethod = () => {
const valueNew_0 = refs.orientation.current === 'horizontal' ? (refs.value.current?.x || 0) + refs.velocity.current : (refs.value.current?.y || 0) + refs.velocity.current;
const {
width: width_,
height: height_
} = refs.carousel.current.getBoundingClientRect();
const {
scrollWidth: scrollWidth_,
scrollHeight: scrollHeight_
} = refs.carousel.current;
if (refs.orientation.current === 'horizontal') {
const min = 0;
let max = (width_ + gap * theme.space.unit) * (refs.itemsLength.current - 1);
if (refs.itemSize.current === 'auto') {
max = scrollWidth_ - scrollWidth_ / refs.itemsLength.current + gap * theme.space.unit * (refs.itemsLength.current - 1);
}
refs.value.current = _objectSpread(_objectSpread({}, refs.value.current), {}, {
index: Math.floor(valueNew_0 / (max / (refs.itemsLength.current - 1))),
x: valueNew_0
});
if (valueNew_0 <= min || valueNew_0 >= max) {
// Done
return refs.carousel.current?.style.removeProperty('transition');
} else {
refs.value.current = _objectSpread(_objectSpread({}, refs.value.current), {}, {
index: Math.floor(valueNew_0 / (max / (refs.itemsLength.current - 1))),
x: valueNew_0
});
onUpdatePosition(refs.value.current);
}
}
if (refs.orientation.current === 'vertical') {
const min_0 = 0;
let max_0 = (height_ + gap * theme.space.unit) * (refs.itemsLength.current - 1);
if (refs.itemSize.current === 'auto') {
max_0 = scrollHeight_ - scrollHeight_ / refs.itemsLength.current + gap * theme.space.unit * (refs.itemsLength.current - 1);
}
if (valueNew_0 <= min_0 || valueNew_0 >= max_0) {
// Done
return refs.carousel.current?.style.removeProperty('transition');
} else {
refs.value.current = _objectSpread(_objectSpread({}, refs.value.current), {}, {
index: Math.floor(valueNew_0 / (max_0 / (refs.itemsLength.current - 1))),
y: valueNew_0
});
onUpdatePosition(refs.value.current);
}
}
refs.velocity.current *= 0.95;
if (Math.abs(refs.velocity.current) > 0.5) refs.momentumID.current = requestAnimationFrame(momentumMethod);else {
// Done
refs.carousel.current?.style.removeProperty('transition');
}
};
const momentumStart = () => {
refs.momentumID.current = requestAnimationFrame(momentumMethod);
};
const onUpdatePosition = valuePosition_ => {
// Momentum
momentumClear();
const valueNew_1 = _objectSpread(_objectSpread({}, valuePosition_), {}, {
additional: 0
});
if (valuePosition_.additional === undefined && refs.version.current === 'regular' && refs.itemSize.current !== 'auto') {
const max_1 = refs.width.current / 2;
const valuePosition = valueNew_1[refs.orientation.current === 'horizontal' ? 'x' : 'y'];
const part = valuePosition - (refs.mouseDownPosition.current?.[refs.orientation.current === 'horizontal' ? 'x' : 'y'] || 0);
const additional = part / max_1 * 100;
valueNew_1.additional = additional;
}
updateValue(valueNew_1);
if (is('function', onUpdatePosition_)) onUpdatePosition_(valueNew_1);
};
const onUpdate = (to = 'next', values = refs.items.current) => {
// Momentum
momentumClear();
// Momentum clean up
refs.carousel.current?.style.removeProperty('transition');
let index = refs.value.current?.index;
if (index === undefined) index = 0;else if (is('number', to)) index = clamp(to, 0, refs.itemsLength.current - 1);else {
index = to === 'next' ? index + 1 : index - 1;
if (index < 0) index = refs.round.current ? refs.itemsLength.current - 1 : 0;
if (index > refs.itemsLength.current - 1) index = refs.round.current ? 0 : refs.itemsLength.current - 1;
}
// Regular
if (version === 'regular' && refs.carousel.current) {
if (refs.orientation.current === 'horizontal') {
if (refs.itemSize.current === 'auto' && refs.moveValue.current !== undefined) {
const x = index * refs.moveValue.current;
onUpdatePosition({
index,
x,
additional: 0
});
} else if (refs.itemSize.current === 'auto' && refs.moveItems.current !== undefined) {
let item_0 = index * clamp(moveItems, 1, refs.items.current.length);
item_0 = refs.carousel.current.children[item_0];
if (item_0) {
const x_0 = item_0.offsetLeft;
onUpdatePosition({
index,
x: x_0,
additional: 0
});
}
} else {
const width__0 = refs.carousel.current.getBoundingClientRect().width;
const scrollWidth__0 = refs.carousel.current.scrollWidth;
const part_0 = refs.itemSize.current === 'auto' ? scrollWidth__0 / refs.itemsLength.current : width__0;
const x_1 = index * part_0 + index * (gap * theme.space.unit);
onUpdatePosition({
index,
x: x_1,
additional: 0
});
}
}
if (refs.orientation.current === 'vertical') {
if (refs.itemSize.current === 'auto' && refs.moveValue.current !== undefined) {
const y = index * refs.moveValue.current;
onUpdatePosition({
index,
y,
additional: 0
});
} else if (refs.itemSize.current === 'auto' && refs.moveItems.current !== undefined) {
let item_1 = index * clamp(moveItems, 1, refs.items.current.length);
item_1 = refs.carousel.current.children[item_1];
if (item_1) {
const y_0 = item_1.offsetTop;
onUpdatePosition({
index,
y: y_0,
additional: 0
});
}
} else {
const height__0 = refs.carousel.current.getBoundingClientRect().height;
const scrollHeight__0 = refs.carousel.current.scrollHeight;
const part_1 = refs.itemSize.current === 'auto' ? scrollHeight__0 / refs.itemsLength.current : height__0;
const y_1 = index * part_1 + index * (gap * theme.space.unit);
onUpdatePosition({
index,
y: y_1,
additional: 0
});
}
}
}
// Transition
const itemNew = values[index];
if (itemNew) {
if (version === 'transition') updateValue({
index,
element: itemNew
});
if (autoHeight) {
if (version === 'regular') {
setTimeout(() => {
const height__1 = refs.carousel.current.children[refs.value.current?.index]?.children[0]?.getBoundingClientRect().height;
if (height__1 > 0) refs.root.current.style.height = `${height__1}px`;
}, 1);
}
if (version === 'transition') {
setTimeout(() => {
const height__2 = refs.carousel.current.children[0]?.children[0]?.getBoundingClientRect().height;
if (height__2 > 0) refs.root.current.style.height = `${height__2}px`;
}, autoHeightDelay);
}
}
}
};
const onMouseUp = event => {
if (refs.mouseDown.current) {
if (refs.mouseDown.current && !refs.momentum.current) refs.carousel.current?.style.removeProperty('transition');
refs.mouseDownDuration.current = new Date().getTime() - refs.mouseDownStart.current;
if (refs.free.current) {
setMouseDown(false);
if (refs.momentum.current) momentumStart();
refs.previousMouseEvent.current = undefined;
return;
}
// Swipe
// less than 140 ms
if (refs.swipe.current && refs.mouseDownDuration.current <= 140) {
const {
clientX: previousClientX,
clientY: previousClientY
} = refs.mouseDown.current.touches?.[0] || refs.mouseDown.current;
const {
clientX,
clientY
} = refs.previousMouseEvent.current || event;
refs.previousMouseEvent.current = undefined;
setMouseDown(false);
if (refs.orientation.current === 'horizontal') {
// As move already updates the index
// so move to that index
if (previousClientX < clientX) return onUpdate(refs.value.current?.index);
if (previousClientX > clientX) return onUpdate('next');
}
if (refs.orientation.current === 'vertical') {
if (previousClientY < clientY) return onUpdate(refs.value.current?.index);
if (previousClientY > clientY) return onUpdate('next');
}
}
// Move
if (refs.version.current === 'regular' && refs.value.current) {
if (refs.orientation.current === 'horizontal') {
const {
x: x_2
} = refs.value.current;
let index_0 = refs.value.current.index;
if (refs.mouseDownPosition.current?.x > x_2) index_0++;
const width__1 = refs.carousel.current.getBoundingClientRect().width;
const original = index_0 * width__1 + index_0 * (gap * theme.space.unit);
const threshold = width__1 / 4;
const moved = Math.abs(original - x_2);
if (x_2 > 0 && x_2 < original && moved >= threshold) onUpdate(index_0 - 1);else if (x_2 > original && moved >= threshold) onUpdate(index_0 + 1);else onUpdate(index_0);
}
if (refs.orientation.current === 'vertical') {
const {
y: y_2
} = refs.value.current;
let index_1 = refs.value.current.index;
if (refs.mouseDownPosition.current?.y > y_2) index_1++;
const height__3 = refs.carousel.current.getBoundingClientRect().height;
const original_0 = index_1 * height__3 + index_1 * (gap * theme.space.unit);
const threshold_0 = height__3 / 4;
const moved_0 = Math.abs(original_0 - y_2);
if (y_2 > 0 && y_2 < original_0 && moved_0 >= threshold_0) onUpdate(index_1 - 1);else if (y_2 > original_0 && moved_0 >= threshold_0) onUpdate(index_1 + 1);else onUpdate(index_1);
}
}
setMouseDown(false);
refs.previousMouseEvent.current = undefined;
}
};
React.useEffect(() => {
const onKeyDown = event_0 => {
if (refs.focus.current) {
switch (event_0.key) {
case 'ArrowLeft':
return onUpdate('previous');
case 'ArrowRight':
return onUpdate('next');
default:
break;
}
}
};
const onMove = (x_, y_) => {
if (refs.version.current === 'regular' && refs.move.current && refs.mouseDown.current && refs.previousMouseEvent.current) {
const incX = x_ - refs.previousMouseEvent.current.clientX;
const incY = y_ - refs.previousMouseEvent.current.clientY;
const {
width: width__2,
height: height__4
} = refs.carousel.current.getBoundingClientRect();
const {
scrollWidth: scrollWidth__1,
scrollHeight: scrollHeight__1
} = refs.carousel.current;
if (refs.orientation.current === 'horizontal' && incX !== 0) {
const min_1 = 0;
let max_2 = (width__2 + gap * theme.space.unit) * (refs.itemsLength.current - 1);
if (refs.itemSize.current === 'auto') {
max_2 = scrollWidth__1 - scrollWidth__1 / refs.itemsLength.current + gap * theme.space.unit * (refs.itemsLength.current - 1);
}
let x_3 = (refs.value.current?.x || 0) - incX;
if (refs.free.current || !refs.moveBeyondEdge.current) x_3 = clamp(x_3, min_1, max_2);
// Move beyond min, max
if (x_3 < min_1 || x_3 > max_2) x_3 = (refs.value.current?.x || 0) - incX / 1.7;
refs.velocity.current = x_3 - (refs.value.current?.x || 0);
onUpdatePosition({
index: Math.floor(x_3 / (max_2 / (refs.itemsLength.current - 1))),
x: x_3
});
}
if (refs.orientation.current === 'vertical' && incY !== 0) {
const min_2 = 0;
let max_3 = (height__4 + gap * theme.space.unit) * (refs.itemsLength.current - 1);
if (refs.itemSize.current === 'auto') {
max_3 = scrollHeight__1 - scrollHeight__1 / refs.itemsLength.current + gap * theme.space.unit * (refs.itemsLength.current - 1);
}
let y_3 = (refs.value.current?.y || 0) - incY;
if (refs.free.current || !refs.moveBeyondEdge.current) y_3 = clamp(y_3, min_2, max_3);
// Move beyond min, max
if (y_3 < min_2 || y_3 > max_3) y_3 = (refs.value.current?.y || 0) - incY / 1.7;
refs.velocity.current = y_3 - (refs.value.current?.y || 0);
onUpdatePosition({
index: Math.floor(y_3 / (max_3 / (refs.itemsLength.current - 1))),
y: y_3
});
}
}
};
// Mouse move
const onMouseMove = event_1 => {
if (refs.mouseDown.current) {
const {
clientY: clientY_0,
clientX: clientX_0
} = event_1;
onMove(clientX_0, clientY_0);
refs.previousMouseEvent.current = event_1;
}
};
// Touch move
const onTouchMove = event_2 => {
if (refs.mouseDown.current) {
const {
clientY: clientY_1,
clientX: clientX_1
} = event_2.touches[0];
onMove(clientX_1, clientY_1);
refs.previousMouseEvent.current = event_2;
// Normalize for use as a mouseDown value
refs.previousMouseEvent.current.clientY = clientY_1;
refs.previousMouseEvent.current.clientX = clientX_1;
}
};
const method = () => onUpdate(refs.value.current?.index);
const observer = new ResizeObserver(method);
method();
observer.observe(refs.root.current);
const rootDocument = isEnvironment('browser') ? refs.root.current?.ownerDocument || window.document : undefined;
rootDocument.addEventListener('keydown', onKeyDown);
rootDocument.addEventListener('mouseup', onMouseUp);
rootDocument.addEventListener('mousemove', onMouseMove);
rootDocument.addEventListener('touchend', onMouseUp);
rootDocument.addEventListener('touchmove', onTouchMove, {
passive: true
});
setInit(true);
if (is('function', refs.onInit.current)) refs.onInit.current();
return () => {
observer.disconnect();
rootDocument.removeEventListener('keydown', onKeyDown);
rootDocument.removeEventListener('mousemove', onMouseMove);
rootDocument.removeEventListener('mouseup', onMouseUp);
rootDocument.removeEventListener('touchmove', onTouchMove);
rootDocument.removeEventListener('touchend', onMouseUp);
};
}, []);
React.useEffect(() => {
if (value_ !== undefined && !equalDeep(value_, refs.value.current)) setValue(valuePrevious => _objectSpread(_objectSpread({}, valuePrevious), value_));
}, [value_]);
React.useEffect(() => {
if (init) {
if (index_ >= 0 && index_ <= refs.itemsLength.current && index_ !== refs.value.current?.index) onUpdate(index_);
}
}, [index_]);
React.useEffect(() => {
if (is('function', onUpdateItems)) onUpdateItems();
}, [items, theme.palette.light]);
React.useEffect(() => {
setItems(items_);
}, [id, items_]);
const onPrevious = () => onUpdate('previous');
const onNext = () => onUpdate('next');
const clear = () => {
clearTimeout(refs.autoPlayTimeout.current);
refs.autoPlay.current = false;
};
const start = () => {
clear();
if (!autoPlay || mouseDown || focus) return;
if (pauseOnHover && hover) return;
refs.autoPlayTimeout.current = setTimeout(onUpdate, autoPlayInterval);
refs.autoPlay.current = true;
};
// autoPlay
React.useEffect(() => {
start();
}, [items, value, autoPlay, autoPlayInterval]);
// OnesySubscription methods
React.useEffect(() => {
const method_0 = (...args) => onUpdate(...args);
if (is('function', updateSub?.subscribe)) updateSub?.subscribe(method_0);
return () => {
if (is('function', updateSub?.unsubscribe)) updateSub?.unsubscribe(method_0);
};
}, [updateSub]);
React.useEffect(() => {
const method_1 = (...args_0) => onUpdate(...args_0);
if (is('function', previousSub?.subscribe)) previousSub?.subscribe(method_1);
return () => {
if (is('function', previousSub?.unsubscribe)) previousSub?.unsubscribe(method_1);
};
}, [previousSub]);
React.useEffect(() => {
const method_2 = (...args_1) => onUpdate(...args_1);
if (is('function', nextSub?.subscribe)) nextSub?.subscribe(method_2);
return () => {
if (is('function', nextSub?.unsubscribe)) nextSub?.unsubscribe(method_2);
};
}, [nextSub]);
React.useEffect(() => {
const values_0 = unique([...items_, ...React.Children.toArray(children)]).filter(Boolean);
const previous = refs.items.current.reduce((result_0, item_2) => result_0 += is('string', item_2) ? item_2 : item_2?.key, '');
const updated = values_0.reduce((result_1, item_3) => result_1 += is('string', item_3) ? item_3 : item_3?.key, '');
if (updated !== previous) {
onUpdate('next', values_0);
setItems(values_0);
}
}, [items_, background, children]);
const onWheel = debounce(event_3 => {
if (refs.orientation.current === 'horizontal' && event_3.deltaX < 0 || refs.orientation.current === 'vertical' && event_3.deltaY < 0) {
event_3.preventDefault();
event_3.stopPropagation();
return onUpdate('previous');
}
if (refs.orientation.current === 'horizontal' && event_3.deltaX > 0 || refs.orientation.current === 'vertical' && event_3.deltaY > 0) {
event_3.preventDefault();
event_3.stopPropagation();
return onUpdate('next');
}
}, 40);
const onBlur = event_4 => {
setFocus(false);
if (is('function', onBlur_)) onBlur_(event_4);
};
const onFocus = event_5 => {
setFocus(true);
if (is('function', onFocus_)) onFocus_(event_5);
};
const onMouseDown = event_6 => {
// Momentum
momentumClear();
setMouseDown(event_6);
refs.mouseDownPosition.current = _objectSpread({}, refs.value.current);
refs.mouseDownStart.current = new Date().getTime();
refs.carousel.current.style.transition = 'none';
};
const onMouseEnter = event_7 => {
setHover(true);
if (refs.autoPlay.current) clear();
if (is('function', onMouseEnter_)) onMouseEnter_(event_7);
};
const onMouseLeave = event_8 => {
setFocus(false);
setHover(false);
if (!refs.autoPlay.current) start();
if (is('function', onMouseLeave_)) onMouseLeave_(event_8);
};
const onArrowMouseEnter = event_9 => {
setHover(true);
if (refs.autoPlay.current) clear();
};
const ArrowPreviousTransitionComponent_ = ArrowPreviousTransitionComponent || ArrowTransitionComponent;
const ArrowNextTransitionComponent_ = ArrowNextTransitionComponent || ArrowTransitionComponent;
let TransitionComponent = TransitionComponent_;
if (noTransition) TransitionComponent = React.Fragment;
if (version === 'regular') {
styles.carousel.transform = `translate3d(${orientation === 'horizontal' ? `${-(value?.x || 0)}px, 0` : `0, ${-(value?.y || 0)}px`}, 0)`;
}
const indexActive = value?.index;
let arrowPreviousIn = focus || arrowsVisibility === 'hover' && hover || arrowsVisibility === 'visible';
let arrowNextIn = focus || arrowsVisibility === 'hover' && hover || arrowsVisibility === 'visible';
if (arrowHideOnStartEnd) {
const min_3 = 0;
let maxX = (width + gap * theme.space.unit) * (refs.itemsLength.current - 1);
let maxY = (height + gap * theme.space.unit) * (refs.itemsLength.current - 1);
if (refs.itemSize.current === 'auto') {
maxX = scrollWidth - scrollWidth / refs.itemsLength.current + gap * theme.space.unit * (refs.itemsLength.current - 1);
maxY = scrollHeight - scrollHeight / refs.itemsLength.current + gap * theme.space.unit * (refs.itemsLength.current - 1);
}
if (value?.x === min_3 || value?.y === min_3) arrowPreviousIn = false;
if (itemSize === 'auto') {
if (value?.x !== undefined && value?.x + 1 >= maxX || value?.y !== undefined && value?.y + 1 >= maxY) arrowNextIn = false;
} else {
if (value?.x !== undefined && value?.x + 1 >= maxX || value?.y + 1 !== undefined && value?.y >= maxY) arrowNextIn = false;
}
}
const ArrowPreviousProps = _objectSpread(_objectSpread({}, ArrowPreviousProps_), {}, {
'aria-label': 'Arrow previous',
'aria-controls': refs.ids.items
});
const ArrowNextProps = _objectSpread(_objectSpread({}, ArrowNextProps_), {}, {
'aria-label': 'Arrow next',
'aria-controls': refs.ids.items
});
const resolveItem = Item => {
if (!Item) return null;
if (is('string', Item)) {
if (background) return /*#__PURE__*/_jsx("div", {
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-background'], classes.background]),
style: {
backgroundImage: `url(${Item})`
}
});
return /*#__PURE__*/_jsx("img", {
src: Item,
alt: ""
});
}
if (is('function', Item)) return Item(refs.value.current);
if (Item?.element) return /*#__PURE__*/React.cloneElement(Item.element);
return /*#__PURE__*/React.cloneElement(Item);
};
return /*#__PURE__*/_jsxs(Surface, _objectSpread(_objectSpread({
ref: item_4 => {
if (ref) {
if (is('function', ref)) ref(item_4);else ref.current = item_4;
}
refs.root.current = item_4;
},
tabIndex: "0",
role: "region",
"aria-roledescription": "carousel",
tonal: tonal,
color: color,
onFocus: onFocus,
onBlur: onBlur,
onMouseEnter: onMouseEnter,
onMouseLeave: onMouseLeave,
Component: Component,
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-root'], className, classes.root, autoHeight && classes.autoHeight])
}, other), {}, {
children: [start_, version === 'regular' && /*#__PURE__*/_jsx(Line, _objectSpread(_objectSpread({
ref: refs.carousel,
gap: gap,
direction: orientation === 'horizontal' ? theme.direction === 'ltr' ? 'row' : 'row-reverse' : 'column',
align: "center",
justify: "flex-start",
onWheel: mouseScroll && onWheel,
onMouseDown: onMouseDown,
onTouchStart: onMouseDown,
onMouseUp: onMouseUp,
onTouchEnd: onMouseUp,
id: refs.ids.items,
"aria-live": "polite"
}, CarouselProps), {}, {
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-carousel'], CarouselProps?.className, classes.carousel, classes[`carousel_version_${version}`]]),
style: _objectSpread(_objectSpread({}, styles.carousel), CarouselProps?.style),
children: items.map((item_5, index_2) => /*#__PURE__*/_jsx(Line, _objectSpread(_objectSpread({
gap: 0,
direction: "column",
align: "center",
justify: "center",
role: "group",
"aria-roledescription": "slide",
"aria-label": `${index_2 + 1} out of ${refs.itemsLength.current}`
}, ItemWrapperProps), {}, {
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-item'], ItemWrapperProps?.className, classes.item, autoHeight && classes[`item_version_${version}_autoHeight`], itemSize && classes[`item_itemSize_${itemSize}`]]),
children: resolveItem(item_5)
}), index_2))
})), version === 'transition' && /*#__PURE__*/_jsx(Line, _objectSpread(_objectSpread({
ref: refs.carousel,
gap: 0.5,
direction: orientation === 'horizontal' ? theme.direction === 'ltr' ? 'row' : 'row-reverse' : 'column',
align: "center",
justify: "center",
onWheel: mouseScroll && onWheel,
onMouseDown: onMouseDown,
onTouchStart: onMouseDown,
onMouseUp: onMouseUp,
onTouchEnd: onMouseUp,
id: refs.ids.items,
"aria-live": "polite"
}, CarouselProps), {}, {
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-carousel'], CarouselProps?.className, classes.carousel]),
children: value && /*#__PURE__*/_jsx(Transitions, _objectSpread(_objectSpread({
mode: "in-out-follow",
switch: true
}, TransitionsProps), {}, {
children: /*#__PURE__*/_jsx(TransitionComponent, _objectSpread(_objectSpread({}, TransitionComponentProps), {}, {
children: /*#__PURE__*/_jsx(Line, {
ref: refs.item,
gap: 0,
direction: "column",
align: "center",
justify: "center",
role: "group",
"aria-roledescription": "slide",
"aria-label": `${value.index + 1} out of ${refs.itemsLength.current}`,
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-item-transition'], classes.item_transition, autoHeight && classes[`item_version_${version}_autoHeight`]]),
children: resolveItem(value.element)
})
}), indexActive)
}))
})), progress && /*#__PURE__*/_jsx(ProgressTransitionComponent, _objectSpread(_objectSpread({
in: focus || progressVisibility === 'hover' && hover || progressVisibility === 'visible'
}, ProgressTransitionComponentProps), {}, {
children: is('function', renderProgress) ? renderProgress(onUpdate) : /*#__PURE__*/_jsx(Line, {
gap: 1,
direction: orientation === 'horizontal' ? theme.direction === 'ltr' ? 'row' : 'row-reverse' : 'column',
align: "center",
justify: "center",
wrap: "wrap",
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-progress'], classes.progress, classes[`progress_orientation_${orientation}`]]),
children: Array.from({
length: refs.itemsLength.current
}).map((item_6, index_3) => /*#__PURE__*/_jsx("span", {
onClick: () => onUpdate(index_3),
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-progress-item', indexActive === index_3 && 'onesy-Carousel-progress-item-active'], classes.progress_item, indexActive === index_3 && classes.progress_item_active])
}, index_3))
})
})), arrows && /*#__PURE__*/_jsx(ArrowPreviousTransitionComponent_, _objectSpread(_objectSpread(_objectSpread({
in: arrowPreviousIn
}, ArrowTransitionComponentProps), ArrowPreviousTransitionComponentProps), {}, {
children: is('function', renderArrowPrevious) ? renderArrowPrevious(() => onUpdate('previous')) : IconButtonPrevious ? /*#__PURE__*/React.cloneElement(IconButtonPrevious, _objectSpread(_objectSpread(_objectSpread({
tonal,
color,
onClick: onPrevious,
onMouseEnter: onArrowMouseEnter
}, ArrowProps), ArrowPreviousProps), {}, {
disabled: !round && indexActive === 0,
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-arrow', 'onesy-Carousel-arrow-previous'], ArrowProps?.className, ArrowPreviousProps?.className, classes.arrow, classes.arrow_previous, classes[`arrow_previous_orientation_${orientation}`]])
})) : /*#__PURE__*/_jsx(IconButton, _objectSpread(_objectSpread(_objectSpread({
tonal: tonal,
color: color,
version: "filled",
onClick: onPrevious,
onMouseEnter: onArrowMouseEnter
}, ArrowProps), ArrowPreviousProps), {}, {
disabled: !round && indexActive === 0,
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-arrow', 'onesy-Carousel-arrow-previous'], ArrowProps?.className, ArrowPreviousProps?.className, classes.arrow, classes.arrow_previous, classes[`arrow_previous_orientation_${orientation}`]]),
children: /*#__PURE__*/_jsx(IconPrevious, {
noRtl: true,
className: classNames([classes[`icon_previous_orientation_${orientation}`]])
})
}))
})), arrows && /*#__PURE__*/_jsx(ArrowNextTransitionComponent_, _objectSpread(_objectSpread(_objectSpread({
in: arrowNextIn
}, ArrowTransitionComponentProps), ArrowNextTransitionComponentProps), {}, {
children: is('function', renderArrowNext) ? renderArrowNext(() => onUpdate('next')) : IconButtonNext ? /*#__PURE__*/React.cloneElement(IconButtonNext, _objectSpread(_objectSpread(_objectSpread({
tonal,
color,
onClick: onNext,
onMouseEnter: onArrowMouseEnter
}, ArrowProps), ArrowNextProps), {}, {
disabled: !round && indexActive === items.length - 1,
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-arrow', 'onesy-Carousel-arrow-next'], ArrowProps?.className, ArrowNextProps?.className, classes.arrow, classes.arrow_next, classes[`arrow_next_orientation_${orientation}`]])
})) : /*#__PURE__*/_jsx(IconButton, _objectSpread(_objectSpread(_objectSpread({
tonal: tonal,
color: color,
version: "filled",
onClick: onNext,
onMouseEnter: onArrowMouseEnter
}, ArrowProps), ArrowNextProps), {}, {
disabled: !round && indexActive === items.length - 1,
className: classNames([staticClassName('Carousel', theme) && ['onesy-Carousel-arrow', 'onesy-Carousel-arrow-next'], ArrowProps?.className, ArrowNextProps?.className, classes.arrow, classes.arrow_next, classes[`arrow_next_orientation_${orientation}`]]),
children: /*#__PURE__*/_jsx(IconNext, {
noRtl: true,
className: classNames([classes[`icon_next_orientation_${orientation}`]])
})
}))
})), end_]
}));
};
Carousel.displayName = 'onesy-Carousel';
export default Carousel;