vue2-excel-grid 2.6.2 → 2.6.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue2-excel-grid",
3
- "version": "2.6.2",
3
+ "version": "2.6.4",
4
4
  "description": "Excel-style grid component for Vue 2.6.14 with virtual scrolling",
5
5
  "license": "MIT",
6
6
  "author": "Fozilbek Raimberdiyev",
@@ -994,6 +994,8 @@ const DEFAULT_COL_WIDTH = 100
994
994
  const OUTLINE_GUTTER = 20
995
995
  const FIT_COLUMNS_MIN_WIDTH = 40
996
996
  const ROW_LIST_EDGE_PAD = 8 // birinchi/oxirgi qator bilan tepa/pastki border orasidagi bo'sh joy (px)
997
+ const FILL_DRAG_EDGE_ZONE = 24 // px from .eg-scroll-body's edge that triggers continuous auto-scroll while fill-dragging
998
+ const FILL_DRAG_MAX_SPEED = 18 // px/frame, at the very edge (scales down to 0 at the zone's outer boundary)
997
999
 
998
1000
  // Classifies a col.width spec so resolveColWidth() knows how to turn it into a
999
1001
  // concrete px number. Plain numbers/px strings resolve instantly with no DOM
@@ -2632,6 +2634,14 @@ const ExcelGridComponent = {
2632
2634
  this._dragScrollRAF = null
2633
2635
  this._dragCleanupTimer = null
2634
2636
 
2637
+ // Fill-handle drag edge auto-scroll (see _updateFillDragAutoScroll) — same
2638
+ // idle-when-0 convention as _dragScrollV/_dragScrollRAF above, just for
2639
+ // both axes since a fill can extend down OR right.
2640
+ this._fillDragScrollV = 0
2641
+ this._fillDragScrollH = 0
2642
+ this._fillDragScrollRAF = null
2643
+ this._fillDragLastEvent = null
2644
+
2635
2645
  // localSyncKey — the last `data` reference a version was actually saved
2636
2646
  // for. Initialized to the current (mount-time) value so an untouched grid
2637
2647
  // that's merely tab-switched away from doesn't spam a "nothing happened"
@@ -2716,6 +2726,7 @@ const ExcelGridComponent = {
2716
2726
  clearTimeout(this._widthSyncChainResetTimer)
2717
2727
  clearTimeout(this._bufferWriteTimer)
2718
2728
  if (this._dragScrollRAF) cancelAnimationFrame(this._dragScrollRAF)
2729
+ if (this._fillDragScrollRAF) cancelAnimationFrame(this._fillDragScrollRAF)
2719
2730
  document.removeEventListener('mousemove', this.onGlobalMouseMove)
2720
2731
  document.removeEventListener('mouseup', this.onGlobalMouseUp)
2721
2732
  document.removeEventListener('keydown', this.onGlobalKeyDown)
@@ -4044,6 +4055,10 @@ const ExcelGridComponent = {
4044
4055
  if (dc !== 0) farCol = this._extendAxis(anchor.col, farCol, dc, this.leafCols.length - 1)
4045
4056
  this.selectionRanges = [buildRange(anchor, { row: farRow, col: farCol })]
4046
4057
  this.emitSelectionChange()
4058
+ // Unlike moveActive(), this doesn't move the active cell — but the newly
4059
+ // extended (far) corner of the range must still be scrolled into view,
4060
+ // exactly like moveActive() does for the active cell itself.
4061
+ this.scrollToCell(farRow, farCol)
4047
4062
  },
4048
4063
 
4049
4064
  _extendAxis(anchorIdx, farIdx, delta, maxIdx) {
@@ -5106,9 +5121,14 @@ const ExcelGridComponent = {
5106
5121
  this.isMouseDown = false
5107
5122
  },
5108
5123
 
5109
- handleFillDragMove(e) {
5124
+ // Resolves which (row, col) the mouse is currently over, given the
5125
+ // scroll body's CURRENT scrollTop/scrollLeft — called both directly from
5126
+ // mousemove and repeatedly from the edge-auto-scroll rAF loop below (as
5127
+ // scrollTop changes on its own, the row under a STATIONARY cursor changes
5128
+ // with it).
5129
+ _fillDragTargetFromEvent(e) {
5110
5130
  const scrollBody = this.$refs.scrollBody
5111
- if (!scrollBody) return
5131
+ if (!scrollBody) return null
5112
5132
  const rect = scrollBody.getBoundingClientRect()
5113
5133
  const relY = e.clientY - rect.top + scrollBody.scrollTop
5114
5134
  const relX = e.clientX - rect.left + scrollBody.scrollLeft
@@ -5133,13 +5153,78 @@ const ExcelGridComponent = {
5133
5153
  if (relX < left) { col = i; break }
5134
5154
  col = i
5135
5155
  }
5156
+ return { row, col }
5157
+ },
5136
5158
 
5137
- this.fillDrag.currentRow = row
5138
- this.fillDrag.currentCol = col
5139
- this.scrollToCell(row, col)
5159
+ handleFillDragMove(e) {
5160
+ this._fillDragLastEvent = e
5161
+ const target = this._fillDragTargetFromEvent(e)
5162
+ if (!target) return
5163
+ this.fillDrag.currentRow = target.row
5164
+ this.fillDrag.currentCol = target.col
5165
+ // Covers the common case of a single big mousemove jump landing the
5166
+ // cursor (and its computed target row/col) outside the visible window.
5167
+ this.scrollToCell(target.row, target.col)
5168
+ // Covers the — far more common in practice — case of the cursor
5169
+ // PINNED at the container's edge (it usually can't travel further,
5170
+ // since the grid typically fills its host layout down to that edge):
5171
+ // keep scrolling for as long as it stays there. Same rAF/edge-zone
5172
+ // pattern as _updateDragAutoScroll (column-drag reordering) below.
5173
+ this._updateFillDragAutoScroll(e.clientX, e.clientY)
5174
+ },
5175
+
5176
+ // Edge auto-scroll for fill-handle dragging — vertical AND horizontal
5177
+ // (column-drag's _updateDragAutoScroll is horizontal-only). Speed scales
5178
+ // with how deep into the 24px edge zone the cursor sits.
5179
+ _updateFillDragAutoScroll(clientX, clientY) {
5180
+ const sb = this.$refs.scrollBody
5181
+ if (!sb) { this._fillDragScrollV = 0; this._fillDragScrollH = 0; return }
5182
+ const rect = sb.getBoundingClientRect()
5183
+ const ZONE = FILL_DRAG_EDGE_ZONE
5184
+
5185
+ let v = 0
5186
+ if (clientY < rect.top + ZONE) v = -Math.ceil((rect.top + ZONE - clientY) / 4)
5187
+ else if (clientY > rect.bottom - ZONE) v = Math.ceil((clientY - (rect.bottom - ZONE)) / 4)
5188
+ this._fillDragScrollV = Math.max(-FILL_DRAG_MAX_SPEED, Math.min(FILL_DRAG_MAX_SPEED, v))
5189
+
5190
+ let h = 0
5191
+ if (clientX < rect.left + ZONE) h = -Math.ceil((rect.left + ZONE - clientX) / 4)
5192
+ else if (clientX > rect.right - ZONE) h = Math.ceil((clientX - (rect.right - ZONE)) / 4)
5193
+ this._fillDragScrollH = Math.max(-FILL_DRAG_MAX_SPEED, Math.min(FILL_DRAG_MAX_SPEED, h))
5194
+
5195
+ if ((this._fillDragScrollV !== 0 || this._fillDragScrollH !== 0) && !this._fillDragScrollRAF) {
5196
+ const step = () => {
5197
+ this._fillDragScrollRAF = null
5198
+ if (!this.fillDrag.active) return
5199
+ const body = this.$refs.scrollBody
5200
+ if (body) {
5201
+ if (this._fillDragScrollV) body.scrollTop = Math.max(0, Math.min(body.scrollHeight - body.clientHeight, body.scrollTop + this._fillDragScrollV))
5202
+ if (this._fillDragScrollH) body.scrollLeft = Math.max(0, Math.min(body.scrollWidth - body.clientWidth, body.scrollLeft + this._fillDragScrollH))
5203
+ // The cursor itself hasn't moved, but the content under it has —
5204
+ // re-derive the fill target at the new scroll position.
5205
+ if (this._fillDragLastEvent) {
5206
+ const target = this._fillDragTargetFromEvent(this._fillDragLastEvent)
5207
+ if (target) { this.fillDrag.currentRow = target.row; this.fillDrag.currentCol = target.col }
5208
+ }
5209
+ }
5210
+ if (this._fillDragScrollV !== 0 || this._fillDragScrollH !== 0) this._fillDragScrollRAF = requestAnimationFrame(step)
5211
+ }
5212
+ this._fillDragScrollRAF = requestAnimationFrame(step)
5213
+ }
5214
+ },
5215
+
5216
+ _stopFillDragAutoScroll() {
5217
+ this._fillDragScrollV = 0
5218
+ this._fillDragScrollH = 0
5219
+ this._fillDragLastEvent = null
5220
+ if (this._fillDragScrollRAF) {
5221
+ cancelAnimationFrame(this._fillDragScrollRAF)
5222
+ this._fillDragScrollRAF = null
5223
+ }
5140
5224
  },
5141
5225
 
5142
5226
  async commitFillDrag() {
5227
+ this._stopFillDragAutoScroll()
5143
5228
  if (this.internalLocked) { this.fillDrag.active = false; return }
5144
5229
  const src = this.fillDrag.sourceRange
5145
5230
  if (!src) { this.fillDrag.active = false; return }