azure-devops-ui
Version:
React components for building web UI in Azure DevOps
138 lines (137 loc) • 9.24 kB
JavaScript
import { __assign, __extends } from "tslib";
import "../../CommonImports";
import "../../Core/core.css";
import "./Dialog.css";
import * as React from "react";
import { EventManagement } from '../../Core/EventManagement';
import { announce } from '../../Core/Util/Accessibility';
import { ScreenContext, ScreenSize } from '../../Core/Util/Screen';
import { format } from '../../Core/Util/String';
import { Callout, ContentJustification, ContentLocation, ContentOrientation, ContentSize } from '../../Callout';
import { FocusZoneKeyStroke } from '../../FocusZone';
import { Icon } from '../../Icon';
import { Observer } from '../../Observer';
import * as Resources from '../../Resources.Layer';
import { Spinner, SpinnerSize } from '../../Spinner';
import { Spacing, Surface, SurfaceContext } from '../../Surface';
import { css, KeyCode } from '../../Util';
var MIN_DIALOG_Size = 320;
var DIALOG_RESIZE_INCREMENT = 2;
var CustomDialog = /** @class */ (function (_super) {
__extends(CustomDialog, _super);
function CustomDialog(props) {
var _this = _super.call(this, props) || this;
_this.events = new EventManagement();
_this.contentRef = React.createRef();
_this.onGripperKeyDown = function (event) {
if (_this.contentRef.current) {
var rect = _this.contentRef.current.getBoundingClientRect();
_this.currentHeight = rect.height;
_this.currentWidth = rect.width;
switch (event.keyCode) {
case KeyCode.leftArrow:
_this.setState({ width: Math.max(_this.currentWidth - DIALOG_RESIZE_INCREMENT, MIN_DIALOG_Size) });
break;
case KeyCode.rightArrow:
_this.setState({ width: _this.currentWidth + DIALOG_RESIZE_INCREMENT });
break;
case KeyCode.upArrow:
_this.setState({ height: Math.max(_this.currentHeight - DIALOG_RESIZE_INCREMENT, MIN_DIALOG_Size) });
break;
case KeyCode.downArrow:
_this.setState({ height: _this.currentHeight + DIALOG_RESIZE_INCREMENT });
break;
default:
return;
}
event.preventDefault();
event.stopPropagation();
announce(format(Resources.SizeFormat, _this.state.height || _this.currentHeight, _this.state.width || _this.currentWidth));
}
};
_this.onGripperMouseDown = function (event) {
_this.onGripperDown(event, event.clientX, event.clientY);
_this.attachMouseWindowEvents();
};
_this.onGripperDown = function (event, xPos, yPos) {
if (_this.contentRef) {
event.preventDefault();
event.stopPropagation();
_this.anchorX = xPos;
_this.anchorY = yPos;
if (_this.contentRef.current) {
var rect = _this.contentRef.current.getBoundingClientRect();
_this.currentHeight = rect.height;
_this.currentWidth = rect.width;
}
}
};
_this.onGripperMouseMove = function (event) {
_this.handleDragEvent(event, event.clientX, event.clientY);
};
_this.onGripperMouseUp = function (event) {
_this.detachMouseWindowEvents();
announce(format(Resources.SizeFormat, _this.state.height, _this.state.width));
};
_this.onKeyDown = function (event) {
var _a;
var _b = _this.props, enterPrimary = _b.enterPrimary, primaryButtonProps = _b.primaryButtonProps;
if (enterPrimary && primaryButtonProps && event.which === KeyCode.enter && !event.defaultPrevented) {
(_a = primaryButtonProps.onClick) === null || _a === void 0 ? void 0 : _a.call(primaryButtonProps, event);
event.preventDefault();
}
};
_this.state = {};
return _this;
}
CustomDialog.prototype.render = function () {
var _this = this;
var _a = this.props, ariaDescribedBy = _a.ariaDescribedBy, ariaLabel = _a.ariaLabel, ariaLabelledBy = _a.ariaLabelledBy, blurDismiss = _a.blurDismiss, calloutClassName = _a.calloutClassName, className = _a.className, calloutContentClassName = _a.calloutContentClassName, contentJustification = _a.contentJustification, contentLocation = _a.contentLocation, defaultActiveElement = _a.defaultActiveElement, defaultFocusableElementAriaLabel = _a.defaultFocusableElementAriaLabel, escDismiss = _a.escDismiss, id = _a.id, lightDismiss = _a.lightDismiss, onDismiss = _a.onDismiss, overlay = _a.overlay, modal = _a.modal, resizable = _a.resizable, role = _a.role, _b = _a.contentSize, contentSize = _b === void 0 ? ContentSize.Medium : _b;
return (React.createElement(Observer, { size: this.context.size }, function (props) {
var mobile = props.size === ScreenSize.xsmall;
return (React.createElement(Callout, { ariaDescribedBy: ariaDescribedBy, ariaLabel: ariaLabel, ariaLabelledBy: ariaLabelledBy, blurDismiss: blurDismiss, className: css(calloutClassName, "bolt-dialog-callout"), contentClassName: css(calloutContentClassName, "bolt-dialog-callout-content relative scroll-auto", mobile && "bolt-dialog-mobile flex-grow"), contentJustification: contentJustification, contentLocation: contentLocation, contentOrientation: ContentOrientation.Column, contentRef: _this.contentRef, contentShadow: true, contentSize: mobile ? undefined : contentSize, escDismiss: escDismiss, focuszoneProps: {
circularNavigation: true,
defaultActiveElement: defaultActiveElement || ".bolt-dialog-focus-element",
focusOnMount: true,
handleTabKey: true,
includeDefaults: true,
selectInputTextOnFocus: _this.props.selectInputTextOnFocus,
postprocessKeyStroke: function (event) {
// We want to prevent moving outside the dialog if there are no focusable elements in the dialog.
event.which === KeyCode.tab && event.preventDefault();
return FocusZoneKeyStroke.IgnoreParents;
}
}, id: id, lightDismiss: lightDismiss, modal: modal, onDismiss: onDismiss, role: role, height: _this.state.height, width: _this.state.width, onKeyDown: _this.onKeyDown },
React.createElement(SurfaceContext.Consumer, null, function (surfaceContext) { return (React.createElement(Surface, __assign({}, surfaceContext, { spacing: Spacing.default }),
React.createElement("div", { className: css(className, "bolt-dialog-root flex-column flex-grow scroll-hidden") },
React.createElement("div", { "aria-label": defaultFocusableElementAriaLabel, className: "bolt-dialog-focus-element no-outline", tabIndex: -1, role: defaultFocusableElementAriaLabel ? "heading" : undefined, "aria-level": defaultFocusableElementAriaLabel ? 1 : undefined }),
_this.props.children,
!mobile && resizable && (React.createElement(Icon, { ariaLabel: Resources.Resize, iconName: "GripperResize", onMouseDown: _this.onGripperMouseDown, onKeyDown: _this.onGripperKeyDown, tabIndex: 0, wrapperClass: "bolt-dialog-resize-icon" })),
overlay && (React.createElement("div", { className: "absolute-fill bolt-dialog-overlay flex-column justify-center" },
React.createElement(Spinner, { size: SpinnerSize.large, ariaLabel: overlay.spinnerAriaLabel, ariaLive: "assertive", label: overlay.spinnerLabel })))))); })));
}));
};
CustomDialog.prototype.handleDragEvent = function (event, xPos, yPos) {
var newWidth = Math.max((this.currentWidth || 0) + (xPos - this.anchorX) * 2, MIN_DIALOG_Size);
var newHeight = Math.max((this.currentHeight || 0) + (yPos - this.anchorY) * 2, MIN_DIALOG_Size);
this.setState({ width: newWidth, height: newHeight });
};
CustomDialog.prototype.attachMouseWindowEvents = function () {
this.events.addEventListener(window, "mousemove", this.onGripperMouseMove);
this.events.addEventListener(window, "mouseup", this.onGripperMouseUp);
};
CustomDialog.prototype.detachMouseWindowEvents = function () {
this.events.removeEventListener(window, "mousemove", this.onGripperMouseMove);
this.events.removeEventListener(window, "mouseup", this.onGripperMouseUp);
};
CustomDialog.defaultProps = {
contentJustification: ContentJustification.Center,
contentLocation: ContentLocation.Center,
escDismiss: true,
lightDismiss: true,
enterPrimary: true
};
CustomDialog.contextType = ScreenContext;
return CustomDialog;
}(React.Component));
export { CustomDialog };