0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-10 22:22:45 -05:00

refactor(console): support placeholder in code editor (#3462)

This commit is contained in:
Xiao Yijun 2023-03-17 15:48:32 +08:00 committed by GitHub
parent 9c62ade9cc
commit d462addfde
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 11 additions and 11 deletions

View file

@ -1,3 +1,4 @@
import { conditional } from '@silverhand/essentials';
import classNames from 'classnames'; import classNames from 'classnames';
import type { ChangeEvent, KeyboardEvent } from 'react'; import type { ChangeEvent, KeyboardEvent } from 'react';
import { useRef } from 'react'; import { useRef } from 'react';
@ -16,17 +17,19 @@ type Props = {
tabSize?: number; tabSize?: number;
hasError?: boolean; hasError?: boolean;
errorMessage?: string; errorMessage?: string;
placeholder?: string;
}; };
const CodeEditor = ({ const CodeEditor = ({
className, className,
language, language,
isReadonly = false, isReadonly = false,
value = '', value,
onChange, onChange,
tabSize = 2, tabSize = 2,
hasError, hasError,
errorMessage, errorMessage,
placeholder,
}: Props) => { }: Props) => {
const textareaRef = useRef<HTMLTextAreaElement>(null); const textareaRef = useRef<HTMLTextAreaElement>(null);
@ -55,7 +58,7 @@ const CodeEditor = ({
return ( return (
<> <>
<div className={classNames(styles.container, className)}> <div className={classNames(styles.container, className)}>
<CopyToClipboard value={value} variant="icon" className={styles.copy} /> <CopyToClipboard value={value ?? ''} variant="icon" className={styles.copy} />
<div className={styles.editor}> <div className={styles.editor}>
{/* SyntaxHighlighter is a readonly component, so a transparent <textarea> layer is needed {/* SyntaxHighlighter is a readonly component, so a transparent <textarea> layer is needed
in order to support user interactions, such as code editing, copy-pasting, etc. */} in order to support user interactions, such as code editing, copy-pasting, etc. */}
@ -68,6 +71,7 @@ const CodeEditor = ({
readOnly={isReadonly} readOnly={isReadonly}
spellCheck="false" spellCheck="false"
value={value} value={value}
placeholder={placeholder}
onChange={handleChange} onChange={handleChange}
onKeyDown={handleKeydown} onKeyDown={handleKeydown}
/> />
@ -93,7 +97,7 @@ const CodeEditor = ({
language={language} language={language}
style={theme} style={theme}
> >
{value} {conditional(Boolean(value) && value) ?? placeholder ?? ''}
</SyntaxHighlighter> </SyntaxHighlighter>
</div> </div>
</div> </div>

View file

@ -95,8 +95,7 @@ const SignInExperience = () => {
} }
return signInExperienceParser.toLocalForm(data); return signInExperienceParser.toLocalForm(data);
// eslint-disable-next-line react-hooks/exhaustive-deps }, [data]);
}, [data, t]); // Form data default value depends on i18n, manually trigger re-render when i18n changes.
useEffect(() => { useEffect(() => {
if (defaultFormData) { if (defaultFormData) {

View file

@ -9,7 +9,7 @@ import useDocumentationUrl from '@/hooks/use-documentation-url';
import type { SignInExperienceForm } from '../../types'; import type { SignInExperienceForm } from '../../types';
import * as tabsStyles from '../index.module.scss'; import * as tabsStyles from '../index.module.scss';
import * as brandingStyles from './index.module.scss'; import * as brandingStyles from './CustomCssForm.module.scss';
const CustomCssForm = () => { const CustomCssForm = () => {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' }); const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
@ -53,6 +53,7 @@ const CustomCssForm = () => {
className={brandingStyles.customCssCodeEditor} className={brandingStyles.customCssCodeEditor}
language="scss" language="scss"
value={value ?? undefined} value={value ?? undefined}
placeholder={t('sign_in_exp.custom_css.css_code_editor_content_placeholder')}
onChange={onChange} onChange={onChange}
/> />
)} )}

View file

@ -1,7 +1,6 @@
import type { SignInExperience, SignUp } from '@logto/schemas'; import type { SignInExperience, SignUp } from '@logto/schemas';
import { SignInMode, SignInIdentifier } from '@logto/schemas'; import { SignInMode, SignInIdentifier } from '@logto/schemas';
import { conditional } from '@silverhand/essentials'; import { conditional } from '@silverhand/essentials';
import { t } from 'i18next';
import type { DeepRequired, FieldErrorsImpl } from 'react-hook-form'; import type { DeepRequired, FieldErrorsImpl } from 'react-hook-form';
import { import {
@ -38,10 +37,7 @@ export const signInExperienceParser = {
...signInExperience, ...signInExperience,
signUp: signInExperienceParser.toLocalSignUp(signUp), signUp: signInExperienceParser.toLocalSignUp(signUp),
createAccountEnabled: signInMode !== SignInMode.SignIn, createAccountEnabled: signInMode !== SignInMode.SignIn,
// CodeEditor component can not properly handle i18n default value, put placeholder here as workaround customCss: customCss ?? undefined,
customCss: customCss?.length
? customCss
: t('admin_console.sign_in_exp.custom_css.css_code_editor_content_placeholder'),
}; };
}, },
toRemoteModel: (setup: SignInExperienceForm): SignInExperience => { toRemoteModel: (setup: SignInExperienceForm): SignInExperience => {