[WIKI-829] fix: add option to only show placeholder on empty editor (#8232)

* feat: add placeholderOnEmpty functionality to editor components

* Update packages/editor/src/core/extensions/placeholder.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* refactor: rename placeholderOnEmpty to showPlaceholderOnEmpty across editor components

* chore : make optional

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Vipin Chaudhary 2025-12-09 21:13:20 +05:30 committed by GitHub
parent 2f45bfb7f6
commit 69b64680d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 23 additions and 2 deletions

View file

@ -72,6 +72,7 @@ export const LiteTextEditor = React.forwardRef(function LiteTextEditor(
placeholder = t("issue.comments.placeholder"), placeholder = t("issue.comments.placeholder"),
disabledExtensions: additionalDisabledExtensions = [], disabledExtensions: additionalDisabledExtensions = [],
editorClassName = "", editorClassName = "",
showPlaceholderOnEmpty = true,
...rest ...rest
} = props; } = props;
// states // states
@ -154,6 +155,7 @@ export const LiteTextEditor = React.forwardRef(function LiteTextEditor(
}), }),
}} }}
placeholder={placeholder} placeholder={placeholder}
showPlaceholderOnEmpty={showPlaceholderOnEmpty}
containerClassName={cn(containerClassName, "relative", { containerClassName={cn(containerClassName, "relative", {
"p-2": !editable, "p-2": !editable,
})} })}

View file

@ -41,6 +41,7 @@ export function EditorWrapper(props: Props) {
handleEditorReady, handleEditorReady,
autofocus, autofocus,
placeholder, placeholder,
showPlaceholderOnEmpty,
tabIndex, tabIndex,
value, value,
} = props; } = props;
@ -67,6 +68,7 @@ export function EditorWrapper(props: Props) {
handleEditorReady, handleEditorReady,
autofocus, autofocus,
placeholder, placeholder,
showPlaceholderOnEmpty,
tabIndex, tabIndex,
value, value,
}); });

View file

@ -47,6 +47,7 @@ type TArguments = Pick<
| "isTouchDevice" | "isTouchDevice"
| "mentionHandler" | "mentionHandler"
| "placeholder" | "placeholder"
| "showPlaceholderOnEmpty"
| "tabIndex" | "tabIndex"
| "extendedEditorProps" | "extendedEditorProps"
> & { > & {
@ -65,6 +66,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
isTouchDevice = false, isTouchDevice = false,
mentionHandler, mentionHandler,
placeholder, placeholder,
showPlaceholderOnEmpty,
tabIndex, tabIndex,
editable, editable,
extendedEditorProps, extendedEditorProps,
@ -108,7 +110,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
TableCell, TableCell,
TableRow, TableRow,
CustomMentionExtension(mentionHandler), CustomMentionExtension(mentionHandler),
CustomPlaceholderExtension({ placeholder }), CustomPlaceholderExtension({ placeholder, showPlaceholderOnEmpty }),
CharacterCount, CharacterCount,
CustomColorExtension, CustomColorExtension,
CustomTextAlignExtension, CustomTextAlignExtension,

View file

@ -6,10 +6,11 @@ import type { IEditorProps } from "@/types";
type TArgs = { type TArgs = {
placeholder: IEditorProps["placeholder"]; placeholder: IEditorProps["placeholder"];
showPlaceholderOnEmpty: IEditorProps["showPlaceholderOnEmpty"];
}; };
export const CustomPlaceholderExtension = (args: TArgs) => { export const CustomPlaceholderExtension = (args: TArgs) => {
const { placeholder } = args; const { placeholder, showPlaceholderOnEmpty = false } = args;
return Placeholder.configure({ return Placeholder.configure({
placeholder: ({ editor, node }) => { placeholder: ({ editor, node }) => {
@ -29,6 +30,13 @@ export const CustomPlaceholderExtension = (args: TArgs) => {
if (shouldHidePlaceholder) return ""; if (shouldHidePlaceholder) return "";
if (showPlaceholderOnEmpty) {
const isDocumentEmpty = editor.state.doc.textContent.length === 0;
if (!isDocumentEmpty) {
return "";
}
}
if (placeholder) { if (placeholder) {
if (typeof placeholder === "string") return placeholder; if (typeof placeholder === "string") return placeholder;
else return placeholder(editor.isFocused, editor.getHTML()); else return placeholder(editor.isFocused, editor.getHTML());

View file

@ -33,6 +33,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorHookProps) =>
mentionHandler, mentionHandler,
onEditorFocus, onEditorFocus,
placeholder, placeholder,
showPlaceholderOnEmpty,
realtimeConfig, realtimeConfig,
serverHandler, serverHandler,
tabIndex, tabIndex,
@ -119,6 +120,7 @@ export const useCollaborativeEditor = (props: TCollaborativeEditorHookProps) =>
onEditorFocus, onEditorFocus,
onTransaction, onTransaction,
placeholder, placeholder,
showPlaceholderOnEmpty,
provider, provider,
tabIndex, tabIndex,
}); });

View file

@ -40,6 +40,7 @@ export const useEditor = (props: TEditorHookProps) => {
onEditorFocus, onEditorFocus,
onTransaction, onTransaction,
placeholder, placeholder,
showPlaceholderOnEmpty,
tabIndex, tabIndex,
provider, provider,
value, value,
@ -70,6 +71,7 @@ export const useEditor = (props: TEditorHookProps) => {
isTouchDevice, isTouchDevice,
mentionHandler, mentionHandler,
placeholder, placeholder,
showPlaceholderOnEmpty,
tabIndex, tabIndex,
provider, provider,
}), }),

View file

@ -164,6 +164,7 @@ export type IEditorProps = {
onEnterKeyPress?: (e?: any) => void; onEnterKeyPress?: (e?: any) => void;
onTransaction?: () => void; onTransaction?: () => void;
placeholder?: string | ((isFocused: boolean, value: string) => string); placeholder?: string | ((isFocused: boolean, value: string) => string);
showPlaceholderOnEmpty?: boolean;
tabIndex?: number; tabIndex?: number;
value?: string | null; value?: string | null;
extendedEditorProps: IEditorPropsExtended; extendedEditorProps: IEditorPropsExtended;

View file

@ -29,6 +29,7 @@ export type TEditorHookProps = TCoreHookProps &
| "onChange" | "onChange"
| "onTransaction" | "onTransaction"
| "placeholder" | "placeholder"
| "showPlaceholderOnEmpty"
| "tabIndex" | "tabIndex"
| "value" | "value"
> & { > & {
@ -50,6 +51,7 @@ export type TCollaborativeEditorHookProps = TCoreHookProps &
| "onChange" | "onChange"
| "onTransaction" | "onTransaction"
| "placeholder" | "placeholder"
| "showPlaceholderOnEmpty"
| "tabIndex" | "tabIndex"
> & > &
Pick< Pick<