UNPKG

@progress/kendo-vue-editor

Version:
367 lines (366 loc) 11.6 kB
/** * @license *------------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the package root for more information *------------------------------------------------------------------------------------------- */ import { defineComponent as U, createVNode as t, isVNode as V } from "vue"; import { Button as f } from "@progress/kendo-vue-buttons"; import { chevronRightIcon as W, chevronLeftIcon as $ } from "@progress/kendo-svg-icons"; import { Window as P } from "@progress/kendo-vue-dialogs"; import { TabStrip as q, TabStripTab as L } from "@progress/kendo-vue-layout"; import { provideLocalizationService as H } from "@progress/kendo-vue-intl"; import { messages as o } from "../messages/main.mjs"; import { EditorToolsSettings as G } from "../config/toolsSettings.mjs"; import { formatString as J } from "../tools/utils.mjs"; import { selectedLineTextOnly as Q, textHighlightKey as X, TextSelection as m, find as Y, replace as Z, replaceAll as ee, findAll as te } from "@progress/kendo-editor-common"; import { Icon as F } from "@progress/kendo-vue-common"; function N(e) { return typeof e == "function" || Object.prototype.toString.call(e) === "[object Object]" && !V(e); } const ne = 13, ce = 27, ae = G.findAndReplace, ge = /* @__PURE__ */ U({ name: "KendoFindAndReplaceDialog", emits: { close: null }, props: { view: Object, settings: { type: Object, default: function() { return ae; } }, dir: String }, inject: { kendoLocalizationService: { default: null } }, created() { this._prevMatch = void 0, this.nextMatch = void 0; }, data() { return { selectedTab: 0, searchText: Q(this.$props.view.state), replaceText: "", matchCase: !1, matchWord: !1, matchCyclic: !1, useRegExp: !1, matches: [], hasMounted: !1 }; }, mounted() { this.$el && document.body.append(this.$el), this.setNextState(), this.hasMounted = !0, setTimeout(function() { const e = document.getElementById("findWhatFind"); e && e.focus(); }, 10); }, /** * @hidden */ updated() { const e = this.matches || [], n = this.nextMatch, c = this.$props.view; if (this._prevMatch !== n) { const a = c.state, i = a.tr, s = []; e.forEach((l) => { s.push({ from: l.from, to: l.to, attrs: { class: n && l.eq(n) ? "k-text-selected" : "k-text-highlighted" } }); }), i.setMeta(X, s), i.setSelection(n || m.create(a.doc, a.selection.from)), c.dispatch(i); } }, unmounted() { this.$el && this.$el.remove(); }, render() { let e, n; const c = H(this), { findReplaceDialogTitle: a, findReplaceTabFind: i, findReplaceTabReplace: s, findReplaceFindWhat: l, findReplaceReplaceWith: p, findReplaceReplace: r, findReplaceReplaceAll: d, findReplaceMatchCase: g, findReplaceMatchWord: x, findReplaceMatchCyclic: k, findReplaceUseRegExp: b, findReplacePrevMatch: C, findReplaceNextMatch: S, findReplaceMatches: v } = this.settings.messages, { matchCase: E, matchWord: _, matchCyclic: j, useRegExp: A, searchText: B, replaceText: I, nextMatch: R } = this, M = t("div", { class: "k-search-options" }, [t("span", null, [t("input", { class: "k-checkbox k-checkbox-md k-rounded-md", type: "checkbox", id: "match-case", checked: E, onChange: this.onMatchCaseChecked }, null), t("label", { for: "match-case", class: "k-checkbox-label" }, [c.toLanguageString(g, o[g])])]), t("span", null, [t("input", { class: "k-checkbox k-checkbox-md k-rounded-md", type: "checkbox", id: "match-whole", checked: _, onChange: this.onMatchWordChecked }, null), t("label", { for: "match-whole", class: "k-checkbox-label" }, [c.toLanguageString(x, o[x])])]), t("span", null, [t("input", { class: "k-checkbox k-checkbox-md k-rounded-md", type: "checkbox", id: "match-cyclic", checked: j, onChange: this.onMatchCyclicChecked }, null), t("label", { for: "match-cyclic", class: "k-checkbox-label" }, [c.toLanguageString(k, o[k])])]), t("span", null, [t("input", { class: "k-checkbox k-checkbox-md k-rounded-md", type: "checkbox", id: "regular-expression", checked: A, onChange: this.onUseRegExpChecked }, null), t("label", { for: "regular-expression", class: "k-checkbox-label" }, [c.toLanguageString(b, o[b])])])]), y = function(h) { const u = this.$props.dir === "rtl", D = t(f, { fillMode: "flat", themeColor: "primary", onClick: this.onFindPrev }, { default: () => [t(F, { name: `chevron-${u ? "right" : "left"}`, icon: u ? W : $ }, null), c.toLanguageString(C, o[C])] }), K = t(f, { fillMode: "flat", themeColor: "primary", onClick: this.onFindNext }, { default: () => [c.toLanguageString(S, o[S]), t(F, { name: `chevron-${u ? "left" : "right"}`, icon: u ? $ : W }, null)] }); return t("div", { class: "k-matches-container" }, [D, this.hasMounted && t("span", { ref: h }, [this.matchesMessage(c.toLanguageString(v, o[v]))]), K]); }, T = function(h) { return t("div", { class: "k-edit-label" }, [t("label", { ref: h, for: h }, [c.toLanguageString(l, o[l])])]); }, w = function(h) { return t("div", { class: "k-edit-field" }, [t("span", { class: "k-textbox k-input k-input-md k-rounded-md k-input-solid" }, [t("input", { id: h, ref: h, type: "text", class: "k-input-inner", value: B, onInput: this.onSearchChange, onFocus: this.onSearchChange, onKeydown: this.onKeyDown }, null)])]); }, O = t("div", { class: "k-edit-label" }, [t("label", { for: "replaceWith" }, [c.toLanguageString(p, o[p])])]), z = t("div", { class: "k-edit-field" }, [t("span", { class: "k-textbox k-input k-input-md k-rounded-md k-input-solid" }, [t("input", { id: "replaceWith", class: "k-input-inner", type: "text", value: I, onInput: this.onReplaceChange }, null)])]); return t(P, { title: c.toLanguageString(a, o[a]), onClose: this.onClose, windowStyle: { width: "auto", height: "auto", userSelect: "none" }, resizable: !1, minimizeButton: () => null, maximizeButton: () => null, dir: this.$props.dir }, { default: () => [t(q, { dir: this.$props.dir, selected: this.selectedTab, class: "k-editor-find-replace", onSelect: this.onTabSelect, animation: !1 }, { default: () => [t(L, { title: c.toLanguageString(i, o[i]) }, { default: () => [t("div", { class: "k-edit-form-container" }, [T.call(this, "findWhatFind"), w.call(this, "findWhatFind")]), t("div", { class: "k-actions k-hstack k-justify-content-end" }, null), M, y.call(this, "findWhatFind")] }), t(L, { title: c.toLanguageString(s, o[s]) }, { default: () => [t("div", { class: "k-edit-form-container" }, [T.call(this, "findWhatReplace"), w.call(this, "findWhatReplace"), O, z]), t("div", { class: "k-actions k-hstack k-justify-content-end" }, [t(f, { disabled: !R, onClick: this.onReplace }, N(e = c.toLanguageString(r, o[r])) ? e : { default: () => [e] }), t(f, { disabled: !R, onClick: this.onReplaceAll }, N(n = c.toLanguageString(d, o[d])) ? n : { default: () => [n] })]), M, y.call(this, "findWhatReplace")] })] })] }); }, methods: { onTabSelect(e) { this.selectedTab = e.selected; }, onClose() { const e = this.$props.view, n = e.state, c = n.tr.setSelection(m.create(n.doc, n.selection.from, n.selection.to)); e.updateState(n.apply(c)), e.focus(), this.$emit("close"); }, matchesMessage(e) { const n = this.matches, c = this.nextMatch; let a = 0, i = 0; if (n && c) { const s = n.findIndex((l) => l.eq(c)); a = s === -1 ? n.length : s + 1, i = n.length; } return J(e, a, i); }, onFindNext() { this.onFind(); }, onFindPrev() { this.onFind(!0); }, onFind(e = !1) { const n = this.$props.view, { searchText: c, matchCase: a, matchCyclic: i, matchWord: s, useRegExp: l } = this.$data, p = { text: c, matchWord: s, matchCase: a, useRegExp: l, backward: e, matchCyclic: i }, r = Y(n.state, p); if (r) { const d = n.state.tr.setSelection(r); d.scrollIntoView(), n.updateState(n.state.apply(d)), this._prevMatch = this.nextMatch, this.nextMatch = r, this._prevMatch !== this.nextMatch && this.$forceUpdate(); } }, onReplace() { const e = this.$props.view, n = e.state.selection, { replaceText: c } = this.$data; if (!n.empty) { const a = n.from, i = a + c.length, s = Z(n, c, e.state.tr); s.setSelection(m.create(s.doc, a, i)), s.scrollIntoView(), e.dispatch(s), this.setNextState({}); } }, onReplaceAll() { const e = this.$props.view, { searchText: n, replaceText: c, matchCase: a, matchWord: i, useRegExp: s } = this.$data, l = { text: n, matchWord: i, matchCase: a, useRegExp: s }; e.dispatch(ee(e.state, c, l)), this.setNextState({}); }, onKeyDown(e) { e.keyCode === ne ? this.onFindNext() : e.keyCode === ce && this.onClose(); }, onMatchCaseChecked(e) { this.matchCase = e.target.checked, this.setNextState(); }, onMatchWordChecked(e) { this.matchWord = e.target.checked, this.setNextState(); }, onMatchCyclicChecked(e) { this.matchCyclic = e.target.checked, this.setNextState(); }, onUseRegExpChecked(e) { this.useRegExp = e.target.checked, this.setNextState(); }, onSearchChange(e) { this.searchText = e.target.value, this.setNextState(); }, onReplaceChange(e) { this.replaceText = e.target.value, this.setNextState(); }, setNextState() { const e = this.$props.view; if (this.searchText) { const n = { text: this.searchText, matchWord: this.matchWord, matchCase: this.matchCase, useRegExp: this.useRegExp }, c = e.state.selection, a = te(e.state.doc, n); let i = !this.searchText && a[0] || a.find((s) => s.from >= c.from) || this.matchCyclic && a[0] || void 0; this._prevMatch = this.nextMatch, this.matches = a, this.nextMatch = i; } else this._prevMatch = this.nextMatch, this.matches = [], this.nextMatch = void 0; } } }); export { ge as FindAndReplaceDialog };