Skip to content

Commit 6e863a3

Browse files
saxumcordissaxumcordis
andauthored
feat(bundle): added customization of display of the settings block (#740)
Co-authored-by: saxumcordis <[email protected]>
1 parent f556e08 commit 6e863a3

File tree

5 files changed

+148
-53
lines changed

5 files changed

+148
-53
lines changed

demo/components/Playground.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {defaultOptions} from '@diplodoc/transform/lib/sanitize';
55
import {Button, DropdownMenu} from '@gravity-ui/uikit';
66

77
import type {ToolbarActionData} from 'src/bundle/Editor';
8+
import type {SettingItems} from 'src/bundle/settings';
89
import type {Extension} from 'src/cm/state';
910
import {FoldingHeading} from 'src/extensions/additional/FoldingHeading';
1011
import {Math} from 'src/extensions/additional/Math';
@@ -57,7 +58,7 @@ const wCommandMenuConfig = wysiwygToolbarConfigs.wCommandMenuConfig.concat(
5758
export type PlaygroundProps = {
5859
initial?: MarkupString;
5960
allowHTML?: boolean;
60-
settingsVisible?: boolean;
61+
settingsVisible?: boolean | SettingItems[];
6162
initialEditor?: MarkdownEditorMode;
6263
preserveEmptyRows?: boolean;
6364
breaks?: boolean;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type {StoryObj} from '@storybook/react';
2+
3+
import {HideSomeSettingsDemo as component} from './HideSomeSettings';
4+
5+
export const Story: StoryObj<typeof component> = {
6+
args: {settingsVisilbe: ['toolbar']},
7+
};
8+
Story.storyName = 'Hide some settings';
9+
10+
export default {
11+
title: 'Experiments / HideSomeSettings',
12+
component,
13+
};
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import {memo, useCallback} from 'react';
2+
3+
import type {SettingItems} from 'src/bundle/settings';
4+
import {MarkdownEditorView, type RenderPreview, useMarkdownEditor} from 'src/index';
5+
6+
import {PlaygroundLayout} from '../../../components/PlaygroundLayout';
7+
import {SplitModePreview} from '../../../components/SplitModePreview';
8+
import {plugins} from '../../../defaults/md-plugins';
9+
10+
type HideSomeSettingsDemoProps = {
11+
settingsVisilbe: SettingItems[];
12+
};
13+
14+
export const HideSomeSettingsDemo = memo<HideSomeSettingsDemoProps>((props) => {
15+
const {settingsVisilbe} = props;
16+
17+
const renderPreview = useCallback<RenderPreview>(
18+
({getValue, md}) => (
19+
<SplitModePreview
20+
getValue={getValue}
21+
allowHTML={md.html}
22+
linkify={md.linkify}
23+
linkifyTlds={md.linkifyTlds}
24+
breaks={md.breaks}
25+
needToSanitizeHtml
26+
plugins={plugins}
27+
/>
28+
),
29+
[],
30+
);
31+
32+
const editor = useMarkdownEditor(
33+
{
34+
initial: {markup: ''},
35+
markupConfig: {renderPreview},
36+
},
37+
[],
38+
);
39+
40+
return (
41+
<PlaygroundLayout
42+
editor={editor}
43+
view={({className}) => (
44+
<MarkdownEditorView
45+
autofocus
46+
stickyToolbar
47+
settingsVisible={settingsVisilbe}
48+
editor={editor}
49+
className={className}
50+
/>
51+
)}
52+
/>
53+
);
54+
});
55+
56+
HideSomeSettingsDemo.displayName = 'HideSomeSettingsDemo';

src/bundle/MarkdownEditorView.tsx

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {MarkupEditorView} from './MarkupEditorView';
2525
import {SplitModeView} from './SplitModeView';
2626
import {WysiwygEditorView} from './WysiwygEditorView';
2727
import {useMarkdownEditorContext} from './context';
28-
import {EditorSettings, type EditorSettingsProps} from './settings';
28+
import {EditorSettings, type EditorSettingsProps, type SettingItems} from './settings';
2929
import {stickyCn} from './sticky';
3030
import type {MToolbarData, MToolbarItemData, WToolbarData, WToolbarItemData} from './toolbar/types';
3131
import {getToolbarsConfigs} from './toolbar/utils/toolbarsConfigs';
@@ -57,7 +57,7 @@ const EditorWrapper = forwardRef<HTMLDivElement, EditorWrapperProps>(
5757
markupHiddenActionsConfig: initialMarkupHiddenActionsConfig,
5858
markupToolbarConfig: initialMarkupToolbarConfig,
5959
qa,
60-
settingsVisible,
60+
settingsVisible: settingsVisibleProp,
6161
showPreview,
6262
stickyToolbar,
6363
toggleShowPreview,
@@ -162,6 +162,10 @@ const EditorWrapper = forwardRef<HTMLDivElement, EditorWrapperProps>(
162162
toolbarVisibility: editor.toolbarVisible && !showPreview,
163163
};
164164

165+
const areSettingsVisible =
166+
settingsVisibleProp === true ||
167+
(Array.isArray(settingsVisibleProp) && settingsVisibleProp.length > 0);
168+
165169
return (
166170
<div
167171
className={b('editor-wrapper')}
@@ -179,15 +183,15 @@ const EditorWrapper = forwardRef<HTMLDivElement, EditorWrapperProps>(
179183
directiveSyntax: editor.directiveSyntax,
180184
})}
181185
</div>
182-
<Settings {...settingsProps} settingsVisible={settingsVisible} />
186+
<Settings {...settingsProps} settingsVisible={settingsVisibleProp} />
183187
</>
184188
) : (
185189
<>
186190
{editorMode === 'wysiwyg' && (
187191
<WysiwygEditorView
188192
editor={editor}
189193
autofocus={autofocus}
190-
settingsVisible={settingsVisible}
194+
settingsVisible={areSettingsVisible}
191195
toolbarConfig={wysiwygToolbarConfig}
192196
toolbarVisible={editor.toolbarVisible}
193197
hiddenActionsConfig={wysiwygHiddenActionsConfig}
@@ -197,15 +201,15 @@ const EditorWrapper = forwardRef<HTMLDivElement, EditorWrapperProps>(
197201
>
198202
<Settings
199203
{...settingsProps}
200-
settingsVisible={settingsVisible && editor.toolbarVisible}
204+
settingsVisible={editor.toolbarVisible && settingsVisibleProp}
201205
/>
202206
</WysiwygEditorView>
203207
)}
204208
{editorMode === 'markup' && (
205209
<MarkupEditorView
206210
editor={editor}
207211
autofocus={autofocus}
208-
settingsVisible={settingsVisible}
212+
settingsVisible={areSettingsVisible}
209213
toolbarConfig={markupToolbarConfig}
210214
toolbarVisible={editor.toolbarVisible}
211215
splitMode={editor.splitMode}
@@ -217,13 +221,13 @@ const EditorWrapper = forwardRef<HTMLDivElement, EditorWrapperProps>(
217221
>
218222
<Settings
219223
{...settingsProps}
220-
settingsVisible={settingsVisible && editor.toolbarVisible}
224+
settingsVisible={editor.toolbarVisible && settingsVisibleProp}
221225
/>
222226
</MarkupEditorView>
223227
)}
224228
<Settings
225229
{...settingsProps}
226-
settingsVisible={!editor.toolbarVisible && settingsVisible}
230+
settingsVisible={!editor.toolbarVisible && settingsVisibleProp}
227231
renderPreviewButton={!editor.toolbarVisible && editorMode === 'markup'}
228232
/>
229233
</>
@@ -257,8 +261,9 @@ type ToolbarConfigs = {
257261
type ViewProps = {
258262
editor?: Editor;
259263
autofocus?: boolean;
264+
// MAJOR: rename to settings
260265
/** @default true */
261-
settingsVisible?: boolean;
266+
settingsVisible?: boolean | SettingItems[];
262267
toolbarsPreset?: ToolbarsPreset;
263268
stickyToolbar: boolean;
264269
enableSubmitInPreview?: boolean;
@@ -322,6 +327,10 @@ export const MarkdownEditorView = forwardRef<HTMLDivElement, MarkdownEditorViewP
322327
}
323328
}, [divRef, showPreview]);
324329

330+
const areSettingsVisible =
331+
settingsVisible === true ||
332+
(Array.isArray(settingsVisible) && settingsVisible.length > 0);
333+
325334
return (
326335
<ErrorBoundary
327336
onError={(e) => {
@@ -351,7 +360,7 @@ export const MarkdownEditorView = forwardRef<HTMLDivElement, MarkdownEditorViewP
351360
data-qa={qa}
352361
className={b(
353362
{
354-
settings: settingsVisible,
363+
settings: areSettingsVisible,
355364
split: markupSplitMode && editor.splitMode,
356365
},
357366
[className],

src/bundle/settings/index.tsx

Lines changed: 58 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const bContent = cn('settings-content');
3535

3636
export type EditorSettingsProps = Omit<SettingsContentProps, 'onClose'> & {
3737
renderPreviewButton?: boolean;
38-
settingsVisible?: boolean;
38+
settingsVisible?: boolean | SettingItems[];
3939
};
4040

4141
export const EditorSettings = memo<EditorSettingsProps>(function EditorSettings(props) {
@@ -44,6 +44,9 @@ export const EditorSettings = memo<EditorSettingsProps>(function EditorSettings(
4444
const [chevronElement, setChevronElement] = useState<HTMLButtonElement | null>(null);
4545
const [popupShown, , hidePopup, togglePopup] = useBooleanState(false);
4646

47+
const areSettingsVisible =
48+
settingsVisible === true || (Array.isArray(settingsVisible) && settingsVisible.length > 0);
49+
4750
return (
4851
<div className={bSettings(null, [className])}>
4952
{renderPreviewButton && (
@@ -69,7 +72,7 @@ export const EditorSettings = memo<EditorSettingsProps>(function EditorSettings(
6972
{settingsVisible && <div className={bSettings('separator')} />}
7073
</>
7174
)}
72-
{settingsVisible && (
75+
{areSettingsVisible && (
7376
<>
7477
<Button
7578
size="m"
@@ -101,6 +104,8 @@ export const EditorSettings = memo<EditorSettingsProps>(function EditorSettings(
101104
);
102105
});
103106

107+
export type SettingItems = 'mode' | 'toolbar' | 'split';
108+
104109
type SettingsContentProps = ClassNameProps &
105110
QAProps & {
106111
mode: MarkdownEditorMode;
@@ -109,6 +114,7 @@ type SettingsContentProps = ClassNameProps &
109114
onShowPreviewChange: (showPreview: boolean) => void;
110115
showPreview: boolean;
111116
toolbarVisibility: boolean;
117+
settingsVisible?: SettingItems[] | boolean;
112118
onToolbarVisibilityChange: (val: boolean) => void;
113119
splitMode?: MarkdownEditorSplitMode;
114120
splitModeEnabled?: boolean;
@@ -128,53 +134,63 @@ const SettingsContent: React.FC<SettingsContentProps> = function SettingsContent
128134
splitModeEnabled,
129135
className,
130136
showPreview,
137+
settingsVisible,
131138
qa,
132139
}) {
140+
const isSettingsArray = Array.isArray(settingsVisible);
141+
const showModeSetting = isSettingsArray ? settingsVisible?.includes('mode') : true;
142+
const showToolbarSetting = isSettingsArray ? settingsVisible?.includes('toolbar') : true;
143+
const showSplitModeSetting = isSettingsArray ? settingsVisible?.includes('split') : true;
144+
133145
return (
134146
<div className={bContent(null, [className])} data-qa={qa}>
135-
<Menu size="l" className={bContent('mode')}>
136-
<Menu.Item
137-
qa="g-md-settings-mode-wysiwyg"
138-
active={mode === 'wysiwyg'}
139-
onClick={() => {
140-
onModeChange('wysiwyg');
141-
onClose();
142-
}}
143-
iconStart={<Icon data={WysiwygModeIcon} />}
144-
>
145-
{i18n('settings_wysiwyg')}
146-
</Menu.Item>
147-
<Menu.Item
148-
qa="g-md-settings-mode-markup"
149-
active={mode === 'markup'}
150-
onClick={() => {
151-
onModeChange('markup');
152-
onClose();
153-
}}
154-
iconStart={<Icon data={LogoMarkdown} />}
155-
>
156-
{i18n('settings_markup')}
157-
<HelpMark
158-
popoverProps={{
159-
placement: mdHelpPlacement,
160-
modal: false,
147+
{showModeSetting && (
148+
<Menu size="l" className={bContent('mode')}>
149+
<Menu.Item
150+
qa="g-md-settings-mode-wysiwyg"
151+
active={mode === 'wysiwyg'}
152+
onClick={() => {
153+
onModeChange('wysiwyg');
154+
onClose();
161155
}}
162-
className={bContent('mode-help')}
156+
iconStart={<Icon data={WysiwygModeIcon} />}
163157
>
164-
<div
165-
onClick={(e) => {
166-
// stop clicks propagation
167-
// because otherwise click in MarkdownHints handled as click on MenuItem
168-
e.stopPropagation();
158+
{i18n('settings_wysiwyg')}
159+
</Menu.Item>
160+
<Menu.Item
161+
qa="g-md-settings-mode-markup"
162+
active={mode === 'markup'}
163+
onClick={() => {
164+
onModeChange('markup');
165+
onClose();
166+
}}
167+
iconStart={<Icon data={LogoMarkdown} />}
168+
>
169+
{i18n('settings_markup')}
170+
<HelpMark
171+
popoverProps={{
172+
placement: mdHelpPlacement,
173+
modal: false,
169174
}}
175+
className={bContent('mode-help')}
170176
>
171-
<MarkdownHints />
172-
</div>
173-
</HelpMark>
174-
</Menu.Item>
175-
</Menu>
176-
<div className={bContent('separator')} />
177-
{!showPreview && (
177+
<div
178+
onClick={(e) => {
179+
// stop clicks propagation
180+
// because otherwise click in MarkdownHints handled as click on MenuItem
181+
e.stopPropagation();
182+
}}
183+
>
184+
<MarkdownHints />
185+
</div>
186+
</HelpMark>
187+
</Menu.Item>
188+
</Menu>
189+
)}
190+
{showModeSetting && (showSplitModeSetting || showToolbarSetting) && (
191+
<div className={bContent('separator')} />
192+
)}
193+
{showToolbarSetting && !showPreview && (
178194
<div className={bContent('toolbar')}>
179195
<Checkbox
180196
size="m"
@@ -186,7 +202,7 @@ const SettingsContent: React.FC<SettingsContentProps> = function SettingsContent
186202
<div className={bContent('toolbar-hint')}>{i18n('settings_hint')}</div>
187203
</div>
188204
)}
189-
{splitMode && (
205+
{showSplitModeSetting && splitMode && (
190206
<div className={bContent('split-mode')}>
191207
<Checkbox
192208
size="m"

0 commit comments

Comments
 (0)