UNPKG

@progress/kendo-vue-editor

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