diff --git a/packages/renderless/src/rich-text-edtior/index.ts b/packages/renderless/src/rich-text-edtior/index.ts new file mode 100644 index 0000000000..9acb007a24 --- /dev/null +++ b/packages/renderless/src/rich-text-edtior/index.ts @@ -0,0 +1,81 @@ +export const handleChange = (editor) => { + return (event) => { + const file = event.target.files[0] + if (!file.type.match("image.*")) { + console.log("请选择图片文件!") + return + } + const reader = new FileReader() + reader.onload = function (e) { + editor.value.chain().focus().setImage({ src: e.target?.result }).run() + } + reader.readAsDataURL(file) + } +} +export const setLink = (editor) => { + return () => { + const previousUrl = editor.value.getAttributes('link').href + const url = window.prompt('URL', previousUrl) + if (url === null) { + return + } + if (url === '') { + editor.value + .chain() + .focus() + .extendMarkRange('link') + .unsetLink() + .run() + return + } + editor.value + .chain() + .focus() + .extendMarkRange('link') + .setLink({ href: url }) + .run() + } +} +// table 处理逻辑 +export const handleMove = (state, box) => { + return (e) => { + let { x, y } = box.value.getBoundingClientRect() + state.flagX = Math.ceil((e.x - x) / 30) // 后期改变30就可以 + state.flagY = Math.ceil((e.y - y) / 30) + } +} +export const handleClickOutside = (state, box) => { + return (e) => { + if (!box.value?.contains(e.target)) { + state.isShow = false + removeClickOutside(state, box)() + } + } + +} +export const removeClickOutside = (state, box) => { + return () => { + window.removeEventListener('click', handleClickOutside(state, box)) + } +} +export const handleClick = (state, box) => { + return (e) => { + e.stopPropagation(); + if (state.isShow) { + if (state.flagX && state.flagY) { + state.editor.chain().focus().insertTable({ rows: state.flagX, cols: state.flagY, withHeaderRow: true }).run() + } + state.flagX = 0 + state.flagY = 0 + removeClickOutside(state, box)() + } else { + window.addEventListener('click', handleClickOutside(state, box)) + } + state.isShow = !state.isShow + } +} +// bubble菜单 +export const shouldShow = ({ editor, view, state, oldState, from, to }) => { + // 仅在无序列表选中的时候才显示 气泡菜单 + return editor.isActive("table"); +}; \ No newline at end of file diff --git a/packages/renderless/src/rich-text-edtior/vue.ts b/packages/renderless/src/rich-text-edtior/vue.ts index 24f813462c..ec0764d019 100644 --- a/packages/renderless/src/rich-text-edtior/vue.ts +++ b/packages/renderless/src/rich-text-edtior/vue.ts @@ -1,3 +1,4 @@ +import { handleChange, setLink, handleMove, handleClickOutside, removeClickOutside, handleClick, shouldShow } from './index' export const api = ['state', 'setLink', 'handleChange', 'box', 'handleMove', 'handleClickOutside', 'removeClickOutside', 'handleClick', 'shouldShow'] export const renderless = ( props, @@ -47,74 +48,7 @@ export const renderless = ( editable: true, injectCSS: false, }) - const handleChange = (event) => { - const file = event.target.files[0] - if (!file.type.match("image.*")) { - console.log("请选择图片文件!") - return - } - const reader = new FileReader() - reader.onload = function (e) { - editor.value.chain().focus().setImage({ src: e.target?.result }).run() - } - reader.readAsDataURL(file) - } - const setLink = () => { - const previousUrl = editor.value.getAttributes('link').href - const url = window.prompt('URL', previousUrl) - if (url === null) { - return - } - if (url === '') { - editor.value - .chain() - .focus() - .extendMarkRange('link') - .unsetLink() - .run() - return - } - editor.value - .chain() - .focus() - .extendMarkRange('link') - .setLink({ href: url }) - .run() - } - // table 处理逻辑 - const handleMove = (e) => { - let { x, y } = box.value.getBoundingClientRect() - state.flagX = Math.ceil((e.x - x) / 30) // 后期改变30就可以 - state.flagY = Math.ceil((e.y - y) / 30) - } - const handleClickOutside = (e) => { - if (!box.value?.contains(e.target)) { - state.isShow = false - removeClickOutside() - } - } - const removeClickOutside = () => { - window.removeEventListener('click', handleClickOutside) - } - const handleClick = (e) => { - e.stopPropagation(); - if (state.isShow) { - if (state.flagX && state.flagY) { - state.editor.chain().focus().insertTable({ rows: state.flagX, cols: state.flagY, withHeaderRow: true }).run() - } - state.flagX = 0 - state.flagY = 0 - removeClickOutside() - } else { - window.addEventListener('click', handleClickOutside) - } - state.isShow = !state.isShow - } - // bubble菜单 - const shouldShow = ({ editor, view, state, oldState, from, to }) => { - // 仅在无序列表选中的时候才显示 气泡菜单 - return editor.isActive("table"); - }; + const box = ref(null) const state = reactive({ editor: null, @@ -126,16 +60,16 @@ export const renderless = ( state.editor = editor const api = { state, - setLink, - handleChange, + setLink: setLink(editor), + handleChange: handleChange(editor), // table处理函数 box, - handleMove, - handleClickOutside, - removeClickOutside, - handleClick, + handleMove: handleMove(state, box), + handleClickOutside: handleClickOutside(state, box), + removeClickOutside: removeClickOutside(state, box), + handleClick: handleClick(state, box), // bubble 菜单 - shouldShow, + shouldShow: shouldShow, } onBeforeUnmount(() => { state.editor.destroy() diff --git a/packages/theme/src/rich-text-editor/index.less b/packages/theme/src/rich-text-editor/index.less index da1a7640e5..7035a56137 100644 --- a/packages/theme/src/rich-text-editor/index.less +++ b/packages/theme/src/rich-text-editor/index.less @@ -1,12 +1,16 @@ +@import './vars.less'; + .tiny-rich-text-editor { + .component-css-vars-rich-text-editor(); + width: 500px; height: 350px; margin: 0 auto; - outline: 3px solid rgb(203, 203, 203); + outline: 3px solid var(--ti-rich-text-editor-box-outline-color); border-radius: 8px 8px 0 0; &:hover { - outline: 3px solid black; + outline: 3px solid var(--ti-rich-text-editor-box-outline-hover-color); } .button-area { @@ -26,18 +30,18 @@ cursor: pointer; &:hover { - background-color: #d2e4ff; + background-color: var(--ti-rich-text-editor-button-hover); } } button:disabled { // color: rgba(34, 47, 62, .5); - background-color: rgba(203, 203, 203, .3); + background-color: var(--ti-rich-text-editor-button-disabled); cursor: not-allowed; } button.is-active { - background-color: #d2e4ff; + background-color: var(--ti-rich-text-editor-button-active); } .tiny-svg { diff --git a/packages/theme/src/rich-text-editor/vars.less b/packages/theme/src/rich-text-editor/vars.less index 1f559bf6e8..99597a5a60 100644 --- a/packages/theme/src/rich-text-editor/vars.less +++ b/packages/theme/src/rich-text-editor/vars.less @@ -1 +1,9 @@ -.component-css-vars-roles() {} \ No newline at end of file +.component-css-vars-rich-text-editor() { + --ti-rich-text-editor-box-outline-color: var(--ti-common-color-line-normal); + --ti-rich-text-editor-box-outline-hover-color: var(--ti-common-color-line-hover); + --ti-rich-text-editor-button-hover: var(--ti-base-color-brand-8); + --ti-rich-text-editor-button-disabled: var(--ti-common-color-primary-disabled-bgcolor); + --ti-rich-text-editor-button-active: var(--ti-base-color-brand-8); + --ti-rich-text-editor-poplist-item-selected-bg-color: var(--ti-common-color-selected-background); + --ti-rich-text-editor-poplist-item-selected-text-color: var(--ti-common-color-selected-text-color); +} \ No newline at end of file