UNPKG

@razorpay/blade

Version:

The Design System that powers Razorpay

411 lines (406 loc) 16 kB
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