sense-react-timeline-editor 1.1.38 → 1.1.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.
@@ -15,6 +15,7 @@ export interface UseRowDragOptions {
15
15
  allowCreateTrack?: boolean;
16
16
  rowHeight?: number;
17
17
  onUpdateEditorData?: (editorData: TimelineRow, actions: TimelineAction[]) => void;
18
+ onPreviewChange?: (plan: MultiDragPlan | null) => void;
18
19
  }
19
20
  export interface MultiDragState {
20
21
  /** 是否正在多选拖拽 */
@@ -53,6 +54,17 @@ declare type StoredActionPosition = {
53
54
  left: number;
54
55
  width: number;
55
56
  };
57
+ declare type MultiDragPlacement = {
58
+ actionId: string;
59
+ rowId: string;
60
+ start: number;
61
+ end: number;
62
+ conflicted: boolean;
63
+ };
64
+ export declare type MultiDragPlan = {
65
+ placements: MultiDragPlacement[];
66
+ rows: TimelineRow[];
67
+ };
56
68
  export declare const useRowDrag: (options: UseRowDragOptions) => {
57
69
  onDragStart: ({ action }: {
58
70
  action: TimelineAction;
package/dist/index.esm.js CHANGED
@@ -2188,7 +2188,8 @@ var hasMultiDragConflict = function hasMultiDragConflict(_ref3) {
2188
2188
  selectedActionIds = _ref3.selectedActionIds,
2189
2189
  primaryAction = _ref3.primaryAction,
2190
2190
  timeOffset = _ref3.timeOffset,
2191
- rowDelta = _ref3.rowDelta;
2191
+ rowDelta = _ref3.rowDelta,
2192
+ allowCreateTrack = _ref3.allowCreateTrack;
2192
2193
  var selectedSet = new Set(selectedActionIds);
2193
2194
  return selectedActionIds.some(function (selectedId) {
2194
2195
  var sourceRowIndex = -1;
@@ -2205,7 +2206,7 @@ var hasMultiDragConflict = function hasMultiDragConflict(_ref3) {
2205
2206
  var initialAction = sourceAction || (selectedId === primaryAction.id ? primaryAction : undefined);
2206
2207
  if (!initialAction || sourceRowIndex < 0) return true;
2207
2208
  var targetRow = editorData[sourceRowIndex + rowDelta];
2208
- if (!targetRow) return true;
2209
+ if (!targetRow) return !allowCreateTrack;
2209
2210
  var nextStart = initialAction.start + timeOffset;
2210
2211
  var nextEnd = initialAction.end + timeOffset;
2211
2212
  return targetRow.actions.some(function (item) {
@@ -2431,7 +2432,8 @@ var EditActionO = function EditActionO(_ref8) {
2431
2432
  selectedActionIds: selectedActionIds || [],
2432
2433
  primaryAction: action,
2433
2434
  timeOffset: currentRange.start - action.start,
2434
- rowDelta: Math.round((top || 0) / rowHeight)
2435
+ rowDelta: Math.round((top || 0) / rowHeight),
2436
+ allowCreateTrack: allowCreateTrack
2435
2437
  }) : false;
2436
2438
  if (multiDragConflict) {
2437
2439
  setInsertPreview === null || setInsertPreview === void 0 ? void 0 : setInsertPreview({
@@ -3264,6 +3266,25 @@ var useRowSelection = function useRowSelection(options) {
3264
3266
  };
3265
3267
  };
3266
3268
 
3269
+ var buildResetPreviewPlan = function buildResetPreviewPlan(_ref) {
3270
+ var editorData = _ref.editorData,
3271
+ initialPositions = _ref.initialPositions,
3272
+ selectedActionIds = _ref.selectedActionIds;
3273
+ return {
3274
+ rows: editorData,
3275
+ placements: selectedActionIds.map(function (actionId) {
3276
+ var initial = initialPositions.get(actionId);
3277
+ if (!initial) return null;
3278
+ return {
3279
+ actionId: actionId,
3280
+ rowId: initial.rowId,
3281
+ start: initial.start,
3282
+ end: initial.end,
3283
+ conflicted: true
3284
+ };
3285
+ }).filter(Boolean)
3286
+ };
3287
+ };
3267
3288
  var resetMultiDragState = function resetMultiDragState() {
3268
3289
  return {
3269
3290
  isMultiDrag: false,
@@ -3286,6 +3307,17 @@ var cloneRows = function cloneRows(rows) {
3286
3307
  });
3287
3308
  });
3288
3309
  };
3310
+ var createEmptyRow = function createEmptyRow(_ref2) {
3311
+ var templateRow = _ref2.templateRow,
3312
+ order = _ref2.order;
3313
+ return _objectSpread2(_objectSpread2({}, templateRow), {}, {
3314
+ id: "row_".concat(Date.now(), "_").concat(Math.random().toString(36).slice(2, 9)),
3315
+ actions: [],
3316
+ order: order,
3317
+ selected: false,
3318
+ isPreview: false
3319
+ });
3320
+ };
3289
3321
  var removeActionFromRows = function removeActionFromRows(rows, actionId) {
3290
3322
  for (var i = 0; i < rows.length; i++) {
3291
3323
  var actionIndex = rows[i].actions.findIndex(function (item) {
@@ -3306,17 +3338,82 @@ var removeActionFromRows = function removeActionFromRows(rows, actionId) {
3306
3338
  action: undefined
3307
3339
  };
3308
3340
  };
3309
- var buildMultiDragPlacements = function buildMultiDragPlacements(_ref4) {
3310
- var editorData = _ref4.editorData,
3311
- initialPositions = _ref4.initialPositions,
3312
- selectedActionIds = _ref4.selectedActionIds,
3313
- timeOffset = _ref4.timeOffset,
3314
- rowDelta = _ref4.rowDelta;
3341
+ var buildMultiDragPlacements = function buildMultiDragPlacements(_ref3) {
3342
+ var editorData = _ref3.editorData,
3343
+ initialPositions = _ref3.initialPositions,
3344
+ selectedActionIds = _ref3.selectedActionIds,
3345
+ timeOffset = _ref3.timeOffset,
3346
+ rowDelta = _ref3.rowDelta,
3347
+ allowCreateTrack = _ref3.allowCreateTrack;
3315
3348
  var selectedSet = new Set(selectedActionIds);
3316
- return selectedActionIds.map(function (actionId) {
3349
+ var selectedInitials = selectedActionIds.map(function (actionId) {
3317
3350
  var initial = initialPositions.get(actionId);
3318
- if (!initial) return null;
3319
- var candidateRow = editorData[initial.rowIndex + rowDelta];
3351
+ return initial ? {
3352
+ actionId: actionId,
3353
+ initial: initial
3354
+ } : null;
3355
+ }).filter(Boolean);
3356
+ if (selectedInitials.length === 0) {
3357
+ return {
3358
+ placements: [],
3359
+ rows: editorData
3360
+ };
3361
+ }
3362
+ var targetIndexes = selectedInitials.map(function (_ref4) {
3363
+ var initial = _ref4.initial;
3364
+ return initial.rowIndex + rowDelta;
3365
+ });
3366
+ var minTargetIndex = Math.min.apply(Math, _toConsumableArray(targetIndexes));
3367
+ var maxTargetIndex = Math.max.apply(Math, _toConsumableArray(targetIndexes));
3368
+ var prependCount = minTargetIndex < 0 ? -minTargetIndex : 0;
3369
+ var appendCount = maxTargetIndex >= editorData.length ? maxTargetIndex - editorData.length + 1 : 0;
3370
+ if (!allowCreateTrack && (prependCount > 0 || appendCount > 0)) {
3371
+ return {
3372
+ rows: editorData,
3373
+ placements: selectedInitials.map(function (_ref5) {
3374
+ var actionId = _ref5.actionId,
3375
+ initial = _ref5.initial;
3376
+ return {
3377
+ actionId: actionId,
3378
+ rowId: initial.rowId,
3379
+ start: initial.start,
3380
+ end: initial.end,
3381
+ conflicted: true
3382
+ };
3383
+ })
3384
+ };
3385
+ }
3386
+ var minOrder = Math.min.apply(Math, _toConsumableArray(editorData.map(function (row) {
3387
+ var _row$order;
3388
+ return Number((_row$order = row.order) !== null && _row$order !== void 0 ? _row$order : 0);
3389
+ })));
3390
+ var maxOrder = Math.max.apply(Math, _toConsumableArray(editorData.map(function (row) {
3391
+ var _row$order2;
3392
+ return Number((_row$order2 = row.order) !== null && _row$order2 !== void 0 ? _row$order2 : 0);
3393
+ })));
3394
+ var prependTemplateRow = editorData[0];
3395
+ var appendTemplateRow = editorData[editorData.length - 1];
3396
+ var prependRows = Array.from({
3397
+ length: prependCount
3398
+ }, function (_, index) {
3399
+ return createEmptyRow({
3400
+ templateRow: prependTemplateRow,
3401
+ order: minOrder - prependCount + index
3402
+ });
3403
+ });
3404
+ var appendRows = Array.from({
3405
+ length: appendCount
3406
+ }, function (_, index) {
3407
+ return createEmptyRow({
3408
+ templateRow: appendTemplateRow,
3409
+ order: maxOrder + index + 1
3410
+ });
3411
+ });
3412
+ var expandedRows = [].concat(prependRows, _toConsumableArray(editorData), appendRows);
3413
+ var placements = selectedInitials.map(function (_ref6) {
3414
+ var actionId = _ref6.actionId,
3415
+ initial = _ref6.initial;
3416
+ var candidateRow = expandedRows[initial.rowIndex + rowDelta + prependCount];
3320
3417
  var nextStart = initial.start + timeOffset;
3321
3418
  var nextEnd = initial.end + timeOffset;
3322
3419
  if (!candidateRow) {
@@ -3347,7 +3444,11 @@ var buildMultiDragPlacements = function buildMultiDragPlacements(_ref4) {
3347
3444
  end: nextEnd,
3348
3445
  conflicted: false
3349
3446
  };
3350
- }).filter(Boolean);
3447
+ });
3448
+ return {
3449
+ placements: placements,
3450
+ rows: expandedRows
3451
+ };
3351
3452
  };
3352
3453
  var useRowDrag = function useRowDrag(options) {
3353
3454
  var selectedActionIds = options.selectedActionIds,
@@ -3360,9 +3461,12 @@ var useRowDrag = function useRowDrag(options) {
3360
3461
  _options$startLeft = options.startLeft,
3361
3462
  startLeft = _options$startLeft === void 0 ? 20 : _options$startLeft,
3362
3463
  setEditorData = options.setEditorData,
3464
+ _options$allowCreateT = options.allowCreateTrack,
3465
+ allowCreateTrack = _options$allowCreateT === void 0 ? true : _options$allowCreateT,
3363
3466
  _options$rowHeight = options.rowHeight,
3364
3467
  rowHeight = _options$rowHeight === void 0 ? 35 : _options$rowHeight,
3365
- onUpdateEditorData = options.onUpdateEditorData;
3468
+ onUpdateEditorData = options.onUpdateEditorData,
3469
+ onPreviewChange = options.onPreviewChange;
3366
3470
  // 多选拖拽状态
3367
3471
  var multiDragState = React.useRef(resetMultiDragState());
3368
3472
  // 获取选中的 action DOM 元素
@@ -3372,8 +3476,8 @@ var useRowDrag = function useRowDrag(options) {
3372
3476
  return Array.from(actions);
3373
3477
  }, [containerRef]);
3374
3478
  // 拖拽开始
3375
- var onDragStart = React.useCallback(function (_ref5) {
3376
- var action = _ref5.action;
3479
+ var onDragStart = React.useCallback(function (_ref7) {
3480
+ var action = _ref7.action;
3377
3481
  if (selectedActionIds.length <= 1) {
3378
3482
  multiDragState.current = resetMultiDragState();
3379
3483
  return;
@@ -3456,10 +3560,14 @@ var useRowDrag = function useRowDrag(options) {
3456
3560
  dy = params.dy;
3457
3561
  var state = multiDragState.current;
3458
3562
  if (!state.isMultiDrag || !state.isDraggingSelection || !state.initialElementPositions) {
3563
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(null);
3459
3564
  return;
3460
3565
  }
3461
3566
  var selectedEls = getSelectedActionEls();
3462
- if (selectedEls.length === 0) return;
3567
+ if (selectedEls.length === 0) {
3568
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(null);
3569
+ return;
3570
+ }
3463
3571
  state.offsetX = (_params$gap = params.gap) !== null && _params$gap !== void 0 ? _params$gap : 0;
3464
3572
  state.offsetY = (state.offsetY || 0) + dy;
3465
3573
  selectedEls.forEach(function (el) {
@@ -3473,7 +3581,42 @@ var useRowDrag = function useRowDrag(options) {
3473
3581
  el.setAttribute('data-x', newX.toString());
3474
3582
  el.setAttribute('data-y', newY.toString());
3475
3583
  });
3476
- }, [getSelectedActionEls]);
3584
+ if (actionId !== state.primaryActionId) return;
3585
+ var primaryInitial = state.initialPositions.get(actionId);
3586
+ if (!primaryInitial) {
3587
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(null);
3588
+ return;
3589
+ }
3590
+ var primaryFinalTime = parserTransformToTime({
3591
+ left: params.left,
3592
+ width: params.width
3593
+ }, {
3594
+ startLeft: startLeft,
3595
+ scale: scale,
3596
+ scaleWidth: scaleWidth
3597
+ });
3598
+ var timeOffset = primaryFinalTime.start - primaryInitial.start;
3599
+ var rowDelta = Math.round((params.top || 0) / rowHeight);
3600
+ var plan = buildMultiDragPlacements({
3601
+ editorData: editorData,
3602
+ initialPositions: state.initialPositions,
3603
+ selectedActionIds: selectedActionIds,
3604
+ timeOffset: timeOffset,
3605
+ rowDelta: rowDelta,
3606
+ allowCreateTrack: allowCreateTrack
3607
+ });
3608
+ if (plan.placements.some(function (placement) {
3609
+ return placement.conflicted;
3610
+ })) {
3611
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(buildResetPreviewPlan({
3612
+ editorData: editorData,
3613
+ initialPositions: state.initialPositions,
3614
+ selectedActionIds: selectedActionIds
3615
+ }));
3616
+ return;
3617
+ }
3618
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(plan);
3619
+ }, [allowCreateTrack, editorData, getSelectedActionEls, onPreviewChange, rowHeight, scale, scaleWidth, selectedActionIds, startLeft]);
3477
3620
  // 拖拽结束
3478
3621
  var onDragEnd = React.useCallback(function (params) {
3479
3622
  var state = multiDragState.current;
@@ -3483,6 +3626,7 @@ var useRowDrag = function useRowDrag(options) {
3483
3626
  el.removeAttribute('data-y');
3484
3627
  el.style.transform = '';
3485
3628
  });
3629
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(null);
3486
3630
  if (!state.isMultiDrag || !params || (params === null || params === void 0 ? void 0 : params.actionId) !== state.primaryActionId) {
3487
3631
  multiDragState.current = resetMultiDragState();
3488
3632
  return;
@@ -3518,13 +3662,16 @@ var useRowDrag = function useRowDrag(options) {
3518
3662
  multiDragState.current = resetMultiDragState();
3519
3663
  return;
3520
3664
  }
3521
- var placements = buildMultiDragPlacements({
3522
- editorData: editorData,
3523
- initialPositions: initialPositions,
3524
- selectedActionIds: selectedActionIds,
3525
- timeOffset: timeOffset,
3526
- rowDelta: rowDelta
3527
- });
3665
+ var _buildMultiDragPlacem = buildMultiDragPlacements({
3666
+ editorData: editorData,
3667
+ initialPositions: initialPositions,
3668
+ selectedActionIds: selectedActionIds,
3669
+ timeOffset: timeOffset,
3670
+ rowDelta: rowDelta,
3671
+ allowCreateTrack: allowCreateTrack
3672
+ }),
3673
+ placements = _buildMultiDragPlacem.placements,
3674
+ plannedRows = _buildMultiDragPlacem.rows;
3528
3675
  var hasConflict = placements.some(function (placement) {
3529
3676
  return placement.conflicted;
3530
3677
  });
@@ -3532,7 +3679,7 @@ var useRowDrag = function useRowDrag(options) {
3532
3679
  multiDragState.current = resetMultiDragState();
3533
3680
  return;
3534
3681
  }
3535
- var rows = cloneRows(editorData);
3682
+ var rows = cloneRows(plannedRows);
3536
3683
  var updatedActions = [];
3537
3684
  var removedActions = new Map();
3538
3685
  selectedActionIds.forEach(function (selectedId) {
@@ -3575,7 +3722,7 @@ var useRowDrag = function useRowDrag(options) {
3575
3722
  onUpdateEditorData === null || onUpdateEditorData === void 0 ? void 0 : onUpdateEditorData(primaryTargetRow, updatedActions);
3576
3723
  }
3577
3724
  multiDragState.current = resetMultiDragState();
3578
- }, [editorData, getSelectedActionEls, onUpdateEditorData, rowHeight, scale, scaleWidth, selectedActionIds, setEditorData, startLeft]);
3725
+ }, [allowCreateTrack, editorData, getSelectedActionEls, onPreviewChange, onUpdateEditorData, rowHeight, scale, scaleWidth, selectedActionIds, setEditorData, startLeft]);
3579
3726
  // 检查是否是多选拖拽模式
3580
3727
  var isMultiDragging = React.useCallback(function () {
3581
3728
  return multiDragState.current.isMultiDrag;
@@ -3744,11 +3891,13 @@ var EditAreaO = /*#__PURE__*/React.forwardRef(function (props, ref) {
3744
3891
  var uploadRef = useRef();
3745
3892
  // ---- drag overlay: imperative DOM updates to avoid React re-renders on every mousemove ----
3746
3893
  var insertPreviewDomRef = useRef(null);
3894
+ var multiInsertPreviewDomRef = useRef(null);
3747
3895
  var trackPreviewRowDomRef = useRef(null);
3748
3896
  var trackPreviewLineDomRef = useRef(null);
3749
3897
  var dragIndicatorDomRef = useRef(null);
3750
3898
  // Latest data refs for re-applying positions on scroll
3751
3899
  var insertPreviewDataRef = useRef(null);
3900
+ var multiInsertPreviewDataRef = useRef(null);
3752
3901
  var trackPreviewDataRef = useRef(null);
3753
3902
  var dragIndicatorDataRef = useRef(null);
3754
3903
  // Always-current snapshot of render-time props, read safely inside stable callbacks
@@ -3807,6 +3956,71 @@ var EditAreaO = /*#__PURE__*/React.forwardRef(function (props, ref) {
3807
3956
  div.style.top = "".concat(top - st + 18, "px");
3808
3957
  div.style.height = "".concat(Math.max(rowH - 4, 8), "px");
3809
3958
  }, []);
3959
+ var setMultiInsertPreview = useCallback(function (plan) {
3960
+ multiInsertPreviewDataRef.current = plan;
3961
+ var container = multiInsertPreviewDomRef.current;
3962
+ if (!container) return;
3963
+ if (!plan || plan.placements.length === 0) {
3964
+ container.style.display = 'none';
3965
+ Array.from(container.children).forEach(function (node) {
3966
+ node.style.display = 'none';
3967
+ });
3968
+ return;
3969
+ }
3970
+ var _liveRef$current2 = liveRef.current,
3971
+ st = _liveRef$current2.scrollTop,
3972
+ sl = _liveRef$current2.startLeft,
3973
+ sc = _liveRef$current2.scale,
3974
+ sw = _liveRef$current2.scaleWidth,
3975
+ rh = _liveRef$current2.rowHeight;
3976
+ var rowIndexMap = new Map(plan.rows.map(function (row, index) {
3977
+ return [row.id, index];
3978
+ }));
3979
+ var placements = plan.placements;
3980
+ while (container.children.length < placements.length) {
3981
+ var previewNode = document.createElement('div');
3982
+ previewNode.style.position = 'absolute';
3983
+ previewNode.style.background = 'rgba(160, 160, 160, 0.12)';
3984
+ previewNode.style.border = '1.5px dashed rgba(150, 150, 150, 0.7)';
3985
+ previewNode.style.borderRadius = '8px';
3986
+ previewNode.style.zIndex = '1000';
3987
+ previewNode.style.pointerEvents = 'none';
3988
+ container.appendChild(previewNode);
3989
+ }
3990
+ Array.from(container.children).forEach(function (node, index) {
3991
+ var _plan$rows$targetInde;
3992
+ var previewNode = node;
3993
+ var placement = placements[index];
3994
+ if (!placement) {
3995
+ previewNode.style.display = 'none';
3996
+ return;
3997
+ }
3998
+ var targetIndex = rowIndexMap.get(placement.rowId);
3999
+ if (targetIndex === undefined) {
4000
+ previewNode.style.display = 'none';
4001
+ return;
4002
+ }
4003
+ var top = 0;
4004
+ for (var i = 0; i < targetIndex; i++) {
4005
+ top += (plan.rows[i].rowHeight || rh) + 2;
4006
+ }
4007
+ var rowH = ((_plan$rows$targetInde = plan.rows[targetIndex]) === null || _plan$rows$targetInde === void 0 ? void 0 : _plan$rows$targetInde.rowHeight) || rh;
4008
+ var t = parserTimeToTransform({
4009
+ start: placement.start,
4010
+ end: placement.end
4011
+ }, {
4012
+ startLeft: sl,
4013
+ scale: sc,
4014
+ scaleWidth: sw
4015
+ });
4016
+ previewNode.style.display = 'block';
4017
+ previewNode.style.left = "".concat(t.left, "px");
4018
+ previewNode.style.width = "".concat(t.width, "px");
4019
+ previewNode.style.top = "".concat(top - st + 18, "px");
4020
+ previewNode.style.height = "".concat(Math.max(rowH - 4, 8), "px");
4021
+ });
4022
+ container.style.display = 'block';
4023
+ }, []);
3810
4024
  var setTrackPreview = useCallback(function (preview) {
3811
4025
  trackPreviewDataRef.current = preview;
3812
4026
  var rowDiv = trackPreviewRowDomRef.current;
@@ -3817,10 +4031,10 @@ var EditAreaO = /*#__PURE__*/React.forwardRef(function (props, ref) {
3817
4031
  lineDiv.style.display = 'none';
3818
4032
  return;
3819
4033
  }
3820
- var _liveRef$current2 = liveRef.current,
3821
- st = _liveRef$current2.scrollTop,
3822
- ed = _liveRef$current2.editorData,
3823
- rh = _liveRef$current2.rowHeight;
4034
+ var _liveRef$current3 = liveRef.current,
4035
+ st = _liveRef$current3.scrollTop,
4036
+ ed = _liveRef$current3.editorData,
4037
+ rh = _liveRef$current3.rowHeight;
3824
4038
  if (preview.kind === 'new-row') {
3825
4039
  rowDiv.style.display = 'none';
3826
4040
  var insertIndex = preview.insertIndex;
@@ -3861,10 +4075,10 @@ var EditAreaO = /*#__PURE__*/React.forwardRef(function (props, ref) {
3861
4075
  div.style.display = 'none';
3862
4076
  return;
3863
4077
  }
3864
- var _liveRef$current3 = liveRef.current,
3865
- st = _liveRef$current3.scrollTop,
3866
- ed = _liveRef$current3.editorData,
3867
- rh = _liveRef$current3.rowHeight;
4078
+ var _liveRef$current4 = liveRef.current,
4079
+ st = _liveRef$current4.scrollTop,
4080
+ ed = _liveRef$current4.editorData,
4081
+ rh = _liveRef$current4.rowHeight;
3868
4082
  var top = 0;
3869
4083
  for (var i = 0; i < Math.min(indicator.targetIndex, ed.length); i++) top += ed[i].rowHeight || rh;
3870
4084
  div.style.display = 'block';
@@ -3873,9 +4087,10 @@ var EditAreaO = /*#__PURE__*/React.forwardRef(function (props, ref) {
3873
4087
  // Re-apply overlay positions whenever scroll changes during an active drag
3874
4088
  useLayoutEffect(function () {
3875
4089
  if (insertPreviewDataRef.current) setInsertPreview(insertPreviewDataRef.current);
4090
+ if (multiInsertPreviewDataRef.current) setMultiInsertPreview(multiInsertPreviewDataRef.current);
3876
4091
  if (trackPreviewDataRef.current) setTrackPreview(trackPreviewDataRef.current);
3877
4092
  if (dragIndicatorDataRef.current) setDragIndicator(dragIndicatorDataRef.current);
3878
- }, [scrollTop]);
4093
+ }, [scrollTop, setInsertPreview, setMultiInsertPreview, setTrackPreview, setDragIndicator]);
3879
4094
  // 使用 ref 追踪 handleSelectionChange 的调用深度,避免无限循环
3880
4095
  var selectionChangeDepthRef = useRef(0);
3881
4096
  // 框选功能
@@ -3921,6 +4136,23 @@ var EditAreaO = /*#__PURE__*/React.forwardRef(function (props, ref) {
3921
4136
  onClickOutside = _useRowSelection.onClickOutside,
3922
4137
  onCtrlClick = _useRowSelection.onCtrlClick,
3923
4138
  setSelectedActionIds = _useRowSelection.setSelectedActionIds;
4139
+ useEffect(function () {
4140
+ var selectedIdsFromEditor = editorData.flatMap(function (row) {
4141
+ return row.actions.filter(function (action) {
4142
+ return action.selected;
4143
+ }).map(function (action) {
4144
+ return action.id;
4145
+ });
4146
+ });
4147
+ var normalizedSelectedIds = selectedIdsFromEditor.length > 1 ? selectedIdsFromEditor : [];
4148
+ var hasSameSelection = normalizedSelectedIds.length === selectedActionIds.length && normalizedSelectedIds.every(function (id) {
4149
+ return selectedActionIds.includes(id);
4150
+ });
4151
+ if (hasSameSelection) {
4152
+ return;
4153
+ }
4154
+ setSelectedActionIds(new Set(normalizedSelectedIds));
4155
+ }, [editorData, selectedActionIds, setSelectedActionIds]);
3924
4156
  var _useRowDrag = useRowDrag({
3925
4157
  selectedActionIds: selectedActionIds,
3926
4158
  editorData: editorData,
@@ -3931,7 +4163,8 @@ var EditAreaO = /*#__PURE__*/React.forwardRef(function (props, ref) {
3931
4163
  setEditorData: setEditorData,
3932
4164
  allowCreateTrack: allowCreateTrack,
3933
4165
  rowHeight: _rowHeight,
3934
- onUpdateEditorData: onUpdateEditorData
4166
+ onUpdateEditorData: onUpdateEditorData,
4167
+ onPreviewChange: setMultiInsertPreview
3935
4168
  }),
3936
4169
  onDragStart = _useRowDrag.onDragStart,
3937
4170
  onDragMove = _useRowDrag.onDragMove,
@@ -4242,6 +4475,15 @@ var EditAreaO = /*#__PURE__*/React.forwardRef(function (props, ref) {
4242
4475
  }
4243
4476
  });
4244
4477
  }), /*#__PURE__*/React.createElement(DragSelection, null), /*#__PURE__*/React.createElement("div", {
4478
+ ref: multiInsertPreviewDomRef,
4479
+ style: {
4480
+ display: 'none',
4481
+ position: 'absolute',
4482
+ inset: 0,
4483
+ zIndex: 1000,
4484
+ pointerEvents: 'none'
4485
+ }
4486
+ }), /*#__PURE__*/React.createElement("div", {
4245
4487
  ref: trackPreviewLineDomRef,
4246
4488
  style: {
4247
4489
  display: 'none',
@@ -4857,10 +5099,9 @@ var Timeline = /*#__PURE__*/React.memo(/*#__PURE__*/React.forwardRef(function (p
4857
5099
  var containerEl = document.querySelector('.timeline-editor');
4858
5100
  if (!containerEl) return;
4859
5101
  var left = startLeft + scaleWidth / scale * val;
4860
- var nextScrollLeft = Math.min(Math.max(left, 0), getMaxScrollLeft());
4861
- containerEl.scrollLeft = nextScrollLeft;
5102
+ containerEl.scrollLeft = Math.max(left, 0);
4862
5103
  scrollSync.current && scrollSync.current.setState({
4863
- scrollLeft: nextScrollLeft
5104
+ scrollLeft: Math.max(left, 0)
4864
5105
  });
4865
5106
  },
4866
5107
  setScrollTop: function setScrollTop(val) {
package/dist/index.js CHANGED
@@ -2198,7 +2198,8 @@ var hasMultiDragConflict = function hasMultiDragConflict(_ref3) {
2198
2198
  selectedActionIds = _ref3.selectedActionIds,
2199
2199
  primaryAction = _ref3.primaryAction,
2200
2200
  timeOffset = _ref3.timeOffset,
2201
- rowDelta = _ref3.rowDelta;
2201
+ rowDelta = _ref3.rowDelta,
2202
+ allowCreateTrack = _ref3.allowCreateTrack;
2202
2203
  var selectedSet = new Set(selectedActionIds);
2203
2204
  return selectedActionIds.some(function (selectedId) {
2204
2205
  var sourceRowIndex = -1;
@@ -2215,7 +2216,7 @@ var hasMultiDragConflict = function hasMultiDragConflict(_ref3) {
2215
2216
  var initialAction = sourceAction || (selectedId === primaryAction.id ? primaryAction : undefined);
2216
2217
  if (!initialAction || sourceRowIndex < 0) return true;
2217
2218
  var targetRow = editorData[sourceRowIndex + rowDelta];
2218
- if (!targetRow) return true;
2219
+ if (!targetRow) return !allowCreateTrack;
2219
2220
  var nextStart = initialAction.start + timeOffset;
2220
2221
  var nextEnd = initialAction.end + timeOffset;
2221
2222
  return targetRow.actions.some(function (item) {
@@ -2441,7 +2442,8 @@ var EditActionO = function EditActionO(_ref8) {
2441
2442
  selectedActionIds: selectedActionIds || [],
2442
2443
  primaryAction: action,
2443
2444
  timeOffset: currentRange.start - action.start,
2444
- rowDelta: Math.round((top || 0) / rowHeight)
2445
+ rowDelta: Math.round((top || 0) / rowHeight),
2446
+ allowCreateTrack: allowCreateTrack
2445
2447
  }) : false;
2446
2448
  if (multiDragConflict) {
2447
2449
  setInsertPreview === null || setInsertPreview === void 0 ? void 0 : setInsertPreview({
@@ -3274,6 +3276,25 @@ var useRowSelection = function useRowSelection(options) {
3274
3276
  };
3275
3277
  };
3276
3278
 
3279
+ var buildResetPreviewPlan = function buildResetPreviewPlan(_ref) {
3280
+ var editorData = _ref.editorData,
3281
+ initialPositions = _ref.initialPositions,
3282
+ selectedActionIds = _ref.selectedActionIds;
3283
+ return {
3284
+ rows: editorData,
3285
+ placements: selectedActionIds.map(function (actionId) {
3286
+ var initial = initialPositions.get(actionId);
3287
+ if (!initial) return null;
3288
+ return {
3289
+ actionId: actionId,
3290
+ rowId: initial.rowId,
3291
+ start: initial.start,
3292
+ end: initial.end,
3293
+ conflicted: true
3294
+ };
3295
+ }).filter(Boolean)
3296
+ };
3297
+ };
3277
3298
  var resetMultiDragState = function resetMultiDragState() {
3278
3299
  return {
3279
3300
  isMultiDrag: false,
@@ -3296,6 +3317,17 @@ var cloneRows = function cloneRows(rows) {
3296
3317
  });
3297
3318
  });
3298
3319
  };
3320
+ var createEmptyRow = function createEmptyRow(_ref2) {
3321
+ var templateRow = _ref2.templateRow,
3322
+ order = _ref2.order;
3323
+ return _objectSpread2(_objectSpread2({}, templateRow), {}, {
3324
+ id: "row_".concat(Date.now(), "_").concat(Math.random().toString(36).slice(2, 9)),
3325
+ actions: [],
3326
+ order: order,
3327
+ selected: false,
3328
+ isPreview: false
3329
+ });
3330
+ };
3299
3331
  var removeActionFromRows = function removeActionFromRows(rows, actionId) {
3300
3332
  for (var i = 0; i < rows.length; i++) {
3301
3333
  var actionIndex = rows[i].actions.findIndex(function (item) {
@@ -3316,17 +3348,82 @@ var removeActionFromRows = function removeActionFromRows(rows, actionId) {
3316
3348
  action: undefined
3317
3349
  };
3318
3350
  };
3319
- var buildMultiDragPlacements = function buildMultiDragPlacements(_ref4) {
3320
- var editorData = _ref4.editorData,
3321
- initialPositions = _ref4.initialPositions,
3322
- selectedActionIds = _ref4.selectedActionIds,
3323
- timeOffset = _ref4.timeOffset,
3324
- rowDelta = _ref4.rowDelta;
3351
+ var buildMultiDragPlacements = function buildMultiDragPlacements(_ref3) {
3352
+ var editorData = _ref3.editorData,
3353
+ initialPositions = _ref3.initialPositions,
3354
+ selectedActionIds = _ref3.selectedActionIds,
3355
+ timeOffset = _ref3.timeOffset,
3356
+ rowDelta = _ref3.rowDelta,
3357
+ allowCreateTrack = _ref3.allowCreateTrack;
3325
3358
  var selectedSet = new Set(selectedActionIds);
3326
- return selectedActionIds.map(function (actionId) {
3359
+ var selectedInitials = selectedActionIds.map(function (actionId) {
3327
3360
  var initial = initialPositions.get(actionId);
3328
- if (!initial) return null;
3329
- var candidateRow = editorData[initial.rowIndex + rowDelta];
3361
+ return initial ? {
3362
+ actionId: actionId,
3363
+ initial: initial
3364
+ } : null;
3365
+ }).filter(Boolean);
3366
+ if (selectedInitials.length === 0) {
3367
+ return {
3368
+ placements: [],
3369
+ rows: editorData
3370
+ };
3371
+ }
3372
+ var targetIndexes = selectedInitials.map(function (_ref4) {
3373
+ var initial = _ref4.initial;
3374
+ return initial.rowIndex + rowDelta;
3375
+ });
3376
+ var minTargetIndex = Math.min.apply(Math, _toConsumableArray(targetIndexes));
3377
+ var maxTargetIndex = Math.max.apply(Math, _toConsumableArray(targetIndexes));
3378
+ var prependCount = minTargetIndex < 0 ? -minTargetIndex : 0;
3379
+ var appendCount = maxTargetIndex >= editorData.length ? maxTargetIndex - editorData.length + 1 : 0;
3380
+ if (!allowCreateTrack && (prependCount > 0 || appendCount > 0)) {
3381
+ return {
3382
+ rows: editorData,
3383
+ placements: selectedInitials.map(function (_ref5) {
3384
+ var actionId = _ref5.actionId,
3385
+ initial = _ref5.initial;
3386
+ return {
3387
+ actionId: actionId,
3388
+ rowId: initial.rowId,
3389
+ start: initial.start,
3390
+ end: initial.end,
3391
+ conflicted: true
3392
+ };
3393
+ })
3394
+ };
3395
+ }
3396
+ var minOrder = Math.min.apply(Math, _toConsumableArray(editorData.map(function (row) {
3397
+ var _row$order;
3398
+ return Number((_row$order = row.order) !== null && _row$order !== void 0 ? _row$order : 0);
3399
+ })));
3400
+ var maxOrder = Math.max.apply(Math, _toConsumableArray(editorData.map(function (row) {
3401
+ var _row$order2;
3402
+ return Number((_row$order2 = row.order) !== null && _row$order2 !== void 0 ? _row$order2 : 0);
3403
+ })));
3404
+ var prependTemplateRow = editorData[0];
3405
+ var appendTemplateRow = editorData[editorData.length - 1];
3406
+ var prependRows = Array.from({
3407
+ length: prependCount
3408
+ }, function (_, index) {
3409
+ return createEmptyRow({
3410
+ templateRow: prependTemplateRow,
3411
+ order: minOrder - prependCount + index
3412
+ });
3413
+ });
3414
+ var appendRows = Array.from({
3415
+ length: appendCount
3416
+ }, function (_, index) {
3417
+ return createEmptyRow({
3418
+ templateRow: appendTemplateRow,
3419
+ order: maxOrder + index + 1
3420
+ });
3421
+ });
3422
+ var expandedRows = [].concat(prependRows, _toConsumableArray(editorData), appendRows);
3423
+ var placements = selectedInitials.map(function (_ref6) {
3424
+ var actionId = _ref6.actionId,
3425
+ initial = _ref6.initial;
3426
+ var candidateRow = expandedRows[initial.rowIndex + rowDelta + prependCount];
3330
3427
  var nextStart = initial.start + timeOffset;
3331
3428
  var nextEnd = initial.end + timeOffset;
3332
3429
  if (!candidateRow) {
@@ -3357,7 +3454,11 @@ var buildMultiDragPlacements = function buildMultiDragPlacements(_ref4) {
3357
3454
  end: nextEnd,
3358
3455
  conflicted: false
3359
3456
  };
3360
- }).filter(Boolean);
3457
+ });
3458
+ return {
3459
+ placements: placements,
3460
+ rows: expandedRows
3461
+ };
3361
3462
  };
3362
3463
  var useRowDrag = function useRowDrag(options) {
3363
3464
  var selectedActionIds = options.selectedActionIds,
@@ -3370,9 +3471,12 @@ var useRowDrag = function useRowDrag(options) {
3370
3471
  _options$startLeft = options.startLeft,
3371
3472
  startLeft = _options$startLeft === void 0 ? 20 : _options$startLeft,
3372
3473
  setEditorData = options.setEditorData,
3474
+ _options$allowCreateT = options.allowCreateTrack,
3475
+ allowCreateTrack = _options$allowCreateT === void 0 ? true : _options$allowCreateT,
3373
3476
  _options$rowHeight = options.rowHeight,
3374
3477
  rowHeight = _options$rowHeight === void 0 ? 35 : _options$rowHeight,
3375
- onUpdateEditorData = options.onUpdateEditorData;
3478
+ onUpdateEditorData = options.onUpdateEditorData,
3479
+ onPreviewChange = options.onPreviewChange;
3376
3480
  // 多选拖拽状态
3377
3481
  var multiDragState = React__default['default'].useRef(resetMultiDragState());
3378
3482
  // 获取选中的 action DOM 元素
@@ -3382,8 +3486,8 @@ var useRowDrag = function useRowDrag(options) {
3382
3486
  return Array.from(actions);
3383
3487
  }, [containerRef]);
3384
3488
  // 拖拽开始
3385
- var onDragStart = React__default['default'].useCallback(function (_ref5) {
3386
- var action = _ref5.action;
3489
+ var onDragStart = React__default['default'].useCallback(function (_ref7) {
3490
+ var action = _ref7.action;
3387
3491
  if (selectedActionIds.length <= 1) {
3388
3492
  multiDragState.current = resetMultiDragState();
3389
3493
  return;
@@ -3466,10 +3570,14 @@ var useRowDrag = function useRowDrag(options) {
3466
3570
  dy = params.dy;
3467
3571
  var state = multiDragState.current;
3468
3572
  if (!state.isMultiDrag || !state.isDraggingSelection || !state.initialElementPositions) {
3573
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(null);
3469
3574
  return;
3470
3575
  }
3471
3576
  var selectedEls = getSelectedActionEls();
3472
- if (selectedEls.length === 0) return;
3577
+ if (selectedEls.length === 0) {
3578
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(null);
3579
+ return;
3580
+ }
3473
3581
  state.offsetX = (_params$gap = params.gap) !== null && _params$gap !== void 0 ? _params$gap : 0;
3474
3582
  state.offsetY = (state.offsetY || 0) + dy;
3475
3583
  selectedEls.forEach(function (el) {
@@ -3483,7 +3591,42 @@ var useRowDrag = function useRowDrag(options) {
3483
3591
  el.setAttribute('data-x', newX.toString());
3484
3592
  el.setAttribute('data-y', newY.toString());
3485
3593
  });
3486
- }, [getSelectedActionEls]);
3594
+ if (actionId !== state.primaryActionId) return;
3595
+ var primaryInitial = state.initialPositions.get(actionId);
3596
+ if (!primaryInitial) {
3597
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(null);
3598
+ return;
3599
+ }
3600
+ var primaryFinalTime = parserTransformToTime({
3601
+ left: params.left,
3602
+ width: params.width
3603
+ }, {
3604
+ startLeft: startLeft,
3605
+ scale: scale,
3606
+ scaleWidth: scaleWidth
3607
+ });
3608
+ var timeOffset = primaryFinalTime.start - primaryInitial.start;
3609
+ var rowDelta = Math.round((params.top || 0) / rowHeight);
3610
+ var plan = buildMultiDragPlacements({
3611
+ editorData: editorData,
3612
+ initialPositions: state.initialPositions,
3613
+ selectedActionIds: selectedActionIds,
3614
+ timeOffset: timeOffset,
3615
+ rowDelta: rowDelta,
3616
+ allowCreateTrack: allowCreateTrack
3617
+ });
3618
+ if (plan.placements.some(function (placement) {
3619
+ return placement.conflicted;
3620
+ })) {
3621
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(buildResetPreviewPlan({
3622
+ editorData: editorData,
3623
+ initialPositions: state.initialPositions,
3624
+ selectedActionIds: selectedActionIds
3625
+ }));
3626
+ return;
3627
+ }
3628
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(plan);
3629
+ }, [allowCreateTrack, editorData, getSelectedActionEls, onPreviewChange, rowHeight, scale, scaleWidth, selectedActionIds, startLeft]);
3487
3630
  // 拖拽结束
3488
3631
  var onDragEnd = React__default['default'].useCallback(function (params) {
3489
3632
  var state = multiDragState.current;
@@ -3493,6 +3636,7 @@ var useRowDrag = function useRowDrag(options) {
3493
3636
  el.removeAttribute('data-y');
3494
3637
  el.style.transform = '';
3495
3638
  });
3639
+ onPreviewChange === null || onPreviewChange === void 0 ? void 0 : onPreviewChange(null);
3496
3640
  if (!state.isMultiDrag || !params || (params === null || params === void 0 ? void 0 : params.actionId) !== state.primaryActionId) {
3497
3641
  multiDragState.current = resetMultiDragState();
3498
3642
  return;
@@ -3528,13 +3672,16 @@ var useRowDrag = function useRowDrag(options) {
3528
3672
  multiDragState.current = resetMultiDragState();
3529
3673
  return;
3530
3674
  }
3531
- var placements = buildMultiDragPlacements({
3532
- editorData: editorData,
3533
- initialPositions: initialPositions,
3534
- selectedActionIds: selectedActionIds,
3535
- timeOffset: timeOffset,
3536
- rowDelta: rowDelta
3537
- });
3675
+ var _buildMultiDragPlacem = buildMultiDragPlacements({
3676
+ editorData: editorData,
3677
+ initialPositions: initialPositions,
3678
+ selectedActionIds: selectedActionIds,
3679
+ timeOffset: timeOffset,
3680
+ rowDelta: rowDelta,
3681
+ allowCreateTrack: allowCreateTrack
3682
+ }),
3683
+ placements = _buildMultiDragPlacem.placements,
3684
+ plannedRows = _buildMultiDragPlacem.rows;
3538
3685
  var hasConflict = placements.some(function (placement) {
3539
3686
  return placement.conflicted;
3540
3687
  });
@@ -3542,7 +3689,7 @@ var useRowDrag = function useRowDrag(options) {
3542
3689
  multiDragState.current = resetMultiDragState();
3543
3690
  return;
3544
3691
  }
3545
- var rows = cloneRows(editorData);
3692
+ var rows = cloneRows(plannedRows);
3546
3693
  var updatedActions = [];
3547
3694
  var removedActions = new Map();
3548
3695
  selectedActionIds.forEach(function (selectedId) {
@@ -3585,7 +3732,7 @@ var useRowDrag = function useRowDrag(options) {
3585
3732
  onUpdateEditorData === null || onUpdateEditorData === void 0 ? void 0 : onUpdateEditorData(primaryTargetRow, updatedActions);
3586
3733
  }
3587
3734
  multiDragState.current = resetMultiDragState();
3588
- }, [editorData, getSelectedActionEls, onUpdateEditorData, rowHeight, scale, scaleWidth, selectedActionIds, setEditorData, startLeft]);
3735
+ }, [allowCreateTrack, editorData, getSelectedActionEls, onPreviewChange, onUpdateEditorData, rowHeight, scale, scaleWidth, selectedActionIds, setEditorData, startLeft]);
3589
3736
  // 检查是否是多选拖拽模式
3590
3737
  var isMultiDragging = React__default['default'].useCallback(function () {
3591
3738
  return multiDragState.current.isMultiDrag;
@@ -3754,11 +3901,13 @@ var EditAreaO = /*#__PURE__*/React__default['default'].forwardRef(function (prop
3754
3901
  var uploadRef = React.useRef();
3755
3902
  // ---- drag overlay: imperative DOM updates to avoid React re-renders on every mousemove ----
3756
3903
  var insertPreviewDomRef = React.useRef(null);
3904
+ var multiInsertPreviewDomRef = React.useRef(null);
3757
3905
  var trackPreviewRowDomRef = React.useRef(null);
3758
3906
  var trackPreviewLineDomRef = React.useRef(null);
3759
3907
  var dragIndicatorDomRef = React.useRef(null);
3760
3908
  // Latest data refs for re-applying positions on scroll
3761
3909
  var insertPreviewDataRef = React.useRef(null);
3910
+ var multiInsertPreviewDataRef = React.useRef(null);
3762
3911
  var trackPreviewDataRef = React.useRef(null);
3763
3912
  var dragIndicatorDataRef = React.useRef(null);
3764
3913
  // Always-current snapshot of render-time props, read safely inside stable callbacks
@@ -3817,6 +3966,71 @@ var EditAreaO = /*#__PURE__*/React__default['default'].forwardRef(function (prop
3817
3966
  div.style.top = "".concat(top - st + 18, "px");
3818
3967
  div.style.height = "".concat(Math.max(rowH - 4, 8), "px");
3819
3968
  }, []);
3969
+ var setMultiInsertPreview = React.useCallback(function (plan) {
3970
+ multiInsertPreviewDataRef.current = plan;
3971
+ var container = multiInsertPreviewDomRef.current;
3972
+ if (!container) return;
3973
+ if (!plan || plan.placements.length === 0) {
3974
+ container.style.display = 'none';
3975
+ Array.from(container.children).forEach(function (node) {
3976
+ node.style.display = 'none';
3977
+ });
3978
+ return;
3979
+ }
3980
+ var _liveRef$current2 = liveRef.current,
3981
+ st = _liveRef$current2.scrollTop,
3982
+ sl = _liveRef$current2.startLeft,
3983
+ sc = _liveRef$current2.scale,
3984
+ sw = _liveRef$current2.scaleWidth,
3985
+ rh = _liveRef$current2.rowHeight;
3986
+ var rowIndexMap = new Map(plan.rows.map(function (row, index) {
3987
+ return [row.id, index];
3988
+ }));
3989
+ var placements = plan.placements;
3990
+ while (container.children.length < placements.length) {
3991
+ var previewNode = document.createElement('div');
3992
+ previewNode.style.position = 'absolute';
3993
+ previewNode.style.background = 'rgba(160, 160, 160, 0.12)';
3994
+ previewNode.style.border = '1.5px dashed rgba(150, 150, 150, 0.7)';
3995
+ previewNode.style.borderRadius = '8px';
3996
+ previewNode.style.zIndex = '1000';
3997
+ previewNode.style.pointerEvents = 'none';
3998
+ container.appendChild(previewNode);
3999
+ }
4000
+ Array.from(container.children).forEach(function (node, index) {
4001
+ var _plan$rows$targetInde;
4002
+ var previewNode = node;
4003
+ var placement = placements[index];
4004
+ if (!placement) {
4005
+ previewNode.style.display = 'none';
4006
+ return;
4007
+ }
4008
+ var targetIndex = rowIndexMap.get(placement.rowId);
4009
+ if (targetIndex === undefined) {
4010
+ previewNode.style.display = 'none';
4011
+ return;
4012
+ }
4013
+ var top = 0;
4014
+ for (var i = 0; i < targetIndex; i++) {
4015
+ top += (plan.rows[i].rowHeight || rh) + 2;
4016
+ }
4017
+ var rowH = ((_plan$rows$targetInde = plan.rows[targetIndex]) === null || _plan$rows$targetInde === void 0 ? void 0 : _plan$rows$targetInde.rowHeight) || rh;
4018
+ var t = parserTimeToTransform({
4019
+ start: placement.start,
4020
+ end: placement.end
4021
+ }, {
4022
+ startLeft: sl,
4023
+ scale: sc,
4024
+ scaleWidth: sw
4025
+ });
4026
+ previewNode.style.display = 'block';
4027
+ previewNode.style.left = "".concat(t.left, "px");
4028
+ previewNode.style.width = "".concat(t.width, "px");
4029
+ previewNode.style.top = "".concat(top - st + 18, "px");
4030
+ previewNode.style.height = "".concat(Math.max(rowH - 4, 8), "px");
4031
+ });
4032
+ container.style.display = 'block';
4033
+ }, []);
3820
4034
  var setTrackPreview = React.useCallback(function (preview) {
3821
4035
  trackPreviewDataRef.current = preview;
3822
4036
  var rowDiv = trackPreviewRowDomRef.current;
@@ -3827,10 +4041,10 @@ var EditAreaO = /*#__PURE__*/React__default['default'].forwardRef(function (prop
3827
4041
  lineDiv.style.display = 'none';
3828
4042
  return;
3829
4043
  }
3830
- var _liveRef$current2 = liveRef.current,
3831
- st = _liveRef$current2.scrollTop,
3832
- ed = _liveRef$current2.editorData,
3833
- rh = _liveRef$current2.rowHeight;
4044
+ var _liveRef$current3 = liveRef.current,
4045
+ st = _liveRef$current3.scrollTop,
4046
+ ed = _liveRef$current3.editorData,
4047
+ rh = _liveRef$current3.rowHeight;
3834
4048
  if (preview.kind === 'new-row') {
3835
4049
  rowDiv.style.display = 'none';
3836
4050
  var insertIndex = preview.insertIndex;
@@ -3871,10 +4085,10 @@ var EditAreaO = /*#__PURE__*/React__default['default'].forwardRef(function (prop
3871
4085
  div.style.display = 'none';
3872
4086
  return;
3873
4087
  }
3874
- var _liveRef$current3 = liveRef.current,
3875
- st = _liveRef$current3.scrollTop,
3876
- ed = _liveRef$current3.editorData,
3877
- rh = _liveRef$current3.rowHeight;
4088
+ var _liveRef$current4 = liveRef.current,
4089
+ st = _liveRef$current4.scrollTop,
4090
+ ed = _liveRef$current4.editorData,
4091
+ rh = _liveRef$current4.rowHeight;
3878
4092
  var top = 0;
3879
4093
  for (var i = 0; i < Math.min(indicator.targetIndex, ed.length); i++) top += ed[i].rowHeight || rh;
3880
4094
  div.style.display = 'block';
@@ -3883,9 +4097,10 @@ var EditAreaO = /*#__PURE__*/React__default['default'].forwardRef(function (prop
3883
4097
  // Re-apply overlay positions whenever scroll changes during an active drag
3884
4098
  React.useLayoutEffect(function () {
3885
4099
  if (insertPreviewDataRef.current) setInsertPreview(insertPreviewDataRef.current);
4100
+ if (multiInsertPreviewDataRef.current) setMultiInsertPreview(multiInsertPreviewDataRef.current);
3886
4101
  if (trackPreviewDataRef.current) setTrackPreview(trackPreviewDataRef.current);
3887
4102
  if (dragIndicatorDataRef.current) setDragIndicator(dragIndicatorDataRef.current);
3888
- }, [scrollTop]);
4103
+ }, [scrollTop, setInsertPreview, setMultiInsertPreview, setTrackPreview, setDragIndicator]);
3889
4104
  // 使用 ref 追踪 handleSelectionChange 的调用深度,避免无限循环
3890
4105
  var selectionChangeDepthRef = React.useRef(0);
3891
4106
  // 框选功能
@@ -3931,6 +4146,23 @@ var EditAreaO = /*#__PURE__*/React__default['default'].forwardRef(function (prop
3931
4146
  onClickOutside = _useRowSelection.onClickOutside,
3932
4147
  onCtrlClick = _useRowSelection.onCtrlClick,
3933
4148
  setSelectedActionIds = _useRowSelection.setSelectedActionIds;
4149
+ React.useEffect(function () {
4150
+ var selectedIdsFromEditor = editorData.flatMap(function (row) {
4151
+ return row.actions.filter(function (action) {
4152
+ return action.selected;
4153
+ }).map(function (action) {
4154
+ return action.id;
4155
+ });
4156
+ });
4157
+ var normalizedSelectedIds = selectedIdsFromEditor.length > 1 ? selectedIdsFromEditor : [];
4158
+ var hasSameSelection = normalizedSelectedIds.length === selectedActionIds.length && normalizedSelectedIds.every(function (id) {
4159
+ return selectedActionIds.includes(id);
4160
+ });
4161
+ if (hasSameSelection) {
4162
+ return;
4163
+ }
4164
+ setSelectedActionIds(new Set(normalizedSelectedIds));
4165
+ }, [editorData, selectedActionIds, setSelectedActionIds]);
3934
4166
  var _useRowDrag = useRowDrag({
3935
4167
  selectedActionIds: selectedActionIds,
3936
4168
  editorData: editorData,
@@ -3941,7 +4173,8 @@ var EditAreaO = /*#__PURE__*/React__default['default'].forwardRef(function (prop
3941
4173
  setEditorData: setEditorData,
3942
4174
  allowCreateTrack: allowCreateTrack,
3943
4175
  rowHeight: _rowHeight,
3944
- onUpdateEditorData: onUpdateEditorData
4176
+ onUpdateEditorData: onUpdateEditorData,
4177
+ onPreviewChange: setMultiInsertPreview
3945
4178
  }),
3946
4179
  onDragStart = _useRowDrag.onDragStart,
3947
4180
  onDragMove = _useRowDrag.onDragMove,
@@ -4252,6 +4485,15 @@ var EditAreaO = /*#__PURE__*/React__default['default'].forwardRef(function (prop
4252
4485
  }
4253
4486
  });
4254
4487
  }), /*#__PURE__*/React__default['default'].createElement(DragSelection, null), /*#__PURE__*/React__default['default'].createElement("div", {
4488
+ ref: multiInsertPreviewDomRef,
4489
+ style: {
4490
+ display: 'none',
4491
+ position: 'absolute',
4492
+ inset: 0,
4493
+ zIndex: 1000,
4494
+ pointerEvents: 'none'
4495
+ }
4496
+ }), /*#__PURE__*/React__default['default'].createElement("div", {
4255
4497
  ref: trackPreviewLineDomRef,
4256
4498
  style: {
4257
4499
  display: 'none',
@@ -4867,10 +5109,9 @@ var Timeline = /*#__PURE__*/React__default['default'].memo(/*#__PURE__*/React__d
4867
5109
  var containerEl = document.querySelector('.timeline-editor');
4868
5110
  if (!containerEl) return;
4869
5111
  var left = startLeft + scaleWidth / scale * val;
4870
- var nextScrollLeft = Math.min(Math.max(left, 0), getMaxScrollLeft());
4871
- containerEl.scrollLeft = nextScrollLeft;
5112
+ containerEl.scrollLeft = Math.max(left, 0);
4872
5113
  scrollSync.current && scrollSync.current.setState({
4873
- scrollLeft: nextScrollLeft
5114
+ scrollLeft: Math.max(left, 0)
4874
5115
  });
4875
5116
  },
4876
5117
  setScrollTop: function setScrollTop(val) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sense-react-timeline-editor",
3
- "version": "1.1.38",
3
+ "version": "1.1.40",
4
4
  "author": "xzdarcy",
5
5
  "license": "MIT",
6
6
  "keywords": [