vue2-excel-grid 2.6.2 → 2.6.3

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.3",
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)
@@ -5106,9 +5117,14 @@ const ExcelGridComponent = {
5106
5117
  this.isMouseDown = false
5107
5118
  },
5108
5119
 
5109
- handleFillDragMove(e) {
5120
+ // Resolves which (row, col) the mouse is currently over, given the
5121
+ // scroll body's CURRENT scrollTop/scrollLeft — called both directly from
5122
+ // mousemove and repeatedly from the edge-auto-scroll rAF loop below (as
5123
+ // scrollTop changes on its own, the row under a STATIONARY cursor changes
5124
+ // with it).
5125
+ _fillDragTargetFromEvent(e) {
5110
5126
  const scrollBody = this.$refs.scrollBody
5111
- if (!scrollBody) return
5127
+ if (!scrollBody) return null
5112
5128
  const rect = scrollBody.getBoundingClientRect()
5113
5129
  const relY = e.clientY - rect.top + scrollBody.scrollTop
5114
5130
  const relX = e.clientX - rect.left + scrollBody.scrollLeft
@@ -5133,13 +5149,78 @@ const ExcelGridComponent = {
5133
5149
  if (relX < left) { col = i; break }
5134
5150
  col = i
5135
5151
  }
5152
+ return { row, col }
5153
+ },
5136
5154
 
5137
- this.fillDrag.currentRow = row
5138
- this.fillDrag.currentCol = col
5139
- this.scrollToCell(row, col)
5155
+ handleFillDragMove(e) {
5156
+ this._fillDragLastEvent = e
5157
+ const target = this._fillDragTargetFromEvent(e)
5158
+ if (!target) return
5159
+ this.fillDrag.currentRow = target.row
5160
+ this.fillDrag.currentCol = target.col
5161
+ // Covers the common case of a single big mousemove jump landing the
5162
+ // cursor (and its computed target row/col) outside the visible window.
5163
+ this.scrollToCell(target.row, target.col)
5164
+ // Covers the — far more common in practice — case of the cursor
5165
+ // PINNED at the container's edge (it usually can't travel further,
5166
+ // since the grid typically fills its host layout down to that edge):
5167
+ // keep scrolling for as long as it stays there. Same rAF/edge-zone
5168
+ // pattern as _updateDragAutoScroll (column-drag reordering) below.
5169
+ this._updateFillDragAutoScroll(e.clientX, e.clientY)
5170
+ },
5171
+
5172
+ // Edge auto-scroll for fill-handle dragging — vertical AND horizontal
5173
+ // (column-drag's _updateDragAutoScroll is horizontal-only). Speed scales
5174
+ // with how deep into the 24px edge zone the cursor sits.
5175
+ _updateFillDragAutoScroll(clientX, clientY) {
5176
+ const sb = this.$refs.scrollBody
5177
+ if (!sb) { this._fillDragScrollV = 0; this._fillDragScrollH = 0; return }
5178
+ const rect = sb.getBoundingClientRect()
5179
+ const ZONE = FILL_DRAG_EDGE_ZONE
5180
+
5181
+ let v = 0
5182
+ if (clientY < rect.top + ZONE) v = -Math.ceil((rect.top + ZONE - clientY) / 4)
5183
+ else if (clientY > rect.bottom - ZONE) v = Math.ceil((clientY - (rect.bottom - ZONE)) / 4)
5184
+ this._fillDragScrollV = Math.max(-FILL_DRAG_MAX_SPEED, Math.min(FILL_DRAG_MAX_SPEED, v))
5185
+
5186
+ let h = 0
5187
+ if (clientX < rect.left + ZONE) h = -Math.ceil((rect.left + ZONE - clientX) / 4)
5188
+ else if (clientX > rect.right - ZONE) h = Math.ceil((clientX - (rect.right - ZONE)) / 4)
5189
+ this._fillDragScrollH = Math.max(-FILL_DRAG_MAX_SPEED, Math.min(FILL_DRAG_MAX_SPEED, h))
5190
+
5191
+ if ((this._fillDragScrollV !== 0 || this._fillDragScrollH !== 0) && !this._fillDragScrollRAF) {
5192
+ const step = () => {
5193
+ this._fillDragScrollRAF = null
5194
+ if (!this.fillDrag.active) return
5195
+ const body = this.$refs.scrollBody
5196
+ if (body) {
5197
+ if (this._fillDragScrollV) body.scrollTop = Math.max(0, Math.min(body.scrollHeight - body.clientHeight, body.scrollTop + this._fillDragScrollV))
5198
+ if (this._fillDragScrollH) body.scrollLeft = Math.max(0, Math.min(body.scrollWidth - body.clientWidth, body.scrollLeft + this._fillDragScrollH))
5199
+ // The cursor itself hasn't moved, but the content under it has —
5200
+ // re-derive the fill target at the new scroll position.
5201
+ if (this._fillDragLastEvent) {
5202
+ const target = this._fillDragTargetFromEvent(this._fillDragLastEvent)
5203
+ if (target) { this.fillDrag.currentRow = target.row; this.fillDrag.currentCol = target.col }
5204
+ }
5205
+ }
5206
+ if (this._fillDragScrollV !== 0 || this._fillDragScrollH !== 0) this._fillDragScrollRAF = requestAnimationFrame(step)
5207
+ }
5208
+ this._fillDragScrollRAF = requestAnimationFrame(step)
5209
+ }
5210
+ },
5211
+
5212
+ _stopFillDragAutoScroll() {
5213
+ this._fillDragScrollV = 0
5214
+ this._fillDragScrollH = 0
5215
+ this._fillDragLastEvent = null
5216
+ if (this._fillDragScrollRAF) {
5217
+ cancelAnimationFrame(this._fillDragScrollRAF)
5218
+ this._fillDragScrollRAF = null
5219
+ }
5140
5220
  },
5141
5221
 
5142
5222
  async commitFillDrag() {
5223
+ this._stopFillDragAutoScroll()
5143
5224
  if (this.internalLocked) { this.fillDrag.active = false; return }
5144
5225
  const src = this.fillDrag.sourceRange
5145
5226
  if (!src) { this.fillDrag.active = false; return }