diff --git a/demo/scripts/controlsV2/roosterjsReact/inputDialog/component/InputDialog.tsx b/demo/scripts/controlsV2/roosterjsReact/inputDialog/component/InputDialog.tsx index 2307e35c966..9576cdd066b 100644 --- a/demo/scripts/controlsV2/roosterjsReact/inputDialog/component/InputDialog.tsx +++ b/demo/scripts/controlsV2/roosterjsReact/inputDialog/component/InputDialog.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; import InputDialogItem from './InputDialogItem'; import { DefaultButton, PrimaryButton } from '@fluentui/react/lib/Button'; -import { Dialog, DialogFooter, DialogType } from '@fluentui/react/lib/Dialog'; import { getLocalizedString } from '../../common/index'; import { getObjectKeys } from 'roosterjs-content-model-dom'; +import { Dialog, DialogFooter, DialogType, IDialogContentProps } from '@fluentui/react/lib/Dialog'; import type { DialogItem } from '../type/DialogItem'; import type { CancelButtonStringKey, @@ -26,6 +26,7 @@ export interface InputDialogProps Record | null; onOk: (values: Record) => void; onCancel: () => void; + rows?: number; } /** @@ -34,11 +35,25 @@ export interface InputDialogProps( props: InputDialogProps ) { - const { items, strings, dialogTitleKey, unlocalizedTitle, onOk, onCancel, onChange } = props; - const dialogContentProps = React.useMemo( + const { + items, + strings, + dialogTitleKey, + unlocalizedTitle, + onOk, + onCancel, + onChange, + rows, + } = props; + const dialogContentProps: IDialogContentProps = React.useMemo( () => ({ type: DialogType.normal, title: getLocalizedString(strings, dialogTitleKey, unlocalizedTitle), + styles: { + innerContent: { + height: rows ? '200px' : undefined, + }, + }, }), [strings, dialogTitleKey, unlocalizedTitle] ); @@ -80,6 +95,7 @@ export default function InputDialog ))} diff --git a/demo/scripts/controlsV2/roosterjsReact/inputDialog/component/InputDialogItem.tsx b/demo/scripts/controlsV2/roosterjsReact/inputDialog/component/InputDialogItem.tsx index 4c642972037..69a62c97249 100644 --- a/demo/scripts/controlsV2/roosterjsReact/inputDialog/component/InputDialogItem.tsx +++ b/demo/scripts/controlsV2/roosterjsReact/inputDialog/component/InputDialogItem.tsx @@ -15,6 +15,7 @@ export interface InputDialogItemProps; onEnterKey: () => void; onChanged: (itemName: ItemNames, newValue: string) => void; + rows?: number; } const classNames = mergeStyleSets({ @@ -33,7 +34,7 @@ const classNames = mergeStyleSets({ export default function InputDialogItem( props: InputDialogItemProps ) { - const { itemName, strings, items, currentValues, onChanged, onEnterKey } = props; + const { itemName, strings, items, currentValues, onChanged, onEnterKey, rows } = props; const { labelKey, unlocalizedLabel, autoFocus } = items[itemName]; const value = currentValues[itemName]; const onValueChange = React.useCallback( @@ -64,6 +65,8 @@ export default function InputDialogItem diff --git a/demo/scripts/controlsV2/roosterjsReact/inputDialog/utils/showInputDialog.tsx b/demo/scripts/controlsV2/roosterjsReact/inputDialog/utils/showInputDialog.tsx index 4a69eb5d869..1e7746ae38e 100644 --- a/demo/scripts/controlsV2/roosterjsReact/inputDialog/utils/showInputDialog.tsx +++ b/demo/scripts/controlsV2/roosterjsReact/inputDialog/utils/showInputDialog.tsx @@ -28,7 +28,8 @@ export function showInputDialog - ) => Record | null + ) => Record | null, + rows?: number ): Promise | null> { return new Promise | null>(resolve => { let disposer: null | (() => void) = null; @@ -49,6 +50,7 @@ export function showInputDialog ); diff --git a/demo/scripts/controlsV2/sidePane/contentModel/ContentModelPane.tsx b/demo/scripts/controlsV2/sidePane/contentModel/ContentModelPane.tsx index b7d4e006b90..a492c87dd4b 100644 --- a/demo/scripts/controlsV2/sidePane/contentModel/ContentModelPane.tsx +++ b/demo/scripts/controlsV2/sidePane/contentModel/ContentModelPane.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { ContentModelDocument } from 'roosterjs-content-model-types'; import { ContentModelDocumentView } from './components/model/ContentModelDocumentView'; import { exportButton } from './buttons/exportButton'; +import { importModelButton } from './buttons/importModelButton'; import { refreshButton } from './buttons/refreshButton'; import { Ribbon, RibbonButton, RibbonPlugin } from '../../roosterjsReact/ribbon'; import { SidePaneElementProps } from '../SidePaneElement'; @@ -25,7 +26,7 @@ export class ContentModelPane extends React.Component< constructor(props: ContentModelPaneProps) { super(props); - this.contentModelButtons = [refreshButton, exportButton]; + this.contentModelButtons = [refreshButton, exportButton, importModelButton]; this.state = { model: null, diff --git a/demo/scripts/controlsV2/sidePane/contentModel/buttons/importModelButton.ts b/demo/scripts/controlsV2/sidePane/contentModel/buttons/importModelButton.ts new file mode 100644 index 00000000000..5caf0efd76b --- /dev/null +++ b/demo/scripts/controlsV2/sidePane/contentModel/buttons/importModelButton.ts @@ -0,0 +1,45 @@ +import { isBlockGroupOfType } from 'roosterjs-content-model-core'; +import { showInputDialog } from '../../../roosterjsReact/inputDialog/utils/showInputDialog'; +import type { RibbonButton } from '../../../roosterjsReact/ribbon/type/RibbonButton'; + +/** + * @internal + * "Import Model" button on the format ribbon + */ +export const importModelButton: RibbonButton<'buttonNameImportModel'> = { + key: 'buttonNameImportModel', + unlocalizedText: 'Import Model', + iconName: 'Installation', + isChecked: formatState => formatState.isBold, + onClick: (editor, _, strings, uiUtilities) => { + showInputDialog( + uiUtilities, + 'buttonNameImportModel', + 'Import Model', + { + model: { + autoFocus: true, + labelKey: 'buttonNameImportModel' as const, + unlocalizedLabel: 'Insert model', + initValue: '', + }, + }, + strings, + undefined /* onChange */, + 10 /* rows */ + ).then(values => { + try { + const importedModel = JSON.parse(values.model); + if (isBlockGroupOfType(importedModel, 'Document')) { + editor.formatContentModel(model => { + model.blocks = importedModel.blocks; + model.format = importedModel.format; + return true; + }); + } + } catch (e) { + throw new Error('Invalid model'); + } + }); + }, +};