@zero-library/common 2.0.4 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +94 -63
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.css +3 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.esm.js +94 -62
- package/dist/index.esm.js.map +1 -1
- package/package.json +2 -4
package/dist/index.d.mts
CHANGED
|
@@ -112,11 +112,12 @@ interface Props$1 {
|
|
|
112
112
|
}
|
|
113
113
|
declare const _default$2: ({ content, searchValue, customComponents, onChange, onPartialChange }: Props$1) => react_jsx_runtime.JSX.Element;
|
|
114
114
|
|
|
115
|
-
type
|
|
115
|
+
type RenderControlObj<C, P = ObjectType<any>> = {
|
|
116
116
|
visible?: boolean;
|
|
117
117
|
render?: (ctx: C) => React.ReactNode;
|
|
118
118
|
props?: P;
|
|
119
119
|
};
|
|
120
|
+
type RenderControl<C, P = ObjectType<any>> = boolean | RenderControlObj<C, P>;
|
|
120
121
|
interface RenderWrapperProps<C, P> {
|
|
121
122
|
control?: RenderControl<C, P> | null;
|
|
122
123
|
ctx?: C;
|
|
@@ -365,4 +366,4 @@ declare function getSignPath(): string;
|
|
|
365
366
|
declare const LgPrimaryColor: string;
|
|
366
367
|
declare const themeConfig: ThemeConfig;
|
|
367
368
|
|
|
368
|
-
export { _default$c as AudioPlayer, DateFormatType, DateFormatType2, ERROR, FORBIDDEN, FacePastCode, _default$b as FileIcon, _default$a as FilePreview, _default$9 as FilePreviewDrawer, ILLEGAL_PARAMETER, _default$5 as Iframe, _default$4 as LazyComponent, LgPrimaryColor, LoginPastCode, MISSING_PARAMETER, _default$3 as MarkdownEditor, _default$8 as MarkdownPreview, NOT_FOUND, type NsSetIntervalReturnType, OK, OK2, PERMISSION_DENIED, type Params, _default$7 as PdfPreview, type RenderControl, _default$2 as RenderMarkdown, RenderWrapper, TOKEN_KEY, UNAUTHORIZED, _default$1 as UserAvatar, _default$6 as VideoPlayer, absVal, addUrlLastSlash, arrToObj, buildUrlParams, calculate, clearCurrentUser, clearToken, compareNum, copyText, createValtioContext, decimalPlaces, deepCopy, deepEqual, deepMerge, dividedBy, downloadFile, emit, emitToChild, formType, formatDate, formatNumberWithCommas, genNonDuplicateID, generateRandomNumbers, getCurrentUser, getDeviceId, getEndOfTimestamp, getFileName, getSignPath, getStartOfTimestamp, getTimestamp, getToken, getUrlMainSource, getUrlToken, getWebSocketUrl, is, isArray, isBlob, isBoolean, isClient, isDate, isDef, isElement, isEmpty, isEmptyObj, isExpire, isExternal, isFunction, isInteger, isMap, isNegative, isNull, isNullOrUnDef, isNumber, isNumberNoNaN, isObject, isPromise, isRegExp, isServer, isString, isUnDef, isWindow, jsonType, minus, nsSetInterval, objToOptions, plus, precision, propsMerge, _default as request, setCurrentUser, setToken, shouldRender, textAreaView, themeConfig, times, toFixed, useDebounce, useDeepEffect, useIframeRelayBridge, useRefState, useSyncInput, useThrottle, useWebSocket };
|
|
369
|
+
export { _default$c as AudioPlayer, DateFormatType, DateFormatType2, ERROR, FORBIDDEN, FacePastCode, _default$b as FileIcon, _default$a as FilePreview, _default$9 as FilePreviewDrawer, ILLEGAL_PARAMETER, _default$5 as Iframe, _default$4 as LazyComponent, LgPrimaryColor, LoginPastCode, MISSING_PARAMETER, _default$3 as MarkdownEditor, _default$8 as MarkdownPreview, NOT_FOUND, type NsSetIntervalReturnType, OK, OK2, PERMISSION_DENIED, type Params, _default$7 as PdfPreview, type RenderControl, type RenderControlObj, _default$2 as RenderMarkdown, RenderWrapper, TOKEN_KEY, UNAUTHORIZED, _default$1 as UserAvatar, _default$6 as VideoPlayer, absVal, addUrlLastSlash, arrToObj, buildUrlParams, calculate, clearCurrentUser, clearToken, compareNum, copyText, createValtioContext, decimalPlaces, deepCopy, deepEqual, deepMerge, dividedBy, downloadFile, emit, emitToChild, formType, formatDate, formatNumberWithCommas, genNonDuplicateID, generateRandomNumbers, getCurrentUser, getDeviceId, getEndOfTimestamp, getFileName, getSignPath, getStartOfTimestamp, getTimestamp, getToken, getUrlMainSource, getUrlToken, getWebSocketUrl, is, isArray, isBlob, isBoolean, isClient, isDate, isDef, isElement, isEmpty, isEmptyObj, isExpire, isExternal, isFunction, isInteger, isMap, isNegative, isNull, isNullOrUnDef, isNumber, isNumberNoNaN, isObject, isPromise, isRegExp, isServer, isString, isUnDef, isWindow, jsonType, minus, nsSetInterval, objToOptions, plus, precision, propsMerge, _default as request, setCurrentUser, setToken, shouldRender, textAreaView, themeConfig, times, toFixed, useDebounce, useDeepEffect, useIframeRelayBridge, useRefState, useSyncInput, useThrottle, useWebSocket };
|
package/dist/index.d.ts
CHANGED
|
@@ -112,11 +112,12 @@ interface Props$1 {
|
|
|
112
112
|
}
|
|
113
113
|
declare const _default$2: ({ content, searchValue, customComponents, onChange, onPartialChange }: Props$1) => react_jsx_runtime.JSX.Element;
|
|
114
114
|
|
|
115
|
-
type
|
|
115
|
+
type RenderControlObj<C, P = ObjectType<any>> = {
|
|
116
116
|
visible?: boolean;
|
|
117
117
|
render?: (ctx: C) => React.ReactNode;
|
|
118
118
|
props?: P;
|
|
119
119
|
};
|
|
120
|
+
type RenderControl<C, P = ObjectType<any>> = boolean | RenderControlObj<C, P>;
|
|
120
121
|
interface RenderWrapperProps<C, P> {
|
|
121
122
|
control?: RenderControl<C, P> | null;
|
|
122
123
|
ctx?: C;
|
|
@@ -365,4 +366,4 @@ declare function getSignPath(): string;
|
|
|
365
366
|
declare const LgPrimaryColor: string;
|
|
366
367
|
declare const themeConfig: ThemeConfig;
|
|
367
368
|
|
|
368
|
-
export { _default$c as AudioPlayer, DateFormatType, DateFormatType2, ERROR, FORBIDDEN, FacePastCode, _default$b as FileIcon, _default$a as FilePreview, _default$9 as FilePreviewDrawer, ILLEGAL_PARAMETER, _default$5 as Iframe, _default$4 as LazyComponent, LgPrimaryColor, LoginPastCode, MISSING_PARAMETER, _default$3 as MarkdownEditor, _default$8 as MarkdownPreview, NOT_FOUND, type NsSetIntervalReturnType, OK, OK2, PERMISSION_DENIED, type Params, _default$7 as PdfPreview, type RenderControl, _default$2 as RenderMarkdown, RenderWrapper, TOKEN_KEY, UNAUTHORIZED, _default$1 as UserAvatar, _default$6 as VideoPlayer, absVal, addUrlLastSlash, arrToObj, buildUrlParams, calculate, clearCurrentUser, clearToken, compareNum, copyText, createValtioContext, decimalPlaces, deepCopy, deepEqual, deepMerge, dividedBy, downloadFile, emit, emitToChild, formType, formatDate, formatNumberWithCommas, genNonDuplicateID, generateRandomNumbers, getCurrentUser, getDeviceId, getEndOfTimestamp, getFileName, getSignPath, getStartOfTimestamp, getTimestamp, getToken, getUrlMainSource, getUrlToken, getWebSocketUrl, is, isArray, isBlob, isBoolean, isClient, isDate, isDef, isElement, isEmpty, isEmptyObj, isExpire, isExternal, isFunction, isInteger, isMap, isNegative, isNull, isNullOrUnDef, isNumber, isNumberNoNaN, isObject, isPromise, isRegExp, isServer, isString, isUnDef, isWindow, jsonType, minus, nsSetInterval, objToOptions, plus, precision, propsMerge, _default as request, setCurrentUser, setToken, shouldRender, textAreaView, themeConfig, times, toFixed, useDebounce, useDeepEffect, useIframeRelayBridge, useRefState, useSyncInput, useThrottle, useWebSocket };
|
|
369
|
+
export { _default$c as AudioPlayer, DateFormatType, DateFormatType2, ERROR, FORBIDDEN, FacePastCode, _default$b as FileIcon, _default$a as FilePreview, _default$9 as FilePreviewDrawer, ILLEGAL_PARAMETER, _default$5 as Iframe, _default$4 as LazyComponent, LgPrimaryColor, LoginPastCode, MISSING_PARAMETER, _default$3 as MarkdownEditor, _default$8 as MarkdownPreview, NOT_FOUND, type NsSetIntervalReturnType, OK, OK2, PERMISSION_DENIED, type Params, _default$7 as PdfPreview, type RenderControl, type RenderControlObj, _default$2 as RenderMarkdown, RenderWrapper, TOKEN_KEY, UNAUTHORIZED, _default$1 as UserAvatar, _default$6 as VideoPlayer, absVal, addUrlLastSlash, arrToObj, buildUrlParams, calculate, clearCurrentUser, clearToken, compareNum, copyText, createValtioContext, decimalPlaces, deepCopy, deepEqual, deepMerge, dividedBy, downloadFile, emit, emitToChild, formType, formatDate, formatNumberWithCommas, genNonDuplicateID, generateRandomNumbers, getCurrentUser, getDeviceId, getEndOfTimestamp, getFileName, getSignPath, getStartOfTimestamp, getTimestamp, getToken, getUrlMainSource, getUrlToken, getWebSocketUrl, is, isArray, isBlob, isBoolean, isClient, isDate, isDef, isElement, isEmpty, isEmptyObj, isExpire, isExternal, isFunction, isInteger, isMap, isNegative, isNull, isNullOrUnDef, isNumber, isNumberNoNaN, isObject, isPromise, isRegExp, isServer, isString, isUnDef, isWindow, jsonType, minus, nsSetInterval, objToOptions, plus, precision, propsMerge, _default as request, setCurrentUser, setToken, shouldRender, textAreaView, themeConfig, times, toFixed, useDebounce, useDeepEffect, useIframeRelayBridge, useRefState, useSyncInput, useThrottle, useWebSocket };
|
package/dist/index.esm.js
CHANGED
|
@@ -6,7 +6,6 @@ import { Spin, notification, Modal, Result, Splitter, Empty, Image, Flex, Drawer
|
|
|
6
6
|
import parse from 'html-react-parser';
|
|
7
7
|
import { jsonrepair } from 'jsonrepair';
|
|
8
8
|
import markdownit from 'markdown-it';
|
|
9
|
-
import container from 'markdown-it-container';
|
|
10
9
|
import { Worker, Viewer, PasswordStatus } from '@react-pdf-viewer/core';
|
|
11
10
|
import { pageNavigationPlugin } from '@react-pdf-viewer/page-navigation';
|
|
12
11
|
import { thumbnailPlugin } from '@react-pdf-viewer/thumbnail';
|
|
@@ -151,64 +150,92 @@ md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
|
|
|
151
150
|
token.attrPush(["target", "_blank"]);
|
|
152
151
|
return self.renderToken(tokens, idx, options);
|
|
153
152
|
};
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const value = match[3] ?? match[4] ?? "";
|
|
164
|
-
if (key === "data") {
|
|
165
|
-
let obj = {};
|
|
166
|
-
try {
|
|
167
|
-
obj = JSON.parse(value);
|
|
168
|
-
} catch {
|
|
169
|
-
try {
|
|
170
|
-
obj = JSON.parse(jsonrepair(value));
|
|
171
|
-
} catch {
|
|
172
|
-
obj = {};
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
params[key] = replaceSpecialCharacter(JSON.stringify(obj));
|
|
176
|
-
} else {
|
|
177
|
-
params[key] = value;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return params;
|
|
181
|
-
}
|
|
182
|
-
md.use(container, "alert", {
|
|
183
|
-
validate: (params) => /^alert/.test(params.trim()),
|
|
184
|
-
render: function(tokens, idx) {
|
|
185
|
-
const token = tokens[idx];
|
|
186
|
-
if (token.nesting === 1) {
|
|
187
|
-
const info = token.info.trim();
|
|
188
|
-
const params = parseParams(info);
|
|
189
|
-
return `<lazy-component ${Object.entries(params).map(([key, value]) => `${key}=${value}`).join(" ")}>`;
|
|
190
|
-
} else {
|
|
191
|
-
return "</lazy-component>";
|
|
153
|
+
function parseData(raw) {
|
|
154
|
+
let obj = {};
|
|
155
|
+
try {
|
|
156
|
+
obj = JSON.parse(raw);
|
|
157
|
+
} catch {
|
|
158
|
+
try {
|
|
159
|
+
obj = JSON.parse(jsonrepair(raw));
|
|
160
|
+
} catch {
|
|
161
|
+
obj = { _raw: raw };
|
|
192
162
|
}
|
|
193
163
|
}
|
|
194
|
-
|
|
195
|
-
function preprocess(content) {
|
|
196
|
-
return content.replace(
|
|
197
|
-
/:::alert([\s\S]*?):::/g,
|
|
198
|
-
// 匹配 :::alert ... :::
|
|
199
|
-
(match, params) => {
|
|
200
|
-
return `
|
|
201
|
-
:::alert ${params.trim()}
|
|
202
|
-
:::
|
|
203
|
-
`;
|
|
204
|
-
}
|
|
205
|
-
);
|
|
164
|
+
return obj;
|
|
206
165
|
}
|
|
207
166
|
function highlightKeywords(html, keywords) {
|
|
208
167
|
const escaped = keywords.map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
209
168
|
const regex = new RegExp(`(${escaped.join("|")})`, "gi");
|
|
210
169
|
return html.replace(regex, '<span class="cube-hl">$1</span>');
|
|
211
170
|
}
|
|
171
|
+
function makePlaceholder(id) {
|
|
172
|
+
return `__ALERT_DATA_${id}__`;
|
|
173
|
+
}
|
|
174
|
+
function extractAlertPlaceholders(src) {
|
|
175
|
+
let pos = 0;
|
|
176
|
+
let id = 0;
|
|
177
|
+
let out = "";
|
|
178
|
+
const placeholders = /* @__PURE__ */ new Map();
|
|
179
|
+
while (pos < src.length) {
|
|
180
|
+
const start = src.indexOf(":::alert", pos);
|
|
181
|
+
if (start === -1) {
|
|
182
|
+
out += src.slice(pos);
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
out += src.slice(pos, start);
|
|
186
|
+
const afterStart = src.slice(start);
|
|
187
|
+
const relAfter = afterStart.slice(":::alert".length);
|
|
188
|
+
const matchLineEnd = relAfter.search(/\n:::\s*(\n|$)/);
|
|
189
|
+
let endIdx = -1;
|
|
190
|
+
if (matchLineEnd !== -1) {
|
|
191
|
+
endIdx = start + ":::alert".length + matchLineEnd + 1;
|
|
192
|
+
} else {
|
|
193
|
+
const fallback = src.indexOf(":::", start + ":::alert".length);
|
|
194
|
+
if (fallback === -1) {
|
|
195
|
+
out += src.slice(start);
|
|
196
|
+
pos = src.length;
|
|
197
|
+
break;
|
|
198
|
+
} else {
|
|
199
|
+
endIdx = fallback;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const inner = src.slice(start + ":::alert".length, endIdx).trim();
|
|
203
|
+
const typeMatch = inner.match(/type\s*=\s*(?:(['"])(.*?)\1|(\S+))/);
|
|
204
|
+
const type = typeMatch ? typeMatch[2] ?? typeMatch[3] : void 0;
|
|
205
|
+
const dataIdx = inner.search(/\bdata\s*=/);
|
|
206
|
+
let rawData = "";
|
|
207
|
+
if (dataIdx !== -1) {
|
|
208
|
+
rawData = inner.slice(dataIdx + inner.slice(dataIdx).match(/\bdata\s*=/)[0].length).trim();
|
|
209
|
+
}
|
|
210
|
+
const ph = makePlaceholder(id++);
|
|
211
|
+
placeholders.set(ph, rawData);
|
|
212
|
+
const typeText = type ? ` type=${JSON.stringify(type)}` : "";
|
|
213
|
+
out += `:::alert${typeText} data="${ph}" :::`;
|
|
214
|
+
const realClose = src.indexOf(":::", endIdx);
|
|
215
|
+
pos = realClose === -1 ? endIdx : realClose + 3;
|
|
216
|
+
}
|
|
217
|
+
return { text: out, placeholders };
|
|
218
|
+
}
|
|
219
|
+
function alertInlinePlugin(md2) {
|
|
220
|
+
md2.inline.ruler.before("emphasis", "alert_inline", function(state, silent) {
|
|
221
|
+
const pos = state.pos;
|
|
222
|
+
const src = state.src;
|
|
223
|
+
if (src.slice(pos, pos + 3) !== ":::") return false;
|
|
224
|
+
const m = src.slice(pos).match(/^:::alert\b([^\n\r]*?):::/);
|
|
225
|
+
if (!m) return false;
|
|
226
|
+
if (silent) return false;
|
|
227
|
+
const raw = m[1].trim();
|
|
228
|
+
const html = `<lazy-component ${raw}></lazy-component>`;
|
|
229
|
+
const token = state.push("html_inline", "", 0);
|
|
230
|
+
token.content = html;
|
|
231
|
+
state.pos += m[0].length;
|
|
232
|
+
return true;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
md.use(alertInlinePlugin);
|
|
237
|
+
} catch {
|
|
238
|
+
}
|
|
212
239
|
var RenderMarkdown_default = ({ content = "", searchValue, customComponents, onChange, onPartialChange }) => {
|
|
213
240
|
const reactContent = useMemo(() => {
|
|
214
241
|
if (!content) return null;
|
|
@@ -220,8 +247,8 @@ var RenderMarkdown_default = ({ content = "", searchValue, customComponents, onC
|
|
|
220
247
|
incomplete = true;
|
|
221
248
|
fixedContent += ":::";
|
|
222
249
|
}
|
|
223
|
-
|
|
224
|
-
let rawHtml = md.render(
|
|
250
|
+
const { text: preprocessed, placeholders } = extractAlertPlaceholders(fixedContent);
|
|
251
|
+
let rawHtml = md.render(preprocessed);
|
|
225
252
|
rawHtml = searchValue ? highlightKeywords(rawHtml, [searchValue]) : rawHtml;
|
|
226
253
|
let lazyIndex = -1;
|
|
227
254
|
const allLazyMatches = [...rawHtml.matchAll(/<lazy-component/gi)];
|
|
@@ -232,7 +259,12 @@ var RenderMarkdown_default = ({ content = "", searchValue, customComponents, onC
|
|
|
232
259
|
lazyIndex++;
|
|
233
260
|
const el = domNode;
|
|
234
261
|
const type = el.attribs.type;
|
|
235
|
-
const
|
|
262
|
+
const dataAttr = el.attribs.data || "";
|
|
263
|
+
let data = {};
|
|
264
|
+
if (/^__ALERT_DATA_\d+__$/.test(dataAttr)) {
|
|
265
|
+
const raw = placeholders.get(dataAttr) ?? "";
|
|
266
|
+
data = parseData(raw);
|
|
267
|
+
}
|
|
236
268
|
const loading = incomplete && lazyIndex === lastLazyIndex;
|
|
237
269
|
return /* @__PURE__ */ jsx(
|
|
238
270
|
LazyComponent_default,
|
|
@@ -4073,10 +4105,10 @@ var NodeButton = React16.forwardRef(
|
|
|
4073
4105
|
);
|
|
4074
4106
|
NodeButton.displayName = "NodeButton";
|
|
4075
4107
|
var QuoteIcon = React16.memo(({ className, ...props }) => {
|
|
4076
|
-
return /* @__PURE__ */ jsx("svg", { width: "24", height: "24", className, viewBox: "0 0
|
|
4108
|
+
return /* @__PURE__ */ jsx("svg", { width: "24", height: "24", className, viewBox: "0 0 1024 1024", fill: "currentColor", xmlns: "http://www.w3.org/2000/svg", ...props, children: /* @__PURE__ */ jsx(
|
|
4077
4109
|
"path",
|
|
4078
4110
|
{
|
|
4079
|
-
d: "
|
|
4111
|
+
d: "M130.16 789.92V500.25q-1.85-62.51 18-117.41T204 286.23a308 308 0 0 1 86.13-69.1A304.32 304.32 0 0 1 386.26 184 11 11 0 0 1 399 194.86v104.52a11 11 0 0 1-7.21 10.29q-66.13 24.5-91.25 70.31-24.41 44.36-26.32 107a11 11 0 0 0 11 11.3h102.84a11 11 0 0 1 11 11V779a11 11 0 0 1-11 11h-257.9z m403.3 0V500.25q-2-62.51 17.95-117.41t55.85-96.61q35.94-41.6 86.13-69.1A304.7 304.7 0 0 1 789.56 184a11 11 0 0 1 12.76 10.82v104.56a11 11 0 0 1-7.21 10.29Q729 334.18 703.86 380q-24.41 44.36-26.32 107a11 11 0 0 0 11 11.3h102.82a11 11 0 0 1 11 11V779a11 11 0 0 1-11 11H533.45z m0 0",
|
|
4080
4112
|
fill: "currentColor"
|
|
4081
4113
|
}
|
|
4082
4114
|
) });
|
|
@@ -5024,8 +5056,8 @@ var MarkdownEditor_default = ({ value = "", onChange, onScrollPage, searchValue,
|
|
|
5024
5056
|
}, 300);
|
|
5025
5057
|
useEffect(() => {
|
|
5026
5058
|
if (!editor) return;
|
|
5027
|
-
const
|
|
5028
|
-
if (!
|
|
5059
|
+
const container = document.querySelector(".content-wrapper");
|
|
5060
|
+
if (!container) return;
|
|
5029
5061
|
const handleSelectionUpdate = () => {
|
|
5030
5062
|
const { from } = editor.state.selection;
|
|
5031
5063
|
const domAtPos = editor.view.domAtPos(from);
|
|
@@ -5056,11 +5088,11 @@ var MarkdownEditor_default = ({ value = "", onChange, onScrollPage, searchValue,
|
|
|
5056
5088
|
}
|
|
5057
5089
|
};
|
|
5058
5090
|
const handleScroll = () => {
|
|
5059
|
-
const pageNos = Array.from(
|
|
5091
|
+
const pageNos = Array.from(container.querySelectorAll(".page-no"));
|
|
5060
5092
|
if (!pageNos.length) return;
|
|
5061
5093
|
let closestNode = null;
|
|
5062
5094
|
let closestTopDiff = -Infinity;
|
|
5063
|
-
const containerTop =
|
|
5095
|
+
const containerTop = container.getBoundingClientRect().top;
|
|
5064
5096
|
pageNos.forEach((node) => {
|
|
5065
5097
|
const rect = node.getBoundingClientRect();
|
|
5066
5098
|
const top = rect.top - containerTop;
|
|
@@ -5078,10 +5110,10 @@ var MarkdownEditor_default = ({ value = "", onChange, onScrollPage, searchValue,
|
|
|
5078
5110
|
}
|
|
5079
5111
|
};
|
|
5080
5112
|
editor.on("selectionUpdate", handleSelectionUpdate);
|
|
5081
|
-
|
|
5113
|
+
container.addEventListener("scroll", handleScroll);
|
|
5082
5114
|
return () => {
|
|
5083
5115
|
editor.off("selectionUpdate", handleSelectionUpdate);
|
|
5084
|
-
|
|
5116
|
+
container.removeEventListener("scroll", handleScroll);
|
|
5085
5117
|
};
|
|
5086
5118
|
}, [editor]);
|
|
5087
5119
|
useEffect(() => {
|