patches v1.7.2 #115
1 changed files with 108 additions and 109 deletions
|
@ -3,126 +3,125 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineComponent, type PropType } from "vue";
|
import { markRaw, onMounted, onUnmounted, ref, useTemplateRef, watch, type PropType } from "vue";
|
||||||
import Quill, { Delta, type QuillOptions } from "quill";
|
import Quill, { Delta, type QuillOptions } from "quill";
|
||||||
import "quill/dist/quill.core.css";
|
import "quill/dist/quill.core.css";
|
||||||
import "quill/dist/quill.snow.css";
|
import "quill/dist/quill.snow.css";
|
||||||
|
import isEqual from "lodash.isequal";
|
||||||
|
import cloneDeep from "lodash.clonedeep";
|
||||||
|
|
||||||
type RangeStatic = { index: number; length: number };
|
type RangeStatic = { index: number; length: number };
|
||||||
</script>
|
|
||||||
|
|
||||||
<script lang="ts">
|
const quillElement = useTemplateRef("quill");
|
||||||
export default defineComponent({
|
|
||||||
props: {
|
|
||||||
options: {
|
|
||||||
type: Object as PropType<QuillOptions>,
|
|
||||||
default: {},
|
|
||||||
},
|
|
||||||
toolbar: {
|
|
||||||
type: [String, Array, Object],
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
content: {
|
|
||||||
type: [String, Object] as PropType<string | Delta | null>,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
contentType: {
|
|
||||||
type: String as PropType<"delta" | "html" | "text">,
|
|
||||||
default: "text",
|
|
||||||
validator: (value: string) => {
|
|
||||||
return ["delta", "html", "text"].includes(value);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
readonly: { type: Boolean, default: false },
|
|
||||||
placeholder: String,
|
|
||||||
},
|
|
||||||
emits: {
|
|
||||||
"update:content": (content: Delta | string) => true,
|
|
||||||
textChange: (tc: { delta: Delta; oldDelta: Delta; source: string }) => true,
|
|
||||||
selectionChange: (sc: { range: RangeStatic; oldRange: RangeStatic; source: string }) => true,
|
|
||||||
focus: () => true,
|
|
||||||
blur: () => true,
|
|
||||||
ready: (quill: Quill) => true,
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
conent(val, oldVal) {
|
|
||||||
this.setContent(val);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
instance: undefined as undefined | Quill,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
value: {
|
|
||||||
get(): string | Delta {
|
|
||||||
return this.content ?? "";
|
|
||||||
},
|
|
||||||
set(val: string | Delta) {
|
|
||||||
this.$emit("update:content", val);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.instance = new Quill(this.$refs.quill as HTMLElement, {
|
|
||||||
theme: "snow",
|
|
||||||
modules: {
|
|
||||||
toolbar: this.toolbar,
|
|
||||||
},
|
|
||||||
placeholder: this.placeholder,
|
|
||||||
readOnly: this.readonly,
|
|
||||||
...this.options,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.instance.on("selection-change", (range, oldRange, source) => {
|
const instance = ref<undefined | Quill>();
|
||||||
if (!range) {
|
const model = ref<string | Delta>("");
|
||||||
this.$emit("blur");
|
|
||||||
} else {
|
|
||||||
this.$emit("focus");
|
|
||||||
}
|
|
||||||
this.$emit("selectionChange", { range, oldRange, source });
|
|
||||||
});
|
|
||||||
this.instance.on("text-change", (delta, oldDelta, source) => {
|
|
||||||
this.value = this.getContent();
|
|
||||||
this.$emit("textChange", { delta, oldDelta, source });
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$emit("ready", this.instance as Quill);
|
const props = defineProps({
|
||||||
this.setContent(this.value);
|
options: {
|
||||||
|
type: Object as PropType<QuillOptions>,
|
||||||
|
default: {},
|
||||||
},
|
},
|
||||||
beforeUnmount() {
|
toolbar: {
|
||||||
this.instance = undefined;
|
type: [String, Array, Object],
|
||||||
|
default: "",
|
||||||
},
|
},
|
||||||
methods: {
|
content: {
|
||||||
getContent(): string | Delta {
|
type: [String, Object] as PropType<string | Delta | null>,
|
||||||
if (this.contentType === "delta") {
|
default: "",
|
||||||
return (this.instance?.getContents() ?? {}) as Delta;
|
},
|
||||||
} else if (this.contentType === "html") {
|
contentType: {
|
||||||
return this.instance?.getSemanticHTML() ?? "";
|
type: String as PropType<"delta" | "html" | "text">,
|
||||||
} else {
|
default: "text",
|
||||||
return this.instance?.getText() ?? "";
|
validator: (value: string) => {
|
||||||
}
|
return ["delta", "html", "text"].includes(value);
|
||||||
},
|
|
||||||
setContent(content: Delta | string) {
|
|
||||||
if (content == "") return;
|
|
||||||
if (this.contentType === "delta") {
|
|
||||||
if (typeof content !== "string") {
|
|
||||||
this.instance?.setContents(content);
|
|
||||||
}
|
|
||||||
} else if (this.contentType === "html") {
|
|
||||||
if (typeof content === "string" && this.instance) {
|
|
||||||
this.instance.root.innerHTML = content;
|
|
||||||
// this.instance.clipboard.dangerouslyPasteHTML(content);
|
|
||||||
// let delta = this.instance.clipboard.convert({ html: content });
|
|
||||||
// this.instance?.setContents(delta);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (typeof content === "string") {
|
|
||||||
this.instance?.setText(content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
readonly: { type: Boolean, default: false },
|
||||||
|
placeholder: String,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits({
|
||||||
|
"update:content": (content: Delta | string) => true,
|
||||||
|
textChange: (tc: { delta: Delta; oldDelta: Delta; source: string }) => true,
|
||||||
|
selectionChange: (sc: { range: RangeStatic; oldRange: RangeStatic; source: string }) => true,
|
||||||
|
focus: () => true,
|
||||||
|
blur: () => true,
|
||||||
|
ready: (quill: Quill) => true,
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.content,
|
||||||
|
(val, oldVal) => {
|
||||||
|
if (!instance.value || !val || isEqual(val, model.value)) return;
|
||||||
|
console.log("hi");
|
||||||
|
setContent(cloneDeep(val));
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
watch(model, (val, oldVal) => {
|
||||||
|
emit("update:content", cloneDeep(val));
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!quillElement.value) return;
|
||||||
|
const quill = new Quill(quillElement.value, {
|
||||||
|
theme: "snow",
|
||||||
|
modules: {
|
||||||
|
toolbar: props.toolbar,
|
||||||
|
},
|
||||||
|
placeholder: props.placeholder,
|
||||||
|
readOnly: props.readonly,
|
||||||
|
...props.options,
|
||||||
|
});
|
||||||
|
|
||||||
|
quill.on(Quill.events.SELECTION_CHANGE, (range, oldRange, source) => {
|
||||||
|
if (!range) {
|
||||||
|
emit("blur");
|
||||||
|
} else {
|
||||||
|
emit("focus");
|
||||||
|
}
|
||||||
|
console.log(range);
|
||||||
|
emit("selectionChange", { range, oldRange, source });
|
||||||
|
});
|
||||||
|
quill.on(Quill.events.TEXT_CHANGE, (delta, oldDelta, source) => {
|
||||||
|
model.value = getContent();
|
||||||
|
emit("textChange", { delta, oldDelta, source });
|
||||||
|
});
|
||||||
|
|
||||||
|
emit("ready", quill);
|
||||||
|
instance.value = markRaw(quill);
|
||||||
|
setContent(cloneDeep(props.content ?? ""));
|
||||||
|
});
|
||||||
|
onUnmounted(() => {
|
||||||
|
instance.value = undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
function getContent(): string | Delta {
|
||||||
|
if (props.contentType === "delta") {
|
||||||
|
return (instance.value?.getContents() ?? {}) as Delta;
|
||||||
|
} else if (props.contentType === "html") {
|
||||||
|
return instance.value?.getSemanticHTML() ?? "";
|
||||||
|
} else {
|
||||||
|
return instance.value?.getText() ?? "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function setContent(content: Delta | string) {
|
||||||
|
if (content == "") return;
|
||||||
|
if (props.contentType === "delta") {
|
||||||
|
if (typeof content !== "string") {
|
||||||
|
instance.value?.setContents(content);
|
||||||
|
}
|
||||||
|
} else if (props.contentType === "html") {
|
||||||
|
if (typeof content === "string" && instance.value) {
|
||||||
|
instance.value.clipboard.dangerouslyPasteHTML(content);
|
||||||
|
let delta = instance.value.clipboard.convert({ html: content });
|
||||||
|
instance.value?.setContents(delta);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (typeof content === "string") {
|
||||||
|
instance.value?.setText(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue