diff --git a/src/components/GridItem/GridItem.tsx b/src/components/GridItem/GridItem.tsx index 59e4f50..30f4eff 100644 --- a/src/components/GridItem/GridItem.tsx +++ b/src/components/GridItem/GridItem.tsx @@ -52,11 +52,11 @@ type GridItemProps = { adjustedWidgetLayout?: ConfigLayout; }) => void; gridLayout?: ReactGridLayoutProps; - id?: string; + id: string; item: ConfigItem; isDragging?: boolean; isDraggedOut?: boolean; - layout?: ConfigLayout[]; + layout: ConfigLayout[]; forwardedRef?: React.Ref; forwardedPluginRef?: (pluginRef: PluginRef) => void; diff --git a/src/components/Item/Item.tsx b/src/components/Item/Item.tsx index 9112087..ca0ec0b 100644 --- a/src/components/Item/Item.tsx +++ b/src/components/Item/Item.tsx @@ -12,7 +12,10 @@ const b = cn('dashkit-item'); type ItemProps = { registerManager: RegisterManager; - rendererProps: Omit; + rendererProps: Omit & { + width?: number; + height?: number; + }; type: string; isPlaceholder?: boolean; forwardedPluginRef?: (pluginRef: PluginRef) => void; diff --git a/src/components/MobileLayout/MobileLayout.tsx b/src/components/MobileLayout/MobileLayout.tsx index 377b796..c9c18a4 100644 --- a/src/components/MobileLayout/MobileLayout.tsx +++ b/src/components/MobileLayout/MobileLayout.tsx @@ -33,7 +33,7 @@ export default class MobileLayout extends React.PureComponent< _memoLayout = this.context.layout; _memoForwardedPluginRef: Array<(refObject: PluginRef) => void> = []; - _memoAdjustWidgetLayout: Record void> = {}; + _memoAdjustWidgetLayout: Record void> = {}; state: MobileLayoutState = { itemsWithActiveAutoheight: {}, @@ -131,7 +131,7 @@ export default class MobileLayout extends React.PureComponent< return this._memoForwardedPluginRef[refIndex]; } - adjustWidgetLayout(id: string, {needSetDefault}: {needSetDefault: boolean}) { + adjustWidgetLayout(id: string, {needSetDefault}: {needSetDefault?: boolean}) { if (needSetDefault) { const indexesOfItemsWithActiveAutoheight = { ...this.state.itemsWithActiveAutoheight, diff --git a/src/hocs/prepareItem.js b/src/hocs/prepareItem.js deleted file mode 100644 index bc7183a..0000000 --- a/src/hocs/prepareItem.js +++ /dev/null @@ -1,111 +0,0 @@ -import React from 'react'; - -import isEqual from 'lodash/isEqual'; -import PropTypes from 'prop-types'; - -import {DashKitContext} from '../context'; - -export function prepareItem(Component) { - return class PrepareItem extends React.Component { - static propTypes = { - gridLayout: PropTypes.object, - adjustWidgetLayout: PropTypes.func.isRequired, - layout: PropTypes.array, - id: PropTypes.string, - item: PropTypes.object, - shouldItemUpdate: PropTypes.bool, - width: PropTypes.number, - height: PropTypes.number, - transform: PropTypes.string, - isPlaceholder: PropTypes.bool, - - onItemRender: PropTypes.func, - onItemMountChange: PropTypes.func, - - forwardedPluginRef: PropTypes.any, - }; - - shouldComponentUpdate(nextProps) { - const {width, height, transform} = this.props; - const {width: widthNext, height: heightNext, transform: transformNext} = nextProps; - if ( - !nextProps.shouldItemUpdate && - width === widthNext && - height === heightNext && - transform === transformNext - ) { - return false; - } - return true; - } - - static contextType = DashKitContext; - - _onStateAndParamsChange = (stateAndParams, options) => { - this.context.onItemStateAndParamsChange(this.props.id, stateAndParams, options); - }; - - _currentRenderProps = {}; - getRenderProps = () => { - const {id, width, height, item, adjustWidgetLayout, layout, isPlaceholder, gridLayout} = - this.props; - const {itemsState, itemsParams, registerManager, settings, context, editMode} = - this.context; - const {data, defaults, namespace} = item; - - const rendererProps = { - data, - editMode, - params: itemsParams[id], - state: itemsState[id], - onStateAndParamsChange: this._onStateAndParamsChange, - width, - height, - id, - defaults, - namespace, - settings, - context, - layout, - gridLayout: gridLayout || registerManager.gridLayout, - adjustWidgetLayout, - isPlaceholder, - }; - - const changedProp = Object.entries(rendererProps).find(([key, value]) => { - // Checking gridLayoout deep as groups gridProperties method has tendancy to creat new objects - if (key === 'gridLayout') { - return !isEqual(this._currentRenderProps[key], value); - } - - return this._currentRenderProps[key] !== value; - }); - - if (changedProp) { - this._currentRenderProps = rendererProps; - } - - return this._currentRenderProps; - }; - - render() { - const {item, isPlaceholder, forwardedPluginRef, onItemMountChange, onItemRender} = - this.props; - const {registerManager} = this.context; - const {type} = item; - - return ( - - ); - } - }; -} diff --git a/src/hocs/prepareItem.tsx b/src/hocs/prepareItem.tsx new file mode 100644 index 0000000..65bd4c5 --- /dev/null +++ b/src/hocs/prepareItem.tsx @@ -0,0 +1,145 @@ +import React from 'react'; + +import isEqual from 'lodash/isEqual'; + +import {DashKitContext} from '../context'; +import type {ConfigItem, ConfigLayout} from '../shared'; +import type { + ItemStateAndParams, + ItemStateAndParamsChangeOptions, +} from '../shared/types/state-and-params'; +import type {PluginRef, PluginWidgetProps, ReactGridLayoutProps} from '../typings'; +import type {RegisterManager} from '../utils/register-manager'; + +type PrepareItemProps = { + gridLayout?: ReactGridLayoutProps; + adjustWidgetLayout: PluginWidgetProps['adjustWidgetLayout']; + layout: ConfigLayout[]; + id: string; + item: ConfigItem; + shouldItemUpdate?: boolean; + width?: number; + height?: number; + transform?: string; + isPlaceholder?: boolean; + + onItemRender?: (item: ConfigItem) => void; + onItemMountChange?: (item: ConfigItem, meta: {isAsync: boolean; isMounted: boolean}) => void; + + forwardedPluginRef?: (ref: PluginRef) => void; +}; + +type RendererProps = Omit & { + width?: number; + height?: number; +}; + +type ItemComponentProps = { + rendererProps: RendererProps; + registerManager: RegisterManager; + type: string; + isPlaceholder?: boolean; + onItemMountChange?: (item: ConfigItem, meta: {isAsync: boolean; isMounted: boolean}) => void; + onItemRender?: (item: ConfigItem) => void; + forwardedPluginRef?: (ref: PluginRef) => void; + item: ConfigItem; +}; + +export function prepareItem( + WrappedComponent: React.ComponentType, +): React.ComponentClass { + return class PrepareItem extends React.Component { + static contextType = DashKitContext; + declare context: React.ContextType; + + _currentRenderProps: RendererProps = {} as RendererProps; + + shouldComponentUpdate(nextProps: PrepareItemProps) { + const {width, height, transform} = this.props; + const {width: widthNext, height: heightNext, transform: transformNext} = nextProps; + if ( + !nextProps.shouldItemUpdate && + width === widthNext && + height === heightNext && + transform === transformNext + ) { + return false; + } + return true; + } + + _onStateAndParamsChange = ( + stateAndParams: ItemStateAndParams, + options?: ItemStateAndParamsChangeOptions, + ) => { + this.context.onItemStateAndParamsChange(this.props.id, stateAndParams, options || {}); + }; + + getRenderProps = (): RendererProps => { + const {id, width, height, item, adjustWidgetLayout, layout, gridLayout} = this.props; + const {itemsState, itemsParams, registerManager, settings, context, editMode} = + this.context; + const {data, defaults, namespace} = item; + + const defaultSettings: PluginWidgetProps['settings'] = { + autoupdateInterval: 0, + silentLoading: false, + }; + const defaultContext: PluginWidgetProps['context'] = {}; + + const rendererProps: RendererProps = { + data, + editMode, + params: itemsParams[id] as RendererProps['params'], + state: itemsState?.[id] || {}, + onStateAndParamsChange: this._onStateAndParamsChange, + width, + height, + id, + defaults, + namespace, + settings: settings || defaultSettings, + context: context || defaultContext, + layout: layout as RendererProps['layout'], + gridLayout: (gridLayout || + registerManager.gridLayout) as RendererProps['gridLayout'], + adjustWidgetLayout, + }; + + const changedProp = Object.entries(rendererProps).find(([key, value]) => { + // Checking gridLayoout deep as groups gridProperties method has tendancy to creat new objects + if (key === 'gridLayout') { + return !isEqual(this._currentRenderProps[key as keyof RendererProps], value); + } + + return this._currentRenderProps[key as keyof RendererProps] !== value; + }); + + if (changedProp) { + this._currentRenderProps = rendererProps; + } + + return this._currentRenderProps; + }; + + render() { + const {item, isPlaceholder, forwardedPluginRef, onItemMountChange, onItemRender} = + this.props; + const {registerManager} = this.context; + const {type} = item; + + return ( + + ); + } + }; +}