lexical-vue
Version:
An extensible Vue 3 web text-editor based on Lexical.
69 lines (68 loc) • 2.98 kB
JavaScript
import { useDefaults } from "vue-vine";
import { computed, createElementVNode, defineComponent, normalizeClass, ref, renderSlot, toDisplayString, toRefs, useSlots } from "vue";
import { useLexicalComposer } from "./LexicalComposer.vine.js";
import { useCharacterLimit } from "./shared/useCharacterLimit.js";
const CharacterLimitPlugin = (()=>{
const __vine = defineComponent({
name: 'CharacterLimitPlugin',
props: {
charset: {
required: true
},
maxLength: {
required: true
}
},
setup (__props, param) {
let { expose: __expose } = param;
__expose();
const props = useDefaults(__props, {
charset: ()=>'UTF-16',
maxLength: ()=>5
});
const { charset, maxLength } = toRefs(props);
useSlots();
const editor = useLexicalComposer();
let textEncoderInstance = null;
function textEncoder() {
if (void 0 === window.TextEncoder) return null;
if (null === textEncoderInstance) textEncoderInstance = new window.TextEncoder();
return textEncoderInstance;
}
function utf8Length(text) {
const currentTextEncoder = textEncoder();
if (null === currentTextEncoder) {
const m = encodeURIComponent(text).match(/%[89AB]/gi);
return text.length + (m ? m.length : 0);
}
return currentTextEncoder.encode(text).length;
}
const remainingCharacters = ref(props.maxLength);
function setRemainingCharacters(payload) {
remainingCharacters.value = payload;
}
const characterLimitProps = computed(()=>({
remainingCharacters: setRemainingCharacters,
strlen: (text)=>{
if ('UTF-8' === props.charset) return utf8Length(text);
if ('UTF-16' === props.charset) return text.length;
throw new Error('Unrecognized charset');
}
}));
useCharacterLimit(editor, props.maxLength, characterLimitProps);
return (_ctx, _cache)=>renderSlot(_ctx.$slots, "default", {
remainingCharacters: remainingCharacters.value
}, ()=>[
createElementVNode("span", {
class: normalizeClass([
'characters-limit',
remainingCharacters.value < 0 ? 'characters-limit-exceeded' : ''
])
}, toDisplayString(remainingCharacters.value), 3)
]);
}
});
__vine.__vue_vine = true;
return __vine;
})();
export { CharacterLimitPlugin };