-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Separate InlineToolbar UI and business logic (#91)
* Separate InlineToolbar UI and business logic * Remova hasActions from InlineToolFacade * Fix lint * Add docs after review * Merge main
- Loading branch information
Showing
15 changed files
with
374 additions
and
206 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import 'reflect-metadata'; | ||
import { Service } from 'typedi'; | ||
|
||
import { SelectionManager } from '../components/SelectionManager.js'; | ||
import { createInlineToolName } from '@editorjs/model'; | ||
import { InlineToolFormatData } from '@editorjs/sdk'; | ||
|
||
/** | ||
* Selection API class | ||
* - provides methods to work with selection | ||
*/ | ||
@Service() | ||
export class SelectionAPI { | ||
#selectionManager: SelectionManager; | ||
|
||
/** | ||
* SelectionAPI class constructor | ||
* @param selectionManager - SelectionManager instance to work with selection and inline fotmatting | ||
*/ | ||
constructor( | ||
selectionManager: SelectionManager | ||
) { | ||
this.#selectionManager = selectionManager; | ||
}; | ||
|
||
/** | ||
* Applies passed inline tool to the current selection | ||
* @param toolName - Inline Tool name from the config to apply on the current selection | ||
* @param data - Inline Tool data to apply to the current selection (eg. link data) | ||
*/ | ||
public applyInlineToolForCurrentSelection(toolName: string, data?: InlineToolFormatData): void { | ||
this.#selectionManager.applyInlineToolForCurrentSelection(createInlineToolName(toolName), data); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import 'reflect-metadata'; | ||
import { Inject, Service } from 'typedi'; | ||
import { BlocksAPI } from './BlocksAPI.js'; | ||
import { SelectionAPI } from './SelectionAPI.js'; | ||
|
||
/** | ||
* Class gathers all Editor's APIs | ||
*/ | ||
@Service() | ||
export class EditorAPI { | ||
/** | ||
* Blocks API instance to work with blocks | ||
*/ | ||
@Inject() | ||
public blocks!: BlocksAPI; | ||
|
||
/** | ||
* Selection API instance to work with selection and inline formatting | ||
*/ | ||
@Inject() | ||
public selection!: SelectionAPI; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
packages/core/src/components/EventBus/core-events/SelectionChangedCoreEvent.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import type { InlineTool } from '@editorjs/sdk'; | ||
import { CoreEventBase } from './CoreEventBase.js'; | ||
import { CoreEventType } from './CoreEventType.js'; | ||
import type { Index, InlineToolName } from '@editorjs/model'; | ||
|
||
/** | ||
* Payload of SelectionChangedCoreEvent custom event | ||
* Contains updated caret index and available inline tools | ||
*/ | ||
export interface SelectionChangedCoreEventPayload { | ||
/** | ||
* Updated caret index | ||
*/ | ||
readonly index: Index | null; | ||
|
||
/** | ||
* Inline tools available for the current selection | ||
*/ | ||
readonly availableInlineTools: Map<InlineToolName, InlineTool>; | ||
} | ||
|
||
/** | ||
* Class for event that is being fired after the selection is changed | ||
*/ | ||
export class SelectionChangedCoreEvent extends CoreEventBase<SelectionChangedCoreEventPayload> { | ||
/** | ||
* SelectionChangedCoreEvent constructor function | ||
* @param payload - SelectionChangedCoreEvent event payload with updated caret index | ||
*/ | ||
constructor(payload: SelectionChangedCoreEventPayload) { | ||
super(CoreEventType.SelectionChanged, payload); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import 'reflect-metadata'; | ||
import { FormattingAdapter } from '@editorjs/dom-adapters'; | ||
import type { CaretManagerEvents, InlineToolName } from '@editorjs/model'; | ||
import { CaretManagerCaretUpdatedEvent, Index, EditorJSModel, createInlineToolData, createInlineToolName } from '@editorjs/model'; | ||
import { EventType } from '@editorjs/model'; | ||
import { Service } from 'typedi'; | ||
import { CoreEventType, EventBus, ToolLoadedCoreEvent } from './EventBus/index.js'; | ||
import { SelectionChangedCoreEvent } from './EventBus/core-events/SelectionChangedCoreEvent.js'; | ||
import { InlineTool, InlineToolFormatData } from '@editorjs/sdk'; | ||
|
||
/** | ||
* SelectionManager responsible for handling selection changes and applying inline tools formatting | ||
*/ | ||
@Service() | ||
export class SelectionManager { | ||
/** | ||
* Editor model instance | ||
* Used for interactions with stored data | ||
*/ | ||
#model: EditorJSModel; | ||
|
||
/** | ||
* FormattingAdapter instance | ||
* Used for inline tools attaching and format apply | ||
*/ | ||
#formattingAdapter: FormattingAdapter; | ||
|
||
/** | ||
* EventBus instance to exchange events between components | ||
*/ | ||
#eventBus: EventBus; | ||
|
||
/** | ||
* Inline Tools instances available for use | ||
*/ | ||
#inlineTools: Map<InlineToolName, InlineTool> = new Map(); | ||
|
||
/** | ||
* @param model - editor model instance | ||
* @param formattingAdapter - needed for applying format to the model | ||
* @param eventBus - EventBus instance to exchange events between components | ||
*/ | ||
constructor( | ||
model: EditorJSModel, | ||
formattingAdapter: FormattingAdapter, | ||
eventBus: EventBus | ||
) { | ||
this.#model = model; | ||
this.#formattingAdapter = formattingAdapter; | ||
this.#eventBus = eventBus; | ||
|
||
this.#eventBus.addEventListener(`core:${CoreEventType.ToolLoaded}`, (event: ToolLoadedCoreEvent) => { | ||
const { tool } = event.detail; | ||
|
||
if (!tool.isInline()) { | ||
return; | ||
} | ||
|
||
const toolInstance = tool.create(); | ||
const name = createInlineToolName(tool.name); | ||
|
||
this.#inlineTools.set(name, toolInstance); | ||
|
||
this.#formattingAdapter.attachTool(name, toolInstance); | ||
}); | ||
|
||
this.#model.addEventListener(EventType.CaretManagerUpdated, (event: CaretManagerEvents) => this.#handleCaretManagerUpdate(event)); | ||
} | ||
|
||
/** | ||
* Handle changes of the caret selection | ||
* @param event - CaretManager event | ||
*/ | ||
#handleCaretManagerUpdate(event: CaretManagerEvents): void { | ||
switch (true) { | ||
case event instanceof CaretManagerCaretUpdatedEvent: | ||
this.#eventBus.dispatchEvent(new SelectionChangedCoreEvent({ | ||
index: event.detail.index !== null ? Index.parse(event.detail.index) : null, | ||
/** | ||
* @todo implement filter by current BlockTool configuration | ||
*/ | ||
availableInlineTools: this.#inlineTools, | ||
})); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
/** | ||
* Apply format with data formed in toolbar | ||
* @param toolName - name of the inline tool, whose format would be applied | ||
* @param data - fragment data for the current selection | ||
*/ | ||
public applyInlineToolForCurrentSelection(toolName: InlineToolName, data: InlineToolFormatData = {}): void { | ||
/** | ||
* @todo pass to applyFormat inline tool data formed in toolbar | ||
*/ | ||
this.#formattingAdapter.applyFormat(toolName, createInlineToolData(data)); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
packages/core/src/ui/InlineToolbar/InlineToolbarRenderedUIEvent.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { UIEventBase } from '../../components/EventBus/index.js'; | ||
|
||
/** | ||
* Payload of the InlineToolbarRenderedUIEvent | ||
* Contains InlineToolbar HTML element | ||
*/ | ||
export interface InlineToolbarRenderedUIEventPayload { | ||
/** | ||
* Toolbox HTML element | ||
*/ | ||
readonly toolbar: HTMLElement; | ||
} | ||
|
||
/** | ||
* Class for event that is being fired after the inline toolbar is rendered | ||
*/ | ||
export class InlineToolbarRenderedUIEvent extends UIEventBase<InlineToolbarRenderedUIEventPayload> { | ||
/** | ||
* ToolboxRenderedUIEvent constructor function | ||
* @param payload - ToolboxRendered event payload | ||
*/ | ||
constructor(payload: InlineToolbarRenderedUIEventPayload) { | ||
super('inline-toolbar:rendered', payload); | ||
} | ||
} |
Oops, something went wrong.
e3d47f4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coverage report for
./packages/model
Test suite run success
404 tests passing in 24 suites.
Report generated by 🧪jest coverage report action from e3d47f4
e3d47f4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Coverage report for
./packages/collaboration-manager
Test suite run success
6 tests passing in 1 suite.
Report generated by 🧪jest coverage report action from e3d47f4