Replies: 2 comments 13 replies
-
Hello @groege const doesRangeHasMark =
(doc: Node, from: number, to: number) => (markType: MarkType) =>
doc.rangeHasMark(from, to, markType);
const isMarkInSet = (marks: readonly Mark[]) => (markType: MarkType) =>
!!markType.isInSet(marks);
export const useActiveMarks = () => {
const { view } = useWidgetViewContext();
const { state } = view;
const { selection } = state;
const activeMarksMap = useMemo(() => {
const { doc, storedMarks } = state;
const { from, to, empty, $from } = selection;
if (empty) {
const isSchemaActive = isMarkInSet(storedMarks || $from.marks());
return {
isStrongActive: isSchemaActive(strongSchema.type()),
isEmphasisActive: isSchemaActive(emphasisSchema.type()),
isStrikethroughActive: isSchemaActive(strikethroughSchema.type()),
};
}
const isSchemaActive = doesRangeHasMark(doc, from, to);
return {
isStrongActive: isSchemaActive(strongSchema.type()),
isEmphasisActive: isSchemaActive(emphasisSchema.type()),
isStrikethroughActive: isSchemaActive(strikethroughSchema.type()),
};
}, [state, selection]);
return activeMarksMap;
}; If you are interested, here is a working demo: https://daredata.github.io/notion-style-editor/ |
Beta Was this translation helpful? Give feedback.
1 reply
-
I've blatantly ripped off plugin-listener to make this selectionListener plugin import {createSlice} from '@milkdown/ctx';
// eslint-disable-next-line import/no-unresolved
import {Plugin, PluginKey} from '@milkdown/prose/state';
import {InitReady, prosePluginsCtx} from '@milkdown/core';
import {debounce} from 'lodash';
export class SelectionManager {
selectionListeners = [];
get listeners() {
return {
selection: this.selectionListeners,
}
}
selection(fn) {
this.selectionListeners.push(fn);
return this;
}
}
export const selectionCtx = createSlice(new SelectionManager(), 'selection-listener');
export const key = new PluginKey('MILKDOWN_SELECTION_LISTENER');
export const selectionListener = (ctx) => {
ctx.inject(selectionCtx, new SelectionManager());
return async () => {
await ctx.wait(InitReady);
const listener = ctx.get(selectionCtx);
const {listeners} = listener;
let prevSelection = null;
const plugin = new Plugin({
key,
state: {
init: () => {
// do nothing
},
apply: (tr) => {
if (tr.selection.eq(prevSelection)) return;
const handler = debounce(() => {
const {selection, doc} = tr;
if (listeners.selection.length > 0 && (prevSelection == null || !prevSelection.eq(selection))) {
listeners.selection.forEach((fn) => {
fn(ctx, selection, doc);
});
}
prevSelection = tr.selection;
}, 200);
return handler();
},
},
});
ctx.update(prosePluginsCtx, (x) => x.concat(plugin));
};
}; |
Beta Was this translation helpful? Give feedback.
12 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hello everybody,
Hope you can help, I have spent more than 10h trying to solve this, I would really appreciate any help, couldn't find anything here/stackoverflow/google...
So I already implemented buttons to toggle i.e. Bold... the thing is I have to implement it as a toggle button... so if nothing is selected the bold button should be active if the text in the cursor position is bold...
If something is selected it should show 3 different states... (only the first 2 states would be fine if point 2 and 3 would be the same)
So 1. problem I have no idea how to listen to the cursor/selection change
And 2. problem I have no idea how to query if the toggle is applied or not (i found some code examples but none of them worked)
I'd be really thankful for anything
Beta Was this translation helpful? Give feedback.
All reactions