@zero-library/common 2.2.7 → 2.2.8

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 CHANGED
@@ -6,9 +6,15 @@ var antd = require('antd');
6
6
  var classNames = require('classnames');
7
7
  var docxPreview = require('docx-preview');
8
8
  var React16 = require('react');
9
+ var AES = require('crypto-js/aes');
10
+ var encUtf8 = require('crypto-js/enc-utf8');
11
+ var MarkdownIt = require('markdown-it');
12
+ var Decimal = require('decimal.js');
13
+ var dayjs = require('dayjs');
14
+ var relativeTime = require('dayjs/plugin/relativeTime');
15
+ var axios = require('axios');
9
16
  var parse = require('html-react-parser');
10
17
  var jsonrepair = require('jsonrepair');
11
- var markdownit = require('markdown-it');
12
18
  var core$1 = require('@react-pdf-viewer/core');
13
19
  var pageNavigation = require('@react-pdf-viewer/page-navigation');
14
20
  var thumbnail = require('@react-pdf-viewer/thumbnail');
@@ -16,12 +22,6 @@ var zoom = require('@react-pdf-viewer/zoom');
16
22
  require('@react-pdf-viewer/core/lib/styles/index.css');
17
23
  var zh_CN = require('@react-pdf-viewer/locales/lib/zh_CN.json');
18
24
  require('@react-pdf-viewer/page-navigation/lib/styles/index.css');
19
- var AES = require('crypto-js/aes');
20
- var encUtf8 = require('crypto-js/enc-utf8');
21
- var Decimal = require('decimal.js');
22
- var dayjs = require('dayjs');
23
- var relativeTime = require('dayjs/plugin/relativeTime');
24
- var axios = require('axios');
25
25
  require('@react-pdf-viewer/thumbnail/lib/styles/index.css');
26
26
  require('@react-pdf-viewer/zoom/lib/styles/index.css');
27
27
  var react = require('@tiptap/react');
@@ -69,15 +69,15 @@ function _interopNamespace(e) {
69
69
  var Icon__default = /*#__PURE__*/_interopDefault(Icon);
70
70
  var classNames__default = /*#__PURE__*/_interopDefault(classNames);
71
71
  var React16__namespace = /*#__PURE__*/_interopNamespace(React16);
72
- var parse__default = /*#__PURE__*/_interopDefault(parse);
73
- var markdownit__default = /*#__PURE__*/_interopDefault(markdownit);
74
- var zh_CN__default = /*#__PURE__*/_interopDefault(zh_CN);
75
72
  var AES__default = /*#__PURE__*/_interopDefault(AES);
76
73
  var encUtf8__default = /*#__PURE__*/_interopDefault(encUtf8);
74
+ var MarkdownIt__default = /*#__PURE__*/_interopDefault(MarkdownIt);
77
75
  var Decimal__default = /*#__PURE__*/_interopDefault(Decimal);
78
76
  var dayjs__default = /*#__PURE__*/_interopDefault(dayjs);
79
77
  var relativeTime__default = /*#__PURE__*/_interopDefault(relativeTime);
80
78
  var axios__default = /*#__PURE__*/_interopDefault(axios);
79
+ var parse__default = /*#__PURE__*/_interopDefault(parse);
80
+ var zh_CN__default = /*#__PURE__*/_interopDefault(zh_CN);
81
81
  var Table__default = /*#__PURE__*/_interopDefault(Table);
82
82
  var TableCell__default = /*#__PURE__*/_interopDefault(TableCell);
83
83
  var TableHeader__default = /*#__PURE__*/_interopDefault(TableHeader);
@@ -101,319 +101,32 @@ var AudioPlayer_default = ({ fileUrl }) => {
101
101
  "\u60A8\u7684\u6D4F\u89C8\u5668\u4E0D\u652F\u6301 audio \u6807\u7B7E\u3002"
102
102
  ] });
103
103
  };
104
- var DocxPreview_default = ({ fileUrl, scale = 1 }) => {
105
- const containerRef = React16.useRef(null);
106
- const [zoomRatio, setZoomRatio] = React16.useState(scale);
107
- React16.useEffect(() => {
108
- if (!fileUrl || !containerRef.current) return;
109
- containerRef.current.innerHTML = "";
110
- fetch(fileUrl).then((res) => res.arrayBuffer()).then(
111
- (arrayBuffer) => docxPreview.renderAsync(arrayBuffer, containerRef.current, null, {
112
- breakPages: true,
113
- renderHeaders: true,
114
- renderFooters: true,
115
- ignoreWidth: false,
116
- ignoreHeight: false
117
- })
118
- ).catch((err) => {
119
- console.error("docx-preview \u6E32\u67D3\u5931\u8D25:", err);
120
- if (containerRef.current) containerRef.current.innerHTML = '<p class="text-center">\u6587\u6863\u52A0\u8F7D\u5931\u8D25</p>';
121
- });
122
- }, [fileUrl]);
123
- const zoomIn = () => setZoomRatio((z) => Math.min(z + 0.1, 3));
124
- const zoomOut = () => setZoomRatio((z) => Math.max(z - 0.1, 0.3));
125
- const resetZoom = () => {
126
- setZoomRatio(1);
127
- };
128
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames__default.default(styles_module_default.nsPreviewDocx, "height-full"), children: [
129
- /* @__PURE__ */ jsxRuntime.jsxs(antd.Flex, { gap: 6, align: "center", className: styles_module_default.docxToolbar, children: [
130
- /* @__PURE__ */ jsxRuntime.jsx(antd.Button, { onClick: zoomOut, icon: /* @__PURE__ */ jsxRuntime.jsx(Icon.MinusCircleOutlined, {}), title: "\u7F29\u5C0F" }),
131
- /* @__PURE__ */ jsxRuntime.jsx(antd.Button, { onClick: zoomIn, icon: /* @__PURE__ */ jsxRuntime.jsx(Icon.PlusCircleOutlined, {}), title: "\u653E\u5927" }),
132
- /* @__PURE__ */ jsxRuntime.jsx(antd.Button, { onClick: resetZoom, icon: /* @__PURE__ */ jsxRuntime.jsx(Icon.RedoOutlined, {}), title: "\u8FD8\u539F" })
133
- ] }),
134
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: classNames__default.default(styles_module_default.docxContent, "height-full", "scroll-fade-in"), children: /* @__PURE__ */ jsxRuntime.jsx(
135
- "div",
136
- {
137
- ref: containerRef,
138
- style: {
139
- transform: `scale(${zoomRatio})`,
140
- transformOrigin: "top center"
141
- }
142
- }
143
- ) })
144
- ] });
145
- };
146
- var FileIcon_default = ({ suffix, fontSize = 22 }) => {
147
- const styles = { fontSize, color: "var(--ant-color-primary)" };
148
- const Icon2 = React16.useMemo(() => {
149
- switch (suffix?.toUpperCase()) {
150
- case "TXT":
151
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileTextOutlined, {});
152
- case "PDF":
153
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.FilePdfOutlined, {});
154
- case "DOC":
155
- case "DOCX":
156
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileWordOutlined, {});
157
- case "XLS":
158
- case "XLSX":
159
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileExcelOutlined, {});
160
- case "PPT":
161
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.FilePptOutlined, {});
162
- case "MP4":
163
- case "MOV":
164
- case "MKV":
165
- case "AVI":
166
- case "FLV":
167
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.VideoCameraOutlined, {});
168
- case "MP3":
169
- case "WAV":
170
- case "M4A":
171
- case "ACC":
172
- case "WMA":
173
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.NotificationOutlined, {});
174
- case "JPG":
175
- case "JPEG":
176
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileJpgOutlined, {});
177
- case "PNG":
178
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileImageOutlined, {});
179
- case "GIF":
180
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileGifOutlined, {});
181
- case "MD":
182
- case "MARKDOWN":
183
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileMarkdownOutlined, {});
184
- case "ZIP":
185
- case "RAR":
186
- case "7Z":
187
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileZipOutlined, {});
188
- case "CATALOG":
189
- return /* @__PURE__ */ jsxRuntime.jsx("i", { style: styles, className: "iconfont icon-wenjianjia" });
190
- // 文件夹图标
191
- default:
192
- return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileUnknownOutlined, {});
193
- }
194
- }, [suffix]);
195
- return /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles, children: Icon2 });
196
- };
197
- var VideoPlayer_default = ({ fileUrl }) => {
198
- return /* @__PURE__ */ jsxRuntime.jsxs("video", { controls: true, className: styles_module_default.nsPreviewVideo, children: [
199
- /* @__PURE__ */ jsxRuntime.jsx("source", { src: fileUrl, type: "video/mp4" }),
200
- "\u60A8\u7684\u6D4F\u89C8\u5668\u4E0D\u652F\u6301 video \u6807\u7B7E\u3002"
201
- ] });
202
- };
203
- var baseComponentMap = {
204
- // renderMarkdown: () => import('@/components/RenderMarkdown')
205
- };
206
- var LazyComponent_default = ({ type, customComponents, ...rest }) => {
207
- const componentMap = React16.useMemo(() => {
208
- return { ...baseComponentMap, ...customComponents };
209
- }, [customComponents]);
210
- const LazyComponent = React16.useMemo(() => {
211
- const loader = componentMap[type];
212
- return loader ? React16.lazy(loader) : null;
213
- }, [type, componentMap]);
214
- if (!LazyComponent) return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
215
- "\u672A\u77E5\u7C7B\u578B\uFF1A",
216
- type
217
- ] });
218
- return /* @__PURE__ */ jsxRuntime.jsx(React16.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx("div", { children: "\u52A0\u8F7D\u4E2D..." }), children: /* @__PURE__ */ jsxRuntime.jsx(LazyComponent, { ...rest }) });
219
- };
220
- var md = markdownit__default.default({ html: true, breaks: true });
221
- md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
222
- const token = tokens[idx];
223
- token.attrPush(["target", "_blank"]);
224
- return self.renderToken(tokens, idx, options);
225
- };
226
- function parseData(raw) {
227
- let obj = {};
228
- try {
229
- obj = JSON.parse(raw);
230
- } catch {
231
- try {
232
- obj = JSON.parse(jsonrepair.jsonrepair(raw));
233
- } catch {
234
- obj = { _raw: raw };
235
- }
236
- }
237
- return obj;
104
+
105
+ // src/utils/is.ts
106
+ var toString = Object.prototype.toString;
107
+ function is(val, type) {
108
+ return toString.call(val) === `[object ${type}]`;
238
109
  }
239
- function highlightKeywords(html, keywords) {
240
- const escaped = keywords.map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
241
- const regex = new RegExp(`(${escaped.join("|")})`, "gi");
242
- return html.replace(regex, '<span class="cube-hl">$1</span>');
110
+ function isUnDef(val) {
111
+ return is(val, "Undefined");
243
112
  }
244
- function makePlaceholder(id) {
245
- return `__ALERT_DATA_${id}__`;
113
+ function isDef(val) {
114
+ return !isUnDef(val);
246
115
  }
247
- function alertMarkClean(src) {
248
- let pos = 0;
249
- let id = 0;
250
- let out = "";
251
- const placeholders = /* @__PURE__ */ new Map();
252
- while (pos < src.length) {
253
- const start = src.indexOf(":::alert", pos);
254
- if (start === -1) {
255
- out += src.slice(pos);
256
- break;
257
- }
258
- out += src.slice(pos, start);
259
- const afterStart = src.slice(start);
260
- const relAfter = afterStart.slice(":::alert".length);
261
- const matchLineEnd = relAfter.search(/\s*:::\s*/);
262
- let endIdx = -1;
263
- let isNoEnd = 1;
264
- if (matchLineEnd !== -1) {
265
- endIdx = start + ":::alert".length + matchLineEnd;
266
- isNoEnd = 0;
267
- } else {
268
- endIdx = src.length;
269
- isNoEnd = 1;
270
- }
271
- const inner = src.slice(start + ":::alert".length, endIdx).trim();
272
- const typeMatch = inner.match(/type\s*=\s*(?:(['"])(.*?)\1|(\S+))/);
273
- const type = typeMatch ? typeMatch[2] ?? typeMatch[3] : void 0;
274
- const dataIdx = inner.search(/\bdata\s*=/);
275
- let rawData = "";
276
- if (dataIdx !== -1) {
277
- rawData = inner.slice(dataIdx + inner.slice(dataIdx).match(/\bdata\s*=/)[0].length).trim();
278
- }
279
- const ph = makePlaceholder(id++);
280
- placeholders.set(ph, rawData);
281
- const typeText = type ? `type=${JSON.stringify(type)}` : "";
282
- out += `:::alert ${typeText} data="${ph}" loading="${isNoEnd}" :::`;
283
- const realClose = src.indexOf(":::", endIdx);
284
- pos = realClose === -1 ? endIdx : realClose + 3;
116
+ function isObject(val) {
117
+ return is(val, "Object");
118
+ }
119
+ function isEmptyObj(val) {
120
+ if (isObject(val)) {
121
+ return Object.keys(val).length === 0;
285
122
  }
286
- return { text: out, placeholders };
123
+ return false;
287
124
  }
288
- function alertInlinePlugin(md2) {
289
- md2.inline.ruler.before("emphasis", "alert_inline", function(state, silent) {
290
- const pos = state.pos;
291
- const src = state.src;
292
- if (src.slice(pos, pos + 3) !== ":::") return false;
293
- const m = src.slice(pos).match(/^:::alert\b([^\n\r]*?):::/);
294
- if (!m) return false;
295
- if (silent) return false;
296
- const raw = m[1].trim();
297
- const html = `<lazy-component ${raw}></lazy-component>`;
298
- const token = state.push("html_inline", "", 0);
299
- token.content = html;
300
- state.pos += m[0].length;
301
- return true;
302
- });
125
+ function isDate(val) {
126
+ return is(val, "Date");
303
127
  }
304
- try {
305
- md.use(alertInlinePlugin);
306
- } catch {
307
- }
308
- var filterMarkdown = (content = "") => {
309
- if (!content) return content;
310
- return content.replace(/<!--[\s\S]*?(?:-->|$)/g, "");
311
- };
312
- var RenderMarkdown_default = ({ content = "", searchValue, customComponents, ...rest }) => {
313
- const reactContent = React16.useMemo(() => {
314
- if (!content) return null;
315
- const { text: preprocessed, placeholders } = alertMarkClean(filterMarkdown(content));
316
- let rawHtml = md.render(preprocessed);
317
- rawHtml = searchValue ? highlightKeywords(rawHtml, [searchValue]) : rawHtml;
318
- let lazyIndex = -1;
319
- return parse__default.default(rawHtml, {
320
- replace: (domNode) => {
321
- if (domNode.name === "lazy-component") {
322
- lazyIndex++;
323
- const el = domNode;
324
- const type = el.attribs.type;
325
- const loading = !!Number(el.attribs.loading);
326
- const dataAttr = el.attribs.data || "";
327
- let data = {};
328
- if (/^__ALERT_DATA_\d+__$/.test(dataAttr)) {
329
- const raw = placeholders.get(dataAttr) ?? "";
330
- data = parseData(raw);
331
- }
332
- return /* @__PURE__ */ jsxRuntime.jsx(LazyComponent_default, { customComponents, type, data, loading, ...rest }, `${type}${lazyIndex}`);
333
- }
334
- }
335
- });
336
- }, [content, searchValue]);
337
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ns-markdown", children: reactContent });
338
- };
339
- var MarkdownPreview_default = ({ fileUrl, searchValue }) => {
340
- const [content, setContent] = React16.useState("");
341
- const [error, setError] = React16.useState("");
342
- const fetchMarkdown = async () => {
343
- const res = await fetch(fileUrl);
344
- if (res.status !== 200) {
345
- throw new Error(`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${res.status}`);
346
- }
347
- const markdownText = await res.text();
348
- if (!markdownText) {
349
- throw new Error("\u8FD4\u56DE\u5185\u5BB9\u4E3A\u7A7A");
350
- }
351
- setContent(markdownText);
352
- };
353
- const init = async () => {
354
- setContent("");
355
- setError("");
356
- if (fileUrl) {
357
- try {
358
- await fetchMarkdown();
359
- } catch (error2) {
360
- setError("\u52A0\u8F7D\u6216\u89E3\u6790 Markdown \u5931\u8D25");
361
- }
362
- }
363
- };
364
- React16.useEffect(() => {
365
- init();
366
- }, [fileUrl]);
367
- return error ? /* @__PURE__ */ jsxRuntime.jsx(antd.Result, { status: "error", title: error }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "height-full", children: /* @__PURE__ */ jsxRuntime.jsx(RenderMarkdown_default, { content, searchValue }) });
368
- };
369
-
370
- // src/hooks/iframe/iframeRelay.ts
371
- function emit(type, data, to = "top") {
372
- const payload = { type, data, to };
373
- try {
374
- window.parent.postMessage(payload, "*");
375
- } catch (err) {
376
- console.warn("emit parent failed", err);
377
- }
378
- }
379
- function emitToChild(iframeWindow, type, data, origin = "*") {
380
- if (!iframeWindow) {
381
- console.warn("emitToChild failed: iframeWindow is null");
382
- return;
383
- }
384
- const payload = { type, data, to: "child" };
385
- try {
386
- iframeWindow.postMessage(payload, origin);
387
- } catch (err) {
388
- console.warn("emit to child failed", err);
389
- }
390
- }
391
-
392
- // src/utils/is.ts
393
- var toString = Object.prototype.toString;
394
- function is(val, type) {
395
- return toString.call(val) === `[object ${type}]`;
396
- }
397
- function isUnDef(val) {
398
- return is(val, "Undefined");
399
- }
400
- function isDef(val) {
401
- return !isUnDef(val);
402
- }
403
- function isObject(val) {
404
- return is(val, "Object");
405
- }
406
- function isEmptyObj(val) {
407
- if (isObject(val)) {
408
- return Object.keys(val).length === 0;
409
- }
410
- return false;
411
- }
412
- function isDate(val) {
413
- return is(val, "Date");
414
- }
415
- function isNull(val) {
416
- return is(val, "Null");
128
+ function isNull(val) {
129
+ return is(val, "Null");
417
130
  }
418
131
  function isNullOrUnDef(val) {
419
132
  return isUnDef(val) || isNull(val);
@@ -535,143 +248,6 @@ var isJson = (text = "") => {
535
248
  return false;
536
249
  }
537
250
  };
538
-
539
- // src/hooks/iframe/useIframeRelayBridge.ts
540
- var useIframeRelayBridge_default = (allowedOrigins = ["*"]) => {
541
- const handlers = React16.useRef({});
542
- React16.useEffect(() => {
543
- const onMessage = (evt) => {
544
- const { data, source, origin } = evt;
545
- if (!data || !isObject(data) || !data.type) return;
546
- if (allowedOrigins[0] !== "*" && !allowedOrigins.includes(origin)) return;
547
- const { type, data: params, to = "parent" } = data;
548
- const isTop = window.parent === window;
549
- if (to === "top" && !isTop) {
550
- window.parent.postMessage(data, allowedOrigins[0] === "*" ? "*" : origin);
551
- return;
552
- }
553
- const fns = handlers.current[type] || [];
554
- fns.forEach((fn) => fn(params, source, origin));
555
- };
556
- window.addEventListener("message", onMessage);
557
- return () => window.removeEventListener("message", onMessage);
558
- }, [allowedOrigins]);
559
- function on(type, handler) {
560
- handlers.current[type] = handlers.current[type] || [];
561
- handlers.current[type].push(handler);
562
- }
563
- function off(type, handler) {
564
- handlers.current[type] = (handlers.current[type] || []).filter((fn) => fn !== handler);
565
- }
566
- return { on, off };
567
- };
568
- var useAutoRefresh_default = (listenValue, shouldRefresh, callback, delay = 1e4) => {
569
- const timerRef = React16.useRef(null);
570
- const shouldRefreshRef = React16.useRef(shouldRefresh);
571
- const callbackRef = React16.useRef(callback);
572
- const [num, setNum] = React16.useState(0);
573
- React16.useEffect(() => {
574
- shouldRefreshRef.current = shouldRefresh;
575
- callbackRef.current = callback;
576
- }, [shouldRefresh, callback]);
577
- React16.useEffect(() => {
578
- if (timerRef.current) {
579
- clearTimeout(timerRef.current);
580
- timerRef.current = null;
581
- }
582
- if (shouldRefreshRef.current(listenValue)) {
583
- timerRef.current = setTimeout(async () => {
584
- await callbackRef.current();
585
- setNum(num + 1);
586
- }, delay);
587
- }
588
- return () => {
589
- if (timerRef.current) {
590
- clearTimeout(timerRef.current);
591
- }
592
- };
593
- }, [listenValue, delay, num]);
594
- };
595
- var useCountDown_default = (callback) => {
596
- const [count, setCount] = React16.useState(0);
597
- const [startCount, setStartCount] = React16.useState(0);
598
- const timer = React16.useRef(null);
599
- const pause = () => {
600
- clearInterval(timer.current);
601
- timer.current = null;
602
- };
603
- const start = (initialValue = 60) => {
604
- pause();
605
- setCount(initialValue);
606
- setStartCount((startCount2) => startCount2 + 1);
607
- timer.current = setInterval(() => {
608
- setCount((count2) => count2 - 1);
609
- }, 1e3);
610
- };
611
- React16.useEffect(() => {
612
- return () => {
613
- pause();
614
- };
615
- }, []);
616
- React16.useEffect(() => {
617
- if (count === 0 && startCount !== 0) {
618
- pause();
619
- callback?.();
620
- }
621
- }, [count]);
622
- return { count, start, pause, startCount };
623
- };
624
- var useCreateValtioContext_default = () => {
625
- const Context = React16.createContext(null);
626
- const ValtioProvider = ({ store, children }) => /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value: store, children });
627
- const useValtioStore = () => {
628
- const store = React16.useContext(Context);
629
- if (!store) throw new Error("useStore must be used within Provider");
630
- return store;
631
- };
632
- return {
633
- ValtioProvider,
634
- useValtioStore,
635
- // 导出 Context 以便外部使用
636
- Context
637
- };
638
- };
639
- var useDebounce_default = (func, wait = 400) => {
640
- const { current } = React16.useRef({ func, timeOut: null });
641
- React16.useEffect(() => {
642
- current.func = func;
643
- }, [func]);
644
- let args;
645
- function debounce(..._args) {
646
- args = _args;
647
- if (current.timeOut) {
648
- clearTimeout(current.timeOut);
649
- current.timeOut = null;
650
- }
651
- return new Promise((resolve, reject) => {
652
- current.timeOut = setTimeout(async () => {
653
- try {
654
- const result = await current.func.apply(null, args);
655
- resolve(result);
656
- } catch (e) {
657
- reject(e);
658
- }
659
- }, wait);
660
- });
661
- }
662
- function cancel() {
663
- if (!current.timeOut) return;
664
- clearTimeout(current.timeOut);
665
- current.timeOut = null;
666
- }
667
- function flush() {
668
- cancel();
669
- return current.func.apply(null, args);
670
- }
671
- debounce.flush = flush;
672
- debounce.cancel = cancel;
673
- return React16.useCallback(debounce, []);
674
- };
675
251
  var OperatorToMethodName = {
676
252
  "+": "plus",
677
253
  "-": "minus",
@@ -1232,7 +808,7 @@ function formatSize(value, options = {}) {
1232
808
  return `${toFixed(size, precision2, !trimZero)}${UNIT_LIST[index]}`;
1233
809
  }
1234
810
  var markdownToText = (() => {
1235
- const md2 = new markdownit__default.default({
811
+ const md2 = new MarkdownIt__default.default({
1236
812
  html: true,
1237
813
  linkify: true,
1238
814
  typographer: false
@@ -1244,174 +820,17 @@ var markdownToText = (() => {
1244
820
  return text;
1245
821
  };
1246
822
  })();
1247
-
1248
- // src/hooks/useDeepEffect.ts
1249
- var useDeepEffect_default = (effect, deps) => {
1250
- const prevDepsRef = React16.useRef();
1251
- const depsChanged = !prevDepsRef.current || deps.length !== prevDepsRef.current.length || deps.some((dep, i) => !deepEqual(dep, prevDepsRef.current[i]));
1252
- React16.useEffect(() => {
1253
- if (depsChanged) {
1254
- prevDepsRef.current = deps;
1255
- return effect();
1256
- }
1257
- }, [depsChanged]);
823
+ dayjs__default.default.extend(relativeTime__default.default);
824
+ var DEFAULT_DATE_TIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
825
+ var DEFAULT_DATE_FORMAT = "YYYY-MM-DD";
826
+ var DEFAULT_YEAR_MONTH_FORMAT = "YYYY\u5E74MM\u6708";
827
+ var DEFAULT_YEAR_MONTH_DAY_FORMAT = "YYYY\u5E74MM\u6708DD\u65E5";
828
+ var DEFAULT_UNIT = "date";
829
+ var getStartOfTimestamp = (date, unit = DEFAULT_UNIT) => {
830
+ return dayjs__default.default(date).startOf(unit).valueOf();
1258
831
  };
1259
- var useRefState_default = (init) => {
1260
- const [state, setState] = React16.useState(init);
1261
- const stateRef = React16.useRef(init);
1262
- const setProxy = (newVal) => {
1263
- stateRef.current = newVal;
1264
- setState(newVal);
1265
- };
1266
- const getState = () => stateRef.current;
1267
- return [state, setProxy, getState];
1268
- };
1269
- var useSpeech_default = ({ onResult, lang = "zh-CN" }) => {
1270
- const [permission, setPermission] = React16.useState("prompt");
1271
- const [isRecording, setIsRecording] = React16.useState(false);
1272
- const recognitionRef = React16.useRef(null);
1273
- React16.useEffect(() => {
1274
- const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
1275
- if (!SpeechRecognition) {
1276
- setPermission("unsupported");
1277
- return;
1278
- }
1279
- const recognition = new SpeechRecognition();
1280
- recognition.continuous = true;
1281
- recognition.interimResults = false;
1282
- recognition.lang = lang;
1283
- recognition.onresult = (event) => {
1284
- let transcript = "";
1285
- for (let i = event.resultIndex; i < event.results.length; i++) {
1286
- transcript += event.results[i][0].transcript;
1287
- }
1288
- onResult?.(transcript.trim());
1289
- };
1290
- recognition.onend = () => {
1291
- setIsRecording(false);
1292
- };
1293
- recognition.onerror = (error) => {
1294
- setIsRecording(false);
1295
- console.error("Speech recognition error:", error);
1296
- };
1297
- recognitionRef.current = recognition;
1298
- return () => {
1299
- recognition.stop?.();
1300
- recognition.onresult = null;
1301
- recognition.onend = null;
1302
- recognition.onerror = null;
1303
- };
1304
- }, [lang, onResult]);
1305
- React16.useEffect(() => {
1306
- if (!navigator.permissions) return;
1307
- navigator.permissions.query({ name: "microphone" }).then((status) => {
1308
- setPermission(status.state);
1309
- status.onchange = () => setPermission(status.state);
1310
- });
1311
- }, []);
1312
- const requestPermission = React16.useCallback(async () => {
1313
- try {
1314
- await navigator.mediaDevices.getUserMedia({ audio: true });
1315
- setPermission("granted");
1316
- } catch {
1317
- setPermission("denied");
1318
- }
1319
- }, []);
1320
- const start = React16.useCallback(() => {
1321
- if (permission === "prompt") {
1322
- requestPermission();
1323
- return;
1324
- }
1325
- if (permission !== "granted") return;
1326
- if (!isRecording) {
1327
- recognitionRef.current?.start();
1328
- setIsRecording(true);
1329
- }
1330
- }, [permission, isRecording, requestPermission]);
1331
- const stop = React16.useCallback(() => {
1332
- try {
1333
- recognitionRef.current?.stop();
1334
- } finally {
1335
- setIsRecording(false);
1336
- }
1337
- }, []);
1338
- return {
1339
- /**
1340
- * 权限状态
1341
- */
1342
- permission,
1343
- /**
1344
- * 录音状态
1345
- */
1346
- isRecording,
1347
- /** 开始语音识别 */
1348
- start,
1349
- /** 停止语音识别 */
1350
- stop
1351
- };
1352
- };
1353
- var useSyncInput_default = (storeValue, setStoreValue) => {
1354
- const [inputValue, setInputValue] = React16.useState(storeValue);
1355
- React16.useEffect(() => {
1356
- if (storeValue !== inputValue) {
1357
- setInputValue(storeValue);
1358
- }
1359
- }, [storeValue]);
1360
- const handleValueChange = (value) => {
1361
- setStoreValue(value);
1362
- setInputValue(value);
1363
- };
1364
- return {
1365
- inputValue,
1366
- setInputValue: handleValueChange
1367
- };
1368
- };
1369
- var useThrottle_default = (func, wait) => {
1370
- const { current } = React16.useRef({ func, timeOut: null });
1371
- React16.useEffect(() => {
1372
- current.func = func;
1373
- }, [func]);
1374
- let args;
1375
- function throttle(..._args) {
1376
- args = _args;
1377
- return new Promise((resolve, reject) => {
1378
- if (!current.timeOut) {
1379
- try {
1380
- const result = current.func.apply(null, args);
1381
- resolve(result);
1382
- } catch (e) {
1383
- reject(e);
1384
- }
1385
- current.timeOut = setTimeout(() => {
1386
- current.timeOut = null;
1387
- }, wait);
1388
- }
1389
- });
1390
- }
1391
- function cancel() {
1392
- if (!current.timeOut) return;
1393
- clearTimeout(current.timeOut);
1394
- current.timeOut = null;
1395
- }
1396
- function flush() {
1397
- cancel();
1398
- return current.func.apply(null, args);
1399
- }
1400
- throttle.flush = flush;
1401
- throttle.cancel = cancel;
1402
- return React16.useCallback(throttle, []);
1403
- };
1404
- dayjs__default.default.extend(relativeTime__default.default);
1405
- var DEFAULT_DATE_TIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
1406
- var DEFAULT_DATE_FORMAT = "YYYY-MM-DD";
1407
- var DEFAULT_YEAR_MONTH_FORMAT = "YYYY\u5E74MM\u6708";
1408
- var DEFAULT_YEAR_MONTH_DAY_FORMAT = "YYYY\u5E74MM\u6708DD\u65E5";
1409
- var DEFAULT_UNIT = "date";
1410
- var getStartOfTimestamp = (date, unit = DEFAULT_UNIT) => {
1411
- return dayjs__default.default(date).startOf(unit).valueOf();
1412
- };
1413
- var getEndOfTimestamp = (date, unit = DEFAULT_UNIT) => {
1414
- return dayjs__default.default(date).endOf(unit).valueOf();
832
+ var getEndOfTimestamp = (date, unit = DEFAULT_UNIT) => {
833
+ return dayjs__default.default(date).endOf(unit).valueOf();
1415
834
  };
1416
835
  var formatDate = (date, fmt = DEFAULT_DATE_TIME_FORMAT) => {
1417
836
  if (date) {
@@ -1760,8 +1179,590 @@ function createTokenManager({ key, storage = localStorage }) {
1760
1179
  clear: tokenManager.clear
1761
1180
  };
1762
1181
  }
1763
-
1764
- // src/hooks/webSocket/useWebSocket.ts
1182
+ var DocxPreview_default = ({ fileUrl, scale = 1 }) => {
1183
+ const containerRef = React16.useRef(null);
1184
+ const [zoomRatio, setZoomRatio] = React16.useState(scale);
1185
+ React16.useEffect(() => {
1186
+ if (!fileUrl || !containerRef.current) return;
1187
+ containerRef.current.innerHTML = "";
1188
+ fetch(fileUrl).then((res) => res.arrayBuffer()).then(async (arrayBuffer) => {
1189
+ await docxPreview.renderAsync(arrayBuffer, containerRef.current, null, {
1190
+ breakPages: true,
1191
+ renderHeaders: true,
1192
+ renderFooters: true,
1193
+ ignoreWidth: false,
1194
+ ignoreHeight: false
1195
+ });
1196
+ containerRef.current.querySelectorAll("a[href]").forEach((linkEle) => {
1197
+ const href = linkEle.getAttribute("href");
1198
+ if (href && isExternal(href)) {
1199
+ linkEle.setAttribute("target", "_blank");
1200
+ linkEle.setAttribute("rel", "noopener noreferrer");
1201
+ }
1202
+ });
1203
+ }).catch((err) => {
1204
+ console.error("docx-preview \u6E32\u67D3\u5931\u8D25:", err);
1205
+ if (containerRef.current) containerRef.current.innerHTML = '<p class="text-center">\u6587\u6863\u52A0\u8F7D\u5931\u8D25</p>';
1206
+ });
1207
+ }, [fileUrl]);
1208
+ const zoomIn = () => setZoomRatio((z) => Math.min(z + 0.1, 3));
1209
+ const zoomOut = () => setZoomRatio((z) => Math.max(z - 0.1, 0.3));
1210
+ const resetZoom = () => {
1211
+ setZoomRatio(1);
1212
+ };
1213
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames__default.default(styles_module_default.nsPreviewDocx, "height-full"), children: [
1214
+ /* @__PURE__ */ jsxRuntime.jsxs(antd.Flex, { gap: 6, align: "center", className: styles_module_default.docxToolbar, children: [
1215
+ /* @__PURE__ */ jsxRuntime.jsx(antd.Button, { onClick: zoomOut, icon: /* @__PURE__ */ jsxRuntime.jsx(Icon.MinusCircleOutlined, {}), title: "\u7F29\u5C0F" }),
1216
+ /* @__PURE__ */ jsxRuntime.jsx(antd.Button, { onClick: zoomIn, icon: /* @__PURE__ */ jsxRuntime.jsx(Icon.PlusCircleOutlined, {}), title: "\u653E\u5927" }),
1217
+ /* @__PURE__ */ jsxRuntime.jsx(antd.Button, { onClick: resetZoom, icon: /* @__PURE__ */ jsxRuntime.jsx(Icon.RedoOutlined, {}), title: "\u8FD8\u539F" })
1218
+ ] }),
1219
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: classNames__default.default(styles_module_default.docxContent, "height-full", "scroll-fade-in"), children: /* @__PURE__ */ jsxRuntime.jsx(
1220
+ "div",
1221
+ {
1222
+ ref: containerRef,
1223
+ style: {
1224
+ transform: `scale(${zoomRatio})`,
1225
+ transformOrigin: "top center"
1226
+ }
1227
+ }
1228
+ ) })
1229
+ ] });
1230
+ };
1231
+ var FileIcon_default = ({ suffix, fontSize = 22 }) => {
1232
+ const styles = { fontSize, color: "var(--ant-color-primary)" };
1233
+ const Icon2 = React16.useMemo(() => {
1234
+ switch (suffix?.toUpperCase()) {
1235
+ case "TXT":
1236
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileTextOutlined, {});
1237
+ case "PDF":
1238
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.FilePdfOutlined, {});
1239
+ case "DOC":
1240
+ case "DOCX":
1241
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileWordOutlined, {});
1242
+ case "XLS":
1243
+ case "XLSX":
1244
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileExcelOutlined, {});
1245
+ case "PPT":
1246
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.FilePptOutlined, {});
1247
+ case "MP4":
1248
+ case "MOV":
1249
+ case "MKV":
1250
+ case "AVI":
1251
+ case "FLV":
1252
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.VideoCameraOutlined, {});
1253
+ case "MP3":
1254
+ case "WAV":
1255
+ case "M4A":
1256
+ case "ACC":
1257
+ case "WMA":
1258
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.NotificationOutlined, {});
1259
+ case "JPG":
1260
+ case "JPEG":
1261
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileJpgOutlined, {});
1262
+ case "PNG":
1263
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileImageOutlined, {});
1264
+ case "GIF":
1265
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileGifOutlined, {});
1266
+ case "MD":
1267
+ case "MARKDOWN":
1268
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileMarkdownOutlined, {});
1269
+ case "ZIP":
1270
+ case "RAR":
1271
+ case "7Z":
1272
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileZipOutlined, {});
1273
+ case "CATALOG":
1274
+ return /* @__PURE__ */ jsxRuntime.jsx("i", { style: styles, className: "iconfont icon-wenjianjia" });
1275
+ // 文件夹图标
1276
+ default:
1277
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon.FileUnknownOutlined, {});
1278
+ }
1279
+ }, [suffix]);
1280
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { style: styles, children: Icon2 });
1281
+ };
1282
+ var VideoPlayer_default = ({ fileUrl }) => {
1283
+ return /* @__PURE__ */ jsxRuntime.jsxs("video", { controls: true, className: styles_module_default.nsPreviewVideo, children: [
1284
+ /* @__PURE__ */ jsxRuntime.jsx("source", { src: fileUrl, type: "video/mp4" }),
1285
+ "\u60A8\u7684\u6D4F\u89C8\u5668\u4E0D\u652F\u6301 video \u6807\u7B7E\u3002"
1286
+ ] });
1287
+ };
1288
+ var baseComponentMap = {
1289
+ // renderMarkdown: () => import('@/components/RenderMarkdown')
1290
+ };
1291
+ var LazyComponent_default = ({ type, customComponents, ...rest }) => {
1292
+ const componentMap = React16.useMemo(() => {
1293
+ return { ...baseComponentMap, ...customComponents };
1294
+ }, [customComponents]);
1295
+ const LazyComponent = React16.useMemo(() => {
1296
+ const loader = componentMap[type];
1297
+ return loader ? React16.lazy(loader) : null;
1298
+ }, [type, componentMap]);
1299
+ if (!LazyComponent) return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1300
+ "\u672A\u77E5\u7C7B\u578B\uFF1A",
1301
+ type
1302
+ ] });
1303
+ return /* @__PURE__ */ jsxRuntime.jsx(React16.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx("div", { children: "\u52A0\u8F7D\u4E2D..." }), children: /* @__PURE__ */ jsxRuntime.jsx(LazyComponent, { ...rest }) });
1304
+ };
1305
+ var md = MarkdownIt__default.default({ html: true, breaks: true });
1306
+ md.renderer.rules.link_open = function(tokens, idx, options, env, self) {
1307
+ const token = tokens[idx];
1308
+ token.attrPush(["target", "_blank"]);
1309
+ return self.renderToken(tokens, idx, options);
1310
+ };
1311
+ function parseData(raw) {
1312
+ let obj = {};
1313
+ try {
1314
+ obj = JSON.parse(raw);
1315
+ } catch {
1316
+ try {
1317
+ obj = JSON.parse(jsonrepair.jsonrepair(raw));
1318
+ } catch {
1319
+ obj = { _raw: raw };
1320
+ }
1321
+ }
1322
+ return obj;
1323
+ }
1324
+ function highlightKeywords(html, keywords) {
1325
+ const escaped = keywords.map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
1326
+ const regex = new RegExp(`(${escaped.join("|")})`, "gi");
1327
+ return html.replace(regex, '<span class="cube-hl">$1</span>');
1328
+ }
1329
+ function makePlaceholder(id) {
1330
+ return `__ALERT_DATA_${id}__`;
1331
+ }
1332
+ function alertMarkClean(src) {
1333
+ let pos = 0;
1334
+ let id = 0;
1335
+ let out = "";
1336
+ const placeholders = /* @__PURE__ */ new Map();
1337
+ while (pos < src.length) {
1338
+ const start = src.indexOf(":::alert", pos);
1339
+ if (start === -1) {
1340
+ out += src.slice(pos);
1341
+ break;
1342
+ }
1343
+ out += src.slice(pos, start);
1344
+ const afterStart = src.slice(start);
1345
+ const relAfter = afterStart.slice(":::alert".length);
1346
+ const matchLineEnd = relAfter.search(/\s*:::\s*/);
1347
+ let endIdx = -1;
1348
+ let isNoEnd = 1;
1349
+ if (matchLineEnd !== -1) {
1350
+ endIdx = start + ":::alert".length + matchLineEnd;
1351
+ isNoEnd = 0;
1352
+ } else {
1353
+ endIdx = src.length;
1354
+ isNoEnd = 1;
1355
+ }
1356
+ const inner = src.slice(start + ":::alert".length, endIdx).trim();
1357
+ const typeMatch = inner.match(/type\s*=\s*(?:(['"])(.*?)\1|(\S+))/);
1358
+ const type = typeMatch ? typeMatch[2] ?? typeMatch[3] : void 0;
1359
+ const dataIdx = inner.search(/\bdata\s*=/);
1360
+ let rawData = "";
1361
+ if (dataIdx !== -1) {
1362
+ rawData = inner.slice(dataIdx + inner.slice(dataIdx).match(/\bdata\s*=/)[0].length).trim();
1363
+ }
1364
+ const ph = makePlaceholder(id++);
1365
+ placeholders.set(ph, rawData);
1366
+ const typeText = type ? `type=${JSON.stringify(type)}` : "";
1367
+ out += `:::alert ${typeText} data="${ph}" loading="${isNoEnd}" :::`;
1368
+ const realClose = src.indexOf(":::", endIdx);
1369
+ pos = realClose === -1 ? endIdx : realClose + 3;
1370
+ }
1371
+ return { text: out, placeholders };
1372
+ }
1373
+ function alertInlinePlugin(md2) {
1374
+ md2.inline.ruler.before("emphasis", "alert_inline", function(state, silent) {
1375
+ const pos = state.pos;
1376
+ const src = state.src;
1377
+ if (src.slice(pos, pos + 3) !== ":::") return false;
1378
+ const m = src.slice(pos).match(/^:::alert\b([^\n\r]*?):::/);
1379
+ if (!m) return false;
1380
+ if (silent) return false;
1381
+ const raw = m[1].trim();
1382
+ const html = `<lazy-component ${raw}></lazy-component>`;
1383
+ const token = state.push("html_inline", "", 0);
1384
+ token.content = html;
1385
+ state.pos += m[0].length;
1386
+ return true;
1387
+ });
1388
+ }
1389
+ try {
1390
+ md.use(alertInlinePlugin);
1391
+ } catch {
1392
+ }
1393
+ var filterMarkdown = (content = "") => {
1394
+ if (!content) return content;
1395
+ return content.replace(/<!--[\s\S]*?(?:-->|$)/g, "");
1396
+ };
1397
+ var RenderMarkdown_default = ({ content = "", searchValue, customComponents, ...rest }) => {
1398
+ const reactContent = React16.useMemo(() => {
1399
+ if (!content) return null;
1400
+ const { text: preprocessed, placeholders } = alertMarkClean(filterMarkdown(content));
1401
+ let rawHtml = md.render(preprocessed);
1402
+ rawHtml = searchValue ? highlightKeywords(rawHtml, [searchValue]) : rawHtml;
1403
+ let lazyIndex = -1;
1404
+ return parse__default.default(rawHtml, {
1405
+ replace: (domNode) => {
1406
+ if (domNode.name === "lazy-component") {
1407
+ lazyIndex++;
1408
+ const el = domNode;
1409
+ const type = el.attribs.type;
1410
+ const loading = !!Number(el.attribs.loading);
1411
+ const dataAttr = el.attribs.data || "";
1412
+ let data = {};
1413
+ if (/^__ALERT_DATA_\d+__$/.test(dataAttr)) {
1414
+ const raw = placeholders.get(dataAttr) ?? "";
1415
+ data = parseData(raw);
1416
+ }
1417
+ return /* @__PURE__ */ jsxRuntime.jsx(LazyComponent_default, { customComponents, type, data, loading, ...rest }, `${type}${lazyIndex}`);
1418
+ }
1419
+ }
1420
+ });
1421
+ }, [content, searchValue]);
1422
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ns-markdown", children: reactContent });
1423
+ };
1424
+ var MarkdownPreview_default = ({ fileUrl, searchValue }) => {
1425
+ const [content, setContent] = React16.useState("");
1426
+ const [error, setError] = React16.useState("");
1427
+ const fetchMarkdown = async () => {
1428
+ const res = await fetch(fileUrl);
1429
+ if (res.status !== 200) {
1430
+ throw new Error(`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${res.status}`);
1431
+ }
1432
+ const markdownText = await res.text();
1433
+ if (!markdownText) {
1434
+ throw new Error("\u8FD4\u56DE\u5185\u5BB9\u4E3A\u7A7A");
1435
+ }
1436
+ setContent(markdownText);
1437
+ };
1438
+ const init = async () => {
1439
+ setContent("");
1440
+ setError("");
1441
+ if (fileUrl) {
1442
+ try {
1443
+ await fetchMarkdown();
1444
+ } catch (error2) {
1445
+ setError("\u52A0\u8F7D\u6216\u89E3\u6790 Markdown \u5931\u8D25");
1446
+ }
1447
+ }
1448
+ };
1449
+ React16.useEffect(() => {
1450
+ init();
1451
+ }, [fileUrl]);
1452
+ return error ? /* @__PURE__ */ jsxRuntime.jsx(antd.Result, { status: "error", title: error }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "height-full", children: /* @__PURE__ */ jsxRuntime.jsx(RenderMarkdown_default, { content, searchValue }) });
1453
+ };
1454
+
1455
+ // src/hooks/iframe/iframeRelay.ts
1456
+ function emit(type, data, to = "top") {
1457
+ const payload = { type, data, to };
1458
+ try {
1459
+ window.parent.postMessage(payload, "*");
1460
+ } catch (err) {
1461
+ console.warn("emit parent failed", err);
1462
+ }
1463
+ }
1464
+ function emitToChild(iframeWindow, type, data, origin = "*") {
1465
+ if (!iframeWindow) {
1466
+ console.warn("emitToChild failed: iframeWindow is null");
1467
+ return;
1468
+ }
1469
+ const payload = { type, data, to: "child" };
1470
+ try {
1471
+ iframeWindow.postMessage(payload, origin);
1472
+ } catch (err) {
1473
+ console.warn("emit to child failed", err);
1474
+ }
1475
+ }
1476
+ var useIframeRelayBridge_default = (allowedOrigins = ["*"]) => {
1477
+ const handlers = React16.useRef({});
1478
+ React16.useEffect(() => {
1479
+ const onMessage = (evt) => {
1480
+ const { data, source, origin } = evt;
1481
+ if (!data || !isObject(data) || !data.type) return;
1482
+ if (allowedOrigins[0] !== "*" && !allowedOrigins.includes(origin)) return;
1483
+ const { type, data: params, to = "parent" } = data;
1484
+ const isTop = window.parent === window;
1485
+ if (to === "top" && !isTop) {
1486
+ window.parent.postMessage(data, allowedOrigins[0] === "*" ? "*" : origin);
1487
+ return;
1488
+ }
1489
+ const fns = handlers.current[type] || [];
1490
+ fns.forEach((fn) => fn(params, source, origin));
1491
+ };
1492
+ window.addEventListener("message", onMessage);
1493
+ return () => window.removeEventListener("message", onMessage);
1494
+ }, [allowedOrigins]);
1495
+ function on(type, handler) {
1496
+ handlers.current[type] = handlers.current[type] || [];
1497
+ handlers.current[type].push(handler);
1498
+ }
1499
+ function off(type, handler) {
1500
+ handlers.current[type] = (handlers.current[type] || []).filter((fn) => fn !== handler);
1501
+ }
1502
+ return { on, off };
1503
+ };
1504
+ var useAutoRefresh_default = (listenValue, shouldRefresh, callback, delay = 1e4) => {
1505
+ const timerRef = React16.useRef(null);
1506
+ const shouldRefreshRef = React16.useRef(shouldRefresh);
1507
+ const callbackRef = React16.useRef(callback);
1508
+ const [num, setNum] = React16.useState(0);
1509
+ React16.useEffect(() => {
1510
+ shouldRefreshRef.current = shouldRefresh;
1511
+ callbackRef.current = callback;
1512
+ }, [shouldRefresh, callback]);
1513
+ React16.useEffect(() => {
1514
+ if (timerRef.current) {
1515
+ clearTimeout(timerRef.current);
1516
+ timerRef.current = null;
1517
+ }
1518
+ if (shouldRefreshRef.current(listenValue)) {
1519
+ timerRef.current = setTimeout(async () => {
1520
+ await callbackRef.current();
1521
+ setNum(num + 1);
1522
+ }, delay);
1523
+ }
1524
+ return () => {
1525
+ if (timerRef.current) {
1526
+ clearTimeout(timerRef.current);
1527
+ }
1528
+ };
1529
+ }, [listenValue, delay, num]);
1530
+ };
1531
+ var useCountDown_default = (callback) => {
1532
+ const [count, setCount] = React16.useState(0);
1533
+ const [startCount, setStartCount] = React16.useState(0);
1534
+ const timer = React16.useRef(null);
1535
+ const pause = () => {
1536
+ clearInterval(timer.current);
1537
+ timer.current = null;
1538
+ };
1539
+ const start = (initialValue = 60) => {
1540
+ pause();
1541
+ setCount(initialValue);
1542
+ setStartCount((startCount2) => startCount2 + 1);
1543
+ timer.current = setInterval(() => {
1544
+ setCount((count2) => count2 - 1);
1545
+ }, 1e3);
1546
+ };
1547
+ React16.useEffect(() => {
1548
+ return () => {
1549
+ pause();
1550
+ };
1551
+ }, []);
1552
+ React16.useEffect(() => {
1553
+ if (count === 0 && startCount !== 0) {
1554
+ pause();
1555
+ callback?.();
1556
+ }
1557
+ }, [count]);
1558
+ return { count, start, pause, startCount };
1559
+ };
1560
+ var useCreateValtioContext_default = () => {
1561
+ const Context = React16.createContext(null);
1562
+ const ValtioProvider = ({ store, children }) => /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value: store, children });
1563
+ const useValtioStore = () => {
1564
+ const store = React16.useContext(Context);
1565
+ if (!store) throw new Error("useStore must be used within Provider");
1566
+ return store;
1567
+ };
1568
+ return {
1569
+ ValtioProvider,
1570
+ useValtioStore,
1571
+ // 导出 Context 以便外部使用
1572
+ Context
1573
+ };
1574
+ };
1575
+ var useDebounce_default = (func, wait = 400) => {
1576
+ const { current } = React16.useRef({ func, timeOut: null });
1577
+ React16.useEffect(() => {
1578
+ current.func = func;
1579
+ }, [func]);
1580
+ let args;
1581
+ function debounce(..._args) {
1582
+ args = _args;
1583
+ if (current.timeOut) {
1584
+ clearTimeout(current.timeOut);
1585
+ current.timeOut = null;
1586
+ }
1587
+ return new Promise((resolve, reject) => {
1588
+ current.timeOut = setTimeout(async () => {
1589
+ try {
1590
+ const result = await current.func.apply(null, args);
1591
+ resolve(result);
1592
+ } catch (e) {
1593
+ reject(e);
1594
+ }
1595
+ }, wait);
1596
+ });
1597
+ }
1598
+ function cancel() {
1599
+ if (!current.timeOut) return;
1600
+ clearTimeout(current.timeOut);
1601
+ current.timeOut = null;
1602
+ }
1603
+ function flush() {
1604
+ cancel();
1605
+ return current.func.apply(null, args);
1606
+ }
1607
+ debounce.flush = flush;
1608
+ debounce.cancel = cancel;
1609
+ return React16.useCallback(debounce, []);
1610
+ };
1611
+ var useDeepEffect_default = (effect, deps) => {
1612
+ const prevDepsRef = React16.useRef();
1613
+ const depsChanged = !prevDepsRef.current || deps.length !== prevDepsRef.current.length || deps.some((dep, i) => !deepEqual(dep, prevDepsRef.current[i]));
1614
+ React16.useEffect(() => {
1615
+ if (depsChanged) {
1616
+ prevDepsRef.current = deps;
1617
+ return effect();
1618
+ }
1619
+ }, [depsChanged]);
1620
+ };
1621
+ var useRefState_default = (init) => {
1622
+ const [state, setState] = React16.useState(init);
1623
+ const stateRef = React16.useRef(init);
1624
+ const setProxy = (newVal) => {
1625
+ stateRef.current = newVal;
1626
+ setState(newVal);
1627
+ };
1628
+ const getState = () => stateRef.current;
1629
+ return [state, setProxy, getState];
1630
+ };
1631
+ var useSpeech_default = ({ onResult, lang = "zh-CN" }) => {
1632
+ const [permission, setPermission] = React16.useState("prompt");
1633
+ const [isRecording, setIsRecording] = React16.useState(false);
1634
+ const recognitionRef = React16.useRef(null);
1635
+ React16.useEffect(() => {
1636
+ const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
1637
+ if (!SpeechRecognition) {
1638
+ setPermission("unsupported");
1639
+ return;
1640
+ }
1641
+ const recognition = new SpeechRecognition();
1642
+ recognition.continuous = true;
1643
+ recognition.interimResults = false;
1644
+ recognition.lang = lang;
1645
+ recognition.onresult = (event) => {
1646
+ let transcript = "";
1647
+ for (let i = event.resultIndex; i < event.results.length; i++) {
1648
+ transcript += event.results[i][0].transcript;
1649
+ }
1650
+ onResult?.(transcript.trim());
1651
+ };
1652
+ recognition.onend = () => {
1653
+ setIsRecording(false);
1654
+ };
1655
+ recognition.onerror = (error) => {
1656
+ setIsRecording(false);
1657
+ console.error("Speech recognition error:", error);
1658
+ };
1659
+ recognitionRef.current = recognition;
1660
+ return () => {
1661
+ recognition.stop?.();
1662
+ recognition.onresult = null;
1663
+ recognition.onend = null;
1664
+ recognition.onerror = null;
1665
+ };
1666
+ }, [lang, onResult]);
1667
+ React16.useEffect(() => {
1668
+ if (!navigator.permissions) return;
1669
+ navigator.permissions.query({ name: "microphone" }).then((status) => {
1670
+ setPermission(status.state);
1671
+ status.onchange = () => setPermission(status.state);
1672
+ });
1673
+ }, []);
1674
+ const requestPermission = React16.useCallback(async () => {
1675
+ try {
1676
+ await navigator.mediaDevices.getUserMedia({ audio: true });
1677
+ setPermission("granted");
1678
+ } catch {
1679
+ setPermission("denied");
1680
+ }
1681
+ }, []);
1682
+ const start = React16.useCallback(() => {
1683
+ if (permission === "prompt") {
1684
+ requestPermission();
1685
+ return;
1686
+ }
1687
+ if (permission !== "granted") return;
1688
+ if (!isRecording) {
1689
+ recognitionRef.current?.start();
1690
+ setIsRecording(true);
1691
+ }
1692
+ }, [permission, isRecording, requestPermission]);
1693
+ const stop = React16.useCallback(() => {
1694
+ try {
1695
+ recognitionRef.current?.stop();
1696
+ } finally {
1697
+ setIsRecording(false);
1698
+ }
1699
+ }, []);
1700
+ return {
1701
+ /**
1702
+ * 权限状态
1703
+ */
1704
+ permission,
1705
+ /**
1706
+ * 录音状态
1707
+ */
1708
+ isRecording,
1709
+ /** 开始语音识别 */
1710
+ start,
1711
+ /** 停止语音识别 */
1712
+ stop
1713
+ };
1714
+ };
1715
+ var useSyncInput_default = (storeValue, setStoreValue) => {
1716
+ const [inputValue, setInputValue] = React16.useState(storeValue);
1717
+ React16.useEffect(() => {
1718
+ if (storeValue !== inputValue) {
1719
+ setInputValue(storeValue);
1720
+ }
1721
+ }, [storeValue]);
1722
+ const handleValueChange = (value) => {
1723
+ setStoreValue(value);
1724
+ setInputValue(value);
1725
+ };
1726
+ return {
1727
+ inputValue,
1728
+ setInputValue: handleValueChange
1729
+ };
1730
+ };
1731
+ var useThrottle_default = (func, wait) => {
1732
+ const { current } = React16.useRef({ func, timeOut: null });
1733
+ React16.useEffect(() => {
1734
+ current.func = func;
1735
+ }, [func]);
1736
+ let args;
1737
+ function throttle(..._args) {
1738
+ args = _args;
1739
+ return new Promise((resolve, reject) => {
1740
+ if (!current.timeOut) {
1741
+ try {
1742
+ const result = current.func.apply(null, args);
1743
+ resolve(result);
1744
+ } catch (e) {
1745
+ reject(e);
1746
+ }
1747
+ current.timeOut = setTimeout(() => {
1748
+ current.timeOut = null;
1749
+ }, wait);
1750
+ }
1751
+ });
1752
+ }
1753
+ function cancel() {
1754
+ if (!current.timeOut) return;
1755
+ clearTimeout(current.timeOut);
1756
+ current.timeOut = null;
1757
+ }
1758
+ function flush() {
1759
+ cancel();
1760
+ return current.func.apply(null, args);
1761
+ }
1762
+ throttle.flush = flush;
1763
+ throttle.cancel = cancel;
1764
+ return React16.useCallback(throttle, []);
1765
+ };
1765
1766
  var useWebSocket_default = ({
1766
1767
  url,
1767
1768
  onMessage,
@@ -1923,7 +1924,7 @@ var ProtectedView = ({
1923
1924
  };
1924
1925
  var openLinksNewTabPlugin = () => {
1925
1926
  const onAnnotationLayerRender = (e) => {
1926
- e.container.querySelectorAll(".rpv-core__annotation--link a").forEach((linkEle) => {
1927
+ e.container.querySelectorAll(".rpv-core__annotation--link a[href]").forEach((linkEle) => {
1927
1928
  const href = linkEle.getAttribute("href");
1928
1929
  if (href && isExternal(href)) {
1929
1930
  linkEle.setAttribute("target", "_blank");