@amaui/ui-react
Version:
UI for React
484 lines (483 loc) • 25.9 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importDefault(require("react"));
const utils_1 = require("@amaui/utils");
const style_react_1 = require("@amaui/style-react");
const IconMaterialNavigateNextW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialNavigateNextW100"));
const IconMaterialNavigateBeforeW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialNavigateBeforeW100"));
const IconMaterialCloseW100_1 = __importDefault(require("@amaui/icons-material-rounded-react/IconMaterialCloseW100"));
const Image_1 = __importDefault(require("../Image"));
const Line_1 = __importDefault(require("../Line"));
const IconButton_1 = __importDefault(require("../IconButton"));
const Interaction_1 = __importDefault(require("../Interaction"));
const Backdrop_1 = __importDefault(require("../Backdrop"));
const utils_2 = require("../utils");
const useMediaQuery_1 = __importDefault(require("../useMediaQuery"));
const useStyle = (0, style_react_1.style)(theme => ({
root: {
position: 'relative',
'&.amaui-Backdrop-root': {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
userSelect: 'none',
zIndex: '14000'
},
'& .amaui-Backdrop-backdrop-root': {
width: '100%',
height: '100%',
pointerEvents: 'none'
}
},
version_regular: {
minHeight: 'clamp(240px, 100%, 100vh)'
},
pointerEventsAuto: {
pointerEvents: 'auto'
},
wrapper: {
height: '100%'
},
header: {
padding: theme.methods.space.value(3, 'px'),
zIndex: '1'
},
main: {
position: 'relative',
zIndex: '14'
},
main_version_modal: {
height: '0',
padding: theme.methods.space.value(5, 'px'),
'& .amaui-Image-root': {
maxHeight: '100%',
// pointerEvents: 'none'
}
},
main_version_regular_size_small: {
height: '340px'
},
main_version_regular_size_regular: {
height: '540px'
},
main_version_regular_size_large: {
height: '740px'
},
noOverflow: {
overflow: 'hidden'
},
footer: {
padding: `${theme.methods.space.value(3, 'px')} ${theme.methods.space.value(1.5, 'px')}`,
zIndex: '1'
},
imageWrapper: {
position: 'relative',
height: '0px',
pointerEvents: 'none',
// zIndex: 1,
transition: theme.methods.transitions.make(['transform'], { duration: 100, timing_function: 'ease' })
},
image: {
objectFit: 'contain',
width: 'auto',
height: 'auto',
maxHeight: '100%',
maxWidth: '100%'
},
itemsWrapper: {
position: 'relative',
pointerEvents: 'auto',
maxWidth: '100%',
userSelect: 'none'
},
items: {
maxWidth: '1024px',
overflow: 'auto hidden',
'&::-webkit-scrollbar': {
width: '16px',
height: '16px'
},
'&::-webkit-scrollbar-track, &::-webkit-scrollbar-corner': {
background: 'transparent'
},
'&::-webkit-scrollbar-thumb': {
borderRadius: theme.methods.shape.radius.value(1, 'px'),
border: '4px solid transparent',
backgroundClip: 'content-box',
backgroundColor: 'rgba(221, 221, 221, 0.4)',
'&:hover': {
backgroundColor: 'rgba(221, 221, 221, 0.7)'
}
}
},
item: {
width: '140px',
height: '140px',
position: 'relative',
backgroundSize: 'contain',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
flex: '0 0 auto',
border: '2px solid transparent',
cursor: 'pointer',
userSelect: 'none',
transition: theme.methods.transitions.make(['border', 'transform']),
'&:active': {
transform: 'scale(0.94)'
}
},
itemSelected: {
border: '2px solid !important',
borderColor: `${theme.methods.palette.color.value('secondary', 30)} !important`
},
arrow: {
flex: '0 0 auto',
alignSelf: 'center',
justifySelf: 'center',
transition: theme.methods.transitions.make(['opacity'], { duration: 'xxs' }),
'&[disabled]': {
opacity: '0'
}
}
}), { name: 'amaui-ImageGallery' });
const ImageGallery = react_1.default.forwardRef((props_, ref) => {
var _a, _b, _c, _d;
const theme = (0, style_react_1.useAmauiTheme)();
const props = react_1.default.useMemo(() => { var _a, _b, _c, _d, _e, _f, _g, _h; return (Object.assign(Object.assign(Object.assign({}, (_d = (_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _a === void 0 ? void 0 : _a.elements) === null || _b === void 0 ? void 0 : _b.all) === null || _c === void 0 ? void 0 : _c.props) === null || _d === void 0 ? void 0 : _d.default), (_h = (_g = (_f = (_e = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _e === void 0 ? void 0 : _e.elements) === null || _f === void 0 ? void 0 : _f.amauiImageGallery) === null || _g === void 0 ? void 0 : _g.props) === null || _h === void 0 ? void 0 : _h.default), props_)); }, [props_]);
const Line = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Line) || Line_1.default; }, [theme]);
const Image = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Image) || Image_1.default; }, [theme]);
const IconButton = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.IconButton) || IconButton_1.default; }, [theme]);
const Interaction = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Interaction) || Interaction_1.default; }, [theme]);
const Backdrop = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Backdrop) || Backdrop_1.default; }, [theme]);
const { version = 'modal', size = 'regular', open: open_, onClose: onClose_, value: value_, items, minZoom: minZoom_ = 1, maxZoom: maxZoom_ = 2, incrementZoom = 0.07, overflow = true, arrows = true, startMain, endMain, startImage, endImage, startThumbnails, endThumbnails, ImageProps, ImageWrapperProps, IconButtonProps, IconStart = IconMaterialNavigateBeforeW100_1.default, IconEnd = IconMaterialNavigateNextW100_1.default, IconClose = IconMaterialCloseW100_1.default, className } = props, other = __rest(props, ["version", "size", "open", "onClose", "value", "items", "minZoom", "maxZoom", "incrementZoom", "overflow", "arrows", "startMain", "endMain", "startImage", "endImage", "startThumbnails", "endThumbnails", "ImageProps", "ImageWrapperProps", "IconButtonProps", "IconStart", "IconEnd", "IconClose", "className"]);
const { classes } = useStyle();
const [loaded, setLoaded] = react_1.default.useState(false);
const [open, setOpen] = react_1.default.useState(false);
const [value, setValue] = react_1.default.useState(0);
const [moveValue, setMoveValue] = react_1.default.useState();
const [imageRef, setImageRef] = react_1.default.useState();
const [keyDown, setKeyDown] = react_1.default.useState();
const refs = {
root: react_1.default.useRef(undefined),
version: react_1.default.useRef(version),
more: react_1.default.useRef(undefined),
image: react_1.default.useRef(),
imageWrapper: react_1.default.useRef(undefined),
media: react_1.default.useRef(undefined),
zoom: react_1.default.useRef(undefined),
incrementZoom: react_1.default.useRef(undefined),
minZoom: react_1.default.useRef(undefined),
maxZoom: react_1.default.useRef(undefined),
mouseDown: react_1.default.useRef(undefined),
mouseMovePrevious: react_1.default.useRef(undefined),
keyDown: react_1.default.useRef(keyDown),
useZoom: react_1.default.useRef(false)
};
const touch = (0, useMediaQuery_1.default)('(pointer: coarse)', { element: refs.root.current });
const minZoom = (0, utils_1.clamp)(minZoom_, 0.1, 1);
const maxZoom = (0, utils_1.clamp)(maxZoom_, 1, 100);
const length = (0, utils_1.clamp)(((items === null || items === void 0 ? void 0 : items.length) || 0) - 1, 0);
const media = items === null || items === void 0 ? void 0 : items[value];
refs.version.current = version;
refs.media.current = !!media;
refs.keyDown.current = keyDown;
refs.useZoom.current = version === 'modal' || keyDown;
refs.incrementZoom.current = incrementZoom;
refs.minZoom.current = minZoom;
refs.maxZoom.current = maxZoom;
const init = react_1.default.useCallback(() => {
setTimeout(() => {
var _a, _b;
setMoveValue({
left: (_a = refs.more.current) === null || _a === void 0 ? void 0 : _a.scrollLeft,
top: (_b = refs.more.current) === null || _b === void 0 ? void 0 : _b.scrollTop
});
setLoaded(true);
}, 14);
}, []);
const cleanUp = react_1.default.useCallback(() => {
refs.mouseDown.current = false;
}, []);
react_1.default.useEffect(() => {
const onKeyDown = (event) => {
setKeyDown(event.metaKey || event.ctrlKey);
};
const onKeyUp = (event) => {
setKeyDown(null);
};
window.document.addEventListener('keydown', onKeyDown);
window.document.addEventListener('keyup', onKeyUp);
return () => {
window.document.removeEventListener('keydown', onKeyDown);
window.document.removeEventListener('keyup', onKeyUp);
};
}, []);
react_1.default.useEffect(() => {
// init
if (open)
init();
else
cleanUp();
}, [open]);
react_1.default.useEffect(() => {
if (open_ !== undefined && open !== open_)
setOpen(open_);
}, [open_]);
react_1.default.useEffect(() => {
if (value_ !== undefined && value !== value_)
setValue((0, utils_1.clamp)(value_, 0, length));
}, [value_]);
const onResetZoom = react_1.default.useCallback(() => {
refs.zoom.current = null;
if (refs.imageWrapper.current) {
refs.imageWrapper.current.style.transition = 'none';
refs.imageWrapper.current.style.removeProperty('transform');
refs.imageWrapper.current.style.removeProperty('left');
refs.imageWrapper.current.style.removeProperty('top');
setTimeout(() => {
refs.imageWrapper.current.style.removeProperty('transition');
}, 14);
}
}, []);
const onValue = react_1.default.useCallback((index) => {
onResetZoom();
setValue(index);
}, [onResetZoom]);
const onOpen = react_1.default.useCallback(() => {
setOpen(true);
}, []);
const onClose = react_1.default.useCallback(() => {
setOpen(false);
setTimeout(() => {
setLoaded(false);
}, 140);
if ((0, utils_1.is)('function', onClose_))
onClose_();
}, [onClose_]);
const move = (forward_ = true) => {
const forward = forward_;
const rect = refs.more.current.getBoundingClientRect();
const moveValue_ = {
left: refs.more.current.scrollLeft + (forward ? 1 : -1) * rect.width,
behavior: 'smooth'
};
refs.more.current.scrollTo(moveValue_);
};
const onMouseDown = react_1.default.useCallback((event) => {
refs.mouseDown.current = true;
refs.mouseMovePrevious.current = {
x: event.clientX,
y: event.clientY
};
}, []);
const onMouseUp = react_1.default.useCallback(() => {
refs.mouseDown.current = false;
refs.mouseMovePrevious.current = null;
}, []);
const onWheel = react_1.default.useCallback((event) => {
var _a, _b, _c;
if (!refs.useZoom.current)
return;
event.preventDefault();
event.stopPropagation();
let scale = ((_a = refs.zoom.current) === null || _a === void 0 ? void 0 : _a.scale) !== undefined ? refs.zoom.current.scale : 1;
const part = refs.incrementZoom.current;
const up = event.wheelDelta > 0 || event.deltaY < 0;
scale = (0, utils_1.clamp)(up ? scale + part : scale - part, refs.minZoom.current, refs.maxZoom.current);
// Only allow in 100's decimal places, ie. 1.01
scale = Math.round(scale * 100) / 100;
const imageBoundingRect = (_b = refs.image.current) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
if (imageBoundingRect.width <= window.innerWidth) {
refs.imageWrapper.current.style.removeProperty('left');
}
if (imageBoundingRect.height <= window.innerHeight) {
refs.imageWrapper.current.style.removeProperty('top');
}
if (scale !== ((_c = refs.zoom.current) === null || _c === void 0 ? void 0 : _c.scale)) {
refs.zoom.current = {
scale
};
refs.imageWrapper.current.style.transform = `scale(${scale})`;
}
}, []);
const onMouseMove = react_1.default.useCallback((event) => {
var _a, _b, _c, _d, _e, _f, _g, _h;
if (!refs.useZoom.current)
return;
if (!(refs.mouseDown.current && refs.image.current))
return;
const x = event.x - (((_a = refs.mouseMovePrevious.current) === null || _a === void 0 ? void 0 : _a.x) || 0);
const y = event.y - (((_b = refs.mouseMovePrevious.current) === null || _b === void 0 ? void 0 : _b.y) || 0);
refs.mouseMovePrevious.current = {
x: event.clientX,
y: event.clientY
};
let left = Number((_e = (_d = (_c = refs.imageWrapper.current) === null || _c === void 0 ? void 0 : _c.style) === null || _d === void 0 ? void 0 : _d.left) === null || _e === void 0 ? void 0 : _e.replace('px', '')) || 0;
let top = Number((_h = (_g = (_f = refs.imageWrapper.current) === null || _f === void 0 ? void 0 : _f.style) === null || _g === void 0 ? void 0 : _g.top) === null || _h === void 0 ? void 0 : _h.replace('px', '')) || 0;
const imageBoundingRect = refs.image.current.getBoundingClientRect();
if ((imageBoundingRect.left <= 0 &&
((imageBoundingRect.left + x <= 0) &&
(imageBoundingRect.width + imageBoundingRect.left + x >= window.innerWidth)))) {
left += x;
refs.imageWrapper.current.style.left = `${left}px`;
}
if ((imageBoundingRect.top <= 0 &&
((imageBoundingRect.top + y <= 0) &&
(imageBoundingRect.height + imageBoundingRect.top + y >= window.innerHeight)))) {
top += y;
refs.imageWrapper.current.style.top = `${top}px`;
}
}, []);
react_1.default.useEffect(() => {
if (refs.useZoom.current) {
if (imageRef)
imageRef.addEventListener('wheel', onWheel, { passive: false });
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', onMouseUp);
window.addEventListener('touchend', onMouseUp);
}
return () => {
if (imageRef)
imageRef.removeEventListener('wheel', onWheel);
window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', onMouseUp);
window.removeEventListener('touchend', onMouseUp);
};
}, [imageRef, refs.useZoom.current]);
const onScroll = react_1.default.useCallback((event) => {
if (!refs.useZoom.current)
return;
if (arrows) {
setMoveValue({
left: refs.more.current.scrollLeft,
top: refs.more.current.scrollTop
});
}
}, [arrows]);
const iconButtonProps = Object.assign({ version: 'filled', color: 'default', tonal: true, size: 'small' }, IconButtonProps);
const arrowPre = moveValue && ((0, jsx_runtime_1.jsx)(IconButton, Object.assign({ onClick: () => move(false), disabled: !moveValue || ((_a = refs.more.current) === null || _a === void 0 ? void 0 : _a.scrollLeft) === 0 }, iconButtonProps, { className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('ImageGallery', theme) && [
'amaui-ImageGallery-arrow',
'amaui-ImageGallery-arrow-start'
],
iconButtonProps === null || iconButtonProps === void 0 ? void 0 : iconButtonProps.className,
classes.arrow
]) }, { children: (0, jsx_runtime_1.jsx)(IconStart, {}) })));
const arrowPost = moveValue && ((0, jsx_runtime_1.jsx)(IconButton, Object.assign({ onClick: () => move(), disabled: Math.ceil(((_b = refs.more.current) === null || _b === void 0 ? void 0 : _b.clientWidth) + ((_c = refs.more.current) === null || _c === void 0 ? void 0 : _c.scrollLeft)) === ((_d = refs.more.current) === null || _d === void 0 ? void 0 : _d.scrollWidth) }, iconButtonProps, { className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('ImageGallery', theme) && [
'amaui-ImageGallery-arrow',
'amaui-ImageGallery-arrow-end'
],
iconButtonProps === null || iconButtonProps === void 0 ? void 0 : iconButtonProps.className,
classes.arrow
]) }, { children: (0, jsx_runtime_1.jsx)(IconEnd, {}) })));
const more = !!(items === null || items === void 0 ? void 0 : items.length);
const onDragStartImage = react_1.default.useCallback((event) => {
event.preventDefault();
}, []);
const url = (media === null || media === void 0 ? void 0 : media.url) || (media === null || media === void 0 ? void 0 : media.urlSmall) || ((0, utils_1.is)('string', media) ? media : '');
const main = (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(Line, Object.assign({ justify: 'center', align: 'center', flex: true, fullWidth: true, className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('ImageGallery', theme) && [
'amaui-ImageGallery-main'
],
classes.main,
classes[`main_version_${version}`],
classes[`main_version_${version}_size_${size}`],
!overflow && classes.noOverflow
]) }, { children: [startMain, (0, jsx_runtime_1.jsxs)(Line, Object.assign({ ref: refs.imageWrapper, justify: 'center', align: 'center', fullWidth: true, flex: true }, ImageWrapperProps, { className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('ImageGallery', theme) && [
'amaui-ImageGallery-image-wrapper'
],
ImageWrapperProps === null || ImageWrapperProps === void 0 ? void 0 : ImageWrapperProps.className,
classes.imageWrapper
]), style: Object.assign({}, ImageWrapperProps === null || ImageWrapperProps === void 0 ? void 0 : ImageWrapperProps.style) }, { children: [startImage, url && ((0, jsx_runtime_1.jsx)(Image, Object.assign({ ref: (item) => {
refs.image.current = item;
setImageRef(item);
}, src: url, alt: media === null || media === void 0 ? void 0 : media.name, onMouseDown: onMouseDown, onMouseUp: onMouseUp, onTouchStart: onMouseDown, onTouchEnd: onMouseUp, onDragStart: onDragStartImage, lazyLoad: version === 'regular' }, ImageProps, { className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('ImageGallery', theme) && [
'amaui-ImageGallery-image'
],
ImageProps === null || ImageProps === void 0 ? void 0 : ImageProps.className,
classes.image,
classes.pointerEventsAuto
]) }))), endImage] })), endMain] })), more && ((0, jsx_runtime_1.jsx)(Line, Object.assign({ align: 'center', fullWidth: true, className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('ImageGallery', theme) && [
'amaui-ImageGallery-footer'
],
classes.footer
]) }, { children: (0, jsx_runtime_1.jsxs)(Line, Object.assign({ gap: 1.5, direction: 'row', justify: 'center', align: 'center', className: (0, style_react_1.classNames)([
classes.itemsWrapper
]) }, { children: [startThumbnails, arrows && arrowPre, (0, jsx_runtime_1.jsx)(Line, Object.assign({ ref: refs.more, gap: 1, direction: 'row', align: 'center', justify: 'flex-start', fullWidth: true, onScroll: onScroll, className: (0, style_react_1.classNames)([
classes.items
]) }, { children: items.map((item, index) => ((0, jsx_runtime_1.jsx)(Line, Object.assign({ onClick: () => onValue(index), className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('ImageGallery', theme) && [
'amaui-ImageGallery-item',
value === index && 'amaui-ImageGallery-item-selected'
],
classes.item,
value === index && classes.itemSelected
]), style: {
backgroundImage: `url('${(item === null || item === void 0 ? void 0 : item.urlSmall) || (item === null || item === void 0 ? void 0 : item.url) || item}')`
} }, { children: (0, jsx_runtime_1.jsx)(Interaction, {}) })))) })), arrows && arrowPost, endThumbnails] })) })))] });
if (version === 'regular') {
return ((0, jsx_runtime_1.jsx)(Line, Object.assign({ ref: item => {
if (ref) {
if ((0, utils_1.is)('function', ref))
ref(item);
else
ref.current = item;
}
refs.root.current = item;
}, fullWidth: true, className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('ImageGallery', theme) && [
'amaui-ImageGallery-root',
`amaui-ImageGallery-version-${version}`,
`amaui-ImageGallery-size-${size}`
],
className,
classes.root,
classes[`version_${version}`]
]) }, other, { children: main })));
}
return ((0, jsx_runtime_1.jsx)(Backdrop, Object.assign({ ref: item => {
if (ref) {
if ((0, utils_1.is)('function', ref))
ref(item);
else
ref.current = item;
}
refs.root.current = item;
}, open: open, onClose: onClose, className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('ImageGallery', theme) && [
'amaui-ImageGallery-root',
`amaui-ImageGallery-version-${version}`
],
className,
classes.root,
classes[`version_${version}`]
]) }, other, { children: (0, jsx_runtime_1.jsxs)(Line, Object.assign({ gap: 0, fullWidth: true, className: classes.wrapper }, { children: [(0, jsx_runtime_1.jsx)(Line, Object.assign({ direction: 'row', justify: 'flex-end', fullWidth: true, className: (0, style_react_1.classNames)([
(0, utils_2.staticClassName)('ImageGallery', theme) && [
'amaui-ImageGallery-header'
],
classes.header
]) }, { children: (0, jsx_runtime_1.jsx)(IconButton, Object.assign({ version: 'filled', color: theme.palette.light ? 'default' : 'inverted', onClick: onClose, className: (0, style_react_1.classNames)([
classes.pointerEventsAuto
]) }, { children: (0, jsx_runtime_1.jsx)(IconClose, {}) })) })), main] })) })));
});
ImageGallery.displayName = 'amaui-ImageGallery';
exports.default = ImageGallery;
;