@razorpay/blade
Version:
The Design System that powers Razorpay
411 lines (406 loc) • 16 kB
JavaScript
import _asyncToGenerator from '@babel/runtime/helpers/asyncToGenerator';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import _regeneratorRuntime from '@babel/runtime/regenerator';
import React__default, { useCallback, useState, useEffect } from 'react';
import { useControls, TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch';
import styled from 'styled-components';
import { usePreviewContext, PreviewProvider } from './PreviewContext.js';
import '../../utils/metaAttribute/index.js';
import getIn from '../../utils/lodashButBetter/get.js';
import '../../tokens/global/index.js';
import '../Box/BaseBox/index.js';
import '../Icons/index.js';
import '../Typography/index.js';
import '../ButtonGroup/index.js';
import '../Button/index.js';
import '../../utils/assignWithoutSideEffects/index.js';
import '../../utils/isValidAllowedChildren/index.js';
import '../Divider/index.js';
import { useControllableState } from '../../utils/useControllable.js';
import { componentZIndices } from '../../utils/componentZIndices.js';
import '../../utils/makeSize/index.js';
import { jsx, jsxs } from 'react/jsx-runtime';
import { BaseBox } from '../Box/BaseBox/BaseBox.web.js';
import Button from '../Button/Button/Button.js';
import FullScreenExitIcon from '../Icons/FullScreenExitIcon/FullScreenExitIcon.js';
import FullScreenEnterIcon from '../Icons/FullScreenEnterIcon/FullScreenEnterIcon.js';
import { Heading } from '../Typography/Heading/Heading.js';
import { Divider } from '../Divider/Divider.js';
import { assignWithoutSideEffects } from '../../utils/assignWithoutSideEffects/assignWithoutSideEffects.js';
import { MetaConstants } from '../../utils/metaAttribute/metaConstants.js';
import ZoomInIcon from '../Icons/ZoomInIcon/ZoomInIcon.js';
import { makeSize } from '../../utils/makeSize/makeSize.js';
import { size } from '../../tokens/global/size.js';
import { Text } from '../Typography/Text/Text.js';
import ZoomOutIcon from '../Icons/ZoomOutIcon/ZoomOutIcon.js';
import RefreshIcon from '../Icons/RefreshIcon/RefreshIcon.js';
import { ButtonGroup } from '../ButtonGroup/ButtonGroup.web.js';
import { getComponentId } from '../../utils/isValidAllowedChildren/isValidAllowedChildren.js';
var _PreviewHeader = function _PreviewHeader(_ref) {
var title = _ref.title,
_onFullScreen = _ref._onFullScreen,
trailing = _ref.trailing;
var _usePreviewContext = usePreviewContext(),
isFullScreen = _usePreviewContext.isFullScreen;
if (!title) {
return /*#__PURE__*/jsx(BaseBox, {
zIndex: componentZIndices.previewPanel,
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
padding: "spacing.4",
backgroundColor: "transparent",
width: "100%",
children: /*#__PURE__*/jsxs(BaseBox, {
display: "flex",
alignItems: "center",
gap: "spacing.3",
backgroundColor: "transparent",
borderRadius: "medium",
children: [/*#__PURE__*/jsx(Button, {
icon: isFullScreen ? FullScreenExitIcon : FullScreenEnterIcon,
variant: "tertiary",
onClick: _onFullScreen,
accessibilityLabel: isFullScreen ? 'Exit Full Screen' : 'Enter Full Screen'
}), trailing]
})
});
}
return /*#__PURE__*/jsxs(BaseBox, {
zIndex: componentZIndices.previewPanel,
backgroundColor: "transparent",
width: "100%",
children: [/*#__PURE__*/jsxs(BaseBox, {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
padding: "spacing.5",
height: "100%",
width: "100%",
children: [/*#__PURE__*/jsx(Heading, {
size: "medium",
weight: "regular",
color: "surface.text.gray.subtle",
children: title
}), /*#__PURE__*/jsxs(BaseBox, {
display: "flex",
alignItems: "center",
gap: "spacing.3",
children: [/*#__PURE__*/jsx(Button, {
icon: isFullScreen ? FullScreenExitIcon : FullScreenEnterIcon,
variant: "tertiary",
onClick: _onFullScreen
}), trailing]
})]
}), /*#__PURE__*/jsx(Divider, {
orientation: "horizontal"
})]
});
};
var PreviewHeader = /*#__PURE__*/assignWithoutSideEffects(_PreviewHeader, {
componentId: MetaConstants.PreviewHeader
});
var _PreviewBody = function _PreviewBody(PreviewBodyProps) {
var children = PreviewBodyProps.children;
return /*#__PURE__*/jsx(BaseBox, {
children: children
});
};
var PreviewBody = /*#__PURE__*/assignWithoutSideEffects(_PreviewBody, {
componentId: MetaConstants.PreviewBody
});
var _PreviewFooter = function _PreviewFooter(PreviewFooterProps) {
var showZoomPercentage = PreviewFooterProps.showZoomPercentage,
trailing = PreviewFooterProps.trailing;
var _useControls = useControls(),
zoomIn = _useControls.zoomIn,
zoomOut = _useControls.zoomOut,
centerView = _useControls.centerView;
var _usePreviewContext2 = usePreviewContext(),
zoom = _usePreviewContext2.zoom,
zoomScaleStep = _usePreviewContext2.zoomScaleStep,
defaultZoom = _usePreviewContext2.defaultZoom;
var handleZoomIn = useCallback(function () {
zoomIn(zoomScaleStep);
}, [zoomScaleStep, zoomIn]);
var handleZoomOut = useCallback(function () {
zoomOut(zoomScaleStep);
}, [zoomScaleStep, zoomOut]);
var handleReset = useCallback(function () {
// thanks to https://github.com/BetterTyped/react-zoom-pan-pinch/issues/286#issuecomment-1442888219
centerView(defaultZoom, 0);
}, [defaultZoom, centerView]);
return /*#__PURE__*/jsxs(BaseBox, {
display: "flex",
justifyContent: trailing ? 'space-between' : 'center',
width: "100%",
backgroundColor: "transparent",
padding: {
base: 'spacing.2',
m: 'spacing.5'
},
zIndex: componentZIndices.previewPanel,
children: [/*#__PURE__*/jsx(BaseBox, {
padding: "spacing.2",
children: showZoomPercentage ? /*#__PURE__*/jsxs(BaseBox, {
display: "flex",
alignItems: "center",
gap: "spacing.2",
children: [/*#__PURE__*/jsx(Button, {
icon: ZoomInIcon,
onClick: handleZoomIn,
variant: "tertiary",
accessibilityLabel: "Zoom In",
isDisabled: zoom >= 8
}), /*#__PURE__*/jsx(BaseBox, {
width: makeSize(size[40]),
textAlign: 'center',
children: /*#__PURE__*/jsxs(Text, {
size: "medium",
children: [" ", Math.round(zoom * 100), "%"]
})
}), /*#__PURE__*/jsx(Button, {
icon: ZoomOutIcon,
onClick: handleZoomOut,
variant: "tertiary",
accessibilityLabel: "Zoom Out",
isDisabled: zoom <= 0.1
}), /*#__PURE__*/jsx(Button, {
icon: RefreshIcon,
onClick: function onClick() {
return handleReset();
},
variant: "tertiary",
accessibilityLabel: "Reset Zoom"
})]
}) : /*#__PURE__*/jsxs(BaseBox, {
display: "flex",
alignItems: "center",
gap: "spacing.2",
children: [/*#__PURE__*/jsxs(ButtonGroup, {
variant: "tertiary",
children: [/*#__PURE__*/jsx(Button, {
icon: ZoomInIcon,
onClick: handleZoomIn,
accessibilityLabel: "Zoom In"
}), /*#__PURE__*/jsx(Button, {
icon: ZoomOutIcon,
onClick: handleZoomOut,
accessibilityLabel: "Zoom Out"
})]
}), /*#__PURE__*/jsx(Button, {
icon: RefreshIcon,
onClick: function onClick() {
return handleReset();
},
accessibilityLabel: "Reset Zoom",
variant: "tertiary"
})]
})
}), trailing]
});
};
var PreviewFooter = /*#__PURE__*/assignWithoutSideEffects(_PreviewFooter, {
componentId: MetaConstants.PreviewFooter
});
var dotSpacing = 16;
var dotOpacity = 0.1;
var dotSize = 1;
var ZoomContainer = /*#__PURE__*/styled.div.withConfig({
displayName: "Previewweb__ZoomContainer",
componentId: "sc-1k59t11-0"
})(["width:100%;height:100%;cursor:", ";background-image:", ";background-size:", "px ", "px;.zoom-wrapper,.zoom-content{width:100%;height:100%;overflow:visible;display:flex;justify-content:center;align-items:center;}transition:cursor 0.1s ease;"], function (_ref2) {
var isDragEnabled = _ref2.isDragEnabled,
isDragging = _ref2.isDragging;
if (!isDragEnabled) return 'default';
return isDragging ? 'grabbing' : 'grab';
}, function (_ref3) {
var isDragEnabled = _ref3.isDragEnabled;
return isDragEnabled ? "radial-gradient(\n circle,\n rgba(0, 0, 0, ".concat(dotOpacity, ") ").concat(dotSize, "px,\n transparent ").concat(dotSize, "px\n )") : 'none';
}, dotSpacing, dotSpacing);
var TransFormWrapperContainer = /*#__PURE__*/styled.div.withConfig({
displayName: "Previewweb__TransFormWrapperContainer",
componentId: "sc-1k59t11-1"
})(["width:100%;height:100%;position:relative;overflow:hidden;background-color:", ";"], function (_ref4) {
var isFullScreen = _ref4.isFullScreen,
theme = _ref4.theme;
return isFullScreen ? getIn(theme.colors, 'surface.background.gray.intense') : 'transparent';
});
var Preview = function Preview(_ref5) {
var children = _ref5.children,
onFullScreenProp = _ref5.onFullScreen,
onZoomChange = _ref5.onZoomChange,
_ref5$zoomScaleStep = _ref5.zoomScaleStep,
zoomScaleStep = _ref5$zoomScaleStep === void 0 ? 0.1 : _ref5$zoomScaleStep,
_ref5$isDragAndZoomDi = _ref5.isDragAndZoomDisabled,
isDragAndZoomDisabled = _ref5$isDragAndZoomDi === void 0 ? false : _ref5$isDragAndZoomDi,
defaultZoom = _ref5.defaultZoom,
onDragChange = _ref5.onDragChange;
var _useControllableState = useControllableState({
onChange: onZoomChange,
defaultValue: defaultZoom !== null && defaultZoom !== void 0 ? defaultZoom : 1
}),
_useControllableState2 = _slicedToArray(_useControllableState, 2),
controlledZoom = _useControllableState2[0],
setControlledZoom = _useControllableState2[1];
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
isFullScreen = _useState2[0],
setIsFullScreen = _useState2[1];
var _useState3 = useState(false),
_useState4 = _slicedToArray(_useState3, 2),
isDragging = _useState4[0],
setIsDragging = _useState4[1];
var containerRef = React__default.useRef(null);
var handleTransformed = function handleTransformed(_ref6) {
var state = _ref6.state;
var scale = state.scale,
positionX = state.positionX,
positionY = state.positionY;
setControlledZoom(function () {
return scale;
});
onDragChange === null || onDragChange === void 0 || onDragChange({
x: positionX,
y: positionY
});
};
var handleFullScreenError = function handleFullScreenError(err) {
if (err instanceof DOMException) {
console.error("Fullscreen request failed: ".concat(err.name, " - ").concat(err.message));
} else {
console.error('Unexpected error during fullscreen request:', err);
}
};
var handleFullScreen = useCallback(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
var _containerRef$current, _t, _t2;
return _regeneratorRuntime.wrap(function (_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
if (document.fullscreenElement) {
_context.next = 5;
break;
}
_context.prev = 1;
_context.next = 2;
return (_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.requestFullscreen();
case 2:
setIsFullScreen(true);
onFullScreenProp === null || onFullScreenProp === void 0 || onFullScreenProp();
_context.next = 4;
break;
case 3:
_context.prev = 3;
_t = _context["catch"](1);
handleFullScreenError(_t);
case 4:
_context.next = 8;
break;
case 5:
_context.prev = 5;
_context.next = 6;
return document.exitFullscreen();
case 6:
setIsFullScreen(false);
onFullScreenProp === null || onFullScreenProp === void 0 || onFullScreenProp();
_context.next = 8;
break;
case 7:
_context.prev = 7;
_t2 = _context["catch"](5);
handleFullScreenError(_t2);
case 8:
case "end":
return _context.stop();
}
}, _callee, null, [[1, 3], [5, 7]]);
})), [onFullScreenProp]);
// this is added to handle the fullscreen change if user exits fullscreen using the escape key, or browser's exit fullscreen button
useEffect(function () {
var handleFullScreenChange = function handleFullScreenChange() {
setIsFullScreen(!!document.fullscreenElement);
};
document.addEventListener('fullscreenchange', handleFullScreenChange);
return function () {
document.removeEventListener('fullscreenchange', handleFullScreenChange);
};
}, []);
// filter out preview header, preview body, preview footer separately using componentId
var previewHeader = React__default.Children.toArray(children).filter(function (child) {
return getComponentId(child) === MetaConstants.PreviewHeader;
}).map(function (child) {
if (/*#__PURE__*/React__default.isValidElement(child)) {
return /*#__PURE__*/React__default.cloneElement(child, {
// @ts-expect-error
_onFullScreen: handleFullScreen
});
}
return child;
});
var previewBody = React__default.Children.toArray(children).filter(function (child) {
return getComponentId(child) === MetaConstants.PreviewBody;
});
var previewFooter = React__default.Children.toArray(children).filter(function (child) {
return getComponentId(child) === MetaConstants.PreviewFooter;
});
return /*#__PURE__*/jsx(PreviewProvider, {
value: {
zoom: controlledZoom,
isFullScreen: isFullScreen,
zoomScaleStep: zoomScaleStep,
defaultZoom: defaultZoom !== null && defaultZoom !== void 0 ? defaultZoom : 1
},
children: /*#__PURE__*/jsx(TransFormWrapperContainer, {
ref: containerRef,
isFullScreen: isFullScreen,
children: /*#__PURE__*/jsx(TransformWrapper, {
onTransformed: handleTransformed,
minScale: 0.1,
maxScale: 8,
disabled: isDragAndZoomDisabled,
initialScale: defaultZoom !== null && defaultZoom !== void 0 ? defaultZoom : controlledZoom,
doubleClick: {
disabled: false
},
onPanningStart: function onPanningStart() {
return setIsDragging(true);
},
onPanningStop: function onPanningStop() {
return setIsDragging(false);
},
panning: {
velocityDisabled: true
},
limitToBounds: false,
centerOnInit: true,
children: function children() {
return /*#__PURE__*/jsxs(BaseBox, {
width: "100%",
height: "100%",
display: "flex",
flexDirection: "column",
position: "relative",
overflow: "visible",
children: [previewHeader, /*#__PURE__*/jsx(BaseBox, {
flex: 1,
overflow: "hidden",
position: "relative",
width: "100%",
children: /*#__PURE__*/jsx(ZoomContainer, {
isDragEnabled: !isDragAndZoomDisabled,
isDragging: isDragging,
children: /*#__PURE__*/jsx(TransformComponent, {
wrapperClass: "zoom-wrapper",
contentClass: "zoom-content",
children: previewBody
})
})
}), previewFooter]
});
}
})
})
});
};
export { Preview, PreviewBody, PreviewFooter, PreviewHeader };
//# sourceMappingURL=Preview.web.js.map