diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/format/BlockFormatView.tsx b/demo/scripts/controlsV2/sidePane/contentModel/components/format/BlockFormatView.tsx index a4e0621e6691..33b51e72a7f2 100644 --- a/demo/scripts/controlsV2/sidePane/contentModel/components/format/BlockFormatView.tsx +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/format/BlockFormatView.tsx @@ -6,6 +6,7 @@ import { DirectionFormatRenderer } from './formatPart/DirectionFormatRenderer'; import { FormatRenderer } from './utils/FormatRenderer'; import { FormatView } from './FormatView'; import { HtmlAlignFormatRenderer } from './formatPart/HtmlAlignFormatRenderer'; +import { IdFormatRenderer } from './formatPart/IdFormatRenderer'; import { LineHeightFormatRenderer } from './formatPart/LineHeightFormatRenderer'; import { MarginFormatRenderer } from './formatPart/MarginFormatRenderer'; import { PaddingFormatRenderer } from './formatPart/PaddingFormatRenderer'; @@ -14,6 +15,7 @@ import { TextIndentFormatRenderer } from './formatPart/TextIndentFormatRenderer' import { WhiteSpaceFormatRenderer } from './formatPart/WhiteSpaceFormatRenderer'; const BlockFormatRenders: FormatRenderer[] = [ + IdFormatRenderer, BackgroundColorFormatRenderer, DirectionFormatRenderer, TextAlignFormatRenderer, diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/format/LinkFormatView.tsx b/demo/scripts/controlsV2/sidePane/contentModel/components/format/LinkFormatView.tsx index d0e89c4e5ea2..eb383a6a3da9 100644 --- a/demo/scripts/controlsV2/sidePane/contentModel/components/format/LinkFormatView.tsx +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/format/LinkFormatView.tsx @@ -1,4 +1,6 @@ import * as React from 'react'; +import { BackgroundColorFormatRenderer } from './formatPart/BackgroundColorFormatRenderer'; +import { BorderFormatRenderers } from './formatPart/BorderFormatRenderers'; import { ContentModelHyperLinkFormat, LinkFormat } from 'roosterjs-content-model-types'; import { createTextFormatRenderer } from './utils/createTextFormatRenderer'; import { DisplayFormatRenderer } from './formatPart/DisplayFormatRenderer'; @@ -6,7 +8,10 @@ import { FormatRenderer } from './utils/FormatRenderer'; import { FormatView } from './FormatView'; import { MarginFormatRenderer } from './formatPart/MarginFormatRenderer'; import { PaddingFormatRenderer } from './formatPart/PaddingFormatRenderer'; +import { SizeFormatRenderers } from './formatPart/SizeFormatRenderers'; +import { TextAlignFormatRenderer } from './formatPart/TextAlignFormatRenderer'; import { TextColorFormatRenderer } from './formatPart/TextColorFormatRenderer'; +import { UndeletableFormatRenderer } from './formatPart/UndeletableFormatRenderer'; import { UnderlineFormatRenderer } from './formatPart/BasicFormatRenderers'; const LinkFormatRenderers: FormatRenderer[] = [ @@ -46,10 +51,15 @@ const LinkFormatRenderers: FormatRenderer[] = [ (format, value) => (format.relationship = value) ), TextColorFormatRenderer, + BackgroundColorFormatRenderer, UnderlineFormatRenderer, DisplayFormatRenderer, + TextAlignFormatRenderer, MarginFormatRenderer, PaddingFormatRenderer, + ...BorderFormatRenderers, + ...SizeFormatRenderers, + UndeletableFormatRenderer, ]; export function LinkFormatView(props: { format: LinkFormat }) { diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/AriaFormatRenderers.ts b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/AriaFormatRenderers.ts new file mode 100644 index 000000000000..30be85400040 --- /dev/null +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/AriaFormatRenderers.ts @@ -0,0 +1,16 @@ +import { AriaFormat } from 'roosterjs-content-model-types'; +import { createTextFormatRenderer } from '../utils/createTextFormatRenderer'; +import { FormatRenderer } from '../utils/FormatRenderer'; + +export const AriaFormatRenderers: FormatRenderer[] = [ + createTextFormatRenderer( + 'AriaDescribedBy', + format => format.ariaDescribedBy, + (format, value) => (format.ariaDescribedBy = value) + ), + createTextFormatRenderer( + 'Title', + format => format.title, + (format, value) => (format.title = value) + ), +]; diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/BoxShadowFormatRenderer.ts b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/BoxShadowFormatRenderer.ts new file mode 100644 index 000000000000..1d57922cd8bc --- /dev/null +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/BoxShadowFormatRenderer.ts @@ -0,0 +1,11 @@ +import { BoxShadowFormat } from 'roosterjs-content-model-types'; +import { createTextFormatRenderer } from '../utils/createTextFormatRenderer'; +import { FormatRenderer } from '../utils/FormatRenderer'; + +export const BoxShadowFormatRenderer: FormatRenderer = createTextFormatRenderer< + BoxShadowFormat +>( + 'BoxShadow', + format => format.boxShadow, + (format, value) => (format.boxShadow = value) +); diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/DataValueFormatRenderer.ts b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/DataValueFormatRenderer.ts new file mode 100644 index 000000000000..79d462a90f6b --- /dev/null +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/DataValueFormatRenderer.ts @@ -0,0 +1,11 @@ +import { createTextFormatRenderer } from '../utils/createTextFormatRenderer'; +import { DataValueFormat } from 'roosterjs-content-model-types'; +import { FormatRenderer } from '../utils/FormatRenderer'; + +export const DataValueFormatRenderer: FormatRenderer = createTextFormatRenderer< + DataValueFormat +>( + 'Data value', + format => format.dataValue, + (format, value) => (format.dataValue = value) +); diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/ImageStateFormatRenderer.ts b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/ImageStateFormatRenderer.ts new file mode 100644 index 000000000000..b17f92f888ab --- /dev/null +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/ImageStateFormatRenderer.ts @@ -0,0 +1,11 @@ +import { createTextFormatRenderer } from '../utils/createTextFormatRenderer'; +import { FormatRenderer } from '../utils/FormatRenderer'; +import { ImageStateFormat } from 'roosterjs-content-model-types'; + +export const ImageStateFormatRenderer: FormatRenderer = createTextFormatRenderer< + ImageStateFormat +>( + 'ImageState', + format => format.imageState, + (format, value) => (format.imageState = value) +); diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/LegacyTableBorderFormatRenderers.ts b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/LegacyTableBorderFormatRenderers.ts new file mode 100644 index 000000000000..f0e3c15dc9a1 --- /dev/null +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/LegacyTableBorderFormatRenderers.ts @@ -0,0 +1,21 @@ +import { createTextFormatRenderer } from '../utils/createTextFormatRenderer'; +import { FormatRenderer } from '../utils/FormatRenderer'; +import { LegacyTableBorderFormat } from 'roosterjs-content-model-types'; + +export const LegacyTableBorderFormatRenderers: FormatRenderer[] = [ + createTextFormatRenderer( + 'LegacyTableBorder', + format => format.legacyTableBorder, + (format, value) => (format.legacyTableBorder = value) + ), + createTextFormatRenderer( + 'CellSpacing', + format => format.cellSpacing, + (format, value) => (format.cellSpacing = value) + ), + createTextFormatRenderer( + 'CellPadding', + format => format.cellPadding, + (format, value) => (format.cellPadding = value) + ), +]; diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/RoleFormatRenderer.ts b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/RoleFormatRenderer.ts new file mode 100644 index 000000000000..6f53c6594860 --- /dev/null +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/RoleFormatRenderer.ts @@ -0,0 +1,9 @@ +import { createTextFormatRenderer } from '../utils/createTextFormatRenderer'; +import { FormatRenderer } from '../utils/FormatRenderer'; +import { RoleFormat } from 'roosterjs-content-model-types'; + +export const RoleFormatRenderer: FormatRenderer = createTextFormatRenderer( + 'Role', + format => format.role, + (format, value) => (format.role = value) +); diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/UndeletableFormatRenderer.ts b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/UndeletableFormatRenderer.ts new file mode 100644 index 000000000000..ee095b7ff3c0 --- /dev/null +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/format/formatPart/UndeletableFormatRenderer.ts @@ -0,0 +1,11 @@ +import { createCheckboxFormatRenderer } from '../utils/createCheckboxFormatRenderer'; +import { FormatRenderer } from '../utils/FormatRenderer'; +import { UndeletableFormat } from 'roosterjs-content-model-types'; + +export const UndeletableFormatRenderer: FormatRenderer = createCheckboxFormatRenderer< + UndeletableFormat +>( + 'Undeletable', + format => format.undeletable, + (format, value) => (format.undeletable = value) +); diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelDataView.scss b/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelDataView.scss new file mode 100644 index 000000000000..70cfac5e52a9 --- /dev/null +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelDataView.scss @@ -0,0 +1,3 @@ +.modelData { + background-color: #609; +} diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelDataView.tsx b/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelDataView.tsx new file mode 100644 index 000000000000..ceb1fa20956f --- /dev/null +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelDataView.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import { ContentModelData, ContentModelDataFormat } from 'roosterjs-content-model-types'; +import { ContentModelView } from '../ContentModelView'; +import { DataValueFormatRenderer } from '../format/formatPart/DataValueFormatRenderer'; +import { FormatRenderer } from '../format/utils/FormatRenderer'; +import { FormatView } from '../format/FormatView'; + +const DataRenderers: FormatRenderer[] = [DataValueFormatRenderer]; + +const styles = require('./ContentModelDataView.scss'); + +export function ContentModelDataView(props: { data: ContentModelData }) { + const { data } = props; + + const getFormat = React.useCallback(() => { + return ; + }, [data.format]); + + return ( + + ); +} diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelEntityView.tsx b/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelEntityView.tsx index 74c65e90c6a8..aa108f0c9070 100644 --- a/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelEntityView.tsx +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelEntityView.tsx @@ -12,10 +12,12 @@ export function ContentModelEntityView(props: { entity: ContentModelEntity }) { const [id, setId] = useProperty(entity.entityFormat.id); const [isReadonly, setIsReadonly] = useProperty(entity.entityFormat.isReadonly); + const [isFakeEntity, setIsFakeEntity] = useProperty(entity.entityFormat.isFakeEntity); const [type, setType] = useProperty(entity.entityFormat.entityType); const idTextBox = React.useRef(null); const isReadonlyCheckBox = React.useRef(null); + const isFakeEntityCheckBox = React.useRef(null); const typeTextBox = React.useRef(null); const onIdChange = React.useCallback(() => { @@ -33,6 +35,11 @@ export function ContentModelEntityView(props: { entity: ContentModelEntity }) { entity.entityFormat.isReadonly = newValue; setIsReadonly(newValue); }, [id, setId]); + const onFakeEntityChange = React.useCallback(() => { + const newValue = isFakeEntityCheckBox.current.checked; + entity.entityFormat.isFakeEntity = newValue; + setIsFakeEntity(newValue); + }, [isFakeEntity, setIsFakeEntity]); const getContent = React.useCallback(() => { return ( @@ -53,9 +60,18 @@ export function ContentModelEntityView(props: { entity: ContentModelEntity }) { onChange={onReadonlyChange} /> +
+ IsFakeEntity: + +
); - }, [type, isReadonly, id]); + }, [type, isReadonly, isFakeEntity, id]); const getFormat = React.useCallback(() => { return ( diff --git a/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelImageView.tsx b/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelImageView.tsx index 56389746bda7..9b9e77f76296 100644 --- a/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelImageView.tsx +++ b/demo/scripts/controlsV2/sidePane/contentModel/components/model/ContentModelImageView.tsx @@ -1,13 +1,18 @@ import * as React from 'react'; +import { BorderFormatRenderers } from '../format/formatPart/BorderFormatRenderers'; +import { BoxShadowFormatRenderer } from '../format/formatPart/BoxShadowFormatRenderer'; import { ContentModelCodeView } from './ContentModelCodeView'; +import { ContentModelDataView } from './ContentModelDataView'; import { ContentModelImage, ContentModelImageFormat } from 'roosterjs-content-model-types'; import { ContentModelLinkView } from './ContentModelLinkView'; import { ContentModelView } from '../ContentModelView'; +import { DisplayFormatRenderer } from '../format/formatPart/DisplayFormatRenderer'; import { FloatFormatRenderer } from '../format/formatPart/FloatFormatRenderer'; import { FormatRenderer } from '../format/utils/FormatRenderer'; import { FormatView } from '../format/FormatView'; import { IdFormatRenderer } from '../format/formatPart/IdFormatRenderer'; import { ImageMetadataFormatRenderers } from '../format/formatPart/ImageMetadataFormatRenderers'; +import { ImageStateFormatRenderer } from '../format/formatPart/ImageStateFormatRenderer'; import { MarginFormatRenderer } from '../format/formatPart/MarginFormatRenderer'; import { MetadataView } from '../format/MetadataView'; import { PaddingFormatRenderer } from '../format/formatPart/PaddingFormatRenderer'; @@ -15,6 +20,7 @@ import { SegmentFormatView } from '../format/SegmentFormatView'; import { SizeFormatRenderers } from '../format/formatPart/SizeFormatRenderers'; import { updateImageMetadata } from 'roosterjs-content-model-dom'; import { useProperty } from '../../hooks/useProperty'; +import { VerticalAlignFormatRenderer } from '../format/formatPart/VerticalAlignFormatRenderer'; const styles = require('./ContentModelImageView.scss'); @@ -23,15 +29,24 @@ const ImageFormatRenderers: FormatRenderer[] = [ ...SizeFormatRenderers, MarginFormatRenderer, PaddingFormatRenderer, + ...BorderFormatRenderers, + BoxShadowFormatRenderer, + DisplayFormatRenderer, FloatFormatRenderer, + VerticalAlignFormatRenderer, + ImageStateFormatRenderer, ]; export function ContentModelImageView(props: { image: ContentModelImage }) { const { image } = props; const srcTextArea = React.useRef(null); + const altInput = React.useRef(null); + const titleInput = React.useRef(null); const imageSelectionCheckBox = React.useRef(null); const [src, setSrc] = useProperty(image.src); + const [alt, setAlt] = useProperty(image.alt || ''); + const [title, setTitle] = useProperty(image.title || ''); const [imageSelected, setImageSelected] = useProperty( image.isSelectedAsImageSelection || false ); @@ -50,6 +65,13 @@ export function ContentModelImageView(props: { image: ContentModelImage }) { <>