From 675c3d412cd61f8706ef67a9063107b369dcde99 Mon Sep 17 00:00:00 2001 From: Yury Kornilov Date: Mon, 1 Dec 2025 15:13:09 +0300 Subject: [PATCH] fix!: move prepareItem from JS to TS --- src/components/GridItem/GridItem.tsx | 4 +- src/components/Item/Item.tsx | 16 +--- src/components/Item/types.ts | 22 +++++ src/components/MobileLayout/MobileLayout.tsx | 4 +- src/context/DashKitContext.ts | 11 ++- src/hocs/{prepareItem.js => prepareItem.tsx} | 93 +++++++++++--------- src/typings/common.ts | 4 +- src/typings/plugin.ts | 5 +- src/utils/register-manager.ts | 6 +- 9 files changed, 96 insertions(+), 69 deletions(-) create mode 100644 src/components/Item/types.ts rename src/hocs/{prepareItem.js => prepareItem.tsx} (55%) 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..26474e7 100644 --- a/src/components/Item/Item.tsx +++ b/src/components/Item/Item.tsx @@ -1,26 +1,14 @@ import React from 'react'; import {prepareItem} from '../../hocs/prepareItem'; -import type {ConfigItem} from '../../shared/types'; -import type {PluginRef, PluginWidgetProps} from '../../typings'; import {cn} from '../../utils/cn'; -import type {RegisterManager} from '../../utils/register-manager'; + +import type {ItemProps} from './types'; import './Item.scss'; const b = cn('dashkit-item'); -type ItemProps = { - registerManager: RegisterManager; - rendererProps: Omit; - type: string; - isPlaceholder?: boolean; - forwardedPluginRef?: (pluginRef: PluginRef) => void; - onItemRender?: (item: ConfigItem) => void; - onItemMountChange?: (item: ConfigItem, meta: {isAsync: boolean; isMounted: boolean}) => void; - item: ConfigItem; -}; - // TODO: getDerivedStateFromError и заглушка с ошибкой const Item: React.FC = ({ registerManager, diff --git a/src/components/Item/types.ts b/src/components/Item/types.ts new file mode 100644 index 0000000..dd733f8 --- /dev/null +++ b/src/components/Item/types.ts @@ -0,0 +1,22 @@ +import type {ConfigItem, ItemParams} from '../../shared/types'; +import type {PluginRef, PluginWidgetProps} from '../../typings'; +import type {RegisterManager} from '../../utils/register-manager'; + +export type RendererProps = Omit< + PluginWidgetProps, + 'onBeforeLoad' | 'width' | 'height' +> & { + width?: number; + height?: number; +}; + +export type ItemProps = { + forwardedPluginRef?: (ref: PluginRef) => void; + isPlaceholder?: boolean; + item: ConfigItem; + registerManager: RegisterManager; + rendererProps: RendererProps; + type: string; + onItemRender?: (item: ConfigItem) => void; + onItemMountChange?: (item: ConfigItem, meta: {isAsync: boolean; isMounted: boolean}) => 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/context/DashKitContext.ts b/src/context/DashKitContext.ts index cdb4581..cea6881 100644 --- a/src/context/DashKitContext.ts +++ b/src/context/DashKitContext.ts @@ -11,7 +11,7 @@ import type { ItemStateAndParams, ItemStateAndParamsChangeOptions, } from '../shared'; -import type {PluginRef, ReactGridLayoutProps} from '../typings'; +import type {ContextProps, PluginRef, ReactGridLayoutProps, SettingsProps} from '../typings'; type DashkitPropsPassedToCtx = Pick< DashKitProps, @@ -42,7 +42,10 @@ type TemporaryLayout = { dragProps: ItemDragProps; }; -export type DashKitCtxShape = DashkitPropsPassedToCtx & { +export type DashKitCtxShape = Omit & { + context: ContextProps; + settings: SettingsProps; + registerManager: RegisterManager; forwardedMetaRef: React.ForwardedRef; @@ -57,12 +60,12 @@ export type DashKitCtxShape = DashkitPropsPassedToCtx & { ) => void; revertToOriginalLayout: (widgetId: string) => void; - itemsState?: Record; + itemsState: Record; itemsParams: Record; onItemStateAndParamsChange: ( id: string, stateAndParams: ItemStateAndParams, - options: ItemStateAndParamsChangeOptions, + options?: ItemStateAndParamsChangeOptions, ) => void; getItemsMeta: (pluginsRefs: Array) => Array>; diff --git a/src/hocs/prepareItem.js b/src/hocs/prepareItem.tsx similarity index 55% rename from src/hocs/prepareItem.js rename to src/hocs/prepareItem.tsx index bc7183a..3846cde 100644 --- a/src/hocs/prepareItem.js +++ b/src/hocs/prepareItem.tsx @@ -1,59 +1,69 @@ import React from 'react'; import isEqual from 'lodash/isEqual'; -import PropTypes from 'prop-types'; +import type {ItemProps, RendererProps} from '../components/Item/types'; 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'; + +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; +}; + +export function prepareItem( + WrappedComponent: React.ComponentType, +): React.ComponentClass { + return class PrepareItem extends React.Component { + static contextType = DashKitContext; + context!: React.ContextType; -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, - }; + _currentRenderProps: RendererProps = {} as RendererProps; - shouldComponentUpdate(nextProps) { + 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; - } - static contextType = DashKitContext; + return ( + nextProps.shouldItemUpdate || + width !== widthNext || + height !== heightNext || + transform !== transformNext + ); + } - _onStateAndParamsChange = (stateAndParams, options) => { + _onStateAndParamsChange = ( + stateAndParams: ItemStateAndParams, + options?: ItemStateAndParamsChangeOptions, + ) => { this.context.onItemStateAndParamsChange(this.props.id, stateAndParams, options); }; - _currentRenderProps = {}; - getRenderProps = () => { - const {id, width, height, item, adjustWidgetLayout, layout, isPlaceholder, gridLayout} = - this.props; + 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 rendererProps = { + const rendererProps: RendererProps = { data, editMode, params: itemsParams[id], @@ -69,16 +79,15 @@ export function prepareItem(Component) { 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 !isEqual(this._currentRenderProps[key as keyof RendererProps], value); } - return this._currentRenderProps[key] !== value; + return this._currentRenderProps[key as keyof RendererProps] !== value; }); if (changedProp) { @@ -95,7 +104,7 @@ export function prepareItem(Component) { const {type} = item; return ( - { id: string; @@ -31,7 +32,9 @@ export interface PluginWidgetProps { settings: SettingsProps; context: ContextProps; layout: WidgetLayout[]; - gridLayout: ReactGridLayout.ReactGridLayoutProps; + gridLayout: Omit & { + compactType?: CompactType; + }; adjustWidgetLayout: (data: { widgetId: string; needSetDefault?: boolean; diff --git a/src/utils/register-manager.ts b/src/utils/register-manager.ts index dfc129d..6b762fc 100644 --- a/src/utils/register-manager.ts +++ b/src/utils/register-manager.ts @@ -1,6 +1,6 @@ import ReactGridLayout from 'react-grid-layout'; -import type {Plugin, PluginDefaultLayout, Settings} from '../typings'; +import type {CompactType, Plugin, PluginDefaultLayout, Settings} from '../typings'; interface RegisterManagerDefaultLayout { x: number; @@ -29,7 +29,9 @@ export class RegisterManager { minW: 4, minH: 2, }; - private _gridLayout: ReactGridLayout.ReactGridLayoutProps = { + private _gridLayout: Omit & { + compactType?: CompactType; + } = { rowHeight: 18, cols: 36, margin: [2, 2],