Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ActionBarItem } from 'src/components/action-bar/action-bar.types';
import { ListSeparator } from 'src/components/list/list-item.types';
import { EditorMenuTypes } from './types';
import { EditorMenuTypes, EditorPluginTypes } from './types';
import { cloneDeep } from 'lodash-es';

const getCommandSymbols = (): {
Expand Down Expand Up @@ -120,6 +120,49 @@ const textEditorMenuItems: Array<

export const getTextEditorMenuItems = () => cloneDeep(textEditorMenuItems);

const secondaryMenuItems: Array<
ActionBarItem<EditorMenuTypes> | ListSeparator
> = [
{
value: EditorPluginTypes.Attach,
text: 'Attach',
icon: 'plus',
iconOnly: true,
},
{
value: EditorPluginTypes.Mention,
text: 'Mention',
icon: '-lime-logo-outlined-colored',
iconOnly: true,
},
{
value: EditorPluginTypes.Tag,
text: 'Tag',
icon: 'hashtag',
iconOnly: true,
},
{
separator: true,
},
{
value: EditorPluginTypes.Emoji,
text: 'Emoji',
icon: 'happy',
iconOnly: true,
},
{
separator: true,
},
{
value: 'Awimbowe',
text: 'Awimbowe',
icon: 'octopus',
iconOnly: true,
},
];

export const getSecondaryMenuItems = () => cloneDeep(secondaryMenuItems);

export const menuTranslationIDs = {
strong: 'editor-menu.bold',
em: 'editor-menu.italic',
Expand Down
14 changes: 14 additions & 0 deletions src/components/text-editor/prosemirror-adapter/menu/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ export const editorMenuTypesArray: EditorMenuTypes[] = Object.values(
EditorMenuTypes,
) as EditorMenuTypes[];

export const EditorPluginTypes = {
Mention: 'mention',
Emoji: 'emoji',
Attach: 'attach',
Tag: 'tag',
};

export type EditorPluginTypes =
(typeof EditorPluginTypes)[keyof typeof EditorPluginTypes];

export const editorPluginTypesArray: EditorPluginTypes[] = Object.values(
EditorPluginTypes,
) as EditorPluginTypes[];

/**
* `LevelMapping` is used to map string identifiers to numerical header levels.
* It provides a way to represent different levels of headings in ProseMirror commands.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Plugin, PluginKey } from 'prosemirror-state';
import { EditorPluginTypes, editorPluginTypesArray } from '../menu/types';

export const secondaryActionBarInteractionPluginKey = new PluginKey(
'secondaryActionBarInteractionPlugin',
);

export const createSecondaryActionBarInteractionPlugin = () => {
return new Plugin({
key: secondaryActionBarInteractionPluginKey,
props: {
handleDOMEvents: {
secondaryActionBarItemClick: (_, event) => {
event.preventDefault();
event.stopPropagation();
const { value } = event.detail;

if (
!editorPluginTypesArray.includes(
value as EditorPluginTypes,
)
) {
console.log(

Check failure on line 23 in src/components/text-editor/prosemirror-adapter/plugins/secondary-menu-action-interaction-plugin.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected console statement
'should emit an event to consumer: ',
value,
);

return false;
}

console.log('we have a plugin: ', value);

Check failure on line 31 in src/components/text-editor/prosemirror-adapter/plugins/secondary-menu-action-interaction-plugin.ts

View workflow job for this annotation

GitHub Actions / Lint

Unexpected console statement

return true;
},
},
},
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
div[contenteditable='true'] {
height: 100%;
}
div.secondary-toolbar {
order: 3;
margin-top: auto;
}
}

* {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@ import { keymap } from 'prosemirror-keymap';
import { ActionBarItem } from 'src/components/action-bar/action-bar.types';
import { ListSeparator } from 'src/components/list/list-item.types';
import { MenuCommandFactory } from './menu/menu-commands';
import { menuTranslationIDs, getTextEditorMenuItems } from './menu/menu-items';
import {
menuTranslationIDs,
getTextEditorMenuItems,
getSecondaryMenuItems,
} from './menu/menu-items';
import { ContentTypeConverter } from '../utils/content-type-converter';
import { MarkdownConverter } from '../utils/markdown-converter';
import { HTMLConverter } from '../utils/html-converter';
import {
EditorMenuTypes,
EditorPluginTypes,
EditorTextLink,
editorMenuTypesArray,
} from './menu/types';
Expand All @@ -40,6 +45,7 @@ import {
import { createImageRemoverPlugin } from './plugins/image-remover-plugin';
import { createMenuStateTrackingPlugin } from './plugins/menu-state-tracking-plugin';
import { createActionBarInteractionPlugin } from './plugins/menu-action-interaction-plugin';
import { createSecondaryActionBarInteractionPlugin } from './plugins/secondary-menu-action-interaction-plugin';

const DEBOUNCE_TIMEOUT = 300;

Expand Down Expand Up @@ -91,6 +97,11 @@ export class ProsemirrorAdapter {
ActionBarItem<EditorMenuTypes> | ListSeparator
> = [];

@State()
private secondaryActionBarItems: Array<
ActionBarItem<EditorMenuTypes> | ListSeparator
> = [];

@State()
private link: EditorTextLink = { href: '' };

Expand All @@ -104,6 +115,7 @@ export class ProsemirrorAdapter {
private schema: Schema;
private contentConverter: ContentTypeConverter;
private actionBarElement: HTMLElement;
private secondaryActionBarElement: HTMLElement;
private lastEmittedValue: string;
private changeWaiting = false;

Expand Down Expand Up @@ -183,15 +195,23 @@ export class ProsemirrorAdapter {

public render() {
return [
<div id="editor" />,
<div class="toolbar">
<div key="editor" id="editor" />,
<div key="toolbar" class="toolbar">
<limel-action-bar
ref={(el) => (this.actionBarElement = el)}
accessibleLabel="Toolbar"
actions={this.actionBarItems}
onItemSelected={this.handleActionBarItem}
/>
</div>,
<div key="secondary-toolbar" class="secondary-toolbar">
<limel-action-bar
ref={(el) => (this.secondaryActionBarElement = el)}
accessibleLabel="Secondary toolbar"
actions={this.secondaryActionBarItems}
onItemSelected={this.handleSecondaryActionBarItem}
/>
</div>,
this.renderLinkMenu(),
];
}
Expand Down Expand Up @@ -236,6 +256,9 @@ export class ProsemirrorAdapter {
this.actionBarItems = getTextEditorMenuItems().map(
this.getTranslatedItem,
);
this.secondaryActionBarItems = getSecondaryMenuItems().map(
this.getTranslatedItem,
);
};

private getTranslatedItem = (item) => {
Expand Down Expand Up @@ -310,6 +333,7 @@ export class ProsemirrorAdapter {
this.updateActiveActionBarItems,
),
createActionBarInteractionPlugin(this.menuCommandFactory),
createSecondaryActionBarInteractionPlugin(),
],
});
}
Expand Down Expand Up @@ -387,6 +411,18 @@ export class ProsemirrorAdapter {
this.view.dom.dispatchEvent(actionBarEvent);
};

private handleSecondaryActionBarItem = (
event: CustomEvent<ActionBarItem<EditorPluginTypes>>,
) => {
event.preventDefault();
event.stopImmediatePropagation();

const actionBarEvent = new CustomEvent('secondaryActionBarItemClick', {
detail: event.detail,
});
this.view.dom.dispatchEvent(actionBarEvent);
};

private handleCancelLinkMenu = (event: CustomEvent<void>) => {
event.preventDefault();
event.stopPropagation();
Expand Down
Loading