Here’s what I’m trying to accomplish:
- Given a starting value (e.g
{{ }}
), when editor is focused I want to create a transaction of selection:{ anchor: 4 }
- Having created the above transaction, I want to run the
startCompletion
command.
However I am having a hard time trying to trigger both a transaction and a subsequent command.
Here’s what I’ve tried:
Transaction Filter
const startFocusEffect = StateEffect.define<boolean>();
const focusExtension = EditorView.focusChangeEffect.of((state, focus) => {
if (focus) {
return startFocusEffect.of(focus);
}
return null;
});
const setSelectionExtension = EditorState.transactionFilter.of((transaction) => {
const transactions = [transaction]
for (const effect of transaction.effects) {
if (effect.is(startFocusEffect)) {
if (transaction.state.doc.toString().trim() === '{{ }}') {
transactions.push({
selection: {
anchor: 3,
}
})
}
}
}
return transactions;
});
I can use the EditorView.focusChangeEffect
to determine the focus
state of the Editor, and then use the EditorState.transactionFilter
to include the transaction based certain conditionals.
However this leaves me with the startCompletion command. The focusChangeEffect facet expects me to return a state effect. startCompletion internally dispatches a state effect,
view.dispatch({ effects: startCompletionEffect.of(true) });
but because it takes view
as an argument (and it doesn’t return the state effect), I’m not able to use it within the focusChangeEffect
facet as that facet only has access to the state
, not the view
.
ViewPlugin Approach
function openCompletionOnFocus() {
return ViewPlugin.fromClass(
class {
update(update) {
if (
update.focusChanged &&
update.view.hasFocus &&
update.state.doc.toString().trim() === "{{ }}"
) {
const transactions = [{selection: {anchor: 4}} ];
// state update error
update.view.dispatch(...transactions);
startCompletion(update.view);
}
}
},
);
}
The other direction is trying to incorporate this within a ViewPlugin. Although this gives access ViewUpdate
class and to the EditorView
class, I get the same error as above.
Taking inspiration from this previous post: Trigger a StateEffect when focus changes I could try the setTimeout
approach, but this feels like the wrong way of approaching this.
Are there any other approaches that I’m not seeing? I’ve looked through the docs in hopes that I can dispatch side-effects based on a focus change, but coming up short. Thank you in advance.