@flexem/fc-gui 3.0.0-alpha.187 → 3.0.0-alpha.188

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.
@@ -42487,6 +42487,181 @@ C140,111.8,99.2,158.4,78,178.6z M78,40.4c-17.8,0-32.4,14.4-32.4,32.2s14.5,32.2,3
42487
42487
  }
42488
42488
  }
42489
42489
 
42490
+ // CONCATENATED MODULE: ./.tmp/elements/alarm/alarm-table-scrollbar.ts
42491
+ /** SVG scrollbar kept outside foreignObject so WKWebView applies the canvas scale. */
42492
+ class AlarmTableScrollbar {
42493
+ constructor(parent, x, y, width, height, visibleRows, onChange, onPause, onResume) {
42494
+ this.y = y;
42495
+ this.height = height;
42496
+ this.visibleRows = visibleRows;
42497
+ this.onChange = onChange;
42498
+ this.onPause = onPause;
42499
+ this.onResume = onResume;
42500
+ this.maxStart = 0;
42501
+ this.start = 0;
42502
+ this.thumbHeight = 0;
42503
+ this.thumbTop = 0;
42504
+ this.dragging = false;
42505
+ this.hovered = false;
42506
+ this.focused = false;
42507
+ this.dragStartY = 0;
42508
+ this.dragStartRow = 0;
42509
+ this.handleStart = (event) => {
42510
+ if (!this.maxStart || ('button' in event && event.button !== 0) || ('touches' in event && event.touches.length !== 1))
42511
+ return;
42512
+ event.preventDefault();
42513
+ event.stopPropagation();
42514
+ this.onPause();
42515
+ const localY = this.getLocalY(event);
42516
+ // The full gutter is clickable, including the transparent sides of the thumb.
42517
+ if (localY < this.y + this.thumbTop || localY > this.y + this.thumbTop + this.thumbHeight) {
42518
+ this.onChange(this.start + (localY < this.y + this.thumbTop ? -this.visibleRows : this.visibleRows));
42519
+ this.onResume();
42520
+ return;
42521
+ }
42522
+ this.dragging = true;
42523
+ this.dragStartY = localY;
42524
+ this.dragStartRow = this.start;
42525
+ this.thumb.setAttribute('fill', '#8f99aa');
42526
+ this.thumb.style.cursor = 'grabbing';
42527
+ this.ownerDocument.addEventListener('mousemove', this.handleMove);
42528
+ this.ownerDocument.addEventListener('mouseup', this.handleEnd);
42529
+ this.ownerDocument.addEventListener('touchmove', this.handleMove, { passive: false });
42530
+ this.ownerDocument.addEventListener('touchend', this.handleEnd);
42531
+ this.ownerDocument.addEventListener('touchcancel', this.handleEnd);
42532
+ this.ownerDocument.defaultView.addEventListener('blur', this.handleEnd);
42533
+ };
42534
+ this.handleMove = (event) => {
42535
+ if (!this.dragging || ('touches' in event && event.touches.length !== 1))
42536
+ return;
42537
+ event.preventDefault();
42538
+ event.stopPropagation();
42539
+ const travel = this.height - this.thumbHeight;
42540
+ if (travel <= 0)
42541
+ return;
42542
+ const rowDelta = Math.round((this.getLocalY(event) - this.dragStartY) / travel * this.maxStart);
42543
+ this.onChange(this.dragStartRow + rowDelta);
42544
+ };
42545
+ this.handleEnd = () => {
42546
+ if (!this.dragging)
42547
+ return;
42548
+ this.dragging = false;
42549
+ this.unbindDrag();
42550
+ this.thumb.setAttribute('fill', '#b6bdc9');
42551
+ this.thumb.style.cursor = 'grab';
42552
+ this.onResume();
42553
+ };
42554
+ this.handleLeave = () => {
42555
+ this.hovered = false;
42556
+ this.onResume();
42557
+ };
42558
+ this.handleEnter = () => {
42559
+ this.hovered = true;
42560
+ this.onPause();
42561
+ };
42562
+ this.handleFocus = () => {
42563
+ this.focused = true;
42564
+ this.onPause();
42565
+ };
42566
+ this.handleBlur = () => {
42567
+ this.focused = false;
42568
+ this.onResume();
42569
+ };
42570
+ this.handleKeyDown = (event) => {
42571
+ const targets = {
42572
+ ArrowUp: this.start - 1,
42573
+ ArrowDown: this.start + 1,
42574
+ PageUp: this.start - this.visibleRows,
42575
+ PageDown: this.start + this.visibleRows,
42576
+ Home: 0,
42577
+ End: this.maxStart
42578
+ };
42579
+ if (!(event.key in targets))
42580
+ return;
42581
+ event.preventDefault();
42582
+ event.stopPropagation();
42583
+ this.onChange(targets[event.key]);
42584
+ };
42585
+ this.ownerDocument = parent.ownerDocument;
42586
+ this.group = this.createElement('g');
42587
+ this.group.setAttribute('role', 'scrollbar');
42588
+ this.group.setAttribute('aria-orientation', 'vertical');
42589
+ this.group.setAttribute('aria-valuemin', '0');
42590
+ this.group.setAttribute('tabindex', '0');
42591
+ this.group.style.cursor = 'default';
42592
+ this.track = this.createElement('rect');
42593
+ this.setRect(this.track, x, y, width, height);
42594
+ this.track.setAttribute('fill', '#eef0f4');
42595
+ this.track.setAttribute('rx', String(width / 2));
42596
+ this.thumb = this.createElement('rect');
42597
+ this.setRect(this.thumb, x + width / 4, y, width / 2, height);
42598
+ this.thumb.setAttribute('fill', '#b6bdc9');
42599
+ this.thumb.setAttribute('rx', String(width / 4));
42600
+ this.thumb.style.cursor = 'grab';
42601
+ this.group.appendChild(this.track);
42602
+ this.group.appendChild(this.thumb);
42603
+ parent.appendChild(this.group);
42604
+ this.group.addEventListener('mousedown', this.handleStart);
42605
+ this.group.addEventListener('touchstart', this.handleStart, { passive: false });
42606
+ this.group.addEventListener('keydown', this.handleKeyDown);
42607
+ this.group.addEventListener('mouseenter', this.handleEnter);
42608
+ this.group.addEventListener('mouseleave', this.handleLeave);
42609
+ this.group.addEventListener('focus', this.handleFocus);
42610
+ this.group.addEventListener('blur', this.handleBlur);
42611
+ }
42612
+ get isInteracting() {
42613
+ return this.dragging || this.hovered || this.focused;
42614
+ }
42615
+ update(start, totalRows) {
42616
+ this.maxStart = Math.max(0, totalRows - this.visibleRows);
42617
+ this.start = Math.min(this.maxStart, Math.max(0, start));
42618
+ this.group.setAttribute('display', this.maxStart ? 'inline' : 'none');
42619
+ this.group.setAttribute('aria-valuemax', String(this.maxStart));
42620
+ this.group.setAttribute('aria-valuenow', String(this.start));
42621
+ this.thumbHeight = Math.min(this.height, Math.max(20, this.height * this.visibleRows / Math.max(1, totalRows)));
42622
+ this.thumbTop = this.maxStart ? (this.height - this.thumbHeight) * this.start / this.maxStart : 0;
42623
+ this.thumb.setAttribute('height', String(this.thumbHeight));
42624
+ this.thumb.setAttribute('y', String(this.y + this.thumbTop));
42625
+ }
42626
+ dispose() {
42627
+ this.dragging = false;
42628
+ this.unbindDrag();
42629
+ this.group.removeEventListener('mousedown', this.handleStart);
42630
+ this.group.removeEventListener('touchstart', this.handleStart);
42631
+ this.group.removeEventListener('keydown', this.handleKeyDown);
42632
+ this.group.removeEventListener('mouseenter', this.handleEnter);
42633
+ this.group.removeEventListener('mouseleave', this.handleLeave);
42634
+ this.group.removeEventListener('focus', this.handleFocus);
42635
+ this.group.removeEventListener('blur', this.handleBlur);
42636
+ this.group.remove();
42637
+ }
42638
+ createElement(name) {
42639
+ return this.ownerDocument.createElementNS('http://www.w3.org/2000/svg', name);
42640
+ }
42641
+ setRect(rect, x, y, width, height) {
42642
+ rect.setAttribute('x', String(x));
42643
+ rect.setAttribute('y', String(y));
42644
+ rect.setAttribute('width', String(width));
42645
+ rect.setAttribute('height', String(height));
42646
+ }
42647
+ getLocalY(event) {
42648
+ const pointer = 'touches' in event ? event.touches[0] : event;
42649
+ const point = this.group.ownerSVGElement.createSVGPoint();
42650
+ point.x = pointer.clientX;
42651
+ point.y = pointer.clientY;
42652
+ const matrix = this.group.getScreenCTM();
42653
+ return matrix ? point.matrixTransform(matrix.inverse()).y : point.y;
42654
+ }
42655
+ unbindDrag() {
42656
+ this.ownerDocument.removeEventListener('mousemove', this.handleMove);
42657
+ this.ownerDocument.removeEventListener('mouseup', this.handleEnd);
42658
+ this.ownerDocument.removeEventListener('touchmove', this.handleMove);
42659
+ this.ownerDocument.removeEventListener('touchend', this.handleEnd);
42660
+ this.ownerDocument.removeEventListener('touchcancel', this.handleEnd);
42661
+ this.ownerDocument.defaultView.removeEventListener('blur', this.handleEnd);
42662
+ }
42663
+ }
42664
+
42490
42665
  // CONCATENATED MODULE: ./.tmp/elements/alarm/alarm-element.ts
42491
42666
 
42492
42667
 
@@ -42494,6 +42669,7 @@ C140,111.8,99.2,158.4,78,178.6z M78,40.4c-17.8,0-32.4,14.4-32.4,32.2s14.5,32.2,3
42494
42669
 
42495
42670
 
42496
42671
 
42672
+
42497
42673
  var AlaertElementStatus;
42498
42674
  (function (AlaertElementStatus) {
42499
42675
  AlaertElementStatus[AlaertElementStatus["Normal"] = 0] = "Normal";
@@ -42532,97 +42708,60 @@ class alarm_element_AlarmElement extends conditional_display_element_Conditional
42532
42708
  this.rowHeight = 0;
42533
42709
  this.touchStartY = 0;
42534
42710
  this.touchScrollAccumulator = 0;
42535
- this.thumbDragStartY = 0;
42536
- this.thumbDragStartWindow = 0;
42537
- this.thumbDragging = false;
42711
+ this.scrollHovered = false;
42712
+ this.touchScrolling = false;
42538
42713
  this.isDisposed = false;
42539
42714
  this.handleScrollWheel = (event) => {
42540
- if (!this.rowHeight)
42715
+ if (!this.rowHeight || !this.getMaxWindowStart())
42541
42716
  return;
42542
42717
  event.preventDefault();
42543
- this.touchScrollAccumulator += event.deltaY;
42544
- const rowDelta = Math.trunc(this.touchScrollAccumulator / this.rowHeight);
42718
+ event.stopPropagation();
42719
+ const screenRowHeight = this.getScreenRowHeight();
42720
+ const delta = event.deltaMode === 1 ? event.deltaY * screenRowHeight
42721
+ : event.deltaMode === 2 ? event.deltaY * screenRowHeight * this.maxVisibleRows : event.deltaY;
42722
+ this.touchScrollAccumulator += delta;
42723
+ const rowDelta = Math.trunc(this.touchScrollAccumulator / screenRowHeight);
42545
42724
  if (rowDelta !== 0) {
42546
- this.touchScrollAccumulator -= rowDelta * this.rowHeight;
42725
+ this.touchScrollAccumulator -= rowDelta * screenRowHeight;
42547
42726
  this.moveScrollWindowBy(rowDelta);
42548
42727
  }
42549
42728
  };
42550
42729
  this.handleScrollTouchStart = (event) => {
42730
+ if (event.touches.length !== 1 || !this.getMaxWindowStart())
42731
+ return;
42732
+ this.touchScrolling = true;
42733
+ clearInterval(this.scrollIntervalId);
42734
+ event.stopPropagation();
42551
42735
  this.touchStartY = event.touches[0].clientY;
42552
42736
  this.touchScrollAccumulator = 0;
42553
42737
  };
42554
42738
  this.handleScrollTouchMove = (event) => {
42555
- if (!this.rowHeight)
42739
+ if (!this.touchScrolling || event.touches.length !== 1)
42556
42740
  return;
42557
42741
  event.preventDefault();
42742
+ event.stopPropagation();
42558
42743
  const currentY = event.touches[0].clientY;
42559
42744
  const deltaY = this.touchStartY - currentY;
42560
42745
  this.touchStartY = currentY;
42561
42746
  this.touchScrollAccumulator += deltaY;
42562
- const rowDelta = Math.trunc(this.touchScrollAccumulator / this.rowHeight);
42747
+ const screenRowHeight = this.getScreenRowHeight();
42748
+ const rowDelta = Math.trunc(this.touchScrollAccumulator / screenRowHeight);
42563
42749
  if (rowDelta !== 0) {
42564
- this.touchScrollAccumulator -= rowDelta * this.rowHeight;
42750
+ this.touchScrollAccumulator -= rowDelta * screenRowHeight;
42565
42751
  this.moveScrollWindowBy(rowDelta);
42566
42752
  }
42567
42753
  };
42568
42754
  this.handleScrollMouseEnter = () => {
42755
+ this.scrollHovered = true;
42569
42756
  clearInterval(this.scrollIntervalId);
42570
42757
  };
42571
42758
  this.handleScrollMouseLeave = () => {
42572
- if (!this.thumbDragging)
42573
- this.startAutoScroll();
42574
- };
42575
- // 拖拽滑块时挂全局 mousemove/mouseup,允许拖出滚动条区域也能继续跟手,松开时才解绑
42576
- this.handleThumbDragStart = (event) => {
42577
- event.preventDefault();
42578
- event.stopPropagation();
42579
- this.thumbDragging = true;
42580
- clearInterval(this.scrollIntervalId);
42581
- this.thumbDragStartY = this.getClientY(event);
42582
- this.thumbDragStartWindow = this.scrollWindowStart;
42583
- document.addEventListener('mousemove', this.handleThumbDragMove);
42584
- document.addEventListener('mouseup', this.handleThumbDragEnd);
42585
- document.addEventListener('touchmove', this.handleThumbDragMove, { passive: false });
42586
- document.addEventListener('touchend', this.handleThumbDragEnd);
42587
- };
42588
- this.handleThumbDragMove = (event) => {
42589
- if (!this.thumbDragging || !this.scrollTrack)
42590
- return;
42591
- event.preventDefault();
42592
- const maxWindowStart = Math.max(0, this.pageSize - this.maxVisibleRows);
42593
- if (maxWindowStart <= 0)
42594
- return;
42595
- const trackHeight = this.scrollTrack.clientHeight;
42596
- const thumbHeightRatio = Math.min(1, this.maxVisibleRows / this.pageSize);
42597
- const thumbHeight = Math.max(20, trackHeight * thumbHeightRatio);
42598
- const maxThumbTop = trackHeight - thumbHeight;
42599
- if (maxThumbTop <= 0)
42600
- return;
42601
- const deltaY = this.getClientY(event) - this.thumbDragStartY;
42602
- const deltaWindow = Math.round((deltaY / maxThumbTop) * maxWindowStart);
42603
- const nextStart = Math.min(maxWindowStart, Math.max(0, this.thumbDragStartWindow + deltaWindow));
42604
- if (nextStart === this.scrollWindowStart)
42605
- return;
42606
- this.scrollWindowStart = nextStart;
42607
- this.renderScrollWindow(this.scrollWindowStart);
42608
- };
42609
- this.handleThumbDragEnd = () => {
42610
- this.thumbDragging = false;
42611
- document.removeEventListener('mousemove', this.handleThumbDragMove);
42612
- document.removeEventListener('mouseup', this.handleThumbDragEnd);
42613
- document.removeEventListener('touchmove', this.handleThumbDragMove);
42614
- document.removeEventListener('touchend', this.handleThumbDragEnd);
42759
+ this.scrollHovered = false;
42615
42760
  this.startAutoScroll();
42616
42761
  };
42617
- // 点击轨道空白处(非滑块)时整页跳转,方向取决于点击位置在滑块上方还是下方
42618
- this.handleTrackClick = (event) => {
42619
- if (event.target !== this.scrollTrack || !this.scrollTrack)
42620
- return;
42621
- const trackRect = this.scrollTrack.getBoundingClientRect();
42622
- const clickTop = event.clientY - trackRect.top;
42623
- const thumbTop = parseFloat(this.scrollThumb.style.top) || 0;
42624
- const rowDelta = clickTop < thumbTop ? -this.maxVisibleRows : this.maxVisibleRows;
42625
- this.moveScrollWindowBy(rowDelta);
42762
+ this.handleScrollTouchEnd = () => {
42763
+ this.touchScrolling = false;
42764
+ this.startAutoScroll();
42626
42765
  };
42627
42766
  this.rootElement.selectAll('*').remove();
42628
42767
  this.setStatusAsLoading();
@@ -42905,7 +43044,7 @@ class alarm_element_AlarmElement extends conditional_display_element_Conditional
42905
43044
  if (useScroll) {
42906
43045
  if (!this.scrollContent)
42907
43046
  return;
42908
- this.scrollWindowStart = Math.min(this.scrollWindowStart, Math.max(0, this.pageSize - this.maxVisibleRows));
43047
+ this.scrollWindowStart = Math.min(this.scrollWindowStart, this.getMaxWindowStart());
42909
43048
  this.renderScrollWindow(this.scrollWindowStart);
42910
43049
  return;
42911
43050
  }
@@ -42940,24 +43079,12 @@ class alarm_element_AlarmElement extends conditional_display_element_Conditional
42940
43079
  }
42941
43080
  this.updateScrollThumb();
42942
43081
  }
42943
- // 滑块高度按"可见行数/总行数"的比例算,位置按当前窗口起始行占可滚动范围的比例算,
42944
- // 只用 top/height 两个数值属性更新,不涉及 transform,不会触发合成层
42945
43082
  updateScrollThumb() {
42946
- if (!this.scrollTrack || !this.scrollThumb)
42947
- return;
42948
- const maxWindowStart = Math.max(0, this.pageSize - this.maxVisibleRows);
42949
- if (maxWindowStart <= 0) {
42950
- this.scrollThumb.style.display = 'none';
42951
- return;
42952
- }
42953
- this.scrollThumb.style.display = 'block';
42954
- const trackHeight = this.scrollTrack.clientHeight;
42955
- const thumbHeightRatio = Math.min(1, this.maxVisibleRows / this.pageSize);
42956
- const thumbHeight = Math.max(20, trackHeight * thumbHeightRatio);
42957
- const maxThumbTop = trackHeight - thumbHeight;
42958
- const thumbTop = maxThumbTop * (this.scrollWindowStart / maxWindowStart);
42959
- this.scrollThumb.style.height = `${thumbHeight}px`;
42960
- this.scrollThumb.style.top = `${thumbTop}px`;
43083
+ if (this.scrollbar)
43084
+ this.scrollbar.update(this.scrollWindowStart, this.alarmList.length);
43085
+ }
43086
+ getMaxWindowStart() {
43087
+ return Math.max(0, this.alarmList.length - this.maxVisibleRows);
42961
43088
  }
42962
43089
  getIconScale() {
42963
43090
  const initSize = this.model.initSize;
@@ -43006,7 +43133,7 @@ class alarm_element_AlarmElement extends conditional_display_element_Conditional
43006
43133
  vertical-align: middle;`;
43007
43134
  for (let col = 0; col < 4; col++) {
43008
43135
  const th = document.createElement('th');
43009
- th.innerHTML = this.getHeaderTextByColumn(col);
43136
+ th.textContent = this.getHeaderTextByColumn(col);
43010
43137
  th.style.cssText = `width: ${this.model.widths[col] / this.model.size.width * 100}%;
43011
43138
  border-style: solid;
43012
43139
  border-color: ${this.model.generalSetting.splitLine};
@@ -43033,7 +43160,7 @@ class alarm_element_AlarmElement extends conditional_display_element_Conditional
43033
43160
  border-left-width: ${!col || this.model.generalSetting.isHiddenColumnSplitLine ? 0 : 1}px;`;
43034
43161
  if (this.alarmList[row]) {
43035
43162
  if (col !== 2) {
43036
- td.innerHTML = this.alarmList[row][col];
43163
+ td.textContent = this.alarmList[row][col];
43037
43164
  td.style.cssText += `${this.model.generalSetting.isUnderline ? 'text-decoration: underline' : ''};`;
43038
43165
  }
43039
43166
  else {
@@ -43052,14 +43179,14 @@ class alarm_element_AlarmElement extends conditional_display_element_Conditional
43052
43179
  border-radius: 5px;
43053
43180
  background: ${levelColors[this.alarmList[row][col]]};
43054
43181
  color: #ffffff;
43055
- width: ${this.model.widths[col] - 30}px;
43182
+ width: calc(100% - 30px);
43056
43183
  height: ${alarmHeight}px;
43057
43184
  max-height: ${rowHeight}px;
43058
43185
  display: flex;
43059
43186
  justify-content: center;
43060
43187
  align-items: center;
43061
43188
  ${this.model.generalSetting.isUnderline ? 'text-decoration: underline' : ''};`;
43062
- alarmLevel.innerHTML = this.model.levelText[this.alarmList[row][col]];
43189
+ alarmLevel.textContent = this.model.levelText[this.alarmList[row][col]];
43063
43190
  td.appendChild(alarmLevel);
43064
43191
  }
43065
43192
  }
@@ -43099,40 +43226,25 @@ class alarm_element_AlarmElement extends conditional_display_element_Conditional
43099
43226
  const dataRowHeight = this.model.heights[1] || this.model.heights[0];
43100
43227
  this.rowHeight = dataRowHeight;
43101
43228
  this.scrollWindowStart = 0;
43102
- // 之前用"表头/表体分两个 table + flex 包裹容器 + overflow/transform 滚动"的结构,
43103
- // 在 iOS WKWebView 上表体会明显放大错位,换了两种滚动实现方式(原生 overflow:auto、
43104
- // JS transform 平移)都复现同样的问题,怀疑是这套多层 div + 双 table 结构本身的问题。
43105
- // 这里改成和 renderPlainTable() 完全同构的单 table 结构(已验证在所有平台上都正常),
43106
- // DOM 里始终只保留 maxVisibleRows 行数据,滚动时只增删 <tr> 内容,不做任何位移/滚动。
43107
- // 自定义滚动条(轨道+滑块)只用 position + top/height 定位,不用 overflow/transform/
43108
- // will-change,这些属性都不会触发 WebKit 合成层提升,不会重新引入 iOS 缩放错位问题。
43109
- const scrollbarWidth = 6;
43110
- const wrapper = document.createElement('div');
43111
- wrapper.style.cssText = `position: relative; width: ${this.model.size.width}px;
43112
- height: ${elementHeight - operationAreaReservedHeight}px;`;
43229
+ // WKWebView can paint positioned HTML descendants outside the SVG scale.
43230
+ // Keep a single unpositioned table directly in foreignObject; the scrollbar
43231
+ // is a sibling SVG group, never an HTML overlay or native scrolling layer.
43232
+ const scrollbarWidth = Math.min(12, this.model.size.width * 0.04);
43233
+ const tableHeight = elementHeight - operationAreaReservedHeight;
43113
43234
  const table = document.createElement('table');
43114
43235
  table.style.cssText = `border: 2px solid ${this.model.generalSetting.stroke};
43115
- height: ${elementHeight - operationAreaReservedHeight}px;
43116
- width: calc(100% - ${scrollbarWidth}px);`;
43236
+ height: ${tableHeight}px; width: 100%; table-layout: fixed;
43237
+ overflow-wrap: break-word; -webkit-text-size-adjust: none; text-size-adjust: none;`;
43117
43238
  table.appendChild(this.buildHeaderRow());
43118
- wrapper.appendChild(table);
43119
- const track = document.createElement('div');
43120
- track.style.cssText = `position: absolute; top: 0; right: 0; width: ${scrollbarWidth}px;
43121
- height: 100%; background: rgba(0,0,0,0.06); border-radius: ${scrollbarWidth / 2}px;`;
43122
- const thumb = document.createElement('div');
43123
- thumb.style.cssText = `position: absolute; left: 0; width: 100%;
43124
- background: rgba(0,0,0,0.35); border-radius: ${scrollbarWidth / 2}px; cursor: pointer;`;
43125
- track.appendChild(thumb);
43126
- wrapper.appendChild(track);
43127
- this.element.appendChild(wrapper);
43239
+ this.element.setAttribute('width', String(this.model.size.width - scrollbarWidth));
43240
+ this.element.appendChild(table);
43128
43241
  this.scrollContent = table;
43129
- this.scrollTrack = track;
43130
- this.scrollThumb = thumb;
43131
43242
  this.renderScrollWindow(0);
43243
+ const headerHeight = Math.min(tableHeight, table.rows[0].getBoundingClientRect().height / this.getCanvasScaleY());
43244
+ this.scrollbar = new AlarmTableScrollbar(this.element.parentNode, this.model.size.width - scrollbarWidth, headerHeight, scrollbarWidth, Math.max(0, tableHeight - headerHeight), this.maxVisibleRows, start => this.moveScrollWindowBy(start - this.scrollWindowStart), () => clearInterval(this.scrollIntervalId), () => this.startAutoScroll());
43132
43245
  this.updateScrollThumb();
43133
43246
  this.hoverTarget = table;
43134
43247
  this.bindScrollHoverEvents();
43135
- this.bindScrollbarEvents();
43136
43248
  this.startAutoScroll();
43137
43249
  }
43138
43250
  bindScrollHoverEvents() {
@@ -43144,10 +43256,16 @@ class alarm_element_AlarmElement extends conditional_display_element_Conditional
43144
43256
  this.hoverTarget.addEventListener('wheel', this.handleScrollWheel, { passive: false });
43145
43257
  this.hoverTarget.addEventListener('touchstart', this.handleScrollTouchStart, { passive: true });
43146
43258
  this.hoverTarget.addEventListener('touchmove', this.handleScrollTouchMove, { passive: false });
43259
+ this.hoverTarget.addEventListener('touchend', this.handleScrollTouchEnd);
43260
+ this.hoverTarget.addEventListener('touchcancel', this.handleScrollTouchEnd);
43147
43261
  }
43148
43262
  }
43149
43263
  unbindScrollHoverEvents() {
43150
- this.unbindScrollbarEvents();
43264
+ if (this.scrollbar)
43265
+ this.scrollbar.dispose();
43266
+ this.scrollbar = null;
43267
+ this.scrollHovered = false;
43268
+ this.touchScrolling = false;
43151
43269
  if (!this.hoverTarget)
43152
43270
  return;
43153
43271
  this.hoverTarget.removeEventListener('mouseenter', this.handleScrollMouseEnter);
@@ -43155,6 +43273,8 @@ class alarm_element_AlarmElement extends conditional_display_element_Conditional
43155
43273
  this.hoverTarget.removeEventListener('wheel', this.handleScrollWheel);
43156
43274
  this.hoverTarget.removeEventListener('touchstart', this.handleScrollTouchStart);
43157
43275
  this.hoverTarget.removeEventListener('touchmove', this.handleScrollTouchMove);
43276
+ this.hoverTarget.removeEventListener('touchend', this.handleScrollTouchEnd);
43277
+ this.hoverTarget.removeEventListener('touchcancel', this.handleScrollTouchEnd);
43158
43278
  this.hoverTarget = null;
43159
43279
  }
43160
43280
  // 手动滚动只在当前可见窗口范围内移动(不触发翻页),到顶/到底停住,
@@ -43162,41 +43282,26 @@ class alarm_element_AlarmElement extends conditional_display_element_Conditional
43162
43282
  moveScrollWindowBy(rowDelta) {
43163
43283
  if (!this.scrollContent)
43164
43284
  return;
43165
- const maxWindowStart = Math.max(0, this.pageSize - this.maxVisibleRows);
43285
+ const maxWindowStart = this.getMaxWindowStart();
43166
43286
  const nextStart = Math.min(maxWindowStart, Math.max(0, this.scrollWindowStart + rowDelta));
43167
43287
  if (nextStart === this.scrollWindowStart)
43168
43288
  return;
43169
43289
  this.scrollWindowStart = nextStart;
43170
43290
  this.renderScrollWindow(this.scrollWindowStart);
43171
43291
  }
43172
- bindScrollbarEvents() {
43173
- if (!this.scrollTrack || !this.scrollThumb)
43174
- return;
43175
- this.scrollThumb.addEventListener('mousedown', this.handleThumbDragStart);
43176
- this.scrollThumb.addEventListener('touchstart', this.handleThumbDragStart, { passive: true });
43177
- this.scrollTrack.addEventListener('mousedown', this.handleTrackClick);
43292
+ getCanvasScaleY() {
43293
+ const matrix = this.element.getScreenCTM();
43294
+ return matrix ? Math.sqrt(matrix.c * matrix.c + matrix.d * matrix.d) || 1 : 1;
43178
43295
  }
43179
- unbindScrollbarEvents() {
43180
- if (this.scrollThumb) {
43181
- this.scrollThumb.removeEventListener('mousedown', this.handleThumbDragStart);
43182
- this.scrollThumb.removeEventListener('touchstart', this.handleThumbDragStart);
43183
- }
43184
- if (this.scrollTrack) {
43185
- this.scrollTrack.removeEventListener('mousedown', this.handleTrackClick);
43186
- }
43187
- document.removeEventListener('mousemove', this.handleThumbDragMove);
43188
- document.removeEventListener('mouseup', this.handleThumbDragEnd);
43189
- document.removeEventListener('touchmove', this.handleThumbDragMove);
43190
- document.removeEventListener('touchend', this.handleThumbDragEnd);
43191
- this.scrollTrack = null;
43192
- this.scrollThumb = null;
43193
- }
43194
- getClientY(event) {
43195
- return 'touches' in event ? event.touches[0].clientY : event.clientY;
43296
+ getScreenRowHeight() {
43297
+ var _a;
43298
+ const row = (_a = this.scrollContent) === null || _a === void 0 ? void 0 : _a.querySelectorAll('tr')[1];
43299
+ return (row === null || row === void 0 ? void 0 : row.getBoundingClientRect().height) || this.rowHeight * this.getCanvasScaleY();
43196
43300
  }
43197
43301
  startAutoScroll() {
43302
+ var _a;
43198
43303
  clearInterval(this.scrollIntervalId);
43199
- if (!this.model.generalSetting.autoScroll)
43304
+ if (this.isDisposed || this.scrollHovered || this.touchScrolling || ((_a = this.scrollbar) === null || _a === void 0 ? void 0 : _a.isInteracting) || !this.model.generalSetting.autoScroll)
43200
43305
  return;
43201
43306
  const totalPages = Math.max(1, Math.ceil(this.totalCount / this.pageSize));
43202
43307
  if (totalPages <= 1 && !this.scrollContent)
@@ -43209,7 +43314,7 @@ class alarm_element_AlarmElement extends conditional_display_element_Conditional
43209
43314
  this.autoNextPage();
43210
43315
  return;
43211
43316
  }
43212
- const maxWindowStart = this.pageSize - this.maxVisibleRows;
43317
+ const maxWindowStart = this.getMaxWindowStart();
43213
43318
  if (maxWindowStart <= 0 || this.scrollWindowStart >= maxWindowStart) {
43214
43319
  this.autoNextPage();
43215
43320
  return;
@@ -45120,7 +45225,7 @@ var shared = __webpack_require__(6);
45120
45225
  // EXTERNAL MODULE: ./.tmp/view/view.service.ts
45121
45226
  var view_service = __webpack_require__(27);
45122
45227
 
45123
- // EXTERNAL MODULE: ./.tmp/gui/gui-view.ts + 126 modules
45228
+ // EXTERNAL MODULE: ./.tmp/gui/gui-view.ts + 127 modules
45124
45229
  var gui_view = __webpack_require__(32);
45125
45230
 
45126
45231
  // EXTERNAL MODULE: external "rxjs/operators"