@shadow-garden/bapbong-input-bridge 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +41 -10
- package/dist/index.js +47 -11
- package/dist/lib/input-bridge.d.ts +3 -0
- package/dist/lib/input-bridge.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -52,7 +52,10 @@ var splitListItem = (state, dispatch) => {
|
|
|
52
52
|
if ($from.parent !== $to.parent) return false;
|
|
53
53
|
if (parent.content.size === 0) {
|
|
54
54
|
dispatch?.(
|
|
55
|
-
state.tr.setNodeMarkup($from.before(), null, {
|
|
55
|
+
state.tr.setNodeMarkup($from.before(), null, {
|
|
56
|
+
...parent.attrs,
|
|
57
|
+
list: null
|
|
58
|
+
})
|
|
56
59
|
);
|
|
57
60
|
return true;
|
|
58
61
|
}
|
|
@@ -128,6 +131,7 @@ var InputBridge = class {
|
|
|
128
131
|
this.dom.appendChild(this.host);
|
|
129
132
|
this.view = new import_prosemirror_view.EditorView(this.host, {
|
|
130
133
|
state: createEditingState(options.doc, options.keys),
|
|
134
|
+
handlePaste: options.handlePaste,
|
|
131
135
|
dispatchTransaction: (tr) => {
|
|
132
136
|
const state = this.view.state.apply(tr);
|
|
133
137
|
this.view.updateState(state);
|
|
@@ -151,7 +155,10 @@ var InputBridge = class {
|
|
|
151
155
|
setSelection(anchor, head = anchor) {
|
|
152
156
|
const { doc } = this.view.state;
|
|
153
157
|
const clamp = (p) => Math.max(0, Math.min(p, doc.content.size));
|
|
154
|
-
const sel = import_prosemirror_state.TextSelection.between(
|
|
158
|
+
const sel = import_prosemirror_state.TextSelection.between(
|
|
159
|
+
doc.resolve(clamp(anchor)),
|
|
160
|
+
doc.resolve(clamp(head))
|
|
161
|
+
);
|
|
155
162
|
this.view.dispatch(this.view.state.tr.setSelection(sel));
|
|
156
163
|
}
|
|
157
164
|
/** Select the word around `pos` (double-click); falls back to a collapsed
|
|
@@ -183,7 +190,10 @@ function placeholderPlugin(text) {
|
|
|
183
190
|
const first = doc.firstChild;
|
|
184
191
|
if (doc.childCount === 1 && first?.isTextblock && first.content.size === 0) {
|
|
185
192
|
return import_prosemirror_view.DecorationSet.create(doc, [
|
|
186
|
-
import_prosemirror_view.Decoration.node(0, first.nodeSize, {
|
|
193
|
+
import_prosemirror_view.Decoration.node(0, first.nodeSize, {
|
|
194
|
+
class: "is-empty",
|
|
195
|
+
"data-placeholder": text
|
|
196
|
+
})
|
|
187
197
|
]);
|
|
188
198
|
}
|
|
189
199
|
return null;
|
|
@@ -200,7 +210,12 @@ function mentionPlugin(handlers) {
|
|
|
200
210
|
const sel = tr.selection;
|
|
201
211
|
if (!sel.empty) return INACTIVE;
|
|
202
212
|
const $from = sel.$from;
|
|
203
|
-
const textBefore = $from.parent.textBetween(
|
|
213
|
+
const textBefore = $from.parent.textBetween(
|
|
214
|
+
0,
|
|
215
|
+
$from.parentOffset,
|
|
216
|
+
"\n",
|
|
217
|
+
"\uFFFC"
|
|
218
|
+
);
|
|
204
219
|
const m = MENTION_RE.exec(textBefore);
|
|
205
220
|
if (!m) return INACTIVE;
|
|
206
221
|
const query = m[1];
|
|
@@ -212,7 +227,10 @@ function mentionPlugin(handlers) {
|
|
|
212
227
|
const st = mentionKey.getState(view.state);
|
|
213
228
|
if (!st?.active) return handlers.query(null);
|
|
214
229
|
const c = view.coordsAtPos(view.state.selection.from);
|
|
215
|
-
handlers.query({
|
|
230
|
+
handlers.query({
|
|
231
|
+
query: st.query,
|
|
232
|
+
coords: { left: c.left, top: c.top, bottom: c.bottom }
|
|
233
|
+
});
|
|
216
234
|
};
|
|
217
235
|
emit(editorView);
|
|
218
236
|
return { update: emit, destroy: () => handlers.query(null) };
|
|
@@ -243,7 +261,8 @@ var CommentComposer = class {
|
|
|
243
261
|
const doc = initialDoc ? schema.nodeFromJSON(initialDoc) : void 0;
|
|
244
262
|
const plugins = [(0, import_prosemirror_history.history)()];
|
|
245
263
|
if (opts?.placeholder) plugins.push(placeholderPlugin(opts.placeholder));
|
|
246
|
-
if (mention && schema.nodes["mention"])
|
|
264
|
+
if (mention && schema.nodes["mention"])
|
|
265
|
+
plugins.push(mentionPlugin(mention));
|
|
247
266
|
const keys = {};
|
|
248
267
|
if (opts?.onEnter) {
|
|
249
268
|
keys["Enter"] = () => (opts.onEnter?.(), true);
|
|
@@ -251,7 +270,10 @@ var CommentComposer = class {
|
|
|
251
270
|
}
|
|
252
271
|
if (opts?.onEscape) keys["Escape"] = () => (opts.onEscape?.(), true);
|
|
253
272
|
if (Object.keys(keys).length) plugins.push((0, import_prosemirror_keymap.keymap)(keys));
|
|
254
|
-
plugins.push(
|
|
273
|
+
plugins.push(
|
|
274
|
+
(0, import_prosemirror_keymap.keymap)({ "Mod-z": import_prosemirror_history.undo, "Shift-Mod-z": import_prosemirror_history.redo }),
|
|
275
|
+
(0, import_prosemirror_keymap.keymap)(import_prosemirror_commands.baseKeymap)
|
|
276
|
+
);
|
|
255
277
|
this.view = new import_prosemirror_view.EditorView(mount, {
|
|
256
278
|
state: import_prosemirror_state.EditorState.create({ ...doc ? { doc } : { schema }, plugins })
|
|
257
279
|
});
|
|
@@ -263,8 +285,14 @@ var CommentComposer = class {
|
|
|
263
285
|
const st = mentionKey.getState(this.view.state);
|
|
264
286
|
if (!st?.active) return;
|
|
265
287
|
const to = this.view.state.selection.from;
|
|
266
|
-
const node = this.schema.nodes["mention"].create({
|
|
267
|
-
|
|
288
|
+
const node = this.schema.nodes["mention"].create({
|
|
289
|
+
id: user.id,
|
|
290
|
+
label: user.label
|
|
291
|
+
});
|
|
292
|
+
const tr = this.view.state.tr.replaceWith(st.from, to, [
|
|
293
|
+
node,
|
|
294
|
+
this.schema.text(" ")
|
|
295
|
+
]);
|
|
268
296
|
tr.setSelection(import_prosemirror_state.TextSelection.create(tr.doc, st.from + 2));
|
|
269
297
|
this.view.dispatch(tr);
|
|
270
298
|
this.view.focus();
|
|
@@ -279,7 +307,10 @@ var CommentComposer = class {
|
|
|
279
307
|
}
|
|
280
308
|
/** Reset to an empty document. */
|
|
281
309
|
clear() {
|
|
282
|
-
const empty = import_prosemirror_state.EditorState.create({
|
|
310
|
+
const empty = import_prosemirror_state.EditorState.create({
|
|
311
|
+
schema: this.schema,
|
|
312
|
+
plugins: this.view.state.plugins
|
|
313
|
+
});
|
|
283
314
|
this.view.updateState(empty);
|
|
284
315
|
}
|
|
285
316
|
focus() {
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,12 @@
|
|
|
2
2
|
import { baseKeymap } from "prosemirror-commands";
|
|
3
3
|
import { history, redo, undo } from "prosemirror-history";
|
|
4
4
|
import { keymap } from "prosemirror-keymap";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
EditorState,
|
|
7
|
+
Plugin,
|
|
8
|
+
PluginKey,
|
|
9
|
+
TextSelection
|
|
10
|
+
} from "prosemirror-state";
|
|
6
11
|
import { canSplit } from "prosemirror-transform";
|
|
7
12
|
import { Decoration, DecorationSet, EditorView } from "prosemirror-view";
|
|
8
13
|
function moveCaretCommand(compute, extend = false) {
|
|
@@ -21,7 +26,10 @@ var splitListItem = (state, dispatch) => {
|
|
|
21
26
|
if ($from.parent !== $to.parent) return false;
|
|
22
27
|
if (parent.content.size === 0) {
|
|
23
28
|
dispatch?.(
|
|
24
|
-
state.tr.setNodeMarkup($from.before(), null, {
|
|
29
|
+
state.tr.setNodeMarkup($from.before(), null, {
|
|
30
|
+
...parent.attrs,
|
|
31
|
+
list: null
|
|
32
|
+
})
|
|
25
33
|
);
|
|
26
34
|
return true;
|
|
27
35
|
}
|
|
@@ -97,6 +105,7 @@ var InputBridge = class {
|
|
|
97
105
|
this.dom.appendChild(this.host);
|
|
98
106
|
this.view = new EditorView(this.host, {
|
|
99
107
|
state: createEditingState(options.doc, options.keys),
|
|
108
|
+
handlePaste: options.handlePaste,
|
|
100
109
|
dispatchTransaction: (tr) => {
|
|
101
110
|
const state = this.view.state.apply(tr);
|
|
102
111
|
this.view.updateState(state);
|
|
@@ -120,7 +129,10 @@ var InputBridge = class {
|
|
|
120
129
|
setSelection(anchor, head = anchor) {
|
|
121
130
|
const { doc } = this.view.state;
|
|
122
131
|
const clamp = (p) => Math.max(0, Math.min(p, doc.content.size));
|
|
123
|
-
const sel = TextSelection.between(
|
|
132
|
+
const sel = TextSelection.between(
|
|
133
|
+
doc.resolve(clamp(anchor)),
|
|
134
|
+
doc.resolve(clamp(head))
|
|
135
|
+
);
|
|
124
136
|
this.view.dispatch(this.view.state.tr.setSelection(sel));
|
|
125
137
|
}
|
|
126
138
|
/** Select the word around `pos` (double-click); falls back to a collapsed
|
|
@@ -152,7 +164,10 @@ function placeholderPlugin(text) {
|
|
|
152
164
|
const first = doc.firstChild;
|
|
153
165
|
if (doc.childCount === 1 && first?.isTextblock && first.content.size === 0) {
|
|
154
166
|
return DecorationSet.create(doc, [
|
|
155
|
-
Decoration.node(0, first.nodeSize, {
|
|
167
|
+
Decoration.node(0, first.nodeSize, {
|
|
168
|
+
class: "is-empty",
|
|
169
|
+
"data-placeholder": text
|
|
170
|
+
})
|
|
156
171
|
]);
|
|
157
172
|
}
|
|
158
173
|
return null;
|
|
@@ -169,7 +184,12 @@ function mentionPlugin(handlers) {
|
|
|
169
184
|
const sel = tr.selection;
|
|
170
185
|
if (!sel.empty) return INACTIVE;
|
|
171
186
|
const $from = sel.$from;
|
|
172
|
-
const textBefore = $from.parent.textBetween(
|
|
187
|
+
const textBefore = $from.parent.textBetween(
|
|
188
|
+
0,
|
|
189
|
+
$from.parentOffset,
|
|
190
|
+
"\n",
|
|
191
|
+
"\uFFFC"
|
|
192
|
+
);
|
|
173
193
|
const m = MENTION_RE.exec(textBefore);
|
|
174
194
|
if (!m) return INACTIVE;
|
|
175
195
|
const query = m[1];
|
|
@@ -181,7 +201,10 @@ function mentionPlugin(handlers) {
|
|
|
181
201
|
const st = mentionKey.getState(view.state);
|
|
182
202
|
if (!st?.active) return handlers.query(null);
|
|
183
203
|
const c = view.coordsAtPos(view.state.selection.from);
|
|
184
|
-
handlers.query({
|
|
204
|
+
handlers.query({
|
|
205
|
+
query: st.query,
|
|
206
|
+
coords: { left: c.left, top: c.top, bottom: c.bottom }
|
|
207
|
+
});
|
|
185
208
|
};
|
|
186
209
|
emit(editorView);
|
|
187
210
|
return { update: emit, destroy: () => handlers.query(null) };
|
|
@@ -212,7 +235,8 @@ var CommentComposer = class {
|
|
|
212
235
|
const doc = initialDoc ? schema.nodeFromJSON(initialDoc) : void 0;
|
|
213
236
|
const plugins = [history()];
|
|
214
237
|
if (opts?.placeholder) plugins.push(placeholderPlugin(opts.placeholder));
|
|
215
|
-
if (mention && schema.nodes["mention"])
|
|
238
|
+
if (mention && schema.nodes["mention"])
|
|
239
|
+
plugins.push(mentionPlugin(mention));
|
|
216
240
|
const keys = {};
|
|
217
241
|
if (opts?.onEnter) {
|
|
218
242
|
keys["Enter"] = () => (opts.onEnter?.(), true);
|
|
@@ -220,7 +244,10 @@ var CommentComposer = class {
|
|
|
220
244
|
}
|
|
221
245
|
if (opts?.onEscape) keys["Escape"] = () => (opts.onEscape?.(), true);
|
|
222
246
|
if (Object.keys(keys).length) plugins.push(keymap(keys));
|
|
223
|
-
plugins.push(
|
|
247
|
+
plugins.push(
|
|
248
|
+
keymap({ "Mod-z": undo, "Shift-Mod-z": redo }),
|
|
249
|
+
keymap(baseKeymap)
|
|
250
|
+
);
|
|
224
251
|
this.view = new EditorView(mount, {
|
|
225
252
|
state: EditorState.create({ ...doc ? { doc } : { schema }, plugins })
|
|
226
253
|
});
|
|
@@ -232,8 +259,14 @@ var CommentComposer = class {
|
|
|
232
259
|
const st = mentionKey.getState(this.view.state);
|
|
233
260
|
if (!st?.active) return;
|
|
234
261
|
const to = this.view.state.selection.from;
|
|
235
|
-
const node = this.schema.nodes["mention"].create({
|
|
236
|
-
|
|
262
|
+
const node = this.schema.nodes["mention"].create({
|
|
263
|
+
id: user.id,
|
|
264
|
+
label: user.label
|
|
265
|
+
});
|
|
266
|
+
const tr = this.view.state.tr.replaceWith(st.from, to, [
|
|
267
|
+
node,
|
|
268
|
+
this.schema.text(" ")
|
|
269
|
+
]);
|
|
237
270
|
tr.setSelection(TextSelection.create(tr.doc, st.from + 2));
|
|
238
271
|
this.view.dispatch(tr);
|
|
239
272
|
this.view.focus();
|
|
@@ -248,7 +281,10 @@ var CommentComposer = class {
|
|
|
248
281
|
}
|
|
249
282
|
/** Reset to an empty document. */
|
|
250
283
|
clear() {
|
|
251
|
-
const empty = EditorState.create({
|
|
284
|
+
const empty = EditorState.create({
|
|
285
|
+
schema: this.schema,
|
|
286
|
+
plugins: this.view.state.plugins
|
|
287
|
+
});
|
|
252
288
|
this.view.updateState(empty);
|
|
253
289
|
}
|
|
254
290
|
focus() {
|
|
@@ -29,6 +29,9 @@ export interface InputBridgeOptions {
|
|
|
29
29
|
/** Called after every dispatched transaction (typing, IME composition
|
|
30
30
|
* steps, undo, selection changes). Re-layout + repaint here. */
|
|
31
31
|
onUpdate: (state: EditorState, tr: Transaction) => void;
|
|
32
|
+
/** editorProps.handlePaste — return true to claim the paste (e.g. image
|
|
33
|
+
* blobs); false lets ProseMirror's default clipboard parsing run. */
|
|
34
|
+
handlePaste?: (view: EditorView, event: ClipboardEvent) => boolean;
|
|
32
35
|
}
|
|
33
36
|
/** Editing state with history + base keymap; exported for headless tests. */
|
|
34
37
|
export declare function createEditingState(doc: PMNode, keys?: Record<string, Command>): EditorState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-bridge.d.ts","sourceRoot":"","sources":["../../src/lib/input-bridge.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,IAAI,MAAM,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,
|
|
1
|
+
{"version":3,"file":"input-bridge.d.ts","sourceRoot":"","sources":["../../src/lib/input-bridge.ts"],"names":[],"mappings":"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"}
|