@keplar-404/react-timeline-editor 1.0.6

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.
Files changed (73) hide show
  1. package/dist/components/control_area/index.d.ts +0 -0
  2. package/dist/components/cursor/cursor.d.ts +20 -0
  3. package/dist/components/cut-overlay/CutOverlay.d.ts +202 -0
  4. package/dist/components/edit_area/cross_row_drag.d.ts +50 -0
  5. package/dist/components/edit_area/drag_lines.d.ts +11 -0
  6. package/dist/components/edit_area/drag_preview.d.ts +14 -0
  7. package/dist/components/edit_area/drag_utils.d.ts +39 -0
  8. package/dist/components/edit_area/edit_action.d.ts +19 -0
  9. package/dist/components/edit_area/edit_area.d.ts +56 -0
  10. package/dist/components/edit_area/edit_row.d.ts +27 -0
  11. package/dist/components/edit_area/hooks/use_drag_line.d.ts +33 -0
  12. package/dist/components/edit_area/insertion_line.d.ts +12 -0
  13. package/dist/components/loop-zone/LoopZoneOverlay.d.ts +243 -0
  14. package/dist/components/row_rnd/hooks/useAutoScroll.d.ts +7 -0
  15. package/dist/components/row_rnd/interactable.d.ts +14 -0
  16. package/dist/components/row_rnd/row_rnd.d.ts +3 -0
  17. package/dist/components/row_rnd/row_rnd_interface.d.ts +47 -0
  18. package/dist/components/time_area/time_area.d.ts +17 -0
  19. package/dist/components/timeline.d.ts +3 -0
  20. package/dist/components/transport/TransportBar.d.ts +132 -0
  21. package/dist/components/transport/useTimelinePlayer.d.ts +164 -0
  22. package/dist/index.cjs.js +13 -0
  23. package/dist/index.d.ts +12 -0
  24. package/dist/index.es.js +10102 -0
  25. package/dist/index.umd.js +13 -0
  26. package/dist/interface/common_prop.d.ts +12 -0
  27. package/dist/interface/const.d.ts +28 -0
  28. package/dist/interface/timeline.d.ts +342 -0
  29. package/dist/react-timeline-editor.css +1 -0
  30. package/dist/utils/check_props.d.ts +2 -0
  31. package/dist/utils/deal_class_prefix.d.ts +1 -0
  32. package/dist/utils/deal_data.d.ts +58 -0
  33. package/dist/utils/logger.d.ts +132 -0
  34. package/package.json +70 -0
  35. package/src/components/control_area/index.tsx +1 -0
  36. package/src/components/cursor/cursor.css +26 -0
  37. package/src/components/cursor/cursor.tsx +105 -0
  38. package/src/components/cut-overlay/CutOverlay.css +68 -0
  39. package/src/components/cut-overlay/CutOverlay.tsx +491 -0
  40. package/src/components/edit_area/cross_row_drag.tsx +174 -0
  41. package/src/components/edit_area/drag_lines.css +13 -0
  42. package/src/components/edit_area/drag_lines.tsx +31 -0
  43. package/src/components/edit_area/drag_preview.tsx +50 -0
  44. package/src/components/edit_area/drag_utils.ts +77 -0
  45. package/src/components/edit_area/edit_action.css +56 -0
  46. package/src/components/edit_area/edit_action.tsx +362 -0
  47. package/src/components/edit_area/edit_area.css +24 -0
  48. package/src/components/edit_area/edit_area.tsx +606 -0
  49. package/src/components/edit_area/edit_row.css +78 -0
  50. package/src/components/edit_area/edit_row.tsx +128 -0
  51. package/src/components/edit_area/hooks/use_drag_line.ts +93 -0
  52. package/src/components/edit_area/insertion_line.tsx +39 -0
  53. package/src/components/loop-zone/LoopZoneOverlay.css +65 -0
  54. package/src/components/loop-zone/LoopZoneOverlay.tsx +461 -0
  55. package/src/components/row_rnd/hooks/useAutoScroll.ts +81 -0
  56. package/src/components/row_rnd/interactable.tsx +55 -0
  57. package/src/components/row_rnd/row_rnd.tsx +365 -0
  58. package/src/components/row_rnd/row_rnd_interface.ts +59 -0
  59. package/src/components/time_area/time_area.css +35 -0
  60. package/src/components/time_area/time_area.tsx +93 -0
  61. package/src/components/timeline.css +12 -0
  62. package/src/components/timeline.tsx +227 -0
  63. package/src/components/transport/TransportBar.css +171 -0
  64. package/src/components/transport/TransportBar.tsx +322 -0
  65. package/src/components/transport/useTimelinePlayer.ts +319 -0
  66. package/src/index.tsx +17 -0
  67. package/src/interface/common_prop.ts +13 -0
  68. package/src/interface/const.ts +32 -0
  69. package/src/interface/timeline.ts +329 -0
  70. package/src/utils/check_props.ts +77 -0
  71. package/src/utils/deal_class_prefix.ts +6 -0
  72. package/src/utils/deal_data.ts +159 -0
  73. package/src/utils/logger.ts +239 -0
@@ -0,0 +1,128 @@
1
+ import React, { FC, useRef, useCallback } from 'react';
2
+ import { TimelineAction, TimelineRow } from '@keplar-404/timeline-engine';
3
+ import { CommonProp } from '../../interface/common_prop';
4
+ import { prefix } from '../../utils/deal_class_prefix';
5
+ import { parserPixelToTime } from '../../utils/deal_data';
6
+ import { DragLineData } from './drag_lines';
7
+ import { EditAction } from './edit_action';
8
+ import './edit_row.css';
9
+
10
+ export type EditRowProps = CommonProp & {
11
+ areaRef: React.RefObject<HTMLDivElement>;
12
+ rowData?: TimelineRow;
13
+ style?: React.CSSProperties;
14
+ dragLineData: DragLineData;
15
+ setEditorData: (params: TimelineRow[]) => void;
16
+ /** Horizontal scroll offset */
17
+ scrollLeft: number;
18
+ /** Horizontal scroll delta */
19
+ deltaScrollLeft: (scrollLeft: number) => void;
20
+ /** Row index in the editor data array */
21
+ rowIndex?: number;
22
+ /** Current row-reorder drag state */
23
+ dragState?: {
24
+ isDragging: boolean;
25
+ draggedIndex: number;
26
+ };
27
+ /** Enable cross-row block drag */
28
+ enableCrossRowDrag?: boolean;
29
+ /** Show ghost preview while block dragging across rows */
30
+ enableGhostPreview?: boolean;
31
+ };
32
+
33
+ export const EditRow: FC<EditRowProps> = (props) => {
34
+ const {
35
+ rowData,
36
+ style = {},
37
+ onClickRow,
38
+ onDoubleClickRow,
39
+ onContextMenuRow,
40
+ areaRef,
41
+ scrollLeft,
42
+ startLeft,
43
+ scale,
44
+ scaleWidth,
45
+ enableRowDrag,
46
+ onRowDragStart,
47
+ rowIndex = -1,
48
+ dragState,
49
+ enableCrossRowDrag,
50
+ enableGhostPreview,
51
+ } = props;
52
+
53
+ const classNames = ['edit-row'];
54
+ if (rowData?.selected) classNames.push('edit-row-selected');
55
+ if (dragState?.isDragging && dragState.draggedIndex === rowIndex) {
56
+ classNames.push('edit-row-dragging');
57
+ }
58
+
59
+ const dragHandleRef = useRef<HTMLDivElement>(null);
60
+
61
+ const handleTime = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
62
+ if (!areaRef.current) return 0;
63
+ const rect = areaRef.current.getBoundingClientRect();
64
+ const position = e.clientX - rect.x;
65
+ const left = position + scrollLeft;
66
+ return parserPixelToTime(left, { startLeft, scale, scaleWidth });
67
+ };
68
+
69
+ // Row-reorder drag handle
70
+ const handleDragHandleMouseDown = useCallback(
71
+ (e: React.MouseEvent<HTMLDivElement>) => {
72
+ if (!enableRowDrag || !rowData || rowIndex === -1) return;
73
+ e.preventDefault();
74
+ e.stopPropagation();
75
+ onRowDragStart?.({ row: rowData });
76
+ },
77
+ [enableRowDrag, rowData, rowIndex, onRowDragStart],
78
+ );
79
+
80
+ return (
81
+ <div
82
+ className={`${prefix(...classNames)} ${(rowData?.classNames || []).join(' ')}`}
83
+ style={style}
84
+ onClick={(e) => {
85
+ if (rowData && onClickRow) {
86
+ const time = handleTime(e);
87
+ onClickRow(e, { row: rowData, time });
88
+ }
89
+ }}
90
+ onDoubleClick={(e) => {
91
+ if (rowData && onDoubleClickRow) {
92
+ const time = handleTime(e);
93
+ onDoubleClickRow(e, { row: rowData, time });
94
+ }
95
+ }}
96
+ onContextMenu={(e) => {
97
+ if (rowData && onContextMenuRow) {
98
+ const time = handleTime(e);
99
+ onContextMenuRow(e, { row: rowData, time });
100
+ }
101
+ }}
102
+ >
103
+ {/* Row-reorder drag handle */}
104
+ {enableRowDrag && rowData && (
105
+ <div
106
+ ref={dragHandleRef}
107
+ className={prefix('edit-row-drag-handle')}
108
+ onMouseDown={handleDragHandleMouseDown}
109
+ title="Drag to reorder row"
110
+ >
111
+ ⋮⋮
112
+ </div>
113
+ )}
114
+
115
+ {(rowData?.actions || []).map((action: TimelineAction) => (
116
+ <EditAction
117
+ key={action.id}
118
+ {...props}
119
+ handleTime={handleTime}
120
+ row={rowData!}
121
+ action={action}
122
+ enableCrossRowDrag={enableCrossRowDrag}
123
+ enableGhostPreview={enableGhostPreview}
124
+ />
125
+ ))}
126
+ </div>
127
+ );
128
+ };
@@ -0,0 +1,93 @@
1
+ import { useState } from "react";
2
+ import { TimelineAction, TimelineRow } from "@keplar-404/timeline-engine";
3
+ import { parserActionsToPositions, parserTimeToTransform } from "../../../utils/deal_data";
4
+ import { DragLineData } from "../drag_lines";
5
+
6
+ export function useDragLine() {
7
+ const [dragLineData, setDragLineData] = useState<DragLineData>({ isMoving: false, movePositions: [], assistPositions: [] });
8
+
9
+ /** Get auxiliary lines */
10
+ const defaultGetAssistPosition = (data: {
11
+ editorData: TimelineRow[];
12
+ assistActionIds?: string[];
13
+ action: TimelineAction;
14
+ row: TimelineRow;
15
+ startLeft: number;
16
+ scale: number;
17
+ scaleWidth: number;
18
+ hideCursor: boolean;
19
+ cursorLeft: number;
20
+ }) => {
21
+ const { editorData, assistActionIds, action, row, scale, scaleWidth, startLeft, cursorLeft, hideCursor } = data;
22
+ const otherActions: TimelineAction[] = [];
23
+ if (assistActionIds) {
24
+ editorData.forEach((rowItem) => {
25
+ rowItem.actions.forEach((actionItem: TimelineAction) => {
26
+ if (assistActionIds.includes(actionItem.id)) otherActions.push(actionItem);
27
+ });
28
+ });
29
+ } else {
30
+ editorData.forEach((rowItem) => {
31
+ if (rowItem.id !== row.id) {
32
+ otherActions.push(...rowItem.actions);
33
+ } else {
34
+ rowItem.actions.forEach((actionItem: TimelineAction) => {
35
+ if (actionItem.id !== action.id) otherActions.push(actionItem);
36
+ });
37
+ }
38
+ });
39
+ }
40
+
41
+ const positions = parserActionsToPositions(otherActions, {
42
+ startLeft,
43
+ scale,
44
+ scaleWidth,
45
+ });
46
+ if (!hideCursor) positions.push(cursorLeft);
47
+
48
+ return positions;
49
+ };
50
+
51
+ /** Get current movement markers */
52
+ const defaultGetMovePosition = (data: { start: number; end: number; dir?: "right" | "left"; startLeft: number; scale: number; scaleWidth: number }) => {
53
+ const { start, end, dir, scale, scaleWidth, startLeft } = data;
54
+ const { left, width } = parserTimeToTransform({ start, end }, { startLeft, scaleWidth, scale });
55
+ if (!dir) return [left, left + width];
56
+ return dir === "right" ? [left + width] : [left];
57
+ };
58
+
59
+ /** Initialize drag lines */
60
+ const initDragLine = (data: { movePositions?: number[]; assistPositions?: number[] }) => {
61
+ const { movePositions, assistPositions } = data;
62
+
63
+ setDragLineData({
64
+ isMoving: true,
65
+ movePositions: movePositions || [],
66
+ assistPositions: assistPositions || [],
67
+ });
68
+ };
69
+
70
+ /** Update drag line */
71
+ const updateDragLine = (data: { movePositions?: number[]; assistPositions?: number[] }) => {
72
+ const { movePositions, assistPositions } = data;
73
+ setDragLineData((pre) => ({
74
+ ...pre,
75
+ movePositions: movePositions || pre.movePositions,
76
+ assistPositions: assistPositions || pre.assistPositions,
77
+ }));
78
+ };
79
+
80
+ /** Dispose drag lines */
81
+ const disposeDragLine = () => {
82
+ setDragLineData({ isMoving: false, movePositions: [], assistPositions: [] });
83
+ };
84
+
85
+ return {
86
+ initDragLine,
87
+ updateDragLine,
88
+ disposeDragLine,
89
+ dragLineData,
90
+ defaultGetAssistPosition,
91
+ defaultGetMovePosition,
92
+ };
93
+ }
@@ -0,0 +1,39 @@
1
+ import React, { FC } from 'react';
2
+ import { prefix } from '../../utils/deal_class_prefix';
3
+ import { TimelineRow } from '@keplar-404/timeline-engine';
4
+ import { calculateInsertionLineTop } from './drag_utils';
5
+
6
+ interface InsertionLineProps {
7
+ /** Distance from top */
8
+ top: number;
9
+ /** Whether the insertion line is visible */
10
+ visible: boolean;
11
+ }
12
+
13
+ /**
14
+ * Insertion line component - displays the drag insertion position
15
+ */
16
+ export const InsertionLine: FC<InsertionLineProps> = ({ top, visible }) => {
17
+ if (!visible || top < 0) {
18
+ return null;
19
+ }
20
+
21
+ // Calculate insertion line position
22
+ // const top = calculateInsertionLineTop(editorData, insertionLineIndex, rowHeight);
23
+
24
+ return (
25
+ <div
26
+ className={prefix('edit-area-insertion-line')}
27
+ style={{
28
+ position: 'absolute',
29
+ left: 0,
30
+ right: 0,
31
+ height: '2px',
32
+ background: '#4a90e2',
33
+ zIndex: 1000,
34
+ pointerEvents: 'none',
35
+ top,
36
+ }}
37
+ />
38
+ );
39
+ };
@@ -0,0 +1,65 @@
1
+ .loop-zone-overlay {
2
+ position: absolute;
3
+ top: 0;
4
+ left: 0;
5
+ right: 0;
6
+ height: 100%;
7
+ pointer-events: none;
8
+ z-index: 4;
9
+ overflow: visible;
10
+ }
11
+ .loop-zone-band {
12
+ position: absolute;
13
+ top: 0;
14
+ height: 100%;
15
+ pointer-events: none;
16
+ border-left: 1px solid transparent;
17
+ border-right: 1px solid transparent;
18
+ border-top: 2px solid transparent;
19
+ }
20
+ .loop-zone-handle {
21
+ position: absolute;
22
+ top: 0;
23
+ height: 100%;
24
+ transform: translateX(-50%);
25
+ pointer-events: none;
26
+ user-select: none;
27
+ }
28
+ .loop-zone-handle__line {
29
+ position: absolute;
30
+ top: 32px;
31
+ bottom: 0;
32
+ left: 50%;
33
+ transform: translateX(-50%);
34
+ width: 1px;
35
+ pointer-events: none;
36
+ border-left: 1px dashed transparent;
37
+ background: currentColor;
38
+ opacity: 0.5;
39
+ }
40
+ .loop-zone-handle__grip {
41
+ position: absolute;
42
+ top: 6px;
43
+ left: 50%;
44
+ transform: translateX(-50%);
45
+ pointer-events: auto;
46
+ cursor: ew-resize;
47
+ user-select: none;
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: center;
51
+ padding: 5px 7px;
52
+ border-radius: 5px;
53
+ transition: filter 0.12s, transform 0.1s;
54
+ }
55
+ .loop-zone-handle__grip:hover {
56
+ filter: brightness(1.2);
57
+ transform: translateX(-50%) scaleY(1.1);
58
+ }
59
+ .loop-zone-handle__grip:active {
60
+ transform: translateX(-50%) scale(0.94);
61
+ }
62
+ .loop-zone-handle__grip svg {
63
+ display: block;
64
+ flex-shrink: 0;
65
+ }