Skip to content

Commit 7af55ca

Browse files
author
Jeremy Mouton
committed
feat: enhance ProseMirror integration with NodeView types and improve image placeholder handling
1 parent bf802ac commit 7af55ca

8 files changed

Lines changed: 26 additions & 24 deletions

File tree

packages/core/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export type { EditorConfig, EditorEvents, EventHandler } from './editor';
3737
// ===========================================================================
3838

3939
export { ProseMirrorAPI } from './pm';
40-
export type { WidgetDecorationSpec, Coords, PosInfo, Command } from './pm';
40+
export type { WidgetDecorationSpec, Coords, PosInfo, Command, NodeView, NodeViewConstructor } from './pm';
4141

4242
// Re-export ProseMirror classes for convenience
4343
export {

packages/core/src/plugins/multiBlockSelectionPlugin.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
* @module
88
*/
99

10-
import { Plugin, PluginKey, EditorState, Transaction } from 'prosemirror-state';
10+
import { Plugin, PluginKey, EditorState } from 'prosemirror-state';
1111
import { EditorView, Decoration, DecorationSet } from 'prosemirror-view';
12-
import { Node as PMNode, ResolvedPos } from 'prosemirror-model';
12+
import { Node as PMNode } from 'prosemirror-model';
1313

1414
/**
1515
* State for multi-block selection.
@@ -59,9 +59,8 @@ function getBlockAtPos(
5959
*/
6060
function getAllBlockPositions(doc: PMNode): number[] {
6161
const positions: number[] = [];
62-
let pos = 0;
6362

64-
doc.forEach((node, offset) => {
63+
doc.forEach((_node, offset) => {
6564
positions.push(offset);
6665
});
6766

@@ -146,7 +145,7 @@ export function createMultiBlockSelectionPlugin(
146145
};
147146
},
148147

149-
apply(tr, state, oldEditorState, newEditorState): MultiBlockSelectionState {
148+
apply(tr, state, _oldEditorState, newEditorState): MultiBlockSelectionState {
150149
// Check for meta to update state
151150
const meta = tr.getMeta(MULTI_BLOCK_SELECTION_KEY);
152151
if (meta) {
@@ -189,7 +188,7 @@ export function createMultiBlockSelectionPlugin(
189188
return createBlockSelectionDecorations(state, pluginState.selectedBlocks);
190189
},
191190

192-
handleClick(view: EditorView, pos: number, event: MouseEvent): boolean {
191+
handleClick(view: EditorView, _pos: number, event: MouseEvent): boolean {
193192
// Clear selection on regular click without modifiers
194193
if (!event.shiftKey && !event.metaKey && !event.ctrlKey) {
195194
const state = MULTI_BLOCK_SELECTION_KEY.getState(view.state);
@@ -269,7 +268,7 @@ export function createMultiBlockSelectionPlugin(
269268

270269
const state = MULTI_BLOCK_SELECTION_KEY.getState(view.state);
271270

272-
if (event.shiftKey && state?.anchorPos !== null) {
271+
if (event.shiftKey && state && state.anchorPos !== null) {
273272
// Range selection
274273
const blocks = getBlocksInRange(view.state.doc, state.anchorPos, block.pos);
275274
view.dispatch(

packages/core/src/pm/ProseMirrorAPI.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
DecorationSet,
2727
DecorationAttrs,
2828
} from 'prosemirror-view';
29-
import type { DecorationSource } from 'prosemirror-view';
29+
import type { DecorationSource, NodeView, NodeViewConstructor } from 'prosemirror-view';
3030
import {
3131
EditorState,
3232
Transaction,
@@ -689,3 +689,5 @@ export {
689689
Slice,
690690
Fragment,
691691
};
692+
693+
export type { NodeView, NodeViewConstructor };

packages/core/src/pm/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@ export {
3535
Slice,
3636
Fragment,
3737
} from './ProseMirrorAPI';
38+
39+
export type { NodeView, NodeViewConstructor } from './ProseMirrorAPI';

packages/core/src/schema/nodes/image.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,17 @@ export const imageNode: NodeSpec = {
6262

6363
// If no src, show a placeholder
6464
if (!src) {
65-
const children: (string | (string | Record<string, string> | 0)[])[] = [
66-
[
67-
'div',
68-
{ class: 'openblock-image-placeholder' },
69-
['span', { class: 'openblock-image-placeholder-icon' }],
70-
['span', { class: 'openblock-image-placeholder-text' }, 'Click to add an image'],
71-
],
72-
];
65+
const placeholderDiv = [
66+
'div',
67+
{ class: 'openblock-image-placeholder' },
68+
['span', { class: 'openblock-image-placeholder-icon' }],
69+
['span', { class: 'openblock-image-placeholder-text' }, 'Click to add an image'],
70+
] as const;
71+
7372
if (caption) {
74-
children.push(['figcaption', {}, caption]);
73+
return ['figure', figureAttrs, placeholderDiv, ['figcaption', {}, caption]];
7574
}
76-
return ['figure', figureAttrs, ...children];
75+
return ['figure', figureAttrs, placeholderDiv];
7776
}
7877

7978
const imgAttrs: Record<string, string> = { src, alt };

packages/react/src/blocks/createReactBlockSpec.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ import React from 'react';
3131
import { createRoot, Root } from 'react-dom/client';
3232
import {
3333
type OpenBlockEditor,
34+
type NodeView,
35+
type NodeViewConstructor,
3436
Node as PMNode,
3537
EditorView,
3638
} from '@labbs/openblock-core';
37-
import type { NodeView, NodeViewConstructor } from 'prosemirror-view';
3839

3940
/**
4041
* Property schema definition for a block
@@ -208,7 +209,7 @@ export function createReactBlockSpec<T extends PropSchema>(
208209

209210
// Create NodeView constructor
210211
const createNodeView = (editor: OpenBlockEditor): NodeViewConstructor => {
211-
return (node: PMNode, _view: EditorView, _getPos: () => number | undefined): NodeView => {
212+
return (node: PMNode, _view: EditorView, _getPos: () => number | undefined, _decorations, _innerDecorations): NodeView => {
212213
// Create container
213214
const dom = document.createElement('div');
214215
dom.className = `openblock-custom-block openblock-${type}`;

packages/react/src/hooks/useOpenBlock.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ export function useOpenBlock(options: UseOpenBlockOptions = {}): OpenBlockEditor
6161
if (customBlocks && customBlocks.length > 0) {
6262
for (const blockSpec of customBlocks) {
6363
// Create a wrapper that will use the editor from the ref
64-
nodeViews[blockSpec.type] = (node: any, view: any, getPos: any) => {
64+
nodeViews[blockSpec.type] = (node: any, view: any, getPos: any, decorations: any, innerDecorations: any) => {
6565
// editorRef.current will be set by the time this is called
6666
const nodeViewConstructor = blockSpec.createNodeView(editorRef.current!);
67-
return nodeViewConstructor(node, view, getPos);
67+
return nodeViewConstructor(node, view, getPos, decorations, innerDecorations);
6868
};
6969
}
7070
}

packages/react/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ export type {
5353
OpenBlockViewProps,
5454
OpenBlockViewRef,
5555
SlashMenuProps,
56-
SlashMenuItem,
5756
BubbleMenuProps,
5857
BubbleMenuItem,
5958
TableMenuProps,

0 commit comments

Comments
 (0)