react-terminal-viewer-cicd 3.0.0-beta.39 → 3.0.0-beta.40

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.
@@ -1,7 +1,7 @@
1
1
  function LogWorker() {
2
2
  var workerPath = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '/worker';
3
3
  var worker = null;
4
- var version = "3.0.0-beta.39" || '0.0.0';
4
+ var version = "3.0.0-beta.40" || '0.0.0';
5
5
  var path = workerPath.includes('http') ? "".concat(workerPath, "/log.worker.js") : "".concat(window.location.origin).concat(workerPath, "/log.worker.js");
6
6
  var blob = new Blob(["importScripts(\"".concat(path, "?v=").concat(version, "\")")], {
7
7
  type: 'application/javascript'
@@ -3,10 +3,10 @@ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableTo
3
3
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
4
4
  function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
5
5
  function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
6
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
6
7
  function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
7
8
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
8
9
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
9
- function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
10
10
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
11
11
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
12
12
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
@@ -28,7 +28,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
28
28
  // §六 IoC 接口注入:fetchGroups / fetchLogs / searchLogs 由外部传入
29
29
  //
30
30
  // 组件生命周期调用时序 (设计文档 §六.2):
31
- // 第一阶段:Mount → Promise.all(fetchGroups, initLoad) 并行首屏加载
31
+ // 第一阶段:Mount → Promise.all([fetchGroups, initLoad]) 并行首屏加载(分组与日志同屏)
32
32
  // 第二阶段:startReached/endReached/轮询 → 单发 loadPrev/loadNext
33
33
  // 第三阶段:搜索 → searchLogs → 若跨页则串行 airdropLoad
34
34
  // ============================================================================
@@ -36,7 +36,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
36
36
  import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from 'react';
37
37
  import { Virtuoso } from 'react-virtuoso';
38
38
  import { GroupHeader, LogRow, SearchBar, StickyHeader } from "./components";
39
- import { BOUNDARY_PREFETCH_INDEX_MARGIN, DEFAULT_MAX_MEMORY_LINES, DEFAULT_PAGE_SIZE, DEFAULT_POLL_INTERVAL, DEFAULT_VIRTUOSO_ITEM_HEIGHT } from "./constants";
39
+ import { BOUNDARY_PREFETCH_INDEX_MARGIN, DEFAULT_MAX_MEMORY_LINES, DEFAULT_PAGE_SIZE, DEFAULT_VIRTUOSO_ITEM_HEIGHT } from "./constants";
40
40
  import useDisplayLogs from "./hooks/useDisplayLogs";
41
41
  import useGroupManager from "./hooks/useGroupManager";
42
42
  import useLogFetcher from "./hooks/useLogFetcher";
@@ -130,6 +130,26 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
130
130
  groups = _useState2[0],
131
131
  setGroups = _useState2[1];
132
132
 
133
+ /** running 轮询时与 fetchLogs(loadNext) 同一节拍拉分组,避免两条请求错拍 */
134
+ var runningPollSync = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
135
+ var groupData;
136
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
137
+ while (1) switch (_context.prev = _context.next) {
138
+ case 0:
139
+ _context.next = 2;
140
+ return fetchGroups();
141
+ case 2:
142
+ groupData = _context.sent;
143
+ if (groupData && groupData.length > 0) {
144
+ setGroups(groupData);
145
+ }
146
+ case 4:
147
+ case "end":
148
+ return _context.stop();
149
+ }
150
+ }, _callee);
151
+ })), [fetchGroups]);
152
+
133
153
  // ===================================================================
134
154
  // 二、日志数据获取与游标管理
135
155
  // ===================================================================
@@ -138,7 +158,8 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
138
158
  fetchLogs: fetchLogs,
139
159
  pageSize: pageSize,
140
160
  maxMemoryLines: maxMemoryLines,
141
- pollInterval: pollInterval
161
+ pollInterval: pollInterval,
162
+ runningPollSync: runningPollSync
142
163
  });
143
164
 
144
165
  // ===================================================================
@@ -169,12 +190,18 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
169
190
  // ===================================================================
170
191
  var cursorRef = useRef(logFetcherResult.cursor);
171
192
  cursorRef.current = logFetcherResult.cursor;
193
+ var airdropLoad = logFetcherResult.airdropLoad;
194
+ var searchAirdropLoad = useCallback(function (targetRow) {
195
+ return airdropLoad(targetRow, {
196
+ silent: true
197
+ });
198
+ }, [airdropLoad]);
172
199
  var logSearchResult = useLogSearch({
173
200
  searchLogs: searchLogs,
174
201
  getCursor: function getCursor() {
175
202
  return cursorRef.current;
176
203
  },
177
- onAirdropLoad: logFetcherResult.airdropLoad,
204
+ onAirdropLoad: searchAirdropLoad,
178
205
  ensureGroupExpanded: groupManager.ensureGroupExpanded,
179
206
  expandAllGroups: groupManager.expandAll
180
207
  });
@@ -192,7 +219,11 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
192
219
  var displayLogsRef = useRef(displayLogs);
193
220
  displayLogsRef.current = displayLogs;
194
221
 
195
- /** 有搜索关键字时禁用 followOutput,避免 running 轮询追加行把 prev/next 的 scrollToIndex 立刻拉回底部 */
222
+ /**
223
+ * 有搜索关键字时禁用 followOutput、并阻止 running 下 currentEndRow 触发的兜底置底。
224
+ * 必须在 handleSearch 内 await 之前同步置 true:setSearchState 尚未提交时 ref 若仍为 false,
225
+ * 轮询增大 currentEndRow 会误触 useLayoutEffect 的 scrollToIndex(LAST),导致刚跳转的命中行被「跳走」。
226
+ */
196
227
  var searchKeywordActiveRef = useRef(false);
197
228
  searchKeywordActiveRef.current = Boolean((_logSearchResult$sear = logSearchResult.searchState.keyword) === null || _logSearchResult$sear === void 0 ? void 0 : _logSearchResult$sear.trim());
198
229
 
@@ -209,6 +240,8 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
209
240
  // displayLogs 的变化,在 React 完成下一次 re-render 后自动执行滚动。
210
241
  // ===================================================================
211
242
  var pendingScrollRowRef = useRef(null);
243
+ /** 与 pendingScrollRowRef 配套的对齐方式:搜索跳转用 center,scrollToTop 用 start */
244
+ var pendingScrollAlignRef = useRef('center');
212
245
 
213
246
  // rangeChanged 边界检测的节流锁:防止在顶/底停留时连续触发加载
214
247
  var boundaryFetchingRef = useRef(false);
@@ -280,14 +313,17 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
280
313
  initLoadRef.current = logFetcherResult.initLoad;
281
314
 
282
315
  /**
283
- * 首屏初始化日志数据
284
- * 加载完成后用 scrollToIndex('LAST') 滚到底部。
316
+ * 首屏:fetchGroups 与 initLoad(fetchLogs) 并行,完成后滚到底部。
285
317
  * Virtuoso 无条件挂载,保证 startReached / endReached / followOutput 正常工作。
286
318
  */
287
319
  useEffect(function () {
288
320
  if (initializedRef.current) return;
289
321
  initializedRef.current = true;
290
- initLoadRef.current().then(function () {
322
+ Promise.all([fetchGroups().then(function (groupData) {
323
+ if (groupData && groupData.length > 0) {
324
+ setGroups(groupData);
325
+ }
326
+ }), initLoadRef.current()]).then(function () {
291
327
  ignoreBoundaryFetchRef.current = Date.now() + 500;
292
328
  requestAnimationFrame(function () {
293
329
  var _virtuosoRef$current;
@@ -299,16 +335,6 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
299
335
  });
300
336
  });
301
337
  }, [fetchLogs, fetchGroups]);
302
- /**
303
- * 首屏初始化分组信息
304
- */
305
- useEffect(function () {
306
- fetchGroups().then(function (groupData) {
307
- if (groupData && groupData.length > 0) {
308
- setGroups(groupData);
309
- }
310
- });
311
- }, [fetchGroups]);
312
338
 
313
339
  // fetchLogs 引用变化 = 新日志源(如外部 logUrl 切换):清空状态并允许首屏 init 重新跑
314
340
  /* eslint-disable react-hooks/exhaustive-deps -- 仅响应 fetchLogs 引用变化;reset/clearSearch/expandAll 为稳定回调 */
@@ -325,6 +351,7 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
325
351
  collapseAirdropActiveRef.current = false;
326
352
  isAtBottomRef.current = true;
327
353
  pendingScrollRowRef.current = null;
354
+ pendingScrollAlignRef.current = 'center';
328
355
  boundaryFetchingRef.current = false;
329
356
  pendingScrollAfterPrevRef.current = null;
330
357
  pendingScrollAfterNextRef.current = null;
@@ -332,23 +359,6 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
332
359
  }, [fetchLogs, logFetcherResult.reset, groupManager.expandAll, logSearchResult.clearSearch]);
333
360
  /* eslint-enable react-hooks/exhaustive-deps */
334
361
 
335
- // running 态定时轮询分组(与 useLogFetcher 中 fetchLogs 轮询策略一致)
336
- useEffect(function () {
337
- if (status !== 'running') return undefined;
338
- var intervalMs = pollInterval !== null && pollInterval !== void 0 ? pollInterval : DEFAULT_POLL_INTERVAL;
339
- var timer = window.setInterval(function () {
340
- if (logFetcherResult.isUserBrowsingHistory) return;
341
- fetchGroups().then(function (groupData) {
342
- if (groupData && groupData.length > 0) {
343
- setGroups(groupData);
344
- }
345
- });
346
- }, intervalMs);
347
- return function () {
348
- return window.clearInterval(timer);
349
- };
350
- }, [status, pollInterval, fetchGroups, logFetcherResult.isUserBrowsingHistory]);
351
-
352
362
  // ===================================================================
353
363
  // 折叠导致可见内容过少时自动跳转到折叠区之前
354
364
  //
@@ -430,8 +440,8 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
430
440
  var anchorRow = (_displayLogsRef$curre = displayLogsRef.current[anchorIndex]) === null || _displayLogsRef$curre === void 0 ? void 0 : _displayLogsRef$curre.absoluteRow;
431
441
  pendingScrollAfterPrevRef.current = anchorRow !== undefined && anchorRow !== null ? anchorRow : null;
432
442
  displayLogsLenBeforeLoadPrevRef.current = displayLogsRef.current.length;
433
- (_virtuosoRef$current2 = virtuosoRef.current) === null || _virtuosoRef$current2 === void 0 || _virtuosoRef$current2.getState(function (_ref3) {
434
- var scrollTop = _ref3.scrollTop;
443
+ (_virtuosoRef$current2 = virtuosoRef.current) === null || _virtuosoRef$current2 === void 0 || _virtuosoRef$current2.getState(function (_ref4) {
444
+ var scrollTop = _ref4.scrollTop;
435
445
  scrollTopBeforeLoadPrevRef.current = scrollTop;
436
446
  });
437
447
  boundaryFetchingRef.current = true;
@@ -460,8 +470,8 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
460
470
  var anchorRow = (_displayLogsRef$curre2 = displayLogsRef.current[anchorIndex]) === null || _displayLogsRef$curre2 === void 0 ? void 0 : _displayLogsRef$curre2.absoluteRow;
461
471
  pendingScrollAfterNextRef.current = anchorRow !== undefined && anchorRow !== null ? anchorRow : null;
462
472
  displayLogsLenBeforeLoadNextRef.current = displayLogsRef.current.length;
463
- (_virtuosoRef$current3 = virtuosoRef.current) === null || _virtuosoRef$current3 === void 0 || _virtuosoRef$current3.getState(function (_ref4) {
464
- var scrollTop = _ref4.scrollTop;
473
+ (_virtuosoRef$current3 = virtuosoRef.current) === null || _virtuosoRef$current3 === void 0 || _virtuosoRef$current3.getState(function (_ref5) {
474
+ var scrollTop = _ref5.scrollTop;
465
475
  scrollTopBeforeLoadNextRef.current = scrollTop;
466
476
  });
467
477
  boundaryFetchingRef.current = true;
@@ -614,6 +624,12 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
614
624
  if (!isAtBottomRef.current) return;
615
625
  requestAnimationFrame(function () {
616
626
  var _virtuosoRef$current4;
627
+ // 在 rAF 回调执行时再次检查,防止在排队期间用户执行了置顶/搜索/折叠等操作(产生竞态被强行拉回底部)
628
+ if (statusRef.current !== 'running') return;
629
+ if (searchKeywordActiveRef.current) return;
630
+ if (groupActionRef.current) return;
631
+ if (collapseAirdropActiveRef.current) return;
632
+ if (userStoppedFollowingRef.current) return;
617
633
  ignoreBoundaryFetchRef.current = Date.now() + 500;
618
634
  (_virtuosoRef$current4 = virtuosoRef.current) === null || _virtuosoRef$current4 === void 0 || _virtuosoRef$current4.scrollToIndex({
619
635
  index: 'LAST',
@@ -627,17 +643,18 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
627
643
  // 搜索跳转滚动
628
644
  // ===================================================================
629
645
  // ===================================================================
630
- // 在 Virtuoso 完成布局后再 scrollToIndex(与 scrollToTop 相同策略)。
646
+ // 在 Virtuoso 完成布局后再 scrollToIndexscrollToTop 需空降时与此相同,走 pendingScrollRowRef)。
631
647
  // 同步调用会因 totalCount / 内部 range 尚未更新而无效;长 setTimeout 只是“等布局”的权宜之计。
632
648
  // ===================================================================
633
649
  var scheduleScrollToDisplayIndex = useCallback(function (displayIndex) {
650
+ var align = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'center';
634
651
  ignoreBoundaryFetchRef.current = Date.now() + 500;
635
652
  requestAnimationFrame(function () {
636
653
  var v = virtuosoRef.current;
637
654
  if (!v || displayLogsRef.current.length === 0) return;
638
655
  v.scrollToIndex({
639
656
  index: displayIndex,
640
- align: 'center',
657
+ align: align,
641
658
  behavior: 'auto'
642
659
  });
643
660
  });
@@ -650,24 +667,26 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
650
667
  });
651
668
  if (displayIndex >= 0) {
652
669
  pendingScrollRowRef.current = null;
653
- scheduleScrollToDisplayIndex(displayIndex);
670
+ var align = pendingScrollAlignRef.current;
671
+ pendingScrollAlignRef.current = 'center';
672
+ scheduleScrollToDisplayIndex(displayIndex, align);
654
673
  }
655
674
  }, [displayLogs, scheduleScrollToDisplayIndex]);
656
675
  var scrollToAbsoluteRow = useCallback( /*#__PURE__*/function () {
657
- var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(absoluteRow) {
676
+ var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(absoluteRow) {
658
677
  var targetRow, currentDisplayLogs, displayIndex;
659
- return _regeneratorRuntime().wrap(function _callee$(_context) {
660
- while (1) switch (_context.prev = _context.next) {
678
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
679
+ while (1) switch (_context2.prev = _context2.next) {
661
680
  case 0:
662
- _context.next = 2;
681
+ _context2.next = 2;
663
682
  return logSearchResult.resolveTargetRow(absoluteRow);
664
683
  case 2:
665
- targetRow = _context.sent;
684
+ targetRow = _context2.sent;
666
685
  if (!(targetRow === null)) {
667
- _context.next = 5;
686
+ _context2.next = 5;
668
687
  break;
669
688
  }
670
- return _context.abrupt("return");
689
+ return _context2.abrupt("return");
671
690
  case 5:
672
691
  currentDisplayLogs = displayLogsRef.current;
673
692
  displayIndex = currentDisplayLogs.findIndex(function (line) {
@@ -675,18 +694,20 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
675
694
  });
676
695
  if (displayIndex >= 0) {
677
696
  pendingScrollRowRef.current = null;
697
+ pendingScrollAlignRef.current = 'center';
678
698
  scheduleScrollToDisplayIndex(displayIndex);
679
699
  } else {
700
+ pendingScrollAlignRef.current = 'center';
680
701
  pendingScrollRowRef.current = targetRow;
681
702
  }
682
703
  case 8:
683
704
  case "end":
684
- return _context.stop();
705
+ return _context2.stop();
685
706
  }
686
- }, _callee);
707
+ }, _callee2);
687
708
  }));
688
709
  return function (_x) {
689
- return _ref5.apply(this, arguments);
710
+ return _ref6.apply(this, arguments);
690
711
  };
691
712
  }(), [logSearchResult, scheduleScrollToDisplayIndex]);
692
713
 
@@ -694,6 +715,7 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
694
715
  var handleSearchPrev = useCallback(function () {
695
716
  var targetRow = logSearchResult.searchPrev();
696
717
  if (targetRow !== null) {
718
+ searchKeywordActiveRef.current = true;
697
719
  scrollToAbsoluteRow(targetRow);
698
720
  }
699
721
  }, [logSearchResult, scrollToAbsoluteRow]);
@@ -702,32 +724,36 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
702
724
  var handleSearchNext = useCallback(function () {
703
725
  var targetRow = logSearchResult.searchNext();
704
726
  if (targetRow !== null) {
727
+ searchKeywordActiveRef.current = true;
705
728
  scrollToAbsoluteRow(targetRow);
706
729
  }
707
730
  }, [logSearchResult, scrollToAbsoluteRow]);
708
731
 
709
732
  // 触发搜索
710
733
  var handleSearch = useCallback( /*#__PURE__*/function () {
711
- var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(keyword) {
734
+ var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(keyword) {
712
735
  var targetRow;
713
- return _regeneratorRuntime().wrap(function _callee2$(_context2) {
714
- while (1) switch (_context2.prev = _context2.next) {
736
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
737
+ while (1) switch (_context3.prev = _context3.next) {
715
738
  case 0:
716
- _context2.next = 2;
739
+ if (keyword.trim()) {
740
+ searchKeywordActiveRef.current = true;
741
+ }
742
+ _context3.next = 3;
717
743
  return logSearchResult.search(keyword);
718
- case 2:
719
- targetRow = _context2.sent;
744
+ case 3:
745
+ targetRow = _context3.sent;
720
746
  if (targetRow !== null) {
721
747
  scrollToAbsoluteRow(targetRow);
722
748
  }
723
- case 4:
749
+ case 5:
724
750
  case "end":
725
- return _context2.stop();
751
+ return _context3.stop();
726
752
  }
727
- }, _callee2);
753
+ }, _callee3);
728
754
  }));
729
755
  return function (_x2) {
730
- return _ref6.apply(this, arguments);
756
+ return _ref7.apply(this, arguments);
731
757
  };
732
758
  }(), [logSearchResult, scrollToAbsoluteRow]);
733
759
 
@@ -809,24 +835,24 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
809
835
  airdropExpandInFlightRef.current = true;
810
836
  setLoadingGroupName(name);
811
837
  var runAirdropThenExpand = /*#__PURE__*/function () {
812
- var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
838
+ var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
813
839
  var ok;
814
- return _regeneratorRuntime().wrap(function _callee3$(_context3) {
815
- while (1) switch (_context3.prev = _context3.next) {
840
+ return _regeneratorRuntime().wrap(function _callee4$(_context4) {
841
+ while (1) switch (_context4.prev = _context4.next) {
816
842
  case 0:
817
- _context3.prev = 0;
818
- _context3.next = 3;
843
+ _context4.prev = 0;
844
+ _context4.next = 3;
819
845
  return logFetcherResult.airdropLoad(group.start, {
820
846
  window: 'fromStart',
821
847
  silent: true
822
848
  });
823
849
  case 3:
824
- ok = _context3.sent;
850
+ ok = _context4.sent;
825
851
  if (!ok) {
826
- _context3.next = 7;
852
+ _context4.next = 7;
827
853
  break;
828
854
  }
829
- _context3.next = 7;
855
+ _context4.next = 7;
830
856
  return new Promise(function (resolve) {
831
857
  requestAnimationFrame(function () {
832
858
  requestAnimationFrame(function () {
@@ -838,18 +864,18 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
838
864
  });
839
865
  });
840
866
  case 7:
841
- _context3.prev = 7;
867
+ _context4.prev = 7;
842
868
  setLoadingGroupName(null);
843
869
  airdropExpandInFlightRef.current = false;
844
- return _context3.finish(7);
870
+ return _context4.finish(7);
845
871
  case 11:
846
872
  case "end":
847
- return _context3.stop();
873
+ return _context4.stop();
848
874
  }
849
- }, _callee3, null, [[0,, 7, 11]]);
875
+ }, _callee4, null, [[0,, 7, 11]]);
850
876
  }));
851
877
  return function runAirdropThenExpand() {
852
- return _ref7.apply(this, arguments);
878
+ return _ref8.apply(this, arguments);
853
879
  };
854
880
  }();
855
881
  runAirdropThenExpand();
@@ -1037,10 +1063,10 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
1037
1063
  useImperativeHandle(ref, function () {
1038
1064
  return {
1039
1065
  scrollToTop: function () {
1040
- var _scrollToTop = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
1041
- var globalFirstRow, bufStart, needsTopWindow;
1042
- return _regeneratorRuntime().wrap(function _callee4$(_context4) {
1043
- while (1) switch (_context4.prev = _context4.next) {
1066
+ var _scrollToTop = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
1067
+ var globalFirstRow, bufStart, needsTopWindow, ok;
1068
+ return _regeneratorRuntime().wrap(function _callee5$(_context5) {
1069
+ while (1) switch (_context5.prev = _context5.next) {
1044
1070
  case 0:
1045
1071
  groupManager.expandAll();
1046
1072
  userStoppedFollowingRef.current = true;
@@ -1053,23 +1079,34 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
1053
1079
  }))) : 0;
1054
1080
  bufStart = logFetcherResult.cursor.currentStartRow;
1055
1081
  needsTopWindow = bufStart > globalFirstRow;
1082
+ ignoreBoundaryFetchRef.current = Date.now() + 500;
1056
1083
  if (!needsTopWindow) {
1057
- _context4.next = 10;
1084
+ _context5.next = 19;
1058
1085
  break;
1059
1086
  }
1060
- _context4.next = 9;
1087
+ // airdropLoad 完成时 React 尚未提交新 displayLogs,单帧 rAF 里 scrollToIndex(0)
1088
+ // 仍作用在旧列表上(index 0 = 旧缓冲首行),无法置顶;与搜索跨页一致走 pending。
1089
+ pendingScrollAlignRef.current = 'start';
1090
+ pendingScrollRowRef.current = globalFirstRow;
1091
+ _context5.next = 12;
1061
1092
  return logFetcherResult.airdropLoad(globalFirstRow, {
1062
1093
  window: 'fromStart'
1063
1094
  });
1064
- case 9:
1095
+ case 12:
1096
+ ok = _context5.sent;
1097
+ if (ok) {
1098
+ _context5.next = 17;
1099
+ break;
1100
+ }
1101
+ pendingScrollRowRef.current = null;
1102
+ pendingScrollAlignRef.current = 'center';
1103
+ return _context5.abrupt("return");
1104
+ case 17:
1065
1105
  logFetcherResult.updateBoundaryLock({
1066
1106
  isLastPage: false
1067
1107
  });
1068
- case 10:
1069
- // airdropLoad 后 displayLogs 会在下次 re-render 更新,
1070
- // 用 pending 机制在 useLayoutEffect 里执行滚动,确保坐标系已稳定。
1071
- // index: 0 在去掉 firstItemIndex 后永远有效。
1072
- ignoreBoundaryFetchRef.current = Date.now() + 500;
1108
+ return _context5.abrupt("return");
1109
+ case 19:
1073
1110
  requestAnimationFrame(function () {
1074
1111
  var _virtuosoRef$current6;
1075
1112
  (_virtuosoRef$current6 = virtuosoRef.current) === null || _virtuosoRef$current6 === void 0 || _virtuosoRef$current6.scrollToIndex({
@@ -1078,11 +1115,11 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
1078
1115
  behavior: 'auto'
1079
1116
  });
1080
1117
  });
1081
- case 12:
1118
+ case 20:
1082
1119
  case "end":
1083
- return _context4.stop();
1120
+ return _context5.stop();
1084
1121
  }
1085
- }, _callee4);
1122
+ }, _callee5);
1086
1123
  }));
1087
1124
  function scrollToTop() {
1088
1125
  return _scrollToTop.apply(this, arguments);
@@ -1090,20 +1127,20 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
1090
1127
  return scrollToTop;
1091
1128
  }(),
1092
1129
  scrollToBottom: function () {
1093
- var _scrollToBottom = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5() {
1130
+ var _scrollToBottom = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6() {
1094
1131
  var needsFetch;
1095
- return _regeneratorRuntime().wrap(function _callee5$(_context5) {
1096
- while (1) switch (_context5.prev = _context5.next) {
1132
+ return _regeneratorRuntime().wrap(function _callee6$(_context6) {
1133
+ while (1) switch (_context6.prev = _context6.next) {
1097
1134
  case 0:
1098
1135
  groupManager.expandAll();
1099
1136
  userStoppedFollowingRef.current = false;
1100
1137
  collapseAirdropActiveRef.current = false;
1101
1138
  needsFetch = status !== 'running' && !logFetcherResult.boundaryLock.isLastPage || status === 'running' && logFetcherResult.isUserBrowsingHistory;
1102
1139
  if (!needsFetch) {
1103
- _context5.next = 8;
1140
+ _context6.next = 8;
1104
1141
  break;
1105
1142
  }
1106
- _context5.next = 7;
1143
+ _context6.next = 7;
1107
1144
  return logFetcherResult.initLoad();
1108
1145
  case 7:
1109
1146
  logFetcherResult.updateBoundaryLock({
@@ -1120,9 +1157,9 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
1120
1157
  }, 50);
1121
1158
  case 10:
1122
1159
  case "end":
1123
- return _context5.stop();
1160
+ return _context6.stop();
1124
1161
  }
1125
- }, _callee5);
1162
+ }, _callee6);
1126
1163
  }));
1127
1164
  function scrollToBottom() {
1128
1165
  return _scrollToBottom.apply(this, arguments);
@@ -1138,12 +1175,13 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
1138
1175
  };
1139
1176
  }, [handleCollapseAll, handleExpandAll, handleSearch, handleSearchPrev, handleSearchNext, logSearchResult, logFetcherResult, groupManager, groups, status]);
1140
1177
  var lastGroupStatus = useMemo(function () {
1141
- return groups.length > 0 ? groups[groups.length - 1].status : 'idle';
1142
- }, [groups]);
1178
+ return groups.length > 0 ? groups[groups.length - 1].status : status;
1179
+ }, [groups, status]);
1143
1180
  var virtuosoComponents = useMemo(function () {
1181
+ var isRunning = lastGroupStatus === 'running';
1144
1182
  return {
1145
- EmptyPlaceholder: logFetcherResult.loading ? undefined : EmptyPlaceholder,
1146
- Footer: !logFetcherResult.loading && lastGroupStatus === 'running' ? VirtuosoFooterWithLoading : VirtuosoFooterEmpty
1183
+ EmptyPlaceholder: logFetcherResult.loading || isRunning ? undefined : EmptyPlaceholder,
1184
+ Footer: !logFetcherResult.loading && isRunning ? VirtuosoFooterWithLoading : VirtuosoFooterEmpty
1147
1185
  };
1148
1186
  }, [lastGroupStatus, logFetcherResult.loading]);
1149
1187
 
@@ -1166,7 +1204,8 @@ var PipelineLogViewer = /*#__PURE__*/forwardRef(function (_ref2, ref) {
1166
1204
  placeholder: searchPlaceholder,
1167
1205
  inputAddonBefore: headerAddonBefore,
1168
1206
  inputAddonAfter: headerAddonAfter,
1169
- icons: icons
1207
+ icons: icons,
1208
+ searchLoading: logSearchResult.searching || logSearchResult.searchJumpLoading
1170
1209
  }), /*#__PURE__*/React.createElement("div", {
1171
1210
  className: "pipeline-log-viewer__list-container"
1172
1211
  }, /*#__PURE__*/React.createElement(StickyHeader, {
@@ -25,6 +25,10 @@ export interface SearchBarProps {
25
25
  down?: React.ReactNode;
26
26
  clear?: React.ReactNode;
27
27
  };
28
+ /**
29
+ * 搜索请求或跨页拉取匹配行所在日志时,在搜索图标位展示 loading(不阻塞输入)
30
+ */
31
+ searchLoading?: boolean;
28
32
  }
29
33
  declare const _default: React.NamedExoticComponent<SearchBarProps>;
30
34
  export default _default;
@@ -17,7 +17,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
17
17
  // 4. 输入框内容被完全清空或按下 Escape 键时,触发 onClear 清除状态与高亮。
18
18
  // ============================================================================
19
19
 
20
- import { CloseCircleFilled, DownOutlined, SearchOutlined, UpOutlined } from '@ant-design/icons';
20
+ import { CloseCircleFilled, DownOutlined, LoadingOutlined, SearchOutlined, UpOutlined } from '@ant-design/icons';
21
21
  import React, { useCallback, useRef, useState } from 'react';
22
22
  var SearchBar = function SearchBar(_ref) {
23
23
  var total = _ref.total,
@@ -30,7 +30,9 @@ var SearchBar = function SearchBar(_ref) {
30
30
  placeholder = _ref$placeholder === void 0 ? '搜索日志...' : _ref$placeholder,
31
31
  inputAddonBefore = _ref.inputAddonBefore,
32
32
  inputAddonAfter = _ref.inputAddonAfter,
33
- icons = _ref.icons;
33
+ icons = _ref.icons,
34
+ _ref$searchLoading = _ref.searchLoading,
35
+ searchLoading = _ref$searchLoading === void 0 ? false : _ref$searchLoading;
34
36
  var _useState = useState(''),
35
37
  _useState2 = _slicedToArray(_useState, 2),
36
38
  inputValue = _useState2[0],
@@ -85,17 +87,29 @@ var SearchBar = function SearchBar(_ref) {
85
87
  onClear();
86
88
  (_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus();
87
89
  }, [onClear]);
90
+ var searchPrefixIcon;
91
+ if (searchLoading) {
92
+ searchPrefixIcon = /*#__PURE__*/React.createElement(LoadingOutlined, {
93
+ className: "pipeline-log-search-bar__search-icon",
94
+ spin: true
95
+ });
96
+ } else if ( /*#__PURE__*/React.isValidElement(icons === null || icons === void 0 ? void 0 : icons.search)) {
97
+ searchPrefixIcon = /*#__PURE__*/React.cloneElement(icons === null || icons === void 0 ? void 0 : icons.search, {
98
+ className: 'pipeline-log-search-bar__search-icon'
99
+ });
100
+ } else {
101
+ searchPrefixIcon = /*#__PURE__*/React.createElement(SearchOutlined, {
102
+ className: "pipeline-log-search-bar__search-icon"
103
+ });
104
+ }
88
105
  return /*#__PURE__*/React.createElement("div", {
89
106
  className: "pipeline-log-search-bar"
90
107
  }, /*#__PURE__*/React.createElement("div", {
91
108
  className: "pipeline-log-search-bar__input-prefix"
92
109
  }, inputAddonBefore), /*#__PURE__*/React.createElement("div", {
93
- className: "pipeline-log-search-bar__input-wrapper"
94
- }, /*#__PURE__*/React.isValidElement(icons === null || icons === void 0 ? void 0 : icons.search) ? ( /*#__PURE__*/React.cloneElement(icons === null || icons === void 0 ? void 0 : icons.search, {
95
- className: 'pipeline-log-search-bar__search-icon'
96
- })) : /*#__PURE__*/React.createElement(SearchOutlined, {
97
- className: "pipeline-log-search-bar__search-icon"
98
- }), /*#__PURE__*/React.createElement("input", {
110
+ className: "pipeline-log-search-bar__input-wrapper",
111
+ "aria-busy": searchLoading || undefined
112
+ }, searchPrefixIcon, /*#__PURE__*/React.createElement("input", {
99
113
  ref: inputRef,
100
114
  className: "pipeline-log-search-bar__input",
101
115
  type: "text",
@@ -12,6 +12,10 @@ export declare const DEFAULT_VIRTUOSO_ITEM_HEIGHT = 20;
12
12
  export declare const BOUNDARY_PREFETCH_INDEX_MARGIN = 400;
13
13
  /** running 态轮询间隔 (默认值,单位 ms) */
14
14
  export declare const DEFAULT_POLL_INTERVAL = 1000;
15
+ /** running→结束态:收尾 initLoad 之后追加 loadNext 的次数 */
16
+ export declare const TERMINAL_TAIL_LOAD_NEXT_COUNT = 5;
17
+ /** 收尾追加 loadNext 每次之间的间隔 (ms) */
18
+ export declare const TERMINAL_TAIL_LOAD_NEXT_INTERVAL_MS = 1000;
15
19
  /** 空降加载时,取目标行前后各加载多少行 */
16
20
  export declare const AIRDROP_HALF_RANGE = 250;
17
21
  /** 折叠占位行标记文本 */