@progress/kendo-vue-editor
Version:
367 lines (366 loc) • 11.6 kB
JavaScript
/**
* @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
};