Skip to content

Commit 9b32b49

Browse files
committed
feat: add form orientation property to rich text modal dialogs and components
1 parent 78afa6b commit 9b32b49

File tree

10 files changed

+87
-18
lines changed

10 files changed

+87
-18
lines changed

packages/pluggableWidgets/rich-text-web/src/RichText.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@
5555
<enumerationValue key="readPanel">Read panel</enumerationValue>
5656
</enumerationValues>
5757
</property>
58+
<property key="formOrientation" type="enumeration" defaultValue="horizontal">
59+
<caption>Form orientation</caption>
60+
<description>The form orientation for modals (Insert link, Insert image, Insert video).</description>
61+
<enumerationValues>
62+
<enumerationValue key="horizontal">Horizontal</enumerationValue>
63+
<enumerationValue key="vertical">Vertical</enumerationValue>
64+
</enumerationValues>
65+
</property>
5866
</propertyGroup>
5967
<propertyGroup caption="Visibility">
6068
<systemProperty key="Visibility" />

packages/pluggableWidgets/rich-text-web/src/components/Editor.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export interface EditorProps
3838
defaultValue?: string;
3939
onTextChange?: (...args: [delta: Delta, oldContent: Delta, source: EmitterSource]) => void;
4040
onSelectionChange?: (...args: [range: Range, oldRange: Range, source: EmitterSource]) => void;
41+
formOrientation?: "horizontal" | "vertical";
4142
theme: string;
4243
style?: CSSProperties;
4344
className?: string;
@@ -216,6 +217,7 @@ const Editor = forwardRef((props: EditorProps, ref: MutableRefObject<Quill | nul
216217
imageSource={props.imageSource}
217218
imageSourceContent={props.imageSourceContent}
218219
enableDefaultUpload={props.enableDefaultUpload}
220+
formOrientation={props.formOrientation}
219221
{...dialogConfig}
220222
></Dialog>
221223
</Fragment>

packages/pluggableWidgets/rich-text-web/src/components/EditorWrapper.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ function EditorWrapperInner(props: EditorWrapperProps): ReactElement {
5252
tabIndex,
5353
imageSource,
5454
imageSourceContent,
55-
enableDefaultUpload
55+
enableDefaultUpload,
56+
formOrientation
5657
} = props;
5758

5859
const globalState = useContext(EditorContext);
@@ -215,6 +216,7 @@ function EditorWrapperInner(props: EditorWrapperProps): ReactElement {
215216
imageSource={imageSource}
216217
imageSourceContent={imageSourceContent}
217218
enableDefaultUpload={enableDefaultUpload}
219+
formOrientation={formOrientation}
218220
/>
219221
</div>
220222
{enableStatusBar && (

packages/pluggableWidgets/rich-text-web/src/components/ModalDialog/Dialog.scss

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,20 @@
144144
&-content {
145145
padding: 20px;
146146
flex: 1;
147+
148+
&.form-vertical {
149+
.form-group {
150+
flex-direction: column;
151+
152+
.col-sm-3,
153+
.col-sm-9,
154+
.col-sm-12 {
155+
max-width: 100%;
156+
padding-left: 0;
157+
padding-right: 0;
158+
}
159+
}
160+
}
147161
}
148162

149163
&-footer {

packages/pluggableWidgets/rich-text-web/src/components/ModalDialog/Dialog.tsx

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
useRole
1010
} from "@floating-ui/react";
1111
import { If } from "@mendix/widget-plugin-component-kit/If";
12+
import classNames from "classnames";
1213
import { createElement, Fragment, ReactElement } from "react";
1314
import LinkDialog, { LinkDialogProps } from "./LinkDialog";
1415
import VideoDialog, { VideoDialogProps } from "./VideoDialog";
@@ -51,13 +52,24 @@ export type ChildDialogProps =
5152

5253
export type DialogProps = BaseDialogProps &
5354
ChildDialogProps &
54-
Pick<RichTextContainerProps, "imageSource" | "imageSourceContent" | "enableDefaultUpload">;
55+
Pick<RichTextContainerProps, "imageSource" | "imageSourceContent" | "enableDefaultUpload"> & {
56+
formOrientation?: "horizontal" | "vertical";
57+
};
5558

5659
/**
5760
* Dialog components that will be shown on toolbar's button
5861
*/
5962
export default function Dialog(props: DialogProps): ReactElement {
60-
const { isOpen, onOpenChange, dialogType, config, imageSource, imageSourceContent, enableDefaultUpload } = props;
63+
const {
64+
isOpen,
65+
onOpenChange,
66+
dialogType,
67+
config,
68+
imageSource,
69+
imageSourceContent,
70+
enableDefaultUpload,
71+
formOrientation
72+
} = props;
6173
const { refs, context } = useFloating({
6274
open: isOpen,
6375
onOpenChange
@@ -81,17 +93,26 @@ export default function Dialog(props: DialogProps): ReactElement {
8193
></FloatingOverlay>
8294
<FloatingFocusManager context={context}>
8395
<div
84-
className="Dialog mx-layoutgrid widget-rich-text"
96+
className={classNames(
97+
"Dialog mx-layoutgrid widget-rich-text",
98+
formOrientation === "vertical" ? "form-vertical" : ""
99+
)}
85100
ref={refs.setFloating}
86101
aria-labelledby={dialogType}
87102
aria-describedby={dialogType}
88103
{...getFloatingProps()}
89104
>
90105
<If condition={dialogType === "link"}>
91-
<LinkDialog {...(config as LinkDialogProps)}></LinkDialog>
106+
<LinkDialog
107+
formOrientation={formOrientation}
108+
{...(config as LinkDialogProps)}
109+
></LinkDialog>
92110
</If>
93111
<If condition={dialogType === "video"}>
94-
<VideoDialog {...(config as VideoDialogProps)}></VideoDialog>
112+
<VideoDialog
113+
formOrientation={formOrientation}
114+
{...(config as VideoDialogProps)}
115+
></VideoDialog>
95116
</If>
96117
<If condition={dialogType === "view-code"}>
97118
<ViewCodeDialog {...(config as ViewCodeDialogProps)}></ViewCodeDialog>
@@ -101,6 +122,7 @@ export default function Dialog(props: DialogProps): ReactElement {
101122
imageSource={imageSource}
102123
imageSourceContent={imageSourceContent}
103124
enableDefaultUpload={enableDefaultUpload}
125+
formOrientation={formOrientation}
104126
{...(config as ImageDialogProps)}
105127
></ImageDialog>
106128
</If>

packages/pluggableWidgets/rich-text-web/src/components/ModalDialog/DialogContent.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,22 @@ export function DialogHeader(props: DialogHeaderProps): ReactElement {
3636
);
3737
}
3838

39-
export function DialogBody(props: PropsWithChildrenWithClass): ReactElement {
40-
const { children, className } = props;
39+
export function DialogBody(
40+
props: PropsWithChildrenWithClass & { formOrientation?: "horizontal" | "vertical" }
41+
): ReactElement {
42+
const { children, className, formOrientation } = props;
4143

42-
return <div className={classNames("widget-rich-text-modal-content form-horizontal", className)}>{children}</div>;
44+
return (
45+
<div
46+
className={classNames(
47+
"widget-rich-text-modal-content",
48+
formOrientation === "vertical" ? "form-vertical" : "form-horizontal",
49+
className
50+
)}
51+
>
52+
{children}
53+
</div>
54+
);
4355
}
4456

4557
export interface FormControlProps extends PropsWithChildrenWithClass {

packages/pluggableWidgets/rich-text-web/src/components/ModalDialog/ImageDialog.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ export interface ImageDialogProps extends Pick<RichTextContainerProps, "imageSou
2525
onClose(): void;
2626
defaultValue?: imageConfigType;
2727
enableDefaultUpload?: boolean;
28+
formOrientation?: "horizontal" | "vertical";
2829
}
2930

3031
export default function ImageDialog(props: ImageDialogProps): ReactElement {
31-
const { onClose, defaultValue, onSubmit, imageSource, imageSourceContent, enableDefaultUpload } = props;
32+
const { onClose, defaultValue, onSubmit, imageSource, imageSourceContent, enableDefaultUpload, formOrientation } =
33+
props;
3234
const [activeTab, setActiveTab] = useState("general");
3335
const [selectedImageEntity, setSelectedImageEntity] = useState<Image>();
3436
const imageUploadElementRef = useRef<HTMLDivElement>(null);
@@ -127,9 +129,9 @@ export default function ImageDialog(props: ImageDialogProps): ReactElement {
127129
}, [imageUploadElementRef.current]);
128130

129131
return (
130-
<DialogContent className="image-dialog">
132+
<DialogContent className={classNames("image-dialog", formOrientation === "vertical" ? "form-vertical" : "")}>
131133
<DialogHeader onClose={onClose}>{activeTab === "general" ? "Insert/Edit" : "Embed"} Images</DialogHeader>
132-
<DialogBody>
134+
<DialogBody formOrientation={formOrientation}>
133135
<div ref={imageUploadElementRef}>
134136
{!disableEmbed && (
135137
<div>

packages/pluggableWidgets/rich-text-web/src/components/ModalDialog/LinkDialog.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import { ChangeEvent, createElement, ReactElement, useState } from "react";
2+
import classNames from "classnames";
23
import { type linkConfigType } from "../../utils/formats";
34
import { DialogBody, DialogContent, DialogFooter, DialogHeader, FormControl } from "./DialogContent";
45

56
export interface LinkDialogProps {
67
onSubmit(value: linkConfigType): void;
78
onClose(): void;
89
defaultValue?: linkConfigType;
10+
formOrientation?: "horizontal" | "vertical";
911
}
1012

1113
export default function LinkDialog(props: LinkDialogProps): ReactElement {
12-
const { onSubmit, onClose } = props;
14+
const { onSubmit, onClose, formOrientation } = props;
1315
const [formState, setFormState] = useState({
1416
text: props.defaultValue?.text ?? "",
1517
href: props.defaultValue?.href ?? "",
@@ -22,9 +24,9 @@ export default function LinkDialog(props: LinkDialogProps): ReactElement {
2224
};
2325

2426
return (
25-
<DialogContent className="link-dialog">
27+
<DialogContent className={classNames("link-dialog", formOrientation === "vertical" ? "form-vertical" : "")}>
2628
<DialogHeader onClose={onClose}>Insert/Edit Link</DialogHeader>
27-
<DialogBody>
29+
<DialogBody formOrientation={formOrientation}>
2830
<FormControl label="Text">
2931
<input
3032
type="text"

packages/pluggableWidgets/rich-text-web/src/components/ModalDialog/VideoDialog.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface VideoDialogProps {
1313
onClose(): void;
1414
selection?: Range | null;
1515
defaultValue?: videoConfigType;
16+
formOrientation?: "horizontal" | "vertical";
1617
}
1718

1819
export function getValueType(value: VideoFormType): VideoFormType {
@@ -111,14 +112,14 @@ function EmbedVideoDialog(props: VideoDialogProps): ReactElement {
111112
}
112113

113114
export default function VideoDialog(props: VideoDialogProps): ReactElement {
114-
const { onClose, defaultValue } = props;
115+
const { onClose, defaultValue, formOrientation } = props;
115116
const [activeTab, setActiveTab] = useState("general");
116117
// disable embed tab if it is about modifying current video
117118
const disableEmbed = defaultValue?.src && defaultValue.src.length > 0;
118119
return (
119-
<DialogContent className="video-dialog">
120+
<DialogContent className={classNames("video-dialog", formOrientation === "vertical" ? "form-vertical" : "")}>
120121
<DialogHeader onClose={onClose}>{activeTab === "general" ? "Insert/Edit" : "Embed"} Media</DialogHeader>
121-
<DialogBody>
122+
<DialogBody formOrientation={formOrientation}>
122123
<div>
123124
<ul className="nav nav-tabs mx-tabcontainer-tabs" role="tablist">
124125
<li

packages/pluggableWidgets/rich-text-web/typings/RichTextProps.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export type ToolbarLocationEnum = "auto" | "top" | "bottom" | "hide";
1212

1313
export type ReadOnlyStyleEnum = "text" | "bordered" | "readPanel";
1414

15+
export type FormOrientationEnum = "horizontal" | "vertical";
16+
1517
export type WidthUnitEnum = "pixels" | "percentage";
1618

1719
export type HeightUnitEnum = "percentageOfWidth" | "pixels" | "percentageOfParent" | "percentageOfView";
@@ -55,6 +57,7 @@ export interface RichTextContainerProps {
5557
preset: PresetEnum;
5658
toolbarLocation: ToolbarLocationEnum;
5759
readOnlyStyle: ReadOnlyStyleEnum;
60+
formOrientation?: FormOrientationEnum;
5861
widthUnit: WidthUnitEnum;
5962
width: number;
6063
heightUnit: HeightUnitEnum;
@@ -100,6 +103,7 @@ export interface RichTextPreviewProps {
100103
preset: PresetEnum;
101104
toolbarLocation: ToolbarLocationEnum;
102105
readOnlyStyle: ReadOnlyStyleEnum;
106+
formOrientation?: FormOrientationEnum;
103107
widthUnit: WidthUnitEnum;
104108
width: number | null;
105109
heightUnit: HeightUnitEnum;

0 commit comments

Comments
 (0)