@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,12 @@
1
+ import { RequiredEditData } from './timeline';
2
+ /** Common component parameters */
3
+ export interface CommonProp extends RequiredEditData {
4
+ /** Scale count */
5
+ scaleCount: number;
6
+ /** Set scale count */
7
+ setScaleCount: (scaleCount: number) => void;
8
+ /** Cursor time */
9
+ cursorTime: number;
10
+ /** Current timeline width */
11
+ timelineWidth: number;
12
+ }
@@ -0,0 +1,28 @@
1
+ export declare const PREFIX = "timeline-editor";
2
+ /** Cursor time at start */
3
+ export declare const START_CURSOR_TIME = 0;
4
+ /** Default scale */
5
+ export declare const DEFAULT_SCALE = 1;
6
+ /** Default scale split count */
7
+ export declare const DEFAULT_SCALE_SPLIT_COUNT = 10;
8
+ /** Default scale display width */
9
+ export declare const DEFAULT_SCALE_WIDTH = 160;
10
+ /** Default scale start distance from left */
11
+ export declare const DEFAULT_START_LEFT = 20;
12
+ /** Default minimum movement in pixels */
13
+ export declare const DEFAULT_MOVE_GRID = 1;
14
+ /** Default adsorption distance in pixels */
15
+ export declare const DEFAULT_ADSORPTION_DISTANCE = 8;
16
+ /** Default action row height */
17
+ export declare const DEFAULT_ROW_HEIGHT = 32;
18
+ /** Minimum scale count */
19
+ export declare const MIN_SCALE_COUNT = 20;
20
+ /** Maximum scale count */
21
+ export declare const MAX_SCALE_COUNT: number;
22
+ /** Number of scale marks to add each time */
23
+ export declare const ADD_SCALE_COUNT = 5;
24
+ /** Error messages */
25
+ export declare const ERROR: {
26
+ START_TIME_LESS_THEN_ZERO: string;
27
+ END_TIME_LESS_THEN_START_TIME: string;
28
+ };
@@ -0,0 +1,342 @@
1
+ import { Emitter, EventTypes, ITimelineEngine, TimelineAction, TimelineRow, TimelineEffect } from '@keplar-404/timeline-engine';
2
+ import { default as React, ReactNode } from 'react';
3
+ import { OnScrollParams } from 'react-virtualized';
4
+ export interface EditData {
5
+ /**
6
+ * @description Timeline editing data
7
+ */
8
+ editorData: TimelineRow[];
9
+ /**
10
+ * @description Timeline action effect map
11
+ */
12
+ effects: Record<string, TimelineEffect>;
13
+ /**
14
+ * @description Scaling factor for individual scale marks (>0)
15
+ * @default 1
16
+ */
17
+ scale?: number;
18
+ /**
19
+ * @description Minimum number of scale marks (>=1)
20
+ * @default 20
21
+ */
22
+ minScaleCount?: number;
23
+ /**
24
+ * @description Maximum number of scale marks (>=minScaleCount)
25
+ * @default Infinity
26
+ */
27
+ maxScaleCount?: number;
28
+ /**
29
+ * @description Number of subdivision units for a single scale mark (integer >0)
30
+ * @default 10
31
+ */
32
+ scaleSplitCount?: number;
33
+ /**
34
+ * @description Display width of a single scale mark (>0, unit: px)
35
+ * @default 160
36
+ */
37
+ scaleWidth?: number;
38
+ /**
39
+ * @description Distance from the start of the scale to the left edge (>=0, unit: px)
40
+ * @default 20
41
+ */
42
+ startLeft?: number;
43
+ /**
44
+ * @description Default height for each editing row (>0, unit: px)
45
+ * @default 32
46
+ */
47
+ rowHeight?: number;
48
+ /**
49
+ * @description Whether to enable grid movement snapping
50
+ * @default false
51
+ */
52
+ gridSnap?: boolean;
53
+ /**
54
+ * @description Enable snapping to drag auxiliary lines
55
+ * @default false
56
+ */
57
+ dragLine?: boolean;
58
+ /**
59
+ * @description Whether to hide the cursor
60
+ * @default false
61
+ */
62
+ hideCursor?: boolean;
63
+ /**
64
+ * @description Prevent dragging in all action areas
65
+ * @default false
66
+ */
67
+ disableDrag?: boolean;
68
+ /**
69
+ * @description Prevent dragging of all rows
70
+ * @default false
71
+ */
72
+ enableRowDrag?: boolean;
73
+ /**
74
+ * @description Enable dragging action blocks between different rows
75
+ * @default false
76
+ */
77
+ enableCrossRowDrag?: boolean;
78
+ /**
79
+ * @description Show a ghost/preview element following the cursor during cross-row block drag.
80
+ * Set to `false` to disable the ghost entirely, or use `getGhostPreview` for a custom component.
81
+ * @default true
82
+ */
83
+ enableGhostPreview?: boolean;
84
+ /**
85
+ * @description Custom render function for the drag ghost/preview element shown while
86
+ * dragging a block across rows. When provided, replaces the default blue glowing box.
87
+ *
88
+ * The function receives the action being dragged and its source row, so you can
89
+ * render a fully custom preview that matches your block's actual appearance.
90
+ *
91
+ * @param params - The action being dragged and the row it originated from
92
+ * @returns A React node to render inside the ghost container
93
+ *
94
+ * @example
95
+ * ```tsx
96
+ * <Timeline
97
+ * enableCrossRowDrag
98
+ * getGhostPreview={({ action, row }) => (
99
+ * <div style={{ background: '#1a3a5c', border: '2px solid #3b82f6', height: '100%', borderRadius: 4, padding: '0 8px', display: 'flex', alignItems: 'center' }}>
100
+ * <span style={{ color: '#3b82f6', fontSize: 12 }}>{action.id}</span>
101
+ * </div>
102
+ * )}
103
+ * />
104
+ * ```
105
+ */
106
+ getGhostPreview?: (params: {
107
+ action: TimelineAction;
108
+ row: TimelineRow;
109
+ }) => ReactNode;
110
+ /**
111
+ * @description Timeline engine; uses the built-in engine if not provided
112
+ */
113
+ engine?: ITimelineEngine;
114
+ /**
115
+ * @description Custom action area rendering
116
+ */
117
+ getActionRender?: (action: TimelineAction, row: TimelineRow) => ReactNode;
118
+ /**
119
+ * @description Custom scale rendering
120
+ */
121
+ getScaleRender?: (scale: number) => ReactNode;
122
+ /**
123
+ * @description Callback when movement starts
124
+ */
125
+ onActionMoveStart?: (params: {
126
+ action: TimelineAction;
127
+ row: TimelineRow;
128
+ }) => void;
129
+ /**
130
+ * @description Movement callback (return false to prevent movement)
131
+ */
132
+ onActionMoving?: (params: {
133
+ action: TimelineAction;
134
+ row: TimelineRow;
135
+ start: number;
136
+ end: number;
137
+ }) => void | boolean;
138
+ /**
139
+ * @description Movement end callback (return false to prevent onChange from triggering)
140
+ */
141
+ onActionMoveEnd?: (params: {
142
+ action: TimelineAction;
143
+ row: TimelineRow;
144
+ start: number;
145
+ end: number;
146
+ }) => void;
147
+ /**
148
+ * @description Callback when resizing starts
149
+ */
150
+ onActionResizeStart?: (params: {
151
+ action: TimelineAction;
152
+ row: TimelineRow;
153
+ dir: 'right' | 'left';
154
+ }) => void;
155
+ /**
156
+ * @description Resizing callback (return false to prevent change)
157
+ */
158
+ onActionResizing?: (params: {
159
+ action: TimelineAction;
160
+ row: TimelineRow;
161
+ start: number;
162
+ end: number;
163
+ dir: 'right' | 'left';
164
+ }) => void | boolean;
165
+ /**
166
+ * @description Callback when resizing ends (return false to prevent onChange from triggering)
167
+ */
168
+ onActionResizeEnd?: (params: {
169
+ action: TimelineAction;
170
+ row: TimelineRow;
171
+ start: number;
172
+ end: number;
173
+ dir: 'right' | 'left';
174
+ }) => void;
175
+ /**
176
+ * @description Callback when a row is clicked
177
+ */
178
+ onClickRow?: (e: React.MouseEvent<HTMLElement, MouseEvent>, param: {
179
+ row: TimelineRow;
180
+ time: number;
181
+ }) => void;
182
+ /**
183
+ * @description Callback when an action is clicked
184
+ */
185
+ onClickAction?: (e: React.MouseEvent<HTMLElement, MouseEvent>, param: {
186
+ action: TimelineAction;
187
+ row: TimelineRow;
188
+ time: number;
189
+ }) => void;
190
+ /**
191
+ * @description Callback when an action is clicked (not executed when drag is triggered)
192
+ */
193
+ onClickActionOnly?: (e: React.MouseEvent<HTMLElement, MouseEvent>, param: {
194
+ action: TimelineAction;
195
+ row: TimelineRow;
196
+ time: number;
197
+ }) => void;
198
+ /**
199
+ * @description Callback when a row is double-clicked
200
+ */
201
+ onDoubleClickRow?: (e: React.MouseEvent<HTMLElement, MouseEvent>, param: {
202
+ row: TimelineRow;
203
+ time: number;
204
+ }) => void;
205
+ /**
206
+ * @description Callback when an action is double-clicked
207
+ */
208
+ onDoubleClickAction?: (e: React.MouseEvent<HTMLElement, MouseEvent>, param: {
209
+ action: TimelineAction;
210
+ row: TimelineRow;
211
+ time: number;
212
+ }) => void;
213
+ /**
214
+ * @description Callback when a row is right-clicked
215
+ */
216
+ onContextMenuRow?: (e: React.MouseEvent<HTMLElement, MouseEvent>, param: {
217
+ row: TimelineRow;
218
+ time: number;
219
+ }) => void;
220
+ /**
221
+ * @description Callback when an action is right-clicked
222
+ */
223
+ onContextMenuAction?: (e: React.MouseEvent<HTMLElement, MouseEvent>, param: {
224
+ action: TimelineAction;
225
+ row: TimelineRow;
226
+ time: number;
227
+ }) => void;
228
+ /**
229
+ * @description Get a list of action IDs for auxiliary lines, calculated at move/resize start; defaults to all except the current moving action
230
+ */
231
+ getAssistDragLineActionIds?: (params: {
232
+ action: TimelineAction;
233
+ editorData: TimelineRow[];
234
+ row: TimelineRow;
235
+ }) => string[];
236
+ /**
237
+ * @description Cursor start drag event
238
+ */
239
+ onCursorDragStart?: (time: number) => void;
240
+ /**
241
+ * @description Cursor end drag event
242
+ */
243
+ onCursorDragEnd?: (time: number) => void;
244
+ /**
245
+ * @description Cursor drag event
246
+ */
247
+ onCursorDrag?: (time: number) => void;
248
+ /**
249
+ * @description Click on time area event; return false to prevent setting time
250
+ */
251
+ onClickTimeArea?: (time: number, e: React.MouseEvent<HTMLDivElement, MouseEvent>) => boolean | undefined;
252
+ /**
253
+ * @description Row drag start callback
254
+ * @param params row is the data of the row being dragged
255
+ */
256
+ onRowDragStart?: (params: {
257
+ row: TimelineRow;
258
+ }) => void;
259
+ /**
260
+ * @description Row drag end callback
261
+ * @param params row is the data of the row being dragged; editorData is the new data arrangement after the row is dragged
262
+ * @returns
263
+ */
264
+ onRowDragEnd?: (params: {
265
+ row: TimelineRow;
266
+ editorData: TimelineRow[];
267
+ }) => void;
268
+ }
269
+ export interface TimelineState {
270
+ /** DOM node */
271
+ target: HTMLElement | null;
272
+ /** Execution listener */
273
+ listener: Emitter<EventTypes>;
274
+ /** Whether it is playing */
275
+ isPlaying: boolean;
276
+ /** Whether it is paused */
277
+ isPaused: boolean;
278
+ /** Set current playback time */
279
+ setTime: (time: number) => void;
280
+ /** Get current playback time */
281
+ getTime: () => number;
282
+ /** Set playback rate */
283
+ setPlayRate: (rate: number) => void;
284
+ /** Get playback rate */
285
+ getPlayRate: () => number;
286
+ /** Re-render current time */
287
+ reRender: () => void;
288
+ /** Play */
289
+ play: (param: {
290
+ /** Default run from start to end, priority greater than autoEnd */
291
+ toTime?: number;
292
+ /** Whether it is automatically end after playback */
293
+ autoEnd?: boolean;
294
+ /** List of actionIds to run; runs all by default if not provided */
295
+ runActionIds?: string[];
296
+ }) => boolean;
297
+ /** Pause */
298
+ pause: () => void;
299
+ /** Set scroll left */
300
+ setScrollLeft: (val: number) => void;
301
+ /** Set scroll top */
302
+ setScrollTop: (val: number) => void;
303
+ }
304
+ /**
305
+ * Animation editor parameters
306
+ * @export
307
+ * @interface TimelineProp
308
+ */
309
+ export interface TimelineEditor extends EditData {
310
+ /**
311
+ * @description Scroll distance of the editing area from the top (please use ref.setScrollTop instead)
312
+ * @deprecated
313
+ */
314
+ scrollTop?: number;
315
+ /**
316
+ * @description Scroll callback for the editing area (used to control synchronization with scroll of editing rows)
317
+ */
318
+ onScroll?: (params: OnScrollParams) => void;
319
+ /**
320
+ * @description Whether to enable automatic scrolling during dragging
321
+ * @default false
322
+ */
323
+ autoScroll?: boolean;
324
+ /**
325
+ * @description Custom timeline style
326
+ */
327
+ style?: React.CSSProperties;
328
+ /**
329
+ * @description Whether to re-render automatically (update tick when data changes or cursor time changes)
330
+ * @default true
331
+ */
332
+ autoReRender?: boolean;
333
+ /**
334
+ * @description Data change callback, triggered after the end of an action operation changes data (returning false will prevent automatic engine synchronization, used to reduce performance overhead)
335
+ */
336
+ onChange?: (editorData: TimelineRow[]) => void | boolean;
337
+ }
338
+ export type RequiredPick<T, K extends keyof T> = T & {
339
+ [P in K]-?: T[P];
340
+ };
341
+ export type RequiredEditData = RequiredPick<EditData, 'editorData' | 'effects' | 'scale' | 'scaleSplitCount' | 'scaleWidth' | 'startLeft' | 'minScaleCount' | 'maxScaleCount' | 'rowHeight'>;
342
+ export type RequiredTimelineEditor = RequiredPick<TimelineEditor, 'scrollTop'> & RequiredEditData;
@@ -0,0 +1 @@
1
+ .timeline-editor-cursor{cursor:ew-resize;position:absolute;top:32px;height:calc(100% - 32px);box-sizing:border-box;border-left:1px solid #5297FF;border-right:1px solid #5297FF;transform:translate(-25%) scaleX(.5)}.timeline-editor-cursor-top{position:absolute;top:0;left:50%;transform:translate(-50%) scaleX(2);margin:auto}.timeline-editor-cursor-area{width:16px;height:100%;cursor:ew-resize;position:absolute;top:0;left:50%;transform:translate(-50%)}.timeline-editor-drag-line-container{position:absolute;height:100%;top:0;left:0}.timeline-editor-drag-line{width:0;position:absolute;top:0;height:99%;border-left:1px dashed rgba(82,151,255,.6)}.timeline-editor:hover .timeline-editor-edit-area .ReactVirtualized__Grid::-webkit-scrollbar{height:4px}.timeline-editor-edit-area{flex:1 1 auto;margin-top:10px;overflow:hidden;position:relative}.timeline-editor-edit-area .ReactVirtualized__Grid{outline:none!important;overflow:overlay!important}.timeline-editor-edit-area .ReactVirtualized__Grid::-webkit-scrollbar{width:0;height:0}.timeline-editor-edit-area .ReactVirtualized__Grid::-webkit-scrollbar-track{background-color:transparent!important}.timeline-editor-edit-area .ReactVirtualized__Grid::-webkit-scrollbar-thumb{background:#313132;border-radius:16px}.timeline-editor-action{position:absolute;left:0;top:0;background-color:#2f3134;cursor:default;transition:box-shadow .15s ease}.timeline-editor-action.action-cross-row-dragging{box-shadow:0 0 0 2px #63b3edcc,0 0 16px #63b3ed99,0 0 32px #63b3ed4d;opacity:.75;z-index:10}.timeline-editor-action.action-movable{cursor:move}.timeline-editor-action .timeline-editor-action-left-stretch,.timeline-editor-action .timeline-editor-action-right-stretch{position:absolute;top:0;width:10px;border-radius:4px;height:100%;overflow:hidden}.timeline-editor-action .timeline-editor-action-left-stretch:after,.timeline-editor-action .timeline-editor-action-right-stretch:after{position:absolute;top:0;bottom:0;margin:auto;border-radius:4px;border-top:28px solid transparent;border-bottom:28px solid transparent}.timeline-editor-action .timeline-editor-action-left-stretch{left:0;cursor:w-resize}.timeline-editor-action .timeline-editor-action-left-stretch:after{left:0;content:"";border-left:7px solid rgba(255,255,255,.1);border-right:7px solid transparent}.timeline-editor-action .timeline-editor-action-right-stretch{right:0;cursor:e-resize}.timeline-editor-action .timeline-editor-action-right-stretch:after{right:0;content:"";border-right:7px solid rgba(255,255,255,.1);border-left:7px solid transparent}.timeline-editor-edit-row-dragging{opacity:.5}.timeline-editor-edit-row{background-repeat:no-repeat,repeat;background-image:linear-gradient(#191b1d,#191b1d),linear-gradient(90deg,rgba(255,255,255,.08) 1px,transparent 0);display:flex;flex-direction:row;box-sizing:border-box;position:relative;transition:opacity .2s ease,transform .2s ease}.timeline-editor-edit-row-drag-handle{position:absolute;left:4px;top:50%;transform:translateY(-50%);width:16px;height:16px;cursor:grab;display:flex;align-items:center;justify-content:center;color:#666;font-size:12px;-webkit-user-select:none;user-select:none;z-index:10;opacity:.6;transition:opacity .2s ease}.timeline-editor-edit-row-drag-handle:hover{opacity:1;color:#999}.timeline-editor-edit-row-drag-handle:active{cursor:grabbing}.timeline-editor-edit-row-dragged{opacity:.5;transform:scale(.98);pointer-events:none;z-index:1000;position:relative}.timeline-editor-edit-row-dragging{cursor:grabbing}.timeline-editor-edit-row-placeholder{background:#4a90e21a;border:2px dashed #4a90e2;height:4px;min-height:4px;margin:2px 0;opacity:.8}.timeline-editor-edit-row-placeholder .timeline-editor-edit-row-drag-handle,.timeline-editor-edit-row-placeholder .timeline-editor-edit-action{display:none}.timeline-editor-edit-row:before{content:"";position:absolute;left:0;right:0;height:2px;background:#4a90e2;z-index:100;opacity:0;transition:opacity .2s ease}.timeline-editor-edit-row[data-insert-position=top]:before{top:-1px;opacity:1}.timeline-editor-edit-row[data-insert-position=bottom]:before{bottom:-1px;opacity:1}.timeline-editor-time-area{position:relative;height:32px;flex:0 0 auto}.timeline-editor-time-area .ReactVirtualized__Grid{outline:none}.timeline-editor-time-area .ReactVirtualized__Grid::-webkit-scrollbar{display:none}.timeline-editor-time-area-interact{position:absolute;cursor:pointer;left:0;top:0}.timeline-editor-time-unit{border-right:1px solid rgba(255,255,255,.2);position:relative;box-sizing:content-box;height:4px!important;bottom:0!important;top:auto!important}.timeline-editor-time-unit-big{height:8px!important}.timeline-editor-time-unit-scale{color:#fff9;position:absolute;right:0;top:0;transform:translate(50%,-100%)}.timeline-editor{height:600px;width:600px;min-height:32px;position:relative;font-size:12px;font-family:PingFang SC;background-color:#191b1d;display:flex;flex-direction:column;overflow:hidden}.cut-overlay{position:absolute;inset:0;z-index:20;pointer-events:auto;-webkit-user-select:none;user-select:none}.cut-block-clip{position:absolute;pointer-events:none;border-radius:3px;box-sizing:border-box;overflow:visible}.cut-blade{position:absolute;top:0;width:2px;height:100%;transform:translate(-50%);border-radius:1px;pointer-events:none;z-index:2;animation:cut-blade-in .1s ease-out}@keyframes cut-blade-in{0%{opacity:0;transform:translate(-50%) scaleY(.3)}to{opacity:1;transform:translate(-50%) scaleY(1)}}.cut-pill{position:absolute;bottom:calc(100% + 5px);transform:translate(-50%);font-size:10px;font-weight:700;font-family:SF Mono,Cascadia Code,Fira Code,monospace;letter-spacing:.04em;padding:2px 7px;border-radius:4px;white-space:nowrap;pointer-events:none;animation:cut-pill-in .1s ease-out;z-index:25}@keyframes cut-pill-in{0%{opacity:0;transform:translate(-50%) translateY(4px)}to{opacity:1;transform:translate(-50%) translateY(0)}}.loop-zone-overlay{position:absolute;top:0;left:0;right:0;height:100%;pointer-events:none;z-index:4;overflow:visible}.loop-zone-band{position:absolute;top:0;height:100%;pointer-events:none;border-left:1px solid transparent;border-right:1px solid transparent;border-top:2px solid transparent}.loop-zone-handle{position:absolute;top:0;height:100%;transform:translate(-50%);pointer-events:none;-webkit-user-select:none;user-select:none}.loop-zone-handle__line{position:absolute;top:32px;bottom:0;left:50%;transform:translate(-50%);width:1px;pointer-events:none;border-left:1px dashed transparent;background:currentColor;opacity:.5}.loop-zone-handle__grip{position:absolute;top:6px;left:50%;transform:translate(-50%);pointer-events:auto;cursor:ew-resize;-webkit-user-select:none;user-select:none;display:flex;align-items:center;justify-content:center;padding:5px 7px;border-radius:5px;transition:filter .12s,transform .1s}.loop-zone-handle__grip:hover{filter:brightness(1.2);transform:translate(-50%) scaleY(1.1)}.loop-zone-handle__grip:active{transform:translate(-50%) scale(.94)}.loop-zone-handle__grip svg{display:block;flex-shrink:0}.timeline-transport-bar{display:flex;align-items:center;justify-content:space-between;padding:0 16px;height:48px;background:#0a0a14d9;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-bottom:1px solid rgba(255,255,255,.06);gap:16px;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,Inter,Segoe UI,sans-serif}.timeline-transport-controls{display:flex;align-items:center;gap:4px}.timeline-transport-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:6px;border:1px solid rgba(255,255,255,.07);background:#ffffff08;color:#64748b;cursor:pointer;transition:background .12s,color .12s,border-color .12s}.timeline-transport-btn:hover{background:#ffffff14;color:#94a3b8;border-color:#ffffff1f}.timeline-transport-btn--primary{color:#c4c9d4}.timeline-transport-btn--primary:hover{background:#ffffff1a;color:#e2e8f0}.timeline-transport-btn--stop:hover{background:#ef44441f;border-color:#ef44444d;color:#ef4444}.timeline-transport-btn--loop{font-size:14px;line-height:1;width:auto;padding:0 6px;color:#4b5563}.timeline-transport-btn--loop:hover{background:#10b9811a;border-color:#10b9814d;color:#10b981}.timeline-transport-btn--loop-active{background:#10b9812e!important;border-color:#10b98180!important;color:#10b981!important;box-shadow:0 0 10px #10b98140!important}.timeline-transport-divider{width:1px;height:20px;background:#ffffff14;margin:0 4px;flex-shrink:0}.timeline-transport-loop-inputs{display:flex;align-items:center;gap:4px;margin-left:4px}.timeline-transport-loop-input{width:52px;background:#00000059;border:1px solid rgba(16,185,129,.3);border-radius:5px;color:#10b981;font-size:12px;font-family:SF Mono,Cascadia Code,Fira Code,monospace;font-weight:600;padding:2px 6px;text-align:center;outline:none;transition:border-color .12s}.timeline-transport-loop-input:focus{border-color:#10b981b3;box-shadow:0 0 6px #10b98133}.timeline-transport-loop-input::-webkit-inner-spin-button,.timeline-transport-loop-input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.timeline-transport-loop-arrow{font-size:11px;color:#334155}.timeline-transport-loop-unit{font-size:10px;color:#334155;font-family:SF Mono,Cascadia Code,monospace}.timeline-transport-time{display:flex;flex-direction:column;align-items:center;gap:1px;min-width:100px}.timeline-transport-time-value{font-size:22px;font-weight:700;font-family:SF Mono,Cascadia Code,Fira Code,monospace;color:#e2e8f0;letter-spacing:.05em;line-height:1}.timeline-transport-time-label{font-size:9px;font-weight:600;letter-spacing:.15em;color:#475569;text-transform:uppercase}.timeline-transport-rate{display:flex;align-items:center;gap:8px}.timeline-transport-rate-label{font-size:9px;font-weight:600;letter-spacing:.15em;color:#475569;text-transform:uppercase}.timeline-transport-rate-buttons{display:flex;gap:3px}.timeline-transport-rate-btn{padding:3px 8px;border-radius:5px;border:1px solid rgba(255,255,255,.07);background:#ffffff08;color:#475569;font-size:11px;font-weight:600;font-family:SF Mono,Cascadia Code,monospace;cursor:pointer;transition:all .12s}.timeline-transport-rate-btn:hover{background:#ffffff12;color:#94a3b8}.timeline-transport-rate-btn--active{background:#3b82f626;border-color:#3b82f666;color:#3b82f6;box-shadow:0 0 6px #3b82f626}
@@ -0,0 +1,2 @@
1
+ import { RequiredTimelineEditor, TimelineEditor } from '../interface/timeline';
2
+ export declare function checkProps(props: TimelineEditor): RequiredTimelineEditor;
@@ -0,0 +1 @@
1
+ export declare function prefix(...classNames: string[]): string;
@@ -0,0 +1,58 @@
1
+ import { TimelineAction, TimelineRow } from '@keplar-404/timeline-engine';
2
+ /** Time to pixel */
3
+ export declare function parserTimeToPixel(data: number, param: {
4
+ startLeft: number;
5
+ scale: number;
6
+ scaleWidth: number;
7
+ }): number;
8
+ /** Pixel to time */
9
+ export declare function parserPixelToTime(data: number, param: {
10
+ startLeft: number;
11
+ scale: number;
12
+ scaleWidth: number;
13
+ }): number;
14
+ /** Position + Width to Start + End */
15
+ export declare function parserTransformToTime(data: {
16
+ left: number;
17
+ width: number;
18
+ }, param: {
19
+ startLeft: number;
20
+ scale: number;
21
+ scaleWidth: number;
22
+ }): {
23
+ start: number;
24
+ end: number;
25
+ };
26
+ /** Start + End to Position + Width */
27
+ export declare function parserTimeToTransform(data: {
28
+ start: number;
29
+ end: number;
30
+ }, param: {
31
+ startLeft: number;
32
+ scale: number;
33
+ scaleWidth: number;
34
+ }): {
35
+ left: number;
36
+ width: number;
37
+ };
38
+ /** Get number of scale marks based on data */
39
+ export declare function getScaleCountByRows(data: TimelineRow[], param: {
40
+ scale: number;
41
+ }): number;
42
+ /** Get current number of scale marks based on time */
43
+ export declare function getScaleCountByPixel(data: number, param: {
44
+ startLeft: number;
45
+ scaleWidth: number;
46
+ scaleCount: number;
47
+ }): number;
48
+ /** Get collection of positions for all action times */
49
+ export declare function parserActionsToPositions(actions: TimelineAction[], param: {
50
+ startLeft: number;
51
+ scale: number;
52
+ scaleWidth: number;
53
+ }): number[];
54
+ /**
55
+ * Split an action in a row at a given time.
56
+ * Automatically updates start/end times and creates a new adjacent action.
57
+ */
58
+ export declare function splitActionInRow(data: TimelineRow[], rowId: string, actionId: string, cutTime: number): TimelineRow[];
@@ -0,0 +1,132 @@
1
+ export declare enum LogLevel {
2
+ VERBOSE = 0,
3
+ LOG = 1,
4
+ INFO = 2,
5
+ WARN = 3,
6
+ ERROR = 4,
7
+ FATAL = 5,
8
+ SILENT = Infinity
9
+ }
10
+ export declare const LogLevels: {
11
+ VERBOSE: LogLevel;
12
+ LOG: LogLevel;
13
+ INFO: LogLevel;
14
+ WARN: LogLevel;
15
+ ERROR: LogLevel;
16
+ SILENT: LogLevel;
17
+ };
18
+ export default class ConsoleLogger {
19
+ static readonly instances: ConsoleLogger[];
20
+ static level: LogLevel;
21
+ static Levels: {
22
+ VERBOSE: LogLevel;
23
+ LOG: LogLevel;
24
+ INFO: LogLevel;
25
+ WARN: LogLevel;
26
+ ERROR: LogLevel;
27
+ SILENT: LogLevel;
28
+ };
29
+ static noColor: boolean;
30
+ Levels: {
31
+ VERBOSE: LogLevel;
32
+ LOG: LogLevel;
33
+ INFO: LogLevel;
34
+ WARN: LogLevel;
35
+ ERROR: LogLevel;
36
+ SILENT: LogLevel;
37
+ };
38
+ level: LogLevel;
39
+ prefix: string;
40
+ enabled: boolean;
41
+ debugColor: string;
42
+ logColor: string;
43
+ infoColor: string;
44
+ warnColor: string;
45
+ errorColor: string;
46
+ fatalColor: string;
47
+ /**
48
+ * ConsoleLogger
49
+ * @param {string} prefix Logger prefix
50
+ * @return {ConsoleLogger}
51
+ */
52
+ constructor(prefix: string);
53
+ static setLevel(level: LogLevel): void;
54
+ static enable(level?: LogLevel): void;
55
+ static disable(): void;
56
+ /**
57
+ * set logger prefix
58
+ * @param prefix
59
+ */
60
+ setPrefix(prefix: string): void;
61
+ /**
62
+ * enable logger with optional log level
63
+ * @param level
64
+ */
65
+ enable(level?: LogLevel): void;
66
+ /**
67
+ * disable logger
68
+ */
69
+ disable(): void;
70
+ /**
71
+ * Set log level
72
+ * @param {LogLevel} level
73
+ * @return {void}
74
+ */
75
+ setLevel(level: LogLevel): void;
76
+ /**
77
+ * trace
78
+ * @param title
79
+ * @param args
80
+ */
81
+ trace(title: string, ...args: any[]): void;
82
+ /**
83
+ * debug
84
+ * @param title
85
+ * @param args
86
+ */
87
+ debug(title: string, ...args: any[]): void;
88
+ /**
89
+ * log
90
+ * @param title
91
+ * @param args
92
+ */
93
+ log(title: string, ...args: any[]): void;
94
+ /**
95
+ * info
96
+ * @param title
97
+ * @param args
98
+ */
99
+ info(title: string, ...args: any[]): void;
100
+ /**
101
+ * warn
102
+ * @param title
103
+ * @param args
104
+ */
105
+ warn(title: string, ...args: any[]): void;
106
+ /**
107
+ * error
108
+ * @param title
109
+ * @param args
110
+ */
111
+ error(title: string, ...args: any[]): void;
112
+ /**
113
+ * fatal error
114
+ * @param title
115
+ * @param args
116
+ */
117
+ fatal(title: string, ...args: any[]): void;
118
+ /**
119
+ * start a group with label
120
+ * @param label
121
+ */
122
+ group(...label: any[]): void;
123
+ /**
124
+ * end a group
125
+ */
126
+ groupEnd(): void;
127
+ /**
128
+ * collapse log group
129
+ * @param label
130
+ */
131
+ groupCollapsed(...label: any[]): void;
132
+ }
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@keplar-404/react-timeline-editor",
3
+ "version": "1.0.6",
4
+ "author": "keplar-404",
5
+ "license": "MIT",
6
+ "keywords": [
7
+ "timeline",
8
+ "animation",
9
+ "editor",
10
+ "react",
11
+ "typescript"
12
+ ],
13
+ "bugs": {
14
+ "url": "https://github.com/keplar-404/react-timeline-editor/issues"
15
+ },
16
+ "homepage": "https://github.com/keplar-404/react-timeline-editor#readme",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/keplar-404/react-timeline-editor.git"
20
+ },
21
+ "scripts": {
22
+ "build": "bun run clean && vite build",
23
+ "clean": "rm -rf dist"
24
+ },
25
+ "files": [
26
+ "src",
27
+ "dist"
28
+ ],
29
+ "main": "src/index.tsx",
30
+ "module": "src/index.tsx",
31
+ "typings": "src/index.tsx",
32
+ "peerDependencies": {
33
+ "react": ">=18.0.0",
34
+ "react-dom": ">=18.0.0"
35
+ },
36
+ "dependencies": {
37
+ "@interactjs/types": "^1.10.11",
38
+ "@keplar-404/timeline-engine": "workspace:*",
39
+ "@types/react-virtualized": "^9.21.14",
40
+ "framework-utils": "^1.1.0",
41
+ "interactjs": "^1.10.11",
42
+ "react-virtualized": "^9.22.3"
43
+ },
44
+ "devDependencies": {
45
+ "@types/lodash": "^4.14.177",
46
+ "@types/react": "^18.2.0",
47
+ "@types/react-dom": "^18.2.0",
48
+ "@umijs/test": "^3.0.5",
49
+ "@vitejs/plugin-react": "^4.2.0",
50
+ "@vitejs/plugin-react-swc": "^3.5.0",
51
+ "lint-staged": "^10.0.7",
52
+ "lodash": "^4.17.21",
53
+ "prettier": "^2.2.1",
54
+ "react": "^18.2.0",
55
+ "react-dom": "^18.2.0",
56
+ "vite": "^7.0.0",
57
+ "vite-plugin-dts": "^4.5.4",
58
+ "yorkie": "^2.0.0"
59
+ },
60
+ "conditions": {
61
+ "USE_SRC": [
62
+ null,
63
+ {
64
+ "main": "dist/index.es.js",
65
+ "module": "dist/index.es.js",
66
+ "typings": "dist/index.d.ts"
67
+ }
68
+ ]
69
+ }
70
+ }
@@ -0,0 +1 @@
1
+ // TODO: default control components (currently customized by users as needed)