import React, {
memo, useCallback, useMemo, useState,
} from 'react';
import {
type EditorTheme, type KeyMapMode, PasteMode, AllPasteMode, DEFAULT_KEYMAP, DEFAULT_PASTE_MODE, DEFAULT_THEME,
} from '@growi/editor';
import { useTranslation } from 'next-i18next';
import Image from 'next/image';
import {
Dropdown, DropdownToggle, DropdownMenu, Input, FormGroup,
} from 'reactstrap';
import { useIsIndentSizeForced } from '~/stores-universal/context';
import { useEditorSettings, useCurrentIndentSize } from '~/stores/editor';
import {
useIsDeviceLargerThanMd,
} from '~/stores/ui';
type RadioListItemProps = {
onClick: () => void,
icon?: React.ReactNode,
text: string,
checked?: boolean
}
const RadioListItem = (props: RadioListItemProps): JSX.Element => {
const {
onClick, icon, text, checked,
} = props;
return (
{icon}
);
};
type SelectorProps = {
header: string,
onClickBefore: () => void,
items: JSX.Element,
}
const Selector = (props: SelectorProps): JSX.Element => {
const { header, onClickBefore, items } = props;
return (
);
};
type EditorThemeToLabel = {
[key in EditorTheme]: string;
}
const EDITORTHEME_LABEL_MAP: EditorThemeToLabel = {
defaultlight: 'DefaultLight',
eclipse: 'Eclipse',
basic: 'Basic',
ayu: 'Ayu',
rosepine: 'Rosé Pine',
defaultdark: 'DefaultDark',
material: 'Material',
nord: 'Nord',
cobalt: 'Cobalt',
kimbie: 'Kimbie',
};
const ThemeSelector = memo(({ onClickBefore }: {onClickBefore: () => void}): JSX.Element => {
const { t } = useTranslation();
const { data: editorSettings, update } = useEditorSettings();
const selectedTheme = editorSettings?.theme ?? DEFAULT_THEME;
const listItems = useMemo(() => (
<>
{ (Object.keys(EDITORTHEME_LABEL_MAP) as EditorTheme[]).map((theme) => {
const themeLabel = EDITORTHEME_LABEL_MAP[theme];
return (
update({ theme })} text={themeLabel} checked={theme === selectedTheme} />
);
}) }
>
), [update, selectedTheme]);
return (
);
});
ThemeSelector.displayName = 'ThemeSelector';
type KeyMapModeToLabel = {
[key in KeyMapMode]: string;
}
const KEYMAP_LABEL_MAP: KeyMapModeToLabel = {
default: 'Default',
vim: 'Vim',
emacs: 'Emacs',
vscode: 'Visual Studio Code',
};
const KeymapSelector = memo(({ onClickBefore }: {onClickBefore: () => void}): JSX.Element => {
const { t } = useTranslation();
const { data: editorSettings, update } = useEditorSettings();
const selectedKeymapMode = editorSettings?.keymapMode ?? DEFAULT_KEYMAP;
const listItems = useMemo(() => (
<>
{ (Object.keys(KEYMAP_LABEL_MAP) as KeyMapMode[]).map((keymapMode) => {
const keymapLabel = KEYMAP_LABEL_MAP[keymapMode];
const icon = (keymapMode !== 'default')
?
: null;
return (
update({ keymapMode })} icon={icon} text={keymapLabel} checked={keymapMode === selectedKeymapMode} />
);
}) }
>
), [update, selectedKeymapMode]);
return (
);
});
KeymapSelector.displayName = 'KeymapSelector';
const TYPICAL_INDENT_SIZE = [2, 4];
const IndentSizeSelector = memo(({ onClickBefore }: {onClickBefore: () => void}): JSX.Element => {
const { t } = useTranslation();
const { data: currentIndentSize, mutate: mutateCurrentIndentSize } = useCurrentIndentSize();
const listItems = useMemo(() => (
<>
{ TYPICAL_INDENT_SIZE.map((indent) => {
return (
mutateCurrentIndentSize(indent)} text={indent.toString()} checked={indent === currentIndentSize} />
);
}) }
>
), [currentIndentSize, mutateCurrentIndentSize]);
return (
);
});
IndentSizeSelector.displayName = 'IndentSizeSelector';
const PasteSelector = memo(({ onClickBefore }: {onClickBefore: () => void}): JSX.Element => {
const { t } = useTranslation();
const { data: editorSettings, update } = useEditorSettings();
const selectedPasteMode = editorSettings?.pasteMode ?? DEFAULT_PASTE_MODE;
const listItems = useMemo(() => (
<>
{ (AllPasteMode).map((pasteMode) => {
return (
update({ pasteMode })} text={t(`page_edit.paste.${pasteMode}`) ?? ''} checked={pasteMode === selectedPasteMode} />
);
}) }
>
), [update, t, selectedPasteMode]);
return (
);
});
PasteSelector.displayName = 'PasteSelector';
type SwitchItemProps = {
inputId: string,
onChange: () => void,
checked: boolean,
text: string,
};
const SwitchItem = memo((props: SwitchItemProps): JSX.Element => {
const {
inputId, onChange, checked, text,
} = props;
return (
);
});
const ConfigurationSelector = memo((): JSX.Element => {
const { t } = useTranslation();
const { data: editorSettings, update } = useEditorSettings();
const renderActiveLineMenuItem = useCallback(() => {
if (editorSettings == null) {
return <>>;
}
const isActive = editorSettings.styleActiveLine;
return (
update({ styleActiveLine: !isActive })}
checked={isActive}
text={t('page_edit.Show active line')}
/>
);
}, [editorSettings, update, t]);
const renderMarkdownTableAutoFormattingMenuItem = useCallback(() => {
if (editorSettings == null) {
return <>>;
}
const isActive = editorSettings.autoFormatMarkdownTable;
return (
update({ autoFormatMarkdownTable: !isActive })}
checked={isActive}
text={t('page_edit.auto_format_table')}
/>
);
}, [editorSettings, t, update]);
return (
{renderActiveLineMenuItem()}
{renderMarkdownTableAutoFormattingMenuItem()}
);
});
ConfigurationSelector.displayName = 'ConfigurationSelector';
type ChangeStateButtonProps = {
onClick: () => void,
header: string,
data: string,
disabled?: boolean,
}
const ChangeStateButton = memo((props: ChangeStateButtonProps): JSX.Element => {
const {
onClick, header, data, disabled,
} = props;
return (
);
});
const OptionsStatus = {
Home: 'Home',
Theme: 'Theme',
Keymap: 'Keymap',
Indent: 'Indent',
Paste: 'Paste',
} as const;
type OptionStatus = typeof OptionsStatus[keyof typeof OptionsStatus];
export const OptionsSelector = (): JSX.Element => {
const { t } = useTranslation();
const [dropdownOpen, setDropdownOpen] = useState(false);
const [status, setStatus] = useState(OptionsStatus.Home);
const { data: editorSettings } = useEditorSettings();
const { data: currentIndentSize } = useCurrentIndentSize();
const { data: isIndentSizeForced } = useIsIndentSizeForced();
const { data: isDeviceLargerThanMd } = useIsDeviceLargerThanMd();
if (editorSettings == null || currentIndentSize == null || isIndentSizeForced == null) {
return <>>;
}
return (
{ setStatus(OptionsStatus.Home); setDropdownOpen(!dropdownOpen) }} direction="up" className="">
settings
{
isDeviceLargerThanMd
?
: <>>
}
{
status === OptionsStatus.Home && (
setStatus(OptionsStatus.Theme)}
header={t('page_edit.theme')}
data={EDITORTHEME_LABEL_MAP[editorSettings.theme ?? ''] ?? ''}
/>
setStatus(OptionsStatus.Keymap)}
header={t('page_edit.keymap')}
data={KEYMAP_LABEL_MAP[editorSettings.keymapMode ?? ''] ?? ''}
/>
setStatus(OptionsStatus.Indent)}
header={t('page_edit.indent')}
data={currentIndentSize.toString() ?? ''}
/>
setStatus(OptionsStatus.Paste)}
header={t('page_edit.paste.title')}
data={t(`page_edit.paste.${editorSettings.pasteMode ?? PasteMode.both}`) ?? ''}
/>
)
}
{ status === OptionsStatus.Theme && (
setStatus(OptionsStatus.Home)} />
)
}
{ status === OptionsStatus.Keymap && (
setStatus(OptionsStatus.Home)} />
)
}
{ status === OptionsStatus.Indent && (
setStatus(OptionsStatus.Home)} />
)
}
{ status === OptionsStatus.Paste && (
setStatus(OptionsStatus.Home)} />
)}
);
};