diff --git a/README.md b/README.md index 34b4c32..0ac8ae0 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,8 @@ interface DashKitProps { noOverlay?: boolean; focusable?: boolean; draggableHandleClassName?: string; + getPreparedCopyItemOptions?: (options: PreparedCopyItemOptions) => PreparedCopyItemOptions; + onCopyFulfill?: (error: null | Error, data?: PreparedCopyItemOptions) => void; } ``` @@ -84,6 +86,8 @@ interface DashKitProps { - **onResizeStart**: ReactGridLayout called when item resize started - **onResize**: ReactGridLayout called while item resizing - **onResizeStop**: ReactGridLayout called when item resize stoped +- **getPreparedCopyItemOptions**: Called for converting copied item to serializable object before saving it to localstorage. It should be used instead of deprecated `context.getPreparedCopyItemOptions` prop +- **onCopyFulfill**: Called when item copy finished with `error=null` and defined `data` on successful operation done and with `error: Error` without `data` otherwise ## Usage diff --git a/src/components/DashKit/DashKit.tsx b/src/components/DashKit/DashKit.tsx index d3a7121..af418f2 100644 --- a/src/components/DashKit/DashKit.tsx +++ b/src/components/DashKit/DashKit.tsx @@ -29,9 +29,10 @@ import { import {RegisterManager, UpdateManager, reflowLayout} from '../../utils'; import DashKitView from '../DashKitView/DashKitView'; import GridLayout from '../GridLayout/GridLayout'; -import {OverlayControlItem} from '../OverlayControls/OverlayControls'; +import {OverlayControlItem, OverlayControlsCtxShape} from '../OverlayControls/OverlayControls'; -interface DashKitGeneralProps { +interface DashKitGeneralProps + extends Pick { config: Config; editMode: boolean; draggableHandleClassName?: string; diff --git a/src/components/DashKit/__stories__/DashKitShowcase.tsx b/src/components/DashKit/__stories__/DashKitShowcase.tsx index e706f07..f7b6d94 100644 --- a/src/components/DashKit/__stories__/DashKitShowcase.tsx +++ b/src/components/DashKit/__stories__/DashKitShowcase.tsx @@ -236,6 +236,9 @@ export class DashKitShowcase extends React.Component<{}, DashKitDemoState> { overlayControls={this.state.enableOverlayControls ? this.controls : null} overlayMenuItems={this.state.overlayMenuItems} focusable={true} + onCopyFulfill={(_error, data) => + console.info('Copied: ' + JSON.stringify(data)) + } /> diff --git a/src/components/OverlayControls/OverlayControls.tsx b/src/components/OverlayControls/OverlayControls.tsx index 7a11aec..cef6744 100644 --- a/src/components/OverlayControls/OverlayControls.tsx +++ b/src/components/OverlayControls/OverlayControls.tsx @@ -94,7 +94,7 @@ export type PreparedCopyItemOptions = PreparedCopyItemOpt copyContext?: C; }; -type DashKitCtx = React.Context<{ +export interface OverlayControlsCtxShape { overlayControls?: Record; context: Record; menu: MenuItem[]; @@ -103,7 +103,11 @@ type DashKitCtx = React.Context<{ editItem: (item: ConfigItem) => void; removeItem: (id: string) => void; getLayoutItem: (id: string) => ConfigLayout | void; -}>; + getPreparedCopyItemOptions?: (options: PreparedCopyItemOptions) => PreparedCopyItemOptions; + onCopyFulfill?: (error: null | Error, data?: PreparedCopyItemOptions) => void; +} + +type OverlayControlsCtx = React.Context; const DEFAULT_DROPDOWN_MENU = [MenuItems.Copy, MenuItems.Delete]; @@ -114,7 +118,7 @@ class OverlayControls extends React.Component { view: 'flat', size: 'm', }; - context!: React.ContextType; + context!: React.ContextType; render() { const {position} = this.props; const items = this.getItems(); @@ -405,11 +409,27 @@ class OverlayControls extends React.Component { targetInnerId, }; - if (typeof this.context.context?.getPreparedCopyItemOptions === 'function') { + if (this.context.context?.getPreparedCopyItemOptions) { + console.warn?.( + '`context.getPreparedCopyItemOptions` is deprecated. Please use `getPreparedCopyItemOptions` prop instead', + ); + } + + const getPreparedCopyItemOptions = + this.context?.getPreparedCopyItemOptions ?? + this.context.context?.getPreparedCopyItemOptions; + + if (typeof getPreparedCopyItemOptions === 'function') { options = this.context.context.getPreparedCopyItemOptions(options); } - localStorage.setItem(COPIED_WIDGET_STORE_KEY, JSON.stringify(options)); + try { + localStorage.setItem(COPIED_WIDGET_STORE_KEY, JSON.stringify(options)); + this.context.onCopyFulfill?.(null, options); + } catch (e) { + const error = e instanceof Error ? e : new Error('Unknown error while copying item'); + this.context.onCopyFulfill?.(error); + } // https://stackoverflow.com/questions/35865481/storage-event-not-firing window.dispatchEvent(new Event('storage')); this.props.onItemClick?.(); diff --git a/src/hocs/withContext.js b/src/hocs/withContext.js index 227183e..833e226 100644 --- a/src/hocs/withContext.js +++ b/src/hocs/withContext.js @@ -520,12 +520,16 @@ function useMemoStateContext(props) { editItem: props.onItemEdit, removeItem: onItemRemove, getLayoutItem: getLayoutItem, + getPreparedCopyItemOptions: props.getPreparedCopyItemOptions, + onCopyFulfill: props.onCopyFulfill, }), [ props.overlayControls, props.context, props.itemsStateAndParams, props.onItemEdit, + props.getPreparedCopyItemOptions, + props.onCopyFulfill, overlayMenuItems, itemsParams, onItemRemove,