diff --git a/src/components/GridItem/GridItem.js b/src/components/GridItem/GridItem.tsx similarity index 73% rename from src/components/GridItem/GridItem.js rename to src/components/GridItem/GridItem.tsx index 672e9da..59e4f50 100644 --- a/src/components/GridItem/GridItem.js +++ b/src/components/GridItem/GridItem.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import PropTypes from 'prop-types'; - import {FOCUSED_CLASS_NAME} from '../../constants'; import {DashKitContext} from '../../context'; +import type {ConfigItem, ConfigLayout} from '../../shared'; +import type {PluginRef, ReactGridLayoutProps} from '../../typings'; import {cn} from '../../utils/cn'; import Item from '../Item/Item'; import OverlayControls from '../OverlayControls/OverlayControls'; @@ -13,28 +13,28 @@ import './GridItem.scss'; const b = cn('dashkit-grid-item'); class WindowFocusObserver { - constructor() { - this.subscribers = 0; - this.isFocused = !document.hidden; + subscribers = 0; + isFocused = !document.hidden; + constructor() { window.addEventListener('blur', this.blurHandler, true); window.addEventListener('focus', this.focusHandler, true); } - blurHandler = (e) => { + blurHandler = (e: FocusEvent) => { if (e.target === window) { this.isFocused = false; } }; - focusHandler = (e) => { + focusHandler = (e: FocusEvent) => { if (e.target === window) { this.isFocused = true; } }; // Method to get state after all blur\focus events in document are triggered - async getFocusedState() { + async getFocusedState(): Promise { return new Promise((resolve) => { requestAnimationFrame(() => { resolve(this.isFocused); @@ -45,43 +45,53 @@ class WindowFocusObserver { const windowFocusObserver = new WindowFocusObserver(); -class GridItem extends React.PureComponent { - static propTypes = { - adjustWidgetLayout: PropTypes.func.isRequired, - gridLayout: PropTypes.object, - id: PropTypes.string, - item: PropTypes.object, - isDragging: PropTypes.bool, - isDraggedOut: PropTypes.bool, - layout: PropTypes.array, - - forwardedRef: PropTypes.any, - forwardedPluginRef: PropTypes.any, - isPlaceholder: PropTypes.bool, - - onItemMountChange: PropTypes.func, - onItemRender: PropTypes.func, - - // from react-grid-layout: - children: PropTypes.node, - className: PropTypes.string, - style: PropTypes.object, - noOverlay: PropTypes.bool, - focusable: PropTypes.bool, - withCustomHandle: PropTypes.bool, - onMouseDown: PropTypes.func, - onMouseUp: PropTypes.func, - onTouchEnd: PropTypes.func, - onTouchStart: PropTypes.func, - onItemFocus: PropTypes.func, - onItemBlur: PropTypes.func, - }; - +type GridItemProps = { + adjustWidgetLayout: (data: { + widgetId: string; + needSetDefault?: boolean; + adjustedWidgetLayout?: ConfigLayout; + }) => void; + gridLayout?: ReactGridLayoutProps; + id?: string; + item: ConfigItem; + isDragging?: boolean; + isDraggedOut?: boolean; + layout?: ConfigLayout[]; + + forwardedRef?: React.Ref; + forwardedPluginRef?: (pluginRef: PluginRef) => void; + isPlaceholder?: boolean; + + onItemMountChange?: (item: ConfigItem, meta: {isAsync: boolean; isMounted: boolean}) => void; + onItemRender?: (item: ConfigItem) => void; + + // from react-grid-layout: + children?: React.ReactNode; + className?: string; + style?: React.CSSProperties; + noOverlay?: boolean; + focusable?: boolean; + withCustomHandle?: boolean; + onMouseDown?: (e: React.MouseEvent) => void; + onMouseUp?: (e: React.MouseEvent) => void; + onTouchEnd?: (e: React.TouchEvent) => void; + onTouchStart?: (e: React.TouchEvent) => void; + onItemFocus?: (item: ConfigItem) => void; + onItemBlur?: (item: ConfigItem) => void; +}; + +type GridItemState = { + isFocused: boolean; +}; + +class GridItem extends React.PureComponent { static contextType = DashKitContext; + context!: React.ContextType; _isAsyncItem = false; + controller: AbortController | null = null; - state = { + state: GridItemState = { isFocused: false, }; @@ -105,7 +115,7 @@ class GridItem extends React.PureComponent {
); @@ -114,17 +124,13 @@ class GridItem extends React.PureComponent { onOverlayItemClick = () => { // Creating button element to trigger focus out const focusDummy = document.createElement('button'); - const styles = { + Object.assign(focusDummy.style, { width: '0', height: '0', opacity: '0', position: 'fixed', top: '0', left: '0', - }; - - Object.entries(styles).forEach(([key, value]) => { - focusDummy.style[key] = value; }); // requestAnimationFrame to make call after alert() or confirm() @@ -187,14 +193,16 @@ class GridItem extends React.PureComponent { const {editMode} = this.context; const {isFocused} = this.state; - const width = Number.parseInt(style.width, 10); - const height = Number.parseInt(style.height, 10); - const transform = style.transform; + const width = + style?.width === undefined ? undefined : Number.parseInt(String(style.width), 10); + const height = + style?.height === undefined ? undefined : Number.parseInt(String(style.height), 10); + const transform = style?.transform; const preparedClassName = (editMode ? className : className - .replace('react-resizable', '') + ?.replace('react-resizable', '') .replace('react-draggable', '') .replace(FOCUSED_CLASS_NAME, '')) + (isFocused ? ` ${FOCUSED_CLASS_NAME}` : ''); @@ -254,9 +262,11 @@ class GridItem extends React.PureComponent { } } -const GridItemForwarderRef = React.forwardRef((props, ref) => { - return ; -}); +const GridItemForwarderRef = React.forwardRef>( + (props, ref) => { + return ; + }, +); GridItemForwarderRef.displayName = 'forwardRef(GridItem)'; diff --git a/src/components/GridLayout/GridLayout.tsx b/src/components/GridLayout/GridLayout.tsx index c19a7ce..30b16cb 100644 --- a/src/components/GridLayout/GridLayout.tsx +++ b/src/components/GridLayout/GridLayout.tsx @@ -712,10 +712,8 @@ export default class GridLayout extends React.PureComponent ); })} diff --git a/src/components/OverlayControls/OverlayControls.tsx b/src/components/OverlayControls/OverlayControls.tsx index 696334a..992ec68 100644 --- a/src/components/OverlayControls/OverlayControls.tsx +++ b/src/components/OverlayControls/OverlayControls.tsx @@ -75,7 +75,7 @@ interface OverlayControlsDefaultProps { interface OverlayControlsProps extends OverlayControlsDefaultProps { configItem: ConfigItem; - onItemClick?: () => void | null; + onItemClick?: () => void; } type PreparedCopyItemOptionsArg = Pick & {