lexical-vue
Version:
An extensible Vue 3 web text-editor based on Lexical.
73 lines (72 loc) • 3.5 kB
JavaScript
import { createElementBlock, defineComponent, normalizeClass, normalizeStyle, openBlock, renderSlot, unref, useTemplateRef, watchEffect } from "vue";
import { $getNearestBlockElementAncestorOrThrow, mergeRegister } from "@lexical/utils";
import { $getNodeByKey, $getSelection, $isNodeSelection, $isRangeSelection, CLICK_COMMAND, COMMAND_PRIORITY_LOW, FORMAT_ELEMENT_COMMAND } from "lexical";
import { useLexicalComposer } from "./LexicalComposer.vine.js";
import { $isDecoratorBlockNode } from "./LexicalDecoratorBlockNode.js";
import { useLexicalNodeSelection } from "./useLexicalNodeSelection.js";
const BlockWithAlignableContents = (()=>{
const __vine = defineComponent({
name: 'BlockWithAlignableContents',
props: {
format: {},
nodeKey: {
required: true
},
baseClass: {},
focusClass: {}
},
setup (__props, param) {
let { expose: __expose } = param;
__expose();
const props = __props;
const editor = useLexicalComposer();
const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection(()=>props.nodeKey);
const containerRef = useTemplateRef('containerRef');
watchEffect((onInvalidate)=>{
const unregister = mergeRegister(editor.registerCommand(FORMAT_ELEMENT_COMMAND, (formatType)=>{
if (isSelected) {
const selection = $getSelection();
if ($isNodeSelection(selection)) {
const node = $getNodeByKey(props.nodeKey);
if (node && $isDecoratorBlockNode(node)) node.setFormat(formatType);
} else if ($isRangeSelection(selection)) {
const nodes = selection.getNodes();
for (const node of nodes)if ($isDecoratorBlockNode(node)) node.setFormat(formatType);
else {
const element = $getNearestBlockElementAncestorOrThrow(node);
element.setFormat(formatType);
}
}
return true;
}
return false;
}, COMMAND_PRIORITY_LOW), editor.registerCommand(CLICK_COMMAND, (event)=>{
if (event.target === containerRef.value) {
event.preventDefault();
if (!event.shiftKey) clearSelection();
setSelected(!isSelected.value);
return true;
}
return false;
}, COMMAND_PRIORITY_LOW));
onInvalidate(unregister);
});
return (_ctx, _cache)=>(openBlock(), createElementBlock("div", {
ref_key: "containerRef",
ref: containerRef,
class: normalizeClass([
__props.baseClass,
unref(isSelected) ? __props.focusClass : ''
]),
style: normalizeStyle({
textAlign: __props.format
})
}, [
renderSlot(_ctx.$slots, "default")
], 6));
}
});
__vine.__vue_vine = true;
return __vine;
})();
export { BlockWithAlignableContents };