@sap-ux/ui-components
Version:
SAP UI Components Library
115 lines • 4.45 kB
JavaScript
import React from 'react';
import { Callout, getDocument } from '@fluentui/react';
import { isHTMLElement, focusToSibling } from '../../utilities/index.js';
import '../../styles/_shadows.scss';
export const CALLOUT_STYLES = {
background: 'var(--vscode-editorWidget-background)',
boxShadow: 'var(--ui-box-shadow-small)',
borderColor: 'var(--vscode-editorWidget-border)',
text: 'var(--vscode-editorWidget-foreground)',
borderRadius: 'var(--vscode-cornerRadius-small, 4px)'
};
export var UICalloutContentPadding;
(function (UICalloutContentPadding) {
UICalloutContentPadding["None"] = "None";
UICalloutContentPadding["Standard"] = "Standard";
})(UICalloutContentPadding || (UICalloutContentPadding = {}));
// Control content padding with different states to avoid different hardcoded values across extensions
const CALLOUT_CONTENT_PADDING = new Map([[UICalloutContentPadding.Standard, 8]]);
/**
* Method receives callout style and extracts into raw styles object.
*
* @param {IStyleFunctionOrObject<ICalloutContentStyleProps, ICalloutContentStyles> | undefined} styles Callout styles.
* @param {keyof ICalloutContentStyles} name Callout style type.
* @returns {IRawStyle} Raw style object.
*/
const extractRawStyles = (styles, name) => {
if (typeof styles === 'object' && typeof styles[name] === 'object') {
return styles[name];
}
return {};
};
export const getCalloutStyle = (props) => {
return {
root: {
boxShadow: CALLOUT_STYLES.boxShadow,
backgroundColor: CALLOUT_STYLES.background,
borderRadius: CALLOUT_STYLES.borderRadius,
border: `1px solid ${CALLOUT_STYLES.borderColor}`,
...extractRawStyles(props.styles, 'root')
},
beak: {
backgroundColor: CALLOUT_STYLES.background,
boxShadow: CALLOUT_STYLES.boxShadow,
...extractRawStyles(props.styles, 'beak')
},
beakCurtain: {
backgroundColor: CALLOUT_STYLES.background,
borderRadius: CALLOUT_STYLES.borderRadius,
...extractRawStyles(props.styles, 'beakCurtain')
},
calloutMain: {
backgroundColor: 'transparent',
color: CALLOUT_STYLES.text,
borderRadius: CALLOUT_STYLES.borderRadius,
minWidth: props.calloutMinWidth ?? 300,
boxSizing: 'border-box',
padding: CALLOUT_CONTENT_PADDING.get(props.contentPadding ?? UICalloutContentPadding.None),
...extractRawStyles(props.styles, 'calloutMain')
},
container: extractRawStyles(props.styles, 'container')
};
};
/**
* UICallout component.
* based on https://developer.microsoft.com/en-us/fluentui#/controls/web/callout
*
* @exports
* @class UICallout
* @extends {React.Component<ICalloutProps, {}>}
*/
export class UICallout extends React.Component {
/**
* Initializes component properties.
*
* @param {UICalloutProps} props
*/
constructor(props) {
super(props);
this.onKeyDown = this.onKeyDown.bind(this);
}
/**
* Method handles keydown event.
* If "focusTargetSiblingOnTabPress" property is set and 'Tab' key is pressed,
* then method tries to focus next/previous sibling based on target.
*
* @param event Keydown event
*/
onKeyDown(event) {
const { onKeyDown, focusTargetSiblingOnTabPress, target } = this.props;
if (focusTargetSiblingOnTabPress && event.key === 'Tab' && target) {
let targetRef = null;
if (typeof target === 'string') {
const currentDoc = getDocument();
targetRef = currentDoc?.querySelector(target);
}
else if ('getBoundingClientRect' in target && isHTMLElement(target)) {
targetRef = target;
}
if (targetRef && focusToSibling(targetRef, !event.shiftKey)) {
// Stop event bubbling to avoid default browser behavior
event.stopPropagation();
event.preventDefault();
}
}
// Call external subscriber
onKeyDown?.(event);
}
/**
* @returns {JSX.Element}
*/
render() {
return (React.createElement(Callout, { ...this.props, onKeyDown: this.onKeyDown, styles: getCalloutStyle(this.props) }, this.props.children));
}
}
//# sourceMappingURL=UICallout.js.map