Эх сурвалжийг харах

Breaking changes: added keyframes groups styling. Strict TS mode is enabled. See changelog.

Ievgen Naida 2 жил өмнө
parent
commit
d986f5d7a3
100 өөрчлөгдсөн 4432 нэмэгдсэн , 1365 устгасан
  1. 7 0
      .markdownlint.json
  2. 76 0
      CHANGELOG.md
  3. 12 37
      README.md
  4. 101 48
      index.html
  5. 9 0
      lib/README.md
  6. 16 12
      lib/animation-timeline.d.ts
  7. 686 326
      lib/animation-timeline.js
  8. 0 0
      lib/animation-timeline.js.map
  9. 0 0
      lib/animation-timeline.min.js
  10. 7 3
      lib/enums/timelineElementType.d.ts
  11. 6 0
      lib/enums/timelineEventSource.d.ts
  12. 3 0
      lib/enums/timelineEvents.d.ts
  13. 2 2
      lib/enums/timelineInteractionMode.d.ts
  14. 9 0
      lib/enums/timelineSelectionEventSource.d.ts
  15. 11 0
      lib/model/timelineGroup.d.ts
  16. 12 0
      lib/model/timelineKeyframe.d.ts
  17. 4 0
      lib/model/timelineModel.d.ts
  18. 10 0
      lib/model/timelineRanged.d.ts
  19. 8 0
      lib/model/timelineRow.d.ts
  20. 28 0
      lib/models/timelineGroup.d.ts
  21. 28 0
      lib/models/timelineKeyframe.d.ts
  22. 4 0
      lib/models/timelineModel.d.ts
  23. 10 0
      lib/models/timelineRanged.d.ts
  24. 13 0
      lib/models/timelineRow.d.ts
  25. 2 0
      lib/settings/defaults.d.ts
  26. 3 0
      lib/settings/defaults/defaultGroupStyle.d.ts
  27. 2 0
      lib/settings/defaults/defaultTimelineConsts.d.ts
  28. 2 0
      lib/settings/defaults/defaultTimelineKeyframeStyle.d.ts
  29. 2 0
      lib/settings/defaults/defaultTimelineOptions.d.ts
  30. 2 0
      lib/settings/defaults/defaultTimelineRowStyle.d.ts
  31. 2 0
      lib/settings/defaults/defaultTimelineStyle.d.ts
  32. 16 13
      lib/settings/styles/TimelineRowStyle.d.ts
  33. 26 0
      lib/settings/styles/timelineCapStyle.d.ts
  34. 32 0
      lib/settings/styles/timelineGroupStyle.d.ts
  35. 18 4
      lib/settings/styles/timelineKeyframeStyle.d.ts
  36. 24 9
      lib/settings/styles/timelineStyle.d.ts
  37. 16 0
      lib/settings/timelineConsts.d.ts
  38. 16 13
      lib/settings/timelineOptions.d.ts
  39. 81 0
      lib/tests/settingsTests.test.js
  40. 670 0
      lib/tests/styleTests.test.js
  41. 866 0
      lib/tests/timelineTests.test.js
  42. 199 128
      lib/timeline.d.ts
  43. 21 5
      lib/timelineEventsEmitter.d.ts
  44. 11 0
      lib/timelineGroup.d.ts
  45. 5 4
      lib/timelineKeyframe.d.ts
  46. 1 1
      lib/timelineModel.d.ts
  47. 0 8
      lib/timelineRanged.d.ts
  48. 4 2
      lib/timelineRow.d.ts
  49. 5 4
      lib/utils/TimelineElement.d.ts
  50. 1 1
      lib/utils/TimelineElementDragState.d.ts
  51. 3 0
      lib/utils/events/timelineBaseEvent.d.ts
  52. 11 18
      lib/utils/events/timelineClickEvent.d.ts
  53. 10 21
      lib/utils/events/timelineDragEvent.d.ts
  54. 15 5
      lib/utils/events/timelineSelectedEvent.d.ts
  55. 5 2
      lib/utils/events/timelineTimeChangedEvent.d.ts
  56. 1 1
      lib/utils/timelineCalculated.d.ts
  57. 2 1
      lib/utils/timelineCutBoundsRectResults.d.ts
  58. 13 3
      lib/utils/timelineDraggableData.d.ts
  59. 4 1
      lib/utils/timelineModelCalcResults.d.ts
  60. 7 4
      lib/utils/timelineMouseData.d.ts
  61. 22 0
      lib/utils/timelinePoint.d.ts
  62. 7 0
      lib/utils/timelineSelectable.d.ts
  63. 3 3
      lib/utils/timelineSelectionResults.d.ts
  64. 32 28
      lib/utils/timelineStyleUtils.d.ts
  65. 23 6
      lib/utils/timelineUtils.d.ts
  66. 2 2
      lib/utils/timelineValues.d.ts
  67. 24 0
      lib/viewModels/timelineGroupViewModel.d.ts
  68. 26 0
      lib/viewModels/timelineKeyframeViewModel.d.ts
  69. 31 0
      lib/viewModels/timelineRowViewModel.d.ts
  70. 18 0
      lib/viewModels/timelineViewModel.d.ts
  71. 356 259
      package-lock.json
  72. 17 17
      package.json
  73. 17 12
      src/animation-timeline.ts
  74. 6 2
      src/enums/timelineElementType.ts
  75. 6 0
      src/enums/timelineEventSource.ts
  76. 3 0
      src/enums/timelineEvents.ts
  77. 2 2
      src/enums/timelineInteractionMode.ts
  78. 9 0
      src/enums/timelineSelectionEventSource.ts
  79. 28 0
      src/models/timelineGroup.ts
  80. 30 0
      src/models/timelineKeyframe.ts
  81. 1 1
      src/models/timelineModel.ts
  82. 10 0
      src/models/timelineRanged.ts
  83. 14 0
      src/models/timelineRow.ts
  84. 11 0
      src/settings/defaults/defaultGroupStyle.ts
  85. 44 0
      src/settings/defaults/defaultTimelineConsts.ts
  86. 19 0
      src/settings/defaults/defaultTimelineKeyframeStyle.ts
  87. 26 83
      src/settings/defaults/defaultTimelineOptions.ts
  88. 21 0
      src/settings/defaults/defaultTimelineRowStyle.ts
  89. 22 0
      src/settings/defaults/defaultTimelineStyle.ts
  90. 27 0
      src/settings/styles/timelineCapStyle.ts
  91. 33 0
      src/settings/styles/timelineGroupStyle.ts
  92. 18 4
      src/settings/styles/timelineKeyframeStyle.ts
  93. 17 13
      src/settings/styles/timelineRowStyle.ts
  94. 24 9
      src/settings/styles/timelineStyle.ts
  95. 17 0
      src/settings/timelineConsts.ts
  96. 17 13
      src/settings/timelineOptions.ts
  97. 261 193
      src/timeline.ts
  98. 28 10
      src/timelineEventsEmitter.ts
  99. 0 13
      src/timelineKeyframe.ts
  100. 0 19
      src/timelineRanged.ts

+ 7 - 0
.markdownlint.json

@@ -0,0 +1,7 @@
+{
+    "default": true,
+    "MD013": false,
+    "MD024": {
+        "allow_different_nesting": true
+    }
+}

+ 76 - 0
CHANGELOG.md

@@ -0,0 +1,76 @@
+# animation-timeline-control Changelog
+
+## Changes
+
+## [2.3.0] - 11.06.2022 (Breakings changes)
+
+### Added
+
+- Allow to style groups/connection of the keyframes separately.
+(see live demo - [Live demo](https://ievgennaida.github.io/animation-timeline-control/))
+
+### Changed
+
+- Breaking change! Style names are aligned with the HTML namings.
+- Breaking change! Events are sending objects with the change metadata.
+- Breaking change! timelineInteractive is renamed as timelineDraggable
+- Breaking change! keyframe styles are moved to the 'style' property for each keyframe.
+- Internal defaults.ts consts are moved to the default folder into the separate files.
+- Dev packages are updated.
+- timelinePoint -> timelineValues
+- TimelineClickEvent-> added point and prevPoint
+- TimelineDragEvent-> added point and prevPoint
+- Function getScrollLeft/setScrollLeft is changed to the property scrollLeft
+- Function getScrollTop/setScrollTop is changed to the property scrollTop
+- scrollLeft() -> scrollToRightBounds()
+- Renamed private function '_height' as '_canvasClientHeight'
+- Renamed private function '_width' as '_canvasClientWidth'
+- removed getMin and getMax for the ranged properties favor of min, max property. (In a case of calculated values getters can be used).
+- mergeOptions are moved to TimelineUtils
+- Strict TypeScript mode is enabled.
+- Refactoring of the event arguments.
+- models are moved from root src to src\models folders.
+
+## [2.2.3]
+
+### Added
+
+- Added scrollFinished event.
+TODO: group styles, refactoring of the styling system.
+
+### Fixed
+
+- Fixed Dispose method is not removing all scroll container event handlers.
+- Fixed demo nonInteractivePan.
+- Fixed timeline player demo.
+- Fixed rectangular keyframes mouse over detection.
+- Fixed cloning of the HTML element when options are set.
+
+## [2.2.2]
+
+### Added
+
+- Added new option timelineInteractive = true/false to control possibility for user to move timeline position.
+- Added 'nonInteractivePan' interaction mode that is allowing only to pan and change position of the timeline without changing the keyframes position.
+- Added 'none' interaction mode where no interactions are allowed.
+- Added 'play' demo to the index.html
+
+### Changed
+
+- Private property _findDraggable is renamed to_findDraggableElement
+- Options are appended to the current active options, not to default.
+- Fixed order of the build (definitions and tests only after the definitions.)
+- updated build packages.
+
+## [2.2.1]
+
+ TypeScript fixes, updated build packages.
+
+## > [2.0]
+
+- Migrated to TypeScript, Webpack, Babel.
+- API is refined.
+
+## < [2.0]
+
+Vanilla js implementation.

+ 12 - 37
README.md

@@ -194,7 +194,7 @@ Main options:
 | --------------- | ------------------------------------------------------------------------------------------------------------------------- |
 | groupsDraggable         |  keyframes group is draggable. Default: true |
 | keyframesDraggable         | keyframes group is draggable. Default: true                                                      |
-| timelineInteractive     | Timeline can be dragged or position can be changed by user interaction. Default True |
+| timelineDraggable     | Timeline can be dragged or position can be changed by user interaction. Default True |
 
 ### Keyboard shortcuts
 
@@ -216,9 +216,9 @@ Selection - allow to select one or group of the keyframes.
 
 - **selection** - Keyframe selection tool selecting single or group of keyframes.
 - **pan** - Pan tool with the possibility to select keyframes.
-- **nonInteractivePan** - Allow only pan without any keyframes interaction. Timeline still can be moved and controlled by option  'timelineInteractive'.
+- **nonInteractivePan** - Allow only pan without any keyframes interaction. Timeline still can be moved and controlled by option  'timelineDraggable'.
 - **zoom** - zoom tool
-- **none** -  No iteraction, except moving a timeline. Timeline still can be moved and controlled by option 'timelineInteractive'.
+- **none** -  No iteraction, except moving a timeline. Timeline still can be moved and controlled by option 'timelineDraggable'.
 
 Example:
 
@@ -258,48 +258,23 @@ timeline._formatUnitsText = (val)=> { return val + ' ms'; };
 
 ### Styling
 
-Timeline is rendered as a canvas, so has no HTML elements for the css styling.
-Styles can be applied on a few levels:
+The timeline component is rendered as a canvas and has no HTML elements for CSS styling.
+Styles are applied as a part of the keyframes model and can be applied in a cascade order from bottom to the top:
 
 - Global control setting (See TypeScript interface  TimelineStyle)
 - row styles (See TypeScript interface TimelineRowStyle)
+- Keyframe group styles with the underlying keyframe styles. (TimelineGroupStyle)
 - keyframe styles (See TypeScript interface TimelineKeyframeStyle)
 
-Styles are applied by a global settings and can be overridden by a row or keyframe style.
+Separate global styles for the timeline indicator are used:
 
-## Changes
-
-## 2.2.3
-
-- Small fixes.
-- Dispose method will remove also scroll container event handlers.
-- Fixed demo nonInteractivePan.
-- Fixed timeline player demo.
-- Added scrollFinished event.
-
-## 2.2.2
-
-- Added new option timelineInteractive = true/false to control possibility for user to move timeline position.
-- Added 'nonInteractivePan' interaction mode that is allowing only to pan and change position of the timeline without changing the keyframes position.
-- Added 'none' interaction mode where no interactions are allowed.
-- Added 'play' demo to the index.html
-- Private property _findDraggable is renamed to_filterDraggableElements
-- Options are appended to the current active options, not to default.
-- Fixed order of the build (definitions and tests only after the definitions.)
-- updated build packages.
+- TimelineOptions - global component properties and styles.
+  - TimelineStyle timeline indicator styles
+    - TimelineCapStyle - cap of the timeline style.
 
-## 2.2.1
-
- TypeScript fixes, updated build packages.
-
-## > 2.0
-
-- Migrated to TypeScript, Webpack, Babel.
-- API is refined.
-
-## < 2.0
+## Changes
 
-Vanilla js implementation.
+See Changelog [here](./CHANGELOG.md)
 
 ## Development
 

+ 101 - 48
index.html

@@ -184,14 +184,18 @@
         title="Timeline zoom mode. Also ctrl + scroll can be used." onclick="zoomMode()">search</button>
       <button class="button mat-icon material-icons mat-icon-no-color" title="Only view mode."
         onclick="noneMode()">visibility</button>
-      <div style="width: 1px; background:gray; height: 100%;"></div>
+      <div style="width: 1px; background: gray; height: 100%"></div>
       <button class="button mat-icon material-icons mat-icon-no-color"
         title="Use external player to play\stop the timeline. For the demo simple setInterval is used."
-        onclick="onPlayClick()">play_arrow</button>
+        onclick="onPlayClick()">
+        play_arrow
+      </button>
       <button class="button mat-icon material-icons mat-icon-no-color"
         title="Use external player to play\stop the timeline. For the demo simple setInterval is used."
-        onclick="onPauseClick()">pause</button>
-      <div style="flex:1"></div>
+        onclick="onPauseClick()">
+        pause
+      </button>
+      <div style="flex: 1"></div>
       <button class="flex-left button mat-icon material-icons mat-icon-no-color" title="Remove selected keyframe"
         onclick="removeKeyframe()">close</button>
       <button class="flex-left button mat-icon material-icons mat-icon-no-color" title="Add new track with the keyframe"
@@ -214,6 +218,20 @@
     var outlineContainer = document.getElementById('outline-container');
 
     function generateModel() {
+      const groupA = {
+        style: {
+          fillColor: '#6B9080',
+          marginTop: 4,
+        },
+        keyframesStyle: {
+          shape: "rect"
+        }
+      };
+      const groupB = {
+        style: {
+          marginTop: 6,
+        },
+      };
       let rows = [
         {
           selected: false,
@@ -233,10 +251,11 @@
         },
         {
           selected: false,
-          hidden: false,
           keyframes: [
             {
-              cursor: 'default',
+              style:{
+                cursor: 'default',
+              },
               val: 2000,
             },
             {
@@ -248,7 +267,6 @@
           ],
         },
         {
-          hidden: false,
           keyframes: [
             {
               val: 1000,
@@ -292,6 +310,31 @@
             },
           ],
         },
+        {
+          title: 'Groups Different Styles',
+          keyframes: [
+            {
+              val: 100,
+              max: 850,
+              group: groupA,
+            },
+            {
+              val: 500,
+              max: 900,
+              group: groupA,
+            },
+            {
+              min: 900,
+              max: 3400,
+              val: 1900,
+              group: groupB,
+            },
+            {
+              val: 4000,
+              group: groupB,
+            },
+          ],
+        },
         {
           keyframes: [
             {
@@ -306,12 +349,17 @@
           ],
         },
         {
-          title: 'Style Customized',
-          groupHeight: 20,
-          keyframesStyle: {
-            shape: 'rect',
-            width: 5,
-            height: 20,
+          title: 'Keyframe Style Customized',
+          style: {
+            groupsStyle: {
+              height: 5,
+              marginTop: "auto"
+            },
+            keyframesStyle: {
+              shape: 'rect',
+              width: 5,
+              height: 20,
+            }
           },
           keyframes: [
             {
@@ -324,17 +372,18 @@
         },
         {},
         {
-          title: 'Max Value',
+          title: 'Max Value (Not Draggable)',
           max: 4000,
           keyframes: [
-            ,
             {
-              width: 4,
-              height: 20,
-              group: 'block',
-              shape: 'rect',
-              fillColor: 'Red',
-              strokeColor: 'Black',
+              style: {
+                width: 4,
+                height: 20,
+                group: 'block',
+                shape: 'rect',
+                fillColor: 'Red',
+                strokeColor: 'Black',
+              },
               val: 4000,
               selectable: false,
               draggable: false,
@@ -351,12 +400,15 @@
         {},
         {
           title: 'Custom Height',
-          height: 100,
-          keyframesStyle: {
-            shape: 'rect',
-            width: 4,
-            height: 70,
+          style: {
+            height: 100,
+            keyframesStyle: {
+              shape: 'rect',
+              width: 4,
+              height: 70,
+            },
           },
+
           keyframes: [
             {
               val: 40,
@@ -366,9 +418,9 @@
             {
               val: 8600,
               group: 'a',
-            }
+            },
           ],
-        }
+        },
       ];
       return rows;
     }
@@ -384,9 +436,9 @@
         args.preventDefault();
       }
     });
-    var logMessage = function (message, log = 1) {
+    var logMessage = function (message, logPanel = 1) {
       if (message) {
-        let el = document.getElementById('output' + log);
+        let el = document.getElementById('output' + logPanel);
         el.innerHTML = message + '<br/>' + el.innerHTML;
       }
     };
@@ -402,19 +454,19 @@
     });
     function showActivePositionInformation() {
       if (timeline) {
-        const fromPx = timeline.getScrollLeft();
-        const toPx = timeline.getScrollLeft() + timeline.getClientWidth();
+        const fromPx = timeline.scrollLeft;
+        const toPx = timeline.scrollLeft + timeline.getClientWidth();
         const fromMs = timeline.pxToVal(fromPx - timeline._leftMargin());
         const toMs = timeline.pxToVal(toPx - timeline._leftMargin());
         let positionInPixels = timeline.valToPx(timeline.getTime()) + timeline._leftMargin();
-        let message = 'Timeline in ms: ' + timeline.getTime() + 'ms. Displayed from:' + fromMs.toFixed() + 'ms to: ' + toMs.toFixed() + "ms.";
-        message += "<br>";
-        message += "Timeline in px: " + positionInPixels + 'px. Displayed from: ' + fromPx + 'px to: ' + toPx + "px";
+        let message = 'Timeline in ms: ' + timeline.getTime() + 'ms. Displayed from:' + fromMs.toFixed() + 'ms to: ' + toMs.toFixed() + 'ms.';
+        message += '<br>';
+        message += 'Timeline in px: ' + positionInPixels + 'px. Displayed from: ' + fromPx + 'px to: ' + toPx + 'px';
         document.getElementById('currentTime').innerHTML = message;
       }
     }
     timeline.onSelected(function (obj) {
-      logMessage('selected :' + obj.selected.length + '. changed :' + obj.changed.length, 2);
+      logMessage('Selected Event: (' + obj.selected.length + '). changed selection :' + obj.changed.length, 2);
     });
     timeline.onDragStarted(function (obj) {
       logDraggingMessage(obj, 'dragstarted');
@@ -430,11 +482,11 @@
     });
     timeline.onMouseDown(function (obj) {
       var type = obj.target ? obj.target.type : '';
-      logMessage('mousedown:' + obj.val + '.  elements:' + type, 2);
+      logMessage('mousedown:' + obj.val + '.  target:' + type + '. ' + Math.floor(obj.pos.x) + 'x' + Math.floor(obj.pos.y), 2);
     });
     timeline.onDoubleClick(function (obj) {
       var type = obj.target ? obj.target.type : '';
-      logMessage('doubleclick:' + obj.val + '.  elements:' + type, 2);
+      logMessage('doubleclick:' + obj.val + '.  target:' + type + '. ' + Math.floor(obj.pos.x) + 'x' + Math.floor(obj.pos.y), 2);
     });
 
     timeline.onScroll(function (obj) {
@@ -462,11 +514,12 @@
       var headerElement = document.getElementById('outline-header');
       headerElement.style.maxHeight = headerElement.style.minHeight = options.headerHeight + 'px';
       // headerElement.style.backgroundColor = options.headerFillColor;
-      outlineContainer.innerHTML = "";
+      outlineContainer.innerHTML = '';
       rows.forEach(function (row, index) {
         var div = document.createElement('div');
         div.classList.add('outline-node');
-        div.style.maxHeight = div.style.minHeight = (row.height || options.rowsStyle.height) + 'px';
+        const h = (row.style ? row.style.height : 0) || options.rowsStyle.height;
+        div.style.maxHeight = div.style.minHeight = h + 'px';
         div.style.marginBottom = options.rowsStyle.marginBottom + 'px';
         div.innerText = row.title || 'Track ' + index;
         outlineContainer.appendChild(div);
@@ -497,7 +550,7 @@
         if (currentModel && currentModel.rows) {
           currentModel.rows.forEach((row) => {
             if (row.keyframes) {
-              row.keyframes = row.keyframes.filter(p => !p.selected);
+              row.keyframes = row.keyframes.filter((p) => !p.selected);
             }
           });
         }
@@ -518,7 +571,7 @@
     }
     function panMode(interactive) {
       if (timeline) {
-        timeline.setInteractionMode(interactive ? 'pan' : "nonInteractivePan");
+        timeline.setInteractionMode(interactive ? 'pan' : 'nonInteractivePan');
       }
     }
     // Set scroll back to timeline when mouse scroll over the outline
@@ -537,13 +590,13 @@
       if (timeline) {
         this.moveTimelineIntoTheBounds();
         // Don't allow to manipulate timeline during playing (optional).
-        timeline.setOptions({ timelineInteractive: false });
+        timeline.setOptions({ timelineDraggable: false });
       }
     }
     function onPauseClick(event) {
       playing = false;
       if (timeline) {
-        timeline.setOptions({ timelineInteractive: true });
+        timeline.setOptions({ timelineDraggable: true });
       }
     }
 
@@ -553,13 +606,13 @@
           // User is manipulating items, don't move screen in this case.
           return;
         }
-        const fromPx = timeline.getScrollLeft();
-        const toPx = timeline.getScrollLeft() + timeline.getClientWidth();
+        const fromPx = timeline.scrollLeft;
+        const toPx = timeline.scrollLeft + timeline.getClientWidth();
 
         let positionInPixels = timeline.valToPx(timeline.getTime()) + timeline._leftMargin();
         // Scroll to timeline position if timeline is out of the bounds:
         if (positionInPixels <= fromPx || positionInPixels >= toPx) {
-          this.timeline.setScrollLeft(positionInPixels);
+          this.timeline.scrollLeft = positionInPixels;
         }
       }
     }
@@ -573,7 +626,7 @@
         }
       }, playStep);
     }
-    // Note: this can be any other player: audio, video, svg and etc. 
+    // Note: this can be any other player: audio, video, svg and etc.
     // In this case you have to synchronize events of the component and player.
     initPlayer();
     showActivePositionInformation();

+ 9 - 0
lib/README.md

@@ -0,0 +1,9 @@
+# Lib folder
+
+Folder contains automatically generated JavaScript files from the TypeScript code in the src folder.
+
+To build project you have to install node.js and run next command:
+
+```CMD
+npm run build
+```

+ 16 - 12
lib/animation-timeline.d.ts

@@ -1,10 +1,10 @@
 export * from './timeline';
-export * from './timelineModel';
-export * from './timelineRow';
-export * from './timelineKeyframe';
 export * from './timelineEventsEmitter';
 export * from './settings/timelineConsts';
-export * from './timelineRanged';
+export * from './models/timelineRanged';
+export * from './models/timelineModel';
+export * from './models/timelineRow';
+export * from './models/timelineKeyframe';
 export * from './settings/timelineOptions';
 export * from './settings/styles/timelineKeyframeStyle';
 export * from './settings/styles/timelineRowStyle';
@@ -12,18 +12,17 @@ export * from './settings/styles/timelineStyle';
 export * from './utils/timelineStyleUtils';
 export * from './utils/timelineUtils';
 export * from './utils/timelineElement';
-export * from './utils/selectable';
+export * from './utils/timelineSelectable';
 export * from './utils/timelineCutBoundsRectResults';
 export * from './utils/timelineSelectionResults';
-export * from './utils/timelineValues';
+export * from './utils/timelinePoint';
 export * from './utils/timelineMouseData';
 export * from './utils/timelineElementDragState';
 export * from './utils/timelineDraggableData';
-export * from './utils/timelineModelCalcResults';
-export * from './utils/timelineCalculatedRow';
-export * from './utils/timelineCalculatedGroup';
-export * from './utils/timelineCalculated';
-export * from './utils/timelineCalculatedKeyframe';
+export * from './viewModels/timelineGroupViewModel';
+export * from './viewModels/timelineKeyframeViewModel';
+export * from './viewModels/timelineRowViewModel';
+export * from './viewModels/timelineViewModel';
 export * from './utils/events/timelineKeyframeChangedEvent';
 export * from './utils/events/timelineTimeChangedEvent';
 export * from './utils/events/timelineSelectedEvent';
@@ -39,4 +38,9 @@ export * from './enums/timelineCapShape';
 export * from './enums/timelineEventSource';
 export * from './enums/timelineSelectionMode';
 export * from './enums/timelineEvents';
-export * from './settings/defaults';
+export * from './settings/defaults/defaultTimelineStyle';
+export * from './settings/defaults/defaultTimelineRowStyle';
+export * from './settings/defaults/defaultTimelineOptions';
+export * from './settings/defaults/defaultTimelineKeyframeStyle';
+export * from './settings/defaults/defaultTimelineConsts';
+export * from './settings/defaults/defaultGroupStyle';

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 686 - 326
lib/animation-timeline.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
lib/animation-timeline.js.map


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
lib/animation-timeline.min.js


+ 7 - 3
lib/enums/timelineElementType.d.ts

@@ -1,3 +1,6 @@
+/**
+ * Internal element type.
+ */
 export declare enum TimelineElementType {
     /**
      * Timeline
@@ -8,11 +11,12 @@ export declare enum TimelineElementType {
      */
     Keyframe = "keyframe",
     /**
-     * Keyframes group
+     * Keyframes connected and presenting one group.
      */
     Group = "group",
     /**
-     * Row
+     * Timeline row.
      */
-    Row = "row"
+    Row = "row",
+    None = "none"
 }

+ 6 - 0
lib/enums/timelineEventSource.d.ts

@@ -1,5 +1,11 @@
 export declare enum TimelineEventSource {
+    /**
+     * Changed by user interaction events.
+     */
     User = "user",
+    /**
+     * Changed programmatically.
+     */
     Programmatically = "programmatically",
     SetTimeMethod = "setTimeMethod"
 }

+ 3 - 0
lib/enums/timelineEvents.d.ts

@@ -1,3 +1,6 @@
+/**
+ * Event names of the component.
+ */
 export declare enum TimelineEvents {
     Selected = "selected",
     TimeChanged = "timechanged",

+ 2 - 2
lib/enums/timelineInteractionMode.d.ts

@@ -9,7 +9,7 @@ export declare enum TimelineInteractionMode {
     Pan = "pan",
     /**
      * Allow only pan without any keyframes interaction.
-     * Timeline still can be moved and controlled by option 'timelineInteractive'.
+     * Timeline still can be moved and controlled by option 'timelineDraggable'.
      */
     NonInteractivePan = "nonInteractivePan",
     /**
@@ -18,7 +18,7 @@ export declare enum TimelineInteractionMode {
     Zoom = "zoom",
     /**
      * No iteraction, except moving a timeline.
-     * Timeline still can be moved and controlled by option 'timelineInteractive'.
+     * Timeline still can be moved and controlled by option 'timelineDraggable'.
      */
     None = "none"
 }

+ 9 - 0
lib/enums/timelineSelectionEventSource.d.ts

@@ -0,0 +1,9 @@
+/**
+ * Timeline selection event type.
+ */
+export declare enum TimelineSelectionEventSource {
+    /**
+     * Keyframe selection is performed.
+     */
+    Keyframes = "keyframes"
+}

+ 11 - 0
lib/model/timelineGroup.d.ts

@@ -0,0 +1,11 @@
+import { TimelineGroupStyle } from '../settings/styles/timelineGroupStyle';
+/**
+ * Timeline group view model.
+ */
+export interface TimelineGroup {
+    style: TimelineGroupStyle;
+    /**
+     * Whether group of keyframes are draggable.
+     */
+    draggable?: boolean;
+}

+ 12 - 0
lib/model/timelineKeyframe.d.ts

@@ -0,0 +1,12 @@
+import { TimelineKeyframeStyle } from '../settings/styles/timelineKeyframeStyle';
+import { TimelineSelectable } from '../utils/timelineSelectable';
+import { TimelineRanged } from './timelineRanged';
+import { TimelineGroup } from './timelineGroup';
+export interface TimelineKeyframe extends TimelineKeyframeStyle, TimelineSelectable, TimelineRanged {
+  val: number;
+  /**
+   * Related keyframe group.
+   * Timeline keyframes groups are rendered as one instance.
+   */
+  group?: string | TimelineGroup;
+}

+ 4 - 0
lib/model/timelineModel.d.ts

@@ -0,0 +1,4 @@
+import { TimelineRow } from './timelineRow';
+export interface TimelineModel {
+    rows: TimelineRow[];
+}

+ 10 - 0
lib/model/timelineRanged.d.ts

@@ -0,0 +1,10 @@
+export interface TimelineRanged {
+    /**
+     * min
+     */
+    min?: number | null;
+    /**
+     * max.
+     */
+    max?: number | null;
+}

+ 8 - 0
lib/model/timelineRow.d.ts

@@ -0,0 +1,8 @@
+import { TimelineKeyframe } from './timelineKeyframe';
+import { TimelineRowStyle } from '../settings/styles/timelineRowStyle';
+import { TimelineRanged } from './timelineRanged';
+export interface TimelineRow extends TimelineRanged {
+    keyframes?: TimelineKeyframe[] | null;
+    style?: TimelineRowStyle;
+    hidden?: boolean;
+}

+ 28 - 0
lib/models/timelineGroup.d.ts

@@ -0,0 +1,28 @@
+import { TimelineKeyframeStyle } from '../settings/styles/timelineKeyframeStyle';
+import { TimelineGroupStyle } from '../settings/styles/timelineGroupStyle';
+/**
+ * Timeline group view model.
+ */
+export interface TimelineGroup {
+    /**
+     * Group style.
+     */
+    style: TimelineGroupStyle;
+    /**
+     * Child keyframes style.
+     */
+    keyframesStyle: TimelineKeyframeStyle;
+    /**
+     * Whether group is draggable.
+     * Considered to be false when really set as false.
+     */
+    draggable?: boolean;
+    /**
+     * Whether group keyframes are draggable.
+     */
+    keyframesDraggable?: boolean;
+    /**
+     * Whether group is hidden.
+     */
+    hidden?: boolean;
+}

+ 28 - 0
lib/models/timelineKeyframe.d.ts

@@ -0,0 +1,28 @@
+import { TimelineKeyframeStyle } from '../settings/styles/timelineKeyframeStyle';
+import { TimelineSelectable } from '../utils/timelineSelectable';
+import { TimelineRanged } from './timelineRanged';
+import { TimelineGroup } from './timelineGroup';
+export interface TimelineKeyframe extends TimelineSelectable, TimelineRanged {
+    /**
+     * Keyframe value.
+     */
+    val: number;
+    /**
+     * Related keyframe group.
+     * Timeline keyframes groups are rendered as one instance.
+     */
+    group?: string | TimelineGroup;
+    /**
+     * Keyframe style.
+     */
+    style?: TimelineKeyframeStyle;
+    /**
+     * Whether keyframe is hidden.
+     */
+    hidden?: boolean;
+    /**
+     * Whether group is draggable.
+     * Considered to be false when really set as false.
+     */
+    draggable?: boolean;
+}

+ 4 - 0
lib/models/timelineModel.d.ts

@@ -0,0 +1,4 @@
+import { TimelineRow } from './timelineRow';
+export interface TimelineModel {
+    rows: TimelineRow[];
+}

+ 10 - 0
lib/models/timelineRanged.d.ts

@@ -0,0 +1,10 @@
+export interface TimelineRanged {
+    /**
+     * min
+     */
+    min?: number | null;
+    /**
+     * max.
+     */
+    max?: number | null;
+}

+ 13 - 0
lib/models/timelineRow.d.ts

@@ -0,0 +1,13 @@
+import { TimelineKeyframe } from './timelineKeyframe';
+import { TimelineRowStyle } from '../settings/styles/timelineRowStyle';
+import { TimelineRanged } from './timelineRanged';
+export interface TimelineRow extends TimelineRanged {
+    style?: TimelineRowStyle;
+    keyframes?: TimelineKeyframe[] | null;
+    hidden?: boolean;
+    /**
+     * Whether group keyframes are draggable.
+     */
+    keyframesDraggable?: boolean;
+    groupsDraggable?: boolean;
+}

+ 2 - 0
lib/settings/defaults.d.ts

@@ -3,7 +3,9 @@ import { TimelineStyle } from './styles/timelineStyle';
 import { TimelineOptions } from './timelineOptions';
 import { TimelineKeyframeStyle } from './styles/timelineKeyframeStyle';
 import { TimelineRowStyle } from './styles/timelineRowStyle';
+import { TimelineGroupStyle } from './styles/timelineGroupStyle';
 export declare const defaultTimelineStyle: TimelineStyle;
+export declare const defaultGroupStyle: TimelineGroupStyle;
 export declare const defaultTimelineKeyframeStyle: TimelineKeyframeStyle;
 export declare const defaultTimelineRowStyle: TimelineRowStyle;
 export declare const defaultTimelineOptions: TimelineOptions;

+ 3 - 0
lib/settings/defaults/defaultGroupStyle.d.ts

@@ -0,0 +1,3 @@
+import { TimelineGroupStyle } from '../styles/timelineGroupStyle';
+export declare const defaultRowHeight = 24;
+export declare const defaultGroupStyle: TimelineGroupStyle;

+ 2 - 0
lib/settings/defaults/defaultTimelineConsts.d.ts

@@ -0,0 +1,2 @@
+import { TimelineConsts } from '../timelineConsts';
+export declare const defaultTimelineConsts: TimelineConsts;

+ 2 - 0
lib/settings/defaults/defaultTimelineKeyframeStyle.d.ts

@@ -0,0 +1,2 @@
+import { TimelineKeyframeStyle } from '../styles/timelineKeyframeStyle';
+export declare const defaultTimelineKeyframeStyle: TimelineKeyframeStyle;

+ 2 - 0
lib/settings/defaults/defaultTimelineOptions.d.ts

@@ -0,0 +1,2 @@
+import { TimelineOptions } from '../timelineOptions';
+export declare const defaultTimelineOptions: TimelineOptions;

+ 2 - 0
lib/settings/defaults/defaultTimelineRowStyle.d.ts

@@ -0,0 +1,2 @@
+import { TimelineRowStyle } from '../styles/timelineRowStyle';
+export declare const defaultTimelineRowStyle: TimelineRowStyle;

+ 2 - 0
lib/settings/defaults/defaultTimelineStyle.d.ts

@@ -0,0 +1,2 @@
+import { TimelineStyle } from '../styles/timelineStyle';
+export declare const defaultTimelineStyle: TimelineStyle;

+ 16 - 13
lib/settings/styles/TimelineRowStyle.d.ts

@@ -1,25 +1,28 @@
+import { TimelineGroupStyle } from './timelineGroupStyle';
 import { TimelineKeyframeStyle } from './timelineKeyframeStyle';
+/**
+ * Style of the row.
+ */
 export interface TimelineRowStyle {
     /**
-     * Size of the row in pixels, can be set to 'auto'
+     * Size of the row in pixels.
      */
-    height?: string | number;
-    hidden?: boolean;
-    color?: string;
-    selectedColor?: string;
-    marginBottom?: number;
+    height?: number;
     /**
-     * Keyframes bounds group height.
-     * 'auto' to automatically calculate.
-     * number in pixels.
+     * Track fill color.
      */
-    groupHeight?: number | string;
+    fillColor?: string;
     /**
-     * Keyframes bounds group color. Default is used when undefined.
+     * Row margin bottom in pixels between tracks/rows.
      */
-    groupFillColor?: string;
+    marginBottom?: number;
     /**
-     * Style of all keyframes in a current row.
+     * Style for the all keyframes in a current row.
+     * Individual keyframe can have own style.
      */
     keyframesStyle?: TimelineKeyframeStyle;
+    /**
+     * Style of the groups. Keyframe groups can be also styles separately.
+     */
+    groupsStyle?: TimelineGroupStyle;
 }

+ 26 - 0
lib/settings/styles/timelineCapStyle.d.ts

@@ -0,0 +1,26 @@
+import { TimelineCapShape } from '../../enums/timelineCapShape';
+/**
+ * Timeline active/current value indicator style.
+ */
+export interface TimelineCapStyle {
+    /**
+     * Cap style width in pixels.
+     */
+    width?: number;
+    /**
+     * Cap style height in pixels.
+     */
+    height?: number;
+    /**
+     * Cap stroke color.
+     */
+    strokeColor: string;
+    /**
+     * Cap fill color.
+     */
+    fillColor: string;
+    /**
+     * Cap type
+     */
+    capType?: TimelineCapShape;
+}

+ 32 - 0
lib/settings/styles/timelineGroupStyle.d.ts

@@ -0,0 +1,32 @@
+import { TimelineCursorType } from '../../enums/timelineCursorType';
+import { TimelineKeyframeStyle } from '../styles/timelineKeyframeStyle';
+/**
+ * Timeline group style.
+ */
+export interface TimelineGroupStyle {
+    /**
+     * Keyframes style height in pixels.
+     * 'auto' to automatically calculate.
+     */
+    height?: number | string;
+    /**
+     * Group stroke color.
+     */
+    strokeColor: string;
+    /**
+     * Group fill color.
+     */
+    fillColor: string;
+    /**
+     * Group mouse over cursor style.
+     */
+    cursor?: TimelineCursorType;
+    /**
+     * Margin top in px or 'auto' to center element.
+     */
+    marginTop?: number | string;
+    /**
+     * Style for all the keyframes in the current group.
+     */
+    keyframesStyle: TimelineKeyframeStyle;
+}

+ 18 - 4
lib/settings/styles/timelineKeyframeStyle.d.ts

@@ -1,9 +1,14 @@
+import { TimelineCursorType } from '../../enums/timelineCursorType';
 import { TimelineKeyframeShape } from '../../enums/timelineKeyframeShape';
 export interface TimelineKeyframeStyle {
-    cursor?: string;
+    /**
+     * Timeline cursor style.
+     */
+    cursor?: TimelineCursorType;
+    /**
+     * Timeline keyframe shape
+     */
     shape?: TimelineKeyframeShape;
-    draggable?: boolean;
-    hidden?: boolean;
     /**
      * keyframe size, number or text 'auto'
      */
@@ -17,10 +22,19 @@ export interface TimelineKeyframeStyle {
      */
     fillColor?: string | null;
     /**
-     * Keyframe selected  fill color.
+     * Keyframe selected fill color.
      */
     selectedFillColor?: string | null;
+    /**
+     * Keyframe stroke color.
+     */
     strokeColor?: string | null;
+    /**
+     * Keyframe selected stroke color.
+     */
     selectedStrokeColor?: string | null;
+    /**
+     * Keyframe stroke Thickness.
+     */
     strokeThickness?: number | null;
 }

+ 24 - 9
lib/settings/styles/timelineStyle.d.ts

@@ -1,17 +1,32 @@
-import { TimelineCapShape } from '../../enums/timelineCapShape';
+import { TimelineCursorType } from '../../enums/timelineCursorType';
+import { TimelineCapStyle } from './timelineCapStyle';
 /**
- * Timeline indicator style
+ * Timeline active/current value indicator style.
  */
 export interface TimelineStyle {
     width?: number;
+    /**
+     * Margin top in pixels.
+     */
     marginTop?: number;
-    capWidth?: number;
-    capHeight?: number;
     /**
-     * Cap type
+     * Margin bottom in pixels.
+     */
+    marginBottom?: number;
+    /**
+     * Timeline top cap style.
+     */
+    capStyle?: TimelineCapStyle;
+    /**
+     * Timeline indicator stroke color.
+     */
+    strokeColor?: string;
+    /**
+     * Timeline fill color.
+     */
+    fillColor?: string;
+    /**
+     * Timeline cursor.
      */
-    capType?: TimelineCapShape;
-    timelineColor?: string;
-    strokeColor: string;
-    fillColor: string;
+    cursor?: TimelineCursorType;
 }

+ 16 - 0
lib/settings/timelineConsts.d.ts

@@ -1,3 +1,7 @@
+/**
+ * Internal components consts.
+ * Still can be changed thru private property _consts but this is discouraged.
+ */
 export interface TimelineConsts {
     /**
      * Auto pan speed.
@@ -27,4 +31,16 @@ export interface TimelineConsts {
      * Click threshold
      */
     clickThreshold: number;
+    /**
+     * Click min radius for the elements detection.
+     */
+    clickDetectionMinRadius: number;
+    /**
+     * Default auto size for the group. It's percents.
+     */
+    autoPanSpeedLimit: number;
+    /**
+     * Default auto size for the group. It's percents.
+     */
+    defaultGroupHeight: number;
 }

+ 16 - 13
lib/settings/timelineOptions.d.ts

@@ -1,6 +1,6 @@
 import { TimelineRowStyle } from './styles/timelineRowStyle';
 import { TimelineStyle } from './styles/timelineStyle';
-import { TimelineRanged } from '../timelineRanged';
+import { TimelineRanged } from '../models/timelineRanged';
 export interface TimelineOptions extends TimelineRanged {
     /**
      * Id or HTMLElement of the timeline container.
@@ -11,11 +11,11 @@ export interface TimelineOptions extends TimelineRanged {
      */
     snapEnabled?: boolean;
     /**
-     *  Snap all selected keyframes as a bundle during the drag.
+     *  Snap all selected keyframes as one bundle during the drag.
      */
     snapAllKeyframesOnMove?: boolean;
     /**
-     * approximate step for the timeline in pixels for 1 second
+     * Approximate step for the timeline in pixels for 1 second
      */
     stepPx?: number;
     /**
@@ -39,6 +39,9 @@ export interface TimelineOptions extends TimelineRanged {
      * Component background color.
      */
     fillColor?: string;
+    /**
+     * Header labels color.
+     */
     labelsColor?: string;
     /**
      * Header gauge tick color.
@@ -48,15 +51,6 @@ export interface TimelineOptions extends TimelineRanged {
      * Selection rectangle color.
      */
     selectionColor?: string;
-    /**
-     * Default rows style.
-     * Can be overridden by setting style individually for each row.
-     */
-    rowsStyle?: TimelineRowStyle;
-    /**
-     * Timeline indicator style.
-     */
-    timelineStyle?: TimelineStyle;
     /**
      * Header height in pixels
      */
@@ -89,6 +83,15 @@ export interface TimelineOptions extends TimelineRanged {
      * Access the scroll container via this class for e.g. scroll bar styling.
      */
     scrollContainerClass?: string;
+    /**
+     * Default rows style.
+     * Can be overridden by setting style individually for each row.
+     */
+    rowsStyle?: TimelineRowStyle;
+    /**
+     * Timeline indicator style.
+     */
+    timelineStyle?: TimelineStyle;
     /**
      * keyframes group is draggable. Default: true
      */
@@ -100,5 +103,5 @@ export interface TimelineOptions extends TimelineRanged {
     /**
      * Timeline can be dragged or position can be changed by user interaction. Default: true
      */
-    timelineInteractive?: boolean;
+    timelineDraggable?: boolean;
 }

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 81 - 0
lib/tests/settingsTests.test.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 670 - 0
lib/tests/styleTests.test.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 866 - 0
lib/tests/timelineTests.test.js


+ 199 - 128
lib/timeline.d.ts

@@ -1,8 +1,8 @@
-import { TimelineModel } from './timelineModel';
-import { TimelineRow } from './timelineRow';
-import { TimelineKeyframe } from './timelineKeyframe';
 import { TimelineEventsEmitter } from './timelineEventsEmitter';
 import { TimelineConsts } from './settings/timelineConsts';
+import { TimelineModel } from './models/timelineModel';
+import { TimelineRow } from './models/timelineRow';
+import { TimelineKeyframe } from './models/timelineKeyframe';
 import { TimelineOptions } from './settings/timelineOptions';
 import { TimelineElement } from './utils/timelineElement';
 import { TimelineCutBoundsRectResults } from './utils/timelineCutBoundsRectResults';
@@ -10,15 +10,17 @@ import { TimelineSelectionResults } from './utils/timelineSelectionResults';
 import { TimelineMouseData } from './utils/timelineMouseData';
 import { TimelineElementDragState } from './utils/timelineElementDragState';
 import { TimelineDraggableData } from './utils/timelineDraggableData';
-import { TimelineModelCalcResults } from './utils/timelineModelCalcResults';
-import { TimelineCalculatedRow } from './utils/timelineCalculatedRow';
-import { TimelineCalculatedKeyframe } from './utils/timelineCalculatedKeyframe';
+import { TimelineGroupViewModel } from './viewModels/timelineGroupViewModel';
+import { TimelineKeyframeViewModel } from './viewModels/timelineKeyframeViewModel';
+import { TimelineRowViewModel } from './viewModels/timelineRowViewModel';
+import { TimelineViewModel } from './viewModels/timelineViewModel';
 import { TimelineKeyframeChangedEvent } from './utils/events/timelineKeyframeChangedEvent';
 import { TimelineTimeChangedEvent } from './utils/events/timelineTimeChangedEvent';
 import { TimelineSelectedEvent } from './utils/events/timelineSelectedEvent';
 import { TimelineScrollEvent } from './utils/events/timelineScrollEvent';
 import { TimelineClickEvent } from './utils/events/timelineClickEvent';
 import { TimelineDragEvent } from './utils/events/timelineDragEvent';
+import { TimelineKeyframeShape } from './enums/timelineKeyframeShape';
 import { TimelineInteractionMode } from './enums/timelineInteractionMode';
 import { TimelineElementType } from './enums/timelineElementType';
 import { TimelineEventSource } from './enums/timelineEventSource';
@@ -50,11 +52,11 @@ export declare class Timeline extends TimelineEventsEmitter {
     /**
      * Components settings
      */
-    _options: TimelineOptions | null;
+    _options: TimelineOptions;
     /**
      * Drag start position.
      */
-    _startPos: TimelineMouseData | null;
+    _startPosMouseArgs: TimelineMouseData | null;
     /**
      * Drag scroll started position.
      */
@@ -79,7 +81,7 @@ export declare class Timeline extends TimelineEventsEmitter {
     _startedDragWithCtrl: boolean;
     _startedDragWithShiftKey: boolean;
     _scrollProgrammatically: boolean;
-    _clickTimeout?: number;
+    _clickTimeout: number | null;
     _lastClickTime: number;
     _lastClickPoint: DOMPoint | null;
     _consts: TimelineConsts;
@@ -105,7 +107,15 @@ export declare class Timeline extends TimelineEventsEmitter {
      * Private. Ref for the auto pan scroll interval.
      */
     _intervalRef?: number | null;
+    /**
+     * Private.
+     * When last auto pan scroll action was started.
+     */
     _autoPanLastActionDate: number;
+    /**
+     * Private.
+     * Is pan mouse interactions are started.
+     */
     _isPanStarted: boolean;
     /**
      * Private.
@@ -113,6 +123,10 @@ export declare class Timeline extends TimelineEventsEmitter {
      */
     _interactionMode: TimelineInteractionMode;
     _lastUsedArgs: MouseEvent | TouchEvent | null;
+    /**
+     * Private.
+     * Current set timeline model.
+     */
     _model: TimelineModel | null;
     /**
      * Private.
@@ -130,46 +144,56 @@ export declare class Timeline extends TimelineEventsEmitter {
      * @param options Timeline settings.
      * @param model Timeline model.
      */
-    initialize(options: TimelineOptions | null, model: TimelineModel | null): void;
+    initialize: (options: TimelineOptions | null, model: TimelineModel | null) => void;
     /**
      * Generate component html.
      * @param id container.
      */
-    _generateContainers(id: string | HTMLElement): void;
+    _generateContainers: (id: string | HTMLElement) => void;
+    /**
+     * Get drawing context
+     */
+    _getCtx(): CanvasRenderingContext2D | null;
     /**
      * Subscribe current component on the related events.
      * Private. Use initialize method instead.
      */
-    _subscribeComponentEvents(): void;
+    _subscribeComponentEvents: () => void;
     /**
      * Private. Use dispose method instead.
      */
-    _unsubscribeComponentEvents(): void;
+    _unsubscribeComponentEvents: () => void;
     /**
      * Dispose current component: unsubscribe component and user events.
      */
-    dispose(): void;
+    dispose: () => void;
+    /**
+     * On key up is received.
+     */
     _handleKeyUp: (event: KeyboardEvent) => void;
+    /**
+     * On key down is received.
+     */
     _handleKeyDown: (event: KeyboardEvent) => void;
-    _setZoomCursor(e: MouseEvent | KeyboardEvent): void;
+    _setZoomCursor: (e: MouseEvent | KeyboardEvent) => void;
     _handleBlurEvent: () => void;
     _handleWindowResizeEvent: () => void;
-    _clearScrollFinishedTimer(): void;
+    _clearScrollFinishedTimer: () => void;
     _handleScrollMouseDownEvent: () => void;
-    _handleScrollEvent: (args: MouseEvent) => void;
-    _controlKeyPressed(e: MouseEvent | KeyboardEvent | TouchEvent): boolean;
+    _handleScrollEvent: (args: Event) => void;
+    _controlKeyPressed: (e: MouseEvent | KeyboardEvent | TouchEvent) => boolean;
     _handleWheelEvent: (event: WheelEvent) => void;
-    _zoom(direction: number, speed: number, x: number): void;
+    _zoom: (direction: number, speed: number, x: number) => void;
     /**
      * Zoom in
      * @param speed value from 0 to 1
      */
-    zoomIn(speed?: number): void;
+    zoomIn: (speed?: number | undefined) => void;
     /**
      * Zoom out.
      * @param speed value from 0 to 1
      */
-    zoomOut(speed?: number): void;
+    zoomOut: (speed?: number | undefined) => void;
     /**
      * Set direct zoom value.
      * @param zoom zoom value to set. percent 0-1 and etc.
@@ -177,91 +201,112 @@ export declare class Timeline extends TimelineEventsEmitter {
      * @param max max zoom.
      * @return normalized value.
      */
-    _setZoom(zoom: number, min?: number | undefined, max?: number | undefined): number;
+    _setZoom: (zoom: number, min?: number | null | undefined, max?: number | null | undefined) => number;
     /**
      * Set direct zoom value.
      * @public
      * @param zoom zoom value to set. percent 0-1 and etc.
      * @return normalized value.
      */
-    setZoom(zoom: number): number;
+    setZoom: (zoom: number) => number;
     /**
      * Get current zoom level.
      */
-    getZoom(): number;
+    getZoom: () => number;
+    _getClickDetectionRadius: (point: TimelineMouseData) => number;
     /**
      * @param args
      */
-    _handleMouseDownEvent: (args: MouseEvent) => void;
-    _setElementDragState(element: TimelineElement | TimelineElementDragState, val: number): TimelineElementDragState;
-    isLeftButtonClicked(args: MouseEvent | TouchEvent | any): boolean;
-    _handleMouseMoveEvent: (args: MouseEvent | TouchEvent | any) => void;
+    _handleMouseDownEvent: (args: MouseEvent | TouchEvent) => void;
+    _setElementDragState: (element: TimelineElement | TimelineElementDragState, val: number) => TimelineElementDragState;
+    /**
+     * Check is mouse left button is clicked.
+     */
+    isLeftButtonClicked: (args: MouseEvent | TouchEvent | any) => boolean;
+    /**
+     * Browser mouse move handler.
+     */
+    _handleMouseMoveEvent: (args: MouseEvent | TouchEvent | null) => void;
     /**
      * Move elements
      * @param offset vector to move elements along.
      * @param elements Element to move.
      * @returns real moved value.
      */
-    _moveElements(offset: number, elements: Array<TimelineElementDragState>, source?: TimelineEventSource): number;
-    _handleMouseUpEvent: (args: MouseEvent) => void;
+    _moveElements(offset: number, elements: TimelineElementDragState[], source?: TimelineEventSource): number;
     /**
-     * client height.
+     * Mouse up handler.
      */
-    _height(): number;
+    _handleMouseUpEvent: (args: MouseEvent | TouchEvent) => void;
     /**
-     * Client canvas width;
+     * Canvas client height.
      */
-    _width(): number;
+    _canvasClientHeight: () => number;
     /**
-     * Convert virtual calculation results to keyframes
+     * Canvas client width.
      */
-    _mapKeyframes(array: Array<TimelineCalculatedKeyframe | TimelineElement>): Array<TimelineKeyframe>;
+    _canvasClientWidth: () => number;
     /**
      * Get all keyframes under the screen rectangle.
      * @param screenRect screen coordinates to get keyframes.
      */
-    _getKeyframesByRectangle(screenRect: DOMRect): TimelineKeyframe[];
-    _performClick(pos: TimelineMouseData, drag: TimelineDraggableData): boolean;
+    _getKeyframesByRectangle: (screenRect: DOMRect) => TimelineKeyframe[];
+    /**
+     * Private.
+     * Perform timeline click.
+     */
+    _performClick: (pos: TimelineMouseData, drag: TimelineDraggableData | null) => boolean;
     /**
      * Set keyframe value.
      * @param keyframe
      * @param value
      * @return set value.
      */
-    _setKeyframePos(element: TimelineElementDragState, value: number, source?: TimelineEventSource): number;
+    _setKeyframePos: (element: TimelineElementDragState, value: number, source?: TimelineEventSource) => number;
     /**
      * @param cursor to set.
      */
-    _setCursor(cursor: string): void;
+    _setCursor: (cursor: string) => void;
     /**
      * Set component interaction mode.
      */
-    setInteractionMode(mode: TimelineInteractionMode): void;
+    setInteractionMode: (mode: TimelineInteractionMode) => void;
     /**
      * Get current interaction mode.
      */
-    getInteractionMode(): TimelineInteractionMode;
-    _convertToElement(row: TimelineRow, keyframe: TimelineKeyframe): TimelineElement;
-    getSelectedKeyframes(): Array<TimelineKeyframe>;
-    getSelectedElements(): Array<TimelineElement>;
+    getInteractionMode: () => TimelineInteractionMode;
+    /**
+     * Private.
+     * Helper method. Convert model element  to timeline element.
+     */
+    _convertToTimelineElement: (rowModel: TimelineRow | null, keyframe: TimelineKeyframe) => TimelineElement;
+    getSelectedKeyframes: () => TimelineKeyframe[];
+    /**
+     * Get selected timeline elements.
+     */
+    getSelectedElements: () => TimelineElement[];
     /**
      * Get all keyframe models available in the model.
      */
-    getAllKeyframes(): TimelineKeyframe[];
-    selectAllKeyframes(): TimelineSelectionResults;
-    deselectAll(): TimelineSelectionResults;
+    getAllKeyframes: () => TimelineKeyframe[];
+    selectAllKeyframes: () => TimelineSelectionResults;
+    deselectAll: () => TimelineSelectionResults;
     private _changeNodeState;
-    select(nodes: TimelineKeyframe[] | TimelineKeyframe | null, mode?: TimelineSelectionMode): TimelineSelectionResults;
+    select: (nodes: TimelineKeyframe[] | TimelineKeyframe | null, mode?: TimelineSelectionMode) => TimelineSelectionResults;
     /**
      * Select keyframes
      * @param nodes keyframe or list of the keyframes to be selected.
      * @param mode selection mode.
      */
-    _selectInternal(nodes: TimelineKeyframe[] | TimelineKeyframe | null, mode?: TimelineSelectionMode): TimelineSelectionResults;
+    _selectInternal: (nodes: TimelineKeyframe[] | TimelineKeyframe | null, mode?: TimelineSelectionMode) => TimelineSelectionResults;
     /**
      * foreach visible keyframe.
      */
-    _forEachKeyframe(callback: (keyframe: TimelineCalculatedKeyframe, index?: number, newRow?: boolean) => void): void;
+    _forEachKeyframe(callback: (keyframe: TimelineKeyframeViewModel, index?: number, newRow?: boolean) => void): void;
+    /**
+     * Private.
+     * Create extended mouse position and calculate size of the selection rectangle.
+     */
     _trackMousePos(canvas: HTMLCanvasElement, mouseArgs: MouseEvent | TouchEvent): TimelineMouseData;
     /**
      * Get scroll container client width.
@@ -279,11 +324,11 @@ export declare class Timeline extends TimelineEventsEmitter {
     /**
      * Automatically pan. Scroll canvas when selection is made and mouse outside of the bounds.
      */
-    _startAutoPan(): void;
+    _startAutoPan: () => void;
     /**
      * Stop current running auto pan
      */
-    _stopAutoPan(): void;
+    _stopAutoPan: () => void;
     /**
      * Check whether auto pan should be slowed down a bit.
      */
@@ -291,7 +336,7 @@ export declare class Timeline extends TimelineEventsEmitter {
     /**
      * Scroll virtual canvas when pan mode is enabled.
      */
-    _scrollByPan(start: TimelineMouseData, pos: TimelineMouseData, scrollStartPos: DOMPoint): void;
+    _scrollByPan(start: DOMPoint, pos: DOMPoint, scrollStartPos: DOMPoint | null): void;
     _scrollBySelectionOutOfBounds(pos: DOMPoint): boolean;
     /**
      * Convert screen pixel to value.
@@ -300,182 +345,208 @@ export declare class Timeline extends TimelineEventsEmitter {
     /**
      * Convert value to local screen component coordinates.
      */
-    _toScreenPx(val: number): number;
+    _toScreenPx: (val: number) => number;
     /**
      * Convert screen local coordinates to a global value info.
      */
-    _fromScreen(px: number): number;
+    _fromScreen: (px: number) => number;
     /**
      * Convert area value to global screen pixel coordinates.
      */
-    valToPx(val: number): number;
+    valToPx: (val: number) => number;
     /**
      * Snap a value to a nearest grid point.
      */
     snapVal(val: number): number;
-    _mousePosToVal(x: number, snapEnabled?: boolean): number;
+    /**
+     * Convert mouse position to the timeline units considering all the scrolling and offsets.
+     */
+    _mousePosToVal: (x: number, snapEnabled?: boolean) => number;
     /**
      * Format line gauge text.
      * Default formatting is HMS
      * @param ms milliseconds to convert.
      * @param isSeconds whether seconds are passed.
      */
-    _formatUnitsText(ms: number, isSeconds?: boolean): string;
+    _formatUnitsText: (ms: number, isSeconds?: boolean) => string;
     /**
      * Left padding of the timeline.
      */
-    _leftMargin(): number;
-    _renderTicks(): void;
+    _leftMargin: () => number;
+    /**
+     * Private.
+     * Render line gauge ticks.
+     */
+    _renderTicks: () => void;
     /**
-     * calculate virtual mode. Determine screen positions for the elements.
+     * Private.
+     * Calculate virtual view model.
+     * Determine screen positions for the model elements given.
+     */
+    _generateViewModel: () => TimelineViewModel;
+    /**
+     * Render timeline rows.
      */
-    _calculateModel(): TimelineModelCalcResults;
-    _renderRows(): void;
+    _renderRows: () => void;
     /**
-     * Method is used for the optimization.
-     * Only visible part should be rendered.
+     * Render group for the row.
      */
-    _cutBounds(rect: DOMRect): TimelineCutBoundsRectResults;
+    _renderGroupBounds: (rowViewModel: TimelineRowViewModel) => void;
     /**
-     * get keyframe group screen rect coordinates.
+     * Method is used for the canvas drawing optimization.
+     * Bounds are cut to draw only visible parts for the active canvas.
+     */
+    _cutBounds: (rect: DOMRect) => TimelineCutBoundsRectResults | null;
+    _cutBoundsWhenOverlap: (rect: DOMRect, minX: number, maxX: number, minY: number, maxY: number) => TimelineCutBoundsRectResults | null;
+    /**
+     * Calculate keyframe group screen rect size that is used during the rendering.
      * @param row
      * @param rowY row screen coords y position
      */
-    _getKeyframesGroupSize(row: TimelineRow, rowY: number, minValue: number, maxValue: number): DOMRect;
-    _getKeyframePosition(keyframe: TimelineKeyframe, rowCalculated: TimelineCalculatedRow): DOMRect | null;
-    _renderKeyframes(): void;
-    _renderSelectionRect(): void;
-    _renderBackground(): void;
-    _renderTimeline(): void;
-    _renderHeaderBackground(): void;
-    redraw(): void;
+    _getKeyframesGroupSize: (groupViewModel: TimelineGroupViewModel, rowViewModel: TimelineRowViewModel) => DOMRect;
+    _getKeyframePosition: (keyframe: TimelineKeyframe, groupViewModel: TimelineGroupViewModel, rowViewModel: TimelineRowViewModel, keyframeShape: TimelineKeyframeShape) => DOMRect | null;
+    _renderKeyframes: () => void;
+    _renderSelectionRect: () => void;
+    _renderBackground: () => void;
+    _renderTimeline: () => void;
     /**
-     * perform scroll to max left.
+     * Render timeline cap top.
      */
-    scrollLeft(): void;
+    _renderTimelineCap: (timeLinePos: number, y: number) => void;
+    _renderHeaderBackground: () => void;
+    redraw: () => void;
     /**
-     * Redraw parts of the component in the specific order.
+     * perform scroll to max right.
      */
-    _redrawInternal: () => void;
+    scrollToRightBounds: () => void;
     /**
-     * Get row by y coordinate.
-     * @param posY y screen coordinate.
+     * Redraw parts of the component in the specific order.
      */
-    getRowByY(posY: number): TimelineRow;
+    _redrawInternal: () => void;
     /**
      * Find sharp pixel position
      */
-    _getSharp(pos: number, thickness?: number): number;
+    _getSharp: (pos: number, thickness?: number) => number;
     /**
      * Get current time:
      */
-    getTime(): number;
+    getTime: () => number;
     /**
      * Set current time internal
      * @param val value.
      * @param source event source.
      */
-    _setTimeInternal(val: number, source?: TimelineEventSource): boolean;
-    setTime(val: number): boolean;
-    getOptions(): TimelineOptions;
-    setScrollLeft(value: number): void;
-    setScrollTop(value: number): void;
-    getScrollLeft(): number;
-    getScrollTop(): number;
+    _setTimeInternal: (val: number, source?: TimelineEventSource) => boolean;
+    setTime: (val: number) => boolean;
+    getOptions: () => TimelineOptions;
+    /**
+     * Current scroll left position.
+     */
+    get scrollLeft(): number;
+    set scrollLeft(value: number);
+    get scrollTop(): number;
+    set scrollTop(value: number);
     /**
      * Set options and render the component.
      * Note: Options will be merged\appended with the defaults and component will be invalidated/rendered again.
      */
-    setOptions(toSet: TimelineOptions): TimelineOptions;
+    setOptions: (toSet: TimelineOptions) => TimelineOptions;
     /**
      * Private. Apply html container styles from options if any is set.
      */
-    _applyContainersStyles(): void;
-    _setOptions(toSet: TimelineOptions): TimelineOptions;
-    getModel(): TimelineModel;
+    _applyContainersStyles: () => void;
+    _setOptions: (toSet: TimelineOptions) => TimelineOptions;
+    /**
+     * Get current model.
+     */
+    getModel: () => TimelineModel | null;
     /**
      * Set model and redraw application.
      * @param data
      */
-    setModel(data: TimelineModel): void;
-    _getMousePos(canvas: HTMLCanvasElement, e: TouchEvent | MouseEvent | any): TimelineMouseData;
+    setModel: (data: TimelineModel) => void;
+    _getMousePos: (canvas: HTMLCanvasElement, e: TouchEvent | MouseEvent | any) => TimelineMouseData;
     /**
      * Apply container div size to the container on changes detected.
      */
-    _updateCanvasScale(): boolean;
+    _updateCanvasScale: () => boolean;
     /**
      * Rescale and update size of the container.
      */
-    rescale(): boolean;
+    rescale: () => boolean;
     /**
      * This method is used to draw additional space when after there are no keyframes.
      * When scrolled we should allow to indefinitely scroll right, so space should be extended to drag keyframes outside of the current size bounds.
      */
-    _rescaleInternal(newWidth?: number | null, newHeight?: number | null, scrollMode?: TimelineScrollSource): boolean;
+    _rescaleInternal: (newWidth?: number | null, newHeight?: number | null, scrollMode?: TimelineScrollSource) => boolean;
     /**
-     * Filter and sort draggable elements by the priority to get first draggable element.
+     * Filter elements that can be dragged.
      * Filtration is done based on the timeline styles and options.
-     * @param elements to filter and sort.
-     * @param val current mouse value to find best match.
      */
-    _filterDraggableElements(elements: TimelineElement[], val?: number | null): TimelineElement;
+    _filterDraggableElements: (elements: TimelineElement[]) => TimelineElement[];
     /**
-     * get all clickable elements by the given local screen coordinate.
+     * Filter and sort draggable elements by the priority to get first draggable element closest to the passed value.
      */
-    elementFromPoint(pos: DOMPoint, clickRadius?: number, onlyTypes?: TimelineElementType[] | null): TimelineElement[];
-    _cloneOptions(previousOptions: TimelineOptions): TimelineOptions;
+    _findDraggableElement: (elements: TimelineElement[], val?: number | null) => TimelineElement | null;
     /**
-     * Merge options. New keys will be added.
+     * get all clickable elements by the given local screen coordinate.
      */
-    _mergeOptions(previousOptions: TimelineOptions, newOptions: TimelineOptions): TimelineOptions;
+    elementFromPoint: (pos: DOMPoint, clickRadius: number, onlyTypes?: TimelineElementType[] | null) => TimelineElement[];
     /**
      * Subscribe user callback on time changed.
      */
-    onTimeChanged(callback: (eventArgs: TimelineTimeChangedEvent) => void): void;
+    onTimeChanged: (callback: (eventArgs: TimelineTimeChangedEvent) => void) => void;
     /**
      * Subscribe user callback on drag started event.
      */
-    onDragStarted(callback: (eventArgs: TimelineDragEvent) => void): void;
+    onDragStarted: (callback: (eventArgs: TimelineDragEvent) => void) => void;
     /**
      * Subscribe user callback on drag event.
      */
-    onDrag(callback: (eventArgs: TimelineDragEvent) => void): void;
+    onDrag: (callback: (eventArgs: TimelineDragEvent) => void) => void;
     /**
      * Subscribe user callback on drag finished event.
      */
-    onDragFinished(callback: (eventArgs: TimelineDragEvent) => void): void;
+    onDragFinished: (callback: (eventArgs: TimelineDragEvent) => void) => void;
     /**
      * Subscribe user callback on double click.
      */
-    onDoubleClick(callback: (eventArgs: TimelineClickEvent) => void): void;
+    onDoubleClick: (callback: (eventArgs: TimelineClickEvent) => void) => void;
     /**
      * Subscribe user callback on keyframe changed event.
      */
-    onKeyframeChanged(callback: (eventArgs: TimelineKeyframeChangedEvent) => void): void;
+    onKeyframeChanged: (callback: (eventArgs: TimelineKeyframeChangedEvent) => void) => void;
     /**
      * Subscribe user callback on drag finished event.
      */
-    onMouseDown(callback: (eventArgs: TimelineClickEvent) => void): void;
+    onMouseDown: (callback: (eventArgs: TimelineClickEvent) => void) => void;
     /**
      * Subscribe user callback on selected.
      */
-    onSelected(callback: (eventArgs: TimelineSelectedEvent) => void): void;
+    onSelected: (callback: (eventArgs: TimelineSelectedEvent) => void) => void;
     /**
      * Subscribe user callback on scroll event
      */
-    onScroll(callback: (eventArgs: TimelineScrollEvent) => void): void;
-    onScrollFinished(callback: (eventArgs: TimelineScrollEvent) => void): void;
-    _emitScrollEvent(args: MouseEvent | null, scrollProgrammatically: boolean, eventType?: TimelineEvents): TimelineScrollEvent;
-    _emitKeyframeChanged(element: TimelineElementDragState, source?: TimelineEventSource): TimelineKeyframeChangedEvent;
-    _emitDragStartedEvent(): TimelineDragEvent;
+    onScroll: (callback: (eventArgs: TimelineScrollEvent) => void) => void;
+    /**
+     * Subscribe on scroll finished event.
+     */
+    onScrollFinished: (callback: (eventArgs: TimelineScrollEvent) => void) => void;
+    /**
+     * Private.
+     * Emit internally scroll eve
+     */
+    _emitScrollEvent: (args: Event | null, scrollProgrammatically: boolean, eventType?: TimelineEvents) => TimelineScrollEvent;
+    _emitKeyframeChanged: (element: TimelineElementDragState, source?: TimelineEventSource) => TimelineKeyframeChangedEvent;
+    _emitDragStartedEvent: (dragState: TimelineDraggableData) => TimelineDragEvent | null;
     /**
      * Private emit timeline event that dragging element is finished.
      * @param forcePrevent - needed when during dragging components set to the state when they cannot be dragged anymore. (used only as recovery state).
      * @returns
      */
-    _emitDragFinishedEvent(forcePrevent?: boolean): TimelineDragEvent;
-    _preventDrag(dragArgs: TimelineDragEvent, data: TimelineDraggableData, toStart?: boolean): void;
-    _emitDragEvent(): TimelineDragEvent;
-    _emitKeyframesSelected(state: TimelineSelectionResults): TimelineSelectedEvent;
-    _getDragEventArgs(): TimelineDragEvent;
+    _emitDragFinishedEvent: (dragState: TimelineDraggableData, forcePrevent?: boolean) => TimelineDragEvent | null;
+    _preventDrag: (dragArgs: TimelineDragEvent, data: TimelineDraggableData, toStart?: boolean) => void;
+    _emitDragEvent: (dragState: TimelineDraggableData) => TimelineDragEvent | null;
+    _emitKeyframesSelected: (state: TimelineSelectionResults) => TimelineSelectedEvent;
+    _getDragEventArgs: (dragState: TimelineDraggableData, point: TimelineMouseData | null) => TimelineDragEvent;
 }

+ 21 - 5
lib/timelineEventsEmitter.d.ts

@@ -1,18 +1,34 @@
-interface Event {
+interface TimelineEvent {
     topic: string;
     callback: (args: any) => void;
 }
+/**
+ * Timeline events emitter.
+ */
 export declare class TimelineEventsEmitter {
-    protected _subscriptions: Array<Event>;
-    on(topic: string, callback: (args: any) => void): void;
+    /**
+     * Active events subscriptions.
+     */
+    _subscriptions: TimelineEvent[];
+    /**
+     * Subscribe event.
+     * @param topic event name.
+     * @param callback callback to be added.
+     */
+    on<T>(topic: string, callback: (args: T) => void): boolean;
     /**
      * Remove an event from the subscriptions list.
      */
-    off(topic: string, callback: (args: any) => void): void;
+    off<T>(topic: string, callback: (args: T) => void): boolean;
     /**
      * Unsubscribe all
      */
     offAll(): void;
-    emit(topic: string, args: any): void;
+    /**
+     * Emit event.
+     * @param topic Event name.
+     * @param args Event arguments.
+     */
+    emit<T>(topic: string, args: T): void;
 }
 export {};

+ 11 - 0
lib/timelineGroup.d.ts

@@ -0,0 +1,11 @@
+import { TimelineGroupStyle } from './settings/styles/timelineGroupStyle';
+/**
+ * Timeline group view model.
+ */
+export interface TimelineGroup {
+    style: TimelineGroupStyle;
+    /**
+     * Whether group of keyframes are draggable.
+     */
+    draggable?: boolean;
+}

+ 5 - 4
lib/timelineKeyframe.d.ts

@@ -1,11 +1,12 @@
 import { TimelineKeyframeStyle } from './settings/styles/timelineKeyframeStyle';
-import { Selectable } from './utils/selectable';
+import { TimelineSelectable } from './utils/timelineSelectable';
 import { TimelineRanged } from './timelineRanged';
-export interface TimelineKeyframe extends TimelineKeyframeStyle, Selectable, TimelineRanged {
+import { TimelineGroup } from './timelineGroup';
+export interface TimelineKeyframe extends TimelineKeyframeStyle, TimelineSelectable, TimelineRanged {
     val: number;
     /**
      * Related keyframe group.
-     * Timeline keyframes groups are rendered as one bundle.
+     * Timeline keyframes groups are rendered as one instance.
      */
-    group?: any;
+    group?: string | TimelineGroup;
 }

+ 1 - 1
lib/timelineModel.d.ts

@@ -1,4 +1,4 @@
 import { TimelineRow } from './timelineRow';
 export interface TimelineModel {
-    rows: Array<TimelineRow>;
+    rows: TimelineRow[];
 }

+ 0 - 8
lib/timelineRanged.d.ts

@@ -7,12 +7,4 @@ export interface TimelineRanged {
      * max.
      */
     max?: number | null;
-    /**
-     * Allow to calculate min.
-     */
-    getMin?: () => number;
-    /**
-     * Allow to calculate max.
-     */
-    getMax?: () => number;
 }

+ 4 - 2
lib/timelineRow.d.ts

@@ -1,6 +1,8 @@
 import { TimelineKeyframe } from './timelineKeyframe';
 import { TimelineRowStyle } from './settings/styles/timelineRowStyle';
 import { TimelineRanged } from './timelineRanged';
-export interface TimelineRow extends TimelineRowStyle, TimelineRanged {
-    keyframes?: Array<TimelineKeyframe>;
+export interface TimelineRow extends TimelineRanged {
+    keyframes?: TimelineKeyframe[] | null;
+    style?: TimelineRowStyle;
+    hidden?: boolean;
 }

+ 5 - 4
lib/utils/TimelineElement.d.ts

@@ -1,6 +1,7 @@
-import { TimelineKeyframe } from '../timelineKeyframe';
+import { TimelineKeyframe } from '../models/timelineKeyframe';
 import { TimelineElementType } from '../enums/timelineElementType';
-import { TimelineRow } from '../timelineRow';
+import { TimelineRow } from '../models/timelineRow';
+import { TimelineGroup } from '../models/timelineGroup';
 /**
  * Timeline clickable element.
  */
@@ -21,9 +22,9 @@ export interface TimelineElement {
     /**
      * Current group.
      */
-    group?: any;
+    group?: string | TimelineGroup;
     /**
      * List of the selected, grouped, row keyframes.
      */
-    keyframes?: Array<TimelineKeyframe>;
+    keyframes?: TimelineKeyframe[];
 }

+ 1 - 1
lib/utils/TimelineElementDragState.d.ts

@@ -1,7 +1,7 @@
 import { TimelineElement } from './timelineElement';
 export interface TimelineElementDragState extends TimelineElement {
     /**
-     * Drag started value.
+     * Value that preserved before dragging is started.
      */
     startedVal: number;
     /**

+ 3 - 0
lib/utils/events/timelineBaseEvent.d.ts

@@ -1,3 +1,6 @@
+/**
+ * Timeline base preventable event.
+ */
 export declare class TimelineBaseEvent {
     private _prevented;
     /**

+ 11 - 18
lib/utils/events/timelineClickEvent.d.ts

@@ -1,30 +1,23 @@
 import { TimelineElement } from '../timelineElement';
+import { TimelinePoint } from '../timelinePoint';
 import { TimelineBaseEvent } from './timelineBaseEvent';
-import { TimelineValues } from '../timelineValues';
-export declare class TimelineClickEvent extends TimelineBaseEvent implements TimelineValues {
-    args: MouseEvent;
+export declare class TimelineClickEvent extends TimelineBaseEvent {
+    args: MouseEvent | TouchEvent | null;
     /**
      * Clicked screen position.
      */
-    pos: DOMPoint;
+    get pos(): DOMPoint | null;
+    get val(): number;
     /**
-     * Elements list under the click
+     * All elements located under current mouse activity.
      */
-    elements: Array<TimelineElement>;
+    elements: TimelineElement[];
     /**
-     * Target element
+     * Element that selected as target under the click.
      */
-    target: TimelineElement;
+    target: TimelineElement | null;
     /**
-     * Value to be used.
+     * Timeline current active drag position.
      */
-    val: number;
-    /**
-     * Snapped value.
-     */
-    snapVal: number;
-    /**
-     * Unsnapped original value.
-     */
-    originalVal: number;
+    point: TimelinePoint | null;
 }

+ 10 - 21
lib/utils/events/timelineDragEvent.d.ts

@@ -1,34 +1,23 @@
-import { TimelineValues } from '../timelineValues';
+import { TimelinePoint } from '../timelinePoint';
 import { TimelineBaseEvent } from './timelineBaseEvent';
 import { TimelineElementDragState } from '../timelineElementDragState';
-export declare class TimelineDragEvent extends TimelineBaseEvent implements TimelineValues {
-    args: MouseEvent;
-    /**
-     * Clicked screen position.
-     */
-    pos: DOMPoint;
+export declare class TimelineDragEvent extends TimelineBaseEvent {
+    args: MouseEvent | TouchEvent | null;
+    get pos(): DOMPoint | null;
     /**
      * Elements to be dragged as a group.
      */
-    elements: Array<TimelineElementDragState>;
+    elements: TimelineElementDragState[] | null;
     /**
      * Target element
      */
-    target: TimelineElementDragState;
-    /**
-     * Value to be used.
-     */
-    val: number;
-    /**
-     * prev value.
-     */
-    prevVal: number;
+    target: TimelineElementDragState | null;
     /**
-     * Snapped value.
+     * Timeline current active drag position.
      */
-    snapVal: number;
+    point: TimelinePoint | null;
     /**
-     * Unsnapped original value.
+     * Timeline previous drag position.
      */
-    originalVal: number;
+    prevPoint: TimelinePoint | null;
 }

+ 15 - 5
lib/utils/events/timelineSelectedEvent.d.ts

@@ -1,6 +1,16 @@
-import { TimelineKeyframe } from '../../timelineKeyframe';
-import { TimelineBaseEvent } from './timelineBaseEvent';
-export declare class TimelineSelectedEvent extends TimelineBaseEvent {
-    selected: Array<TimelineKeyframe>;
-    changed: Array<TimelineKeyframe>;
+import { TimelineSelectionEventSource } from '../../enums/timelineSelectionEventSource';
+import { TimelineKeyframe } from '../../models/timelineKeyframe';
+export declare class TimelineSelectedEvent {
+    /**
+     * Selected Keyframes list.
+     */
+    selected: TimelineKeyframe[];
+    /**
+     * Changed selection.
+     */
+    changed: TimelineKeyframe[];
+    /**
+     * Selection mode.
+     */
+    mode: TimelineSelectionEventSource;
 }

+ 5 - 2
lib/utils/events/timelineTimeChangedEvent.d.ts

@@ -2,12 +2,15 @@ import { TimelineBaseEvent } from './timelineBaseEvent';
 import { TimelineEventSource } from '../../enums/timelineEventSource';
 export declare class TimelineTimeChangedEvent extends TimelineBaseEvent {
     /**
-     * new value to be set.
+     * New value to be set if not prevented.
      */
     val: number;
     /**
-     * previous value.
+     * previous value, that actually set at the moment.
      */
     prevVal: number;
+    /**
+     * Source of the change.
+     */
     source: TimelineEventSource;
 }

+ 1 - 1
lib/utils/timelineCalculated.d.ts

@@ -8,5 +8,5 @@ export interface TimelineCalculated extends TimelineRanged {
     /**
      * model keyframes.
      */
-    keyframes: Array<TimelineCalculatedKeyframe>;
+    keyframes: TimelineCalculatedKeyframe[];
 }

+ 2 - 1
lib/utils/timelineCutBoundsRectResults.d.ts

@@ -1,7 +1,8 @@
 /**
  * Helper container. Cut bounds method results.
  */
-export interface TimelineCutBoundsRectResults extends DOMRect {
+export interface TimelineCutBoundsRectResults {
+    rect: DOMRect;
     overlapY: boolean;
     overlapX: boolean;
 }

+ 13 - 3
lib/utils/timelineDraggableData.d.ts

@@ -1,7 +1,12 @@
 import { TimelineElementType } from '../enums/timelineElementType';
-import { TimelineValues } from './timelineValues';
 import { TimelineElementDragState } from './timelineElementDragState';
-export interface TimelineDraggableData extends TimelineValues {
+/**
+ * Information about current drag state.
+ */
+export declare class TimelineDraggableData {
+    /**
+     * Whether position was changed.
+     */
     changed: boolean;
     /**
      * Drag initial click target.
@@ -9,12 +14,17 @@ export interface TimelineDraggableData extends TimelineValues {
     target: TimelineElementDragState;
     /**
      * Elements to be dragged.
+     * Can be multiple elements, but drag will be started with target.
      */
-    elements: Array<TimelineElementDragState>;
+    elements: TimelineElementDragState[];
     /**
      * Dragging type.
      */
     type: TimelineElementType;
+    /**
+     * Prev value.
+     */
+    val: number;
     /**
      * Prev value.
      */

+ 4 - 1
lib/utils/timelineModelCalcResults.d.ts

@@ -1,8 +1,11 @@
 import { TimelineCalculated } from './timelineCalculated';
 import { TimelineCalculatedRow } from './timelineCalculatedRow';
+/**
+ * View model given with the calculated information.
+ */
 export interface TimelineModelCalcResults extends TimelineCalculated {
     /**
      * Collection of the rows sizes.
      */
-    rows: Array<TimelineCalculatedRow>;
+    rows: TimelineCalculatedRow[];
 }

+ 7 - 4
lib/utils/timelineMouseData.d.ts

@@ -1,11 +1,14 @@
-import { TimelineValues } from './timelineValues';
+import { TimelinePoint } from './timelinePoint';
 /**
  * Mouse data helper container.
  */
-export interface TimelineMouseData extends TimelineValues, DOMPoint {
+export interface TimelineMouseData extends TimelinePoint {
     /**
-     * Click radius
+     * Originated event args.
+     */
+    args: TouchEvent | MouseEvent;
+    /**
+     * Click radius.
      */
     radius?: number;
-    args?: TouchEvent | MouseEvent;
 }

+ 22 - 0
lib/utils/timelinePoint.d.ts

@@ -0,0 +1,22 @@
+/**
+ * Timeline values interface.
+ */
+export interface TimelinePoint {
+    /**
+     * Value used for the visualization.
+     * It can be snapped or original.
+     */
+    val: number;
+    /**
+     * Snapped value if snapping is enabled. In other case corresponding to original value.
+     */
+    snapVal: number;
+    /**
+     * Unsnapped original value.
+     */
+    originalVal: number;
+    /**
+     * Screen click point.
+     */
+    pos: DOMPoint;
+}

+ 7 - 0
lib/utils/timelineSelectable.d.ts

@@ -0,0 +1,7 @@
+/**
+ * Timeline selectable element.
+ */
+export interface TimelineSelectable {
+    selected?: boolean;
+    selectable?: boolean;
+}

+ 3 - 3
lib/utils/timelineSelectionResults.d.ts

@@ -1,13 +1,13 @@
-import { TimelineKeyframe } from '../timelineKeyframe';
+import { TimelineKeyframe } from '../models/timelineKeyframe';
 export interface TimelineSelectionResults {
     /**
      * Changed nodes.
      */
-    changed: Array<TimelineKeyframe>;
+    changed: TimelineKeyframe[];
     /**
      * Selected nodes.
      */
-    selected: Array<TimelineKeyframe>;
+    selected: TimelineKeyframe[];
     /**
      * Whether data was changed.
      */

+ 32 - 28
lib/utils/timelineStyleUtils.d.ts

@@ -1,37 +1,41 @@
-import { TimelineRow } from '../timelineRow';
 import { TimelineOptions } from '../settings/timelineOptions';
 import { TimelineRowStyle } from '../settings/styles/timelineRowStyle';
-import { TimelineKeyframeStyle } from '../settings/styles/timelineKeyframeStyle';
 import { TimelineKeyframeShape } from '../enums/timelineKeyframeShape';
+import { TimelineGroupStyle } from '../settings/styles/timelineGroupStyle';
+import { TimelineKeyframe } from '../models/timelineKeyframe';
+import { TimelineGroup } from '../models/timelineGroup';
+import { TimelineRow } from '../models/timelineRow';
 export declare class TimelineStyleUtils {
+    static getGroup(groupModel: TimelineGroup | string | null | undefined): TimelineGroup | null;
+    static getGroupStyle(groupModel: TimelineGroup | string | null | undefined): TimelineGroupStyle | null;
+    static getFirstSet<T>(defaultValue: T, ...params: Array<T | undefined | null>): T;
     /**
-     * Get keyframe style from a keyframe, than from a row, than from a global settings.
-     * @param keyframe keyframe to get style for.
-     * @param row keyframe row.
-     * @param propertyName property to get.
-     * @param defaultValue default value to return
-     * @param reverseOrder reverse styling order: global, row, keyframe
+     * Get first value set or default.
+     * @param defaultValue default value in a case when no value is set.
+     * @param returnFalseIfAnyFalse - find first negative bool and return false.
+     * @param params collection of values to check.
+     * @returns value.
      */
-    static getKeyframeStyle<T>(keyframeStyle: TimelineKeyframeStyle | null, rowStyle: TimelineRow | null, options: TimelineOptions | null, propertyName: string, defaultValue?: T, reverseOrder?: boolean): T;
+    static getValue<T>(defaultValue: T, returnFalseIfAnyFalse?: boolean, ...params: Array<T | undefined | null>): T;
+    static getValueOrDefault<T>(value: T, defaultValue: T): T | undefined;
+    static keyframeWidth(keyframe: TimelineKeyframe | null | undefined, group: TimelineGroup | string | null | undefined, rowStyle: TimelineRowStyle | null | undefined, options: TimelineOptions | null | undefined): number | string;
+    static keyframeHeight(keyframe: TimelineKeyframe | null | undefined, group: TimelineGroup | string | null | undefined, rowStyle: TimelineRowStyle | null | undefined, options: TimelineOptions | null | undefined): number | string;
+    static keyframeShape(keyframe: TimelineKeyframe | null, group: TimelineGroup | string | null | undefined, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): TimelineKeyframeShape;
+    static keyframeFillColor(keyframe: TimelineKeyframe | null, group: TimelineGroup | string | null | undefined, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): string;
+    static keyframeSelectedFillColor(keyframe: TimelineKeyframe | null, group: TimelineGroup | string | null | undefined, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): string;
+    static keyframeStrokeThickness(keyframe: TimelineKeyframe | null, group: TimelineGroup | string | null | undefined, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): number;
+    static keyframeStrokeColor(keyframe: TimelineKeyframe | null, group: TimelineGroup | string | null | undefined, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): string;
+    static keyframeSelectedStrokeColor(keyframe: TimelineKeyframe | null, group: TimelineGroup | string | null, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): string;
+    static groupHeight(options: TimelineOptions | null | undefined, group: TimelineGroup | string | null | undefined, rowStyle: TimelineRowStyle | null | undefined): number | string;
+    static groupMarginTop(options: TimelineOptions | null | undefined, group: TimelineGroup | string | null | undefined, rowStyle: TimelineRowStyle | null | undefined): number | string;
+    static groupFillColor(options: TimelineOptions | null | undefined, group: TimelineGroup | string | null | undefined, rowStyle: TimelineRowStyle | null | undefined): string;
     /**
-     * Get row style from default settings or overrides by a row settings.
+     * Get current row height from styles
      */
-    static getRowStyle<T>(rowStyle: TimelineRowStyle, options: TimelineOptions | null, propertyName: string, defaultValue?: T, reverseOrder?: boolean): T | undefined;
-    static keyframeShape(keyframe: TimelineKeyframeStyle | null, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): TimelineKeyframeShape;
-    static keyframeFillColor(keyframe: TimelineKeyframeStyle | null, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): string;
-    static keyframeSelectedFillColor(keyframe: TimelineKeyframeStyle | null, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): string;
-    static keyframeStrokeThickness(keyframe: TimelineKeyframeStyle | null, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): number;
-    static keyframeStrokeColor(keyframe: TimelineKeyframeStyle | null, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): string;
-    static keyframeSelectedStrokeColor(keyframe: TimelineKeyframeStyle | null, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): string;
-    /**
-     * Get current row height from styling
-     */
-    static getRowHeight(rowStyle: TimelineRowStyle, options: TimelineOptions): number;
-    static rowGroupHeight(rowStyle: TimelineRowStyle, options: TimelineOptions): number | string;
-    static groupFillColor(rowStyle: TimelineRowStyle, options: TimelineOptions): string | null;
-    static getRowMarginBottom(rowStyle: TimelineRowStyle, options: TimelineOptions): number;
-    static getRowFillColor(rowStyle: TimelineRowStyle, options: TimelineOptions): string;
-    static headerHeight(options: TimelineOptions | null): number;
-    static keyframeDraggable(keyframe: TimelineKeyframeStyle | null, rowStyle: TimelineRowStyle | null, options: TimelineOptions | null, defaultValue?: boolean): boolean;
-    static groupDraggable(rowStyle: TimelineRowStyle, options: TimelineOptions, defaultValue?: boolean): boolean;
+    static getRowHeight(rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): number;
+    static getRowMarginBottom(rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): number;
+    static getRowFillColor(rowStyle: TimelineRowStyle | null, options: TimelineOptions | null): string;
+    static headerHeight(options: TimelineOptions | null, defaultRowHeight?: number): number;
+    static keyframeDraggable(keyframe: TimelineKeyframe | null, group: TimelineGroup | string | null, row: TimelineRow | null, options: TimelineOptions | null, defaultValue?: boolean): boolean;
+    static groupDraggable(group: TimelineGroup | string | null | undefined, row: TimelineRow | null, options: TimelineOptions): boolean;
 }

+ 23 - 6
lib/utils/timelineUtils.d.ts

@@ -1,13 +1,14 @@
-import { TimelineRanged } from '../timelineRanged';
+import { TimelineRanged } from '../models/timelineRanged';
+import { TimelineOptions } from '../settings/timelineOptions';
 export declare class TimelineUtils {
     static drawLine(ctx: CanvasRenderingContext2D, x1: number, y1: number, x2: number, y2: number): void;
     /**
      * Check is valid number.
      */
-    static isNumber(val?: number): boolean;
+    static isNumber(val?: number | null): boolean;
     static deleteElement<T>(array: Array<T>, element: T): Array<T>;
     /**
-     * Check rectangle overlap.
+     * Check rectangle overlap x,y
      */
     static isOverlap(x: number, y: number, rectangle: DOMRect): boolean;
     /**
@@ -17,11 +18,27 @@ export declare class TimelineUtils {
     /**
      * Keep value in min, max bounds.
      */
-    static keepInBounds(value: number, min?: number | undefined, max?: number | undefined): number;
-    static setMinMax(to: TimelineRanged, from: TimelineRanged, shrink?: boolean): TimelineRanged;
-    static isRectOverlap(rect: DOMRect, rect2: DOMRect): boolean;
+    static keepInBounds(value: number, min?: number | null | undefined, max?: number | null | undefined): number;
+    static setMinMax(to: TimelineRanged, from: TimelineRanged | null, shrink?: boolean): TimelineRanged;
+    static shrinkSelf(rect: DOMRect, value: number): DOMRect;
+    /**
+     * Check whether rectangle intersects another rectangle
+     */
+    static isRectIntersects(rect: DOMRect, rect2: DOMRect, touch?: boolean): boolean;
     static getDistance(x1: number, y1: number, x2?: number, y2?: number): number;
+    /**
+     * Get sign of the number. 1 or -1.
+     */
     static sign(p: number): number;
+    /**
+     * Clear browser text selection.
+     */
     static clearBrowserSelection(): void;
     static getPowArgument(toCheck: number): number;
+    static deepClone: <T>(previousOptions: T) => T;
+    static cloneOptions: (previousOptions: TimelineOptions) => TimelineOptions;
+    /**
+     * Merge options. New keys will be added.
+     */
+    static mergeOptions(previousOptions: TimelineOptions, newOptions: TimelineOptions): TimelineOptions;
 }

+ 2 - 2
lib/utils/timelineValues.d.ts

@@ -3,11 +3,11 @@
  */
 export interface TimelineValues {
     /**
-     * Value to be used.
+     * Value used for the visualization.
      */
     val: number;
     /**
-     * Snapped value.
+     * Snapped value (val property will be snapped if snapping was enabled)
      */
     snapVal?: number;
     /**

+ 24 - 0
lib/viewModels/timelineGroupViewModel.d.ts

@@ -0,0 +1,24 @@
+import { TimelineGroup } from '../models/timelineGroup';
+import { TimelineKeyframeViewModel } from './timelineKeyframeViewModel';
+export interface TimelineGroupViewModel {
+    /**
+     * Size of the element in screen coordinates.
+     */
+    size: DOMRect | null;
+    /**
+     * From value in the timeline keyframes collection.
+     */
+    min: number;
+    /**
+     * To value in the timeline keyframes collection.
+     */
+    max: number;
+    /**
+     * Related Group Model.
+     */
+    groupModel: string | TimelineGroup;
+    /**
+     * Related Grouped keyframes view models.
+     */
+    keyframesViewModels: TimelineKeyframeViewModel[];
+}

+ 26 - 0
lib/viewModels/timelineKeyframeViewModel.d.ts

@@ -0,0 +1,26 @@
+import { TimelineKeyframeShape } from '../enums/timelineKeyframeShape';
+import { TimelineKeyframe } from '../models/timelineKeyframe';
+import { TimelineGroupViewModel } from './timelineGroupViewModel';
+import { TimelineRowViewModel } from './timelineRowViewModel';
+/**
+ * Timeline calculated view model.
+ */
+export interface TimelineKeyframeViewModel {
+    /**
+     * Size of the keyframe.
+     */
+    size: DOMRect;
+    shape: TimelineKeyframeShape;
+    /**
+     * Related keyframe model.
+     */
+    model: TimelineKeyframe;
+    /**
+     * Related calculated parent row view model.
+     */
+    rowViewModel: TimelineRowViewModel;
+    /**
+     * Related calculated parent group view model.
+     */
+    groupViewModel: TimelineGroupViewModel;
+}

+ 31 - 0
lib/viewModels/timelineRowViewModel.d.ts

@@ -0,0 +1,31 @@
+import { TimelineRow } from '../models/timelineRow';
+import { TimelineGroupViewModel } from './timelineGroupViewModel';
+import { TimelineKeyframeViewModel } from './timelineKeyframeViewModel';
+export interface TimelineRowViewModel {
+    /**
+     * Screen coordinates of the element.
+     */
+    size: DOMRect;
+    /**
+     * Related row model.
+     */
+    model: TimelineRow;
+    /**
+     * Current row index.
+     */
+    index: number;
+    /**
+     * Row margin bottom
+     */
+    marginBottom: number;
+    /**
+     * Collection of the keyframes groups view models exists in the current row.
+     */
+    groupsViewModels: TimelineGroupViewModel[];
+    /**
+     * All keyframes in the current row.
+     */
+    keyframesViewModels: TimelineKeyframeViewModel[];
+    min: number | null;
+    max: number | null;
+}

+ 18 - 0
lib/viewModels/timelineViewModel.d.ts

@@ -0,0 +1,18 @@
+import { TimelineKeyframeViewModel } from './timelineKeyframeViewModel';
+import { TimelineRowViewModel } from './timelineRowViewModel';
+export interface TimelineViewModel {
+    /**
+     * Screen coordinates of the element.
+     */
+    size: DOMRect;
+    /**
+     * Keyframes view models.
+     */
+    keyframesViewModels: TimelineKeyframeViewModel[];
+    /**
+     * Collection of the rows sizes.
+     */
+    rowsViewModels: TimelineRowViewModel[];
+    min: number | null;
+    max: number | null;
+}

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 356 - 259
package-lock.json


+ 17 - 17
package.json

@@ -1,33 +1,33 @@
 {
   "name": "animation-timeline-js",
-  "version": "2.2.3",
+  "version": "2.3.0",
   "description": "animation timeline control based on the canvas.",
   "main": "lib/animation-timeline.min.js",
   "types": "lib/animation-timeline.d.ts",
   "devDependencies": {
     "@babel/cli": "7.19.3",
-    "@babel/core": "7.19.6",
+    "@babel/core": "7.20.5",
     "@babel/plugin-proposal-class-properties": "7.18.6",
-    "@babel/preset-env": "7.19.4",
+    "@babel/preset-env": "7.20.2",
     "@babel/preset-typescript": "7.18.6",
-    "@types/chai": "4.3.3",
-    "@types/mocha": "10.0.0",
-    "@typescript-eslint/eslint-plugin": "5.42.0",
-    "@typescript-eslint/parser": "5.42.0",
-    "babel-loader": "9.0.1",
-    "chai": "4.3.6",
-    "eslint": "8.26.0",
+    "@types/chai": "4.3.4",
+    "@types/mocha": "10.0.01",
+    "@typescript-eslint/eslint-plugin": "5.46.1",
+    "@typescript-eslint/parser": "5.46.1",
+    "babel-loader": "9.1.0",
+    "chai": "4.3.7",
+    "eslint": "8.30.0",
     "eslint-config-prettier": "8.5.0",
     "eslint-plugin-prettier": "4.2.1",
-    "mocha": "10.1.0",
-    "prettier": "2.7.1",
-    "ts-loader": "9.4.1",
-    "typescript": "4.8.4",
-    "webpack": "5.74.0",
-    "webpack-cli": "4.10.0"
+    "mocha": "10.2.0",
+    "prettier": "2.8.1",
+    "ts-loader": "9.4.2",
+    "typescript": "4.9.4",
+    "webpack": "5.75.0",
+    "webpack-cli": "5.0.1"
   },
   "scripts": {
-    "start": "echo \"Run index.html in your browser. Build after files are changed.\" && exit 1",
+    "start": "echo \"Run npm build and run index.html in your browser. You have to run build command every time files are changed.\" && exit 1",
     "test": "echo \"Run tests/unittest.html explicitly to execute tests. Build after files are changed.\" && exit 1",
     "build-ts-def": "tsc -emitDeclarationOnly",
     "build": "webpack && npm run build-ts-def && npm run build-tests",

+ 17 - 12
src/animation-timeline.ts

@@ -1,12 +1,13 @@
 // bundle entry point
 
 export * from './timeline';
-export * from './timelineModel';
-export * from './timelineRow';
-export * from './timelineKeyframe';
 export * from './timelineEventsEmitter';
 export * from './settings/timelineConsts';
-export * from './timelineRanged';
+// @ public timeline models.
+export * from './models/timelineRanged';
+export * from './models/timelineModel';
+export * from './models/timelineRow';
+export * from './models/timelineKeyframe';
 
 // @public styles
 export * from './settings/timelineOptions';
@@ -19,20 +20,19 @@ export * from './utils/timelineUtils';
 export * from './utils/timelineElement';
 
 // @private helper containers.
-export * from './utils/selectable';
+export * from './utils/timelineSelectable';
 export * from './utils/timelineCutBoundsRectResults';
 export * from './utils/timelineSelectionResults';
-export * from './utils/timelineValues';
+export * from './utils/timelinePoint';
 export * from './utils/timelineMouseData';
 export * from './utils/timelineElementDragState';
 export * from './utils/timelineDraggableData';
 
 // @private virtual model
-export * from './utils/timelineModelCalcResults';
-export * from './utils/timelineCalculatedRow';
-export * from './utils/timelineCalculatedGroup';
-export * from './utils/timelineCalculated';
-export * from './utils/timelineCalculatedKeyframe';
+export * from './viewModels/timelineGroupViewModel';
+export * from './viewModels/timelineKeyframeViewModel';
+export * from './viewModels/timelineRowViewModel';
+export * from './viewModels/timelineViewModel';
 
 // @public events
 export * from './utils/events/timelineKeyframeChangedEvent';
@@ -53,4 +53,9 @@ export * from './enums/timelineEventSource';
 export * from './enums/timelineSelectionMode';
 export * from './enums/timelineEvents';
 // @private defaults are exposed:
-export * from './settings/defaults';
+export * from './settings/defaults/defaultTimelineStyle';
+export * from './settings/defaults/defaultTimelineRowStyle';
+export * from './settings/defaults/defaultTimelineOptions';
+export * from './settings/defaults/defaultTimelineKeyframeStyle';
+export * from './settings/defaults/defaultTimelineConsts';
+export * from './settings/defaults/defaultGroupStyle';

+ 6 - 2
src/enums/timelineElementType.ts

@@ -1,3 +1,6 @@
+/**
+ * Internal element type.
+ */
 export enum TimelineElementType {
   /**
    * Timeline
@@ -8,11 +11,12 @@ export enum TimelineElementType {
    */
   Keyframe = 'keyframe',
   /**
-   * Keyframes group
+   * Keyframes connected and presenting one group.
    */
   Group = 'group',
   /**
-   * Row
+   * Timeline row.
    */
   Row = 'row',
+  None = 'none',
 }

+ 6 - 0
src/enums/timelineEventSource.ts

@@ -1,5 +1,11 @@
 export enum TimelineEventSource {
+  /**
+   * Changed by user interaction events.
+   */
   User = 'user',
+  /**
+   * Changed programmatically.
+   */
   Programmatically = 'programmatically',
   SetTimeMethod = 'setTimeMethod',
 }

+ 3 - 0
src/enums/timelineEvents.ts

@@ -1,3 +1,6 @@
+/**
+ * Event names of the component.
+ */
 export enum TimelineEvents {
   Selected = 'selected',
   TimeChanged = 'timechanged',

+ 2 - 2
src/enums/timelineInteractionMode.ts

@@ -9,7 +9,7 @@ export enum TimelineInteractionMode {
   Pan = 'pan',
   /**
    * Allow only pan without any keyframes interaction.
-   * Timeline still can be moved and controlled by option 'timelineInteractive'.
+   * Timeline still can be moved and controlled by option 'timelineDraggable'.
    */
   NonInteractivePan = 'nonInteractivePan',
   /**
@@ -19,7 +19,7 @@ export enum TimelineInteractionMode {
 
   /**
    * No iteraction, except moving a timeline.
-   * Timeline still can be moved and controlled by option 'timelineInteractive'.
+   * Timeline still can be moved and controlled by option 'timelineDraggable'.
    */
   None = 'none',
 }

+ 9 - 0
src/enums/timelineSelectionEventSource.ts

@@ -0,0 +1,9 @@
+/**
+ * Timeline selection event type.
+ */
+export enum TimelineSelectionEventSource {
+  /**
+   * Keyframe selection is performed.
+   */
+  Keyframes = 'keyframes',
+}

+ 28 - 0
src/models/timelineGroup.ts

@@ -0,0 +1,28 @@
+import { TimelineKeyframeStyle } from '../settings/styles/timelineKeyframeStyle';
+import { TimelineGroupStyle } from '../settings/styles/timelineGroupStyle';
+/**
+ * Timeline group view model.
+ */
+export interface TimelineGroup {
+  /**
+   * Group style.
+   */
+  style: TimelineGroupStyle;
+  /**
+   * Child keyframes style.
+   */
+  keyframesStyle: TimelineKeyframeStyle;
+  /**
+   * Whether group is draggable.
+   * Considered to be false when really set as false.
+   */
+  draggable?: boolean;
+  /**
+   * Whether group keyframes are draggable.
+   */
+  keyframesDraggable?: boolean;
+  /**
+   * Whether group is hidden.
+   */
+  hidden?: boolean;
+}

+ 30 - 0
src/models/timelineKeyframe.ts

@@ -0,0 +1,30 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { TimelineKeyframeStyle } from '../settings/styles/timelineKeyframeStyle';
+import { TimelineSelectable } from '../utils/timelineSelectable';
+import { TimelineRanged } from './timelineRanged';
+import { TimelineGroup } from './timelineGroup';
+
+export interface TimelineKeyframe extends TimelineSelectable, TimelineRanged {
+  /**
+   * Keyframe value.
+   */
+  val: number;
+  /**
+   * Related keyframe group.
+   * Timeline keyframes groups are rendered as one instance.
+   */
+  group?: string | TimelineGroup;
+  /**
+   * Keyframe style.
+   */
+  style?: TimelineKeyframeStyle;
+  /**
+   * Whether keyframe is hidden.
+   */
+  hidden?: boolean;
+  /**
+   * Whether group is draggable.
+   * Considered to be false when really set as false.
+   */
+  draggable?: boolean;
+}

+ 1 - 1
src/timelineModel.ts → src/models/timelineModel.ts

@@ -1,4 +1,4 @@
 import { TimelineRow } from './timelineRow';
 export interface TimelineModel {
-  rows: Array<TimelineRow>;
+  rows: TimelineRow[];
 }

+ 10 - 0
src/models/timelineRanged.ts

@@ -0,0 +1,10 @@
+export interface TimelineRanged {
+  /**
+   * min
+   */
+  min?: number | null;
+  /**
+   * max.
+   */
+  max?: number | null;
+}

+ 14 - 0
src/models/timelineRow.ts

@@ -0,0 +1,14 @@
+import { TimelineKeyframe } from './timelineKeyframe';
+import { TimelineRowStyle } from '../settings/styles/timelineRowStyle';
+import { TimelineRanged } from './timelineRanged';
+
+export interface TimelineRow extends TimelineRanged {
+  style?: TimelineRowStyle;
+  keyframes?: TimelineKeyframe[] | null;
+  hidden?: boolean;
+  /**
+   * Whether group keyframes are draggable.
+   */
+  keyframesDraggable?: boolean;
+  groupsDraggable?: boolean;
+}

+ 11 - 0
src/settings/defaults/defaultGroupStyle.ts

@@ -0,0 +1,11 @@
+import { TimelineGroupStyle } from '../styles/timelineGroupStyle';
+export const defaultRowHeight = 24;
+const margin = 4;
+export const defaultGroupStyle = {
+  height: 'auto',
+  marginTop: margin,
+  /**
+   * Default group fill color.
+   */
+  fillColor: '#094771',
+} as TimelineGroupStyle;

+ 44 - 0
src/settings/defaults/defaultTimelineConsts.ts

@@ -0,0 +1,44 @@
+import { TimelineConsts } from '../timelineConsts';
+
+export const defaultTimelineConsts: TimelineConsts = {
+  /**
+   * Private. Auto pan speed.
+   */
+  autoPanSpeed: 50,
+  /**
+   * Private. scroll speed when mouse drag is used (from 0 to 1)
+   */
+  scrollByDragSpeed: 0.12,
+  /**
+   * Private. Determine whether item was clicked.
+   */
+  clickDetectionMs: 120,
+  /**
+   * Private. Timeout to detect double click.
+   */
+  doubleClickTimeoutMs: 400,
+  /**
+   * Private. Time in ms used to refresh scrollbars when pan is finished.
+   */
+  scrollFinishedTimeoutMs: 500,
+  /**
+   * Private. Auto pan padding
+   */
+  autoPanByScrollPadding: 10,
+  /**
+   * Private. Click threshold
+   */
+  clickThreshold: 3,
+  /**
+   * Private. Private.Click min radius for the elements detection.
+   */
+  clickDetectionMinRadius: 2,
+  /**
+   * Private. Skip some auto pan/scroll actions if they are executed more rapid than this value.
+   */
+  autoPanSpeedLimit: 10,
+  /**
+   * Private. Default auto size for the group. It's percents.
+   */
+  defaultGroupHeight: 0.7,
+} as TimelineConsts;

+ 19 - 0
src/settings/defaults/defaultTimelineKeyframeStyle.ts

@@ -0,0 +1,19 @@
+import { TimelineKeyframeShape } from '../../enums/timelineKeyframeShape';
+import { TimelineKeyframeStyle } from '../styles/timelineKeyframeStyle';
+
+export const defaultTimelineKeyframeStyle = {
+  /**
+   * keyframe fill color.
+   */
+  fillColor: 'DarkOrange',
+  shape: TimelineKeyframeShape.Rhomb,
+  /**
+   * Selected keyframe fill color.
+   */
+  selectedFillColor: 'red',
+  strokeColor: 'black',
+  selectedStrokeColor: 'black',
+  strokeThickness: 0.2,
+  height: 'auto',
+  width: 'auto',
+} as TimelineKeyframeStyle;

+ 26 - 83
src/settings/defaults.ts → src/settings/defaults/defaultTimelineOptions.ts

@@ -1,54 +1,8 @@
-import { TimelineConsts } from './timelineConsts';
-import { TimelineCapShape } from '../enums/timelineCapShape';
-import { TimelineStyle } from './styles/timelineStyle';
-import { TimelineOptions } from './timelineOptions';
-import { TimelineKeyframeShape } from '../enums/timelineKeyframeShape';
-import { TimelineKeyframeStyle } from './styles/timelineKeyframeStyle';
-import { TimelineRowStyle } from './styles/timelineRowStyle';
-
-export const defaultTimelineStyle = {
-  width: 2,
-  marginTop: 15,
-  capWidth: 4,
-  capHeight: 10,
-  /**
-   * Draw timeline rectangular cap.
-   */
-  capType: TimelineCapShape.Rect,
-  strokeColor: 'DarkOrange',
-  fillColor: 'DarkOrange',
-} as TimelineStyle;
-
-export const defaultTimelineKeyframeStyle = {
-  /**
-   * keyframe fill color.
-   */
-  fillColor: 'DarkOrange',
-  shape: TimelineKeyframeShape.Rhomb,
-  /**
-   * Selected keyframe fill color.
-   */
-  selectedFillColor: 'red',
-  strokeColor: 'black',
-  selectedStrokeColor: 'black',
-  strokeThickness: 0.2,
-  draggable: true,
-} as TimelineKeyframeStyle;
-
-export const defaultTimelineRowStyle = {
-  /**
-   * Row height in pixels.
-   */
-  height: 24,
-  marginBottom: 2,
-  fillColor: '#252526',
-  /**
-   * Keyframes group color
-   */
-  groupFillColor: '#094771',
-  groupHeight: 'auto',
-  keyframesStyle: defaultTimelineKeyframeStyle,
-} as TimelineRowStyle;
+import { TimelineOptions } from '../timelineOptions';
+import { defaultGroupStyle } from './defaultGroupStyle';
+import { defaultTimelineKeyframeStyle } from './defaultTimelineKeyframeStyle';
+import { defaultTimelineRowStyle } from './defaultTimelineRowStyle';
+import { defaultTimelineStyle } from './defaultTimelineStyle';
 
 export const defaultTimelineOptions = {
   /**
@@ -61,6 +15,9 @@ export const defaultTimelineOptions = {
    */
   snapEnabled: true,
 
+  /**
+   * Timeline style.
+   */
   timelineStyle: defaultTimelineStyle,
   /**
    * approximate step for the timeline in pixels for 1 second
@@ -97,6 +54,16 @@ export const defaultTimelineOptions = {
    * Can be overridden by setting style individually for each row.
    */
   rowsStyle: defaultTimelineRowStyle,
+
+  /**
+   * Style for the all keyframes in a current row.
+   * Individual keyframe can have own style.
+   */
+  keyframesStyle: defaultTimelineKeyframeStyle,
+  /**
+   * Style of the groups.
+   */
+  groupsStyle: defaultGroupStyle,
   /**
    * Header height in pixels
    */
@@ -131,44 +98,20 @@ export const defaultTimelineOptions = {
    */
   groupsDraggable: true,
   /**
-   * keyframes group is draggable.
+   * keyframes are draggable.
    */
   keyframesDraggable: true,
   /**
    * Timeline can be dragged or position can be changed by user interaction. Default: true
    */
-  timelineInteractive: true,
-  min: 0,
-  max: Number.MAX_VALUE,
-} as TimelineOptions;
-
-export const defaultTimelineConsts: TimelineConsts = {
-  /**
-   * Auto pan speed.
-   */
-  autoPanSpeed: 50,
-  /**
-   * scroll speed when mouse drag is used (from 0 to 1)
-   */
-  scrollByDragSpeed: 0.12,
+  timelineDraggable: true,
   /**
-   * Determine whether item was clicked.
+   * Start drawing timeline from this min point.
+   * Bounds for the keyframe dragging.
    */
-  clickDetectionMs: 120,
-  /**
-   * Timeout to detect double click.
-   */
-  doubleClickTimeoutMs: 400,
-  /**
-   * Time in ms used to refresh scrollbars when pan is finished.
-   */
-  scrollFinishedTimeoutMs: 500,
-  /**
-   * Auto pan padding
-   */
-  autoPanByScrollPadding: 10,
+  min: 0,
   /**
-   * Click threshold
+   * Max bounds timeline can navigate to.
    */
-  clickThreshold: 3,
-} as TimelineConsts;
+  max: Number.MAX_VALUE,
+} as TimelineOptions;

+ 21 - 0
src/settings/defaults/defaultTimelineRowStyle.ts

@@ -0,0 +1,21 @@
+import { TimelineRowStyle } from '../styles/timelineRowStyle';
+import { defaultGroupStyle, defaultRowHeight } from './defaultGroupStyle';
+import { defaultTimelineKeyframeStyle } from './defaultTimelineKeyframeStyle';
+
+export const defaultTimelineRowStyle = {
+  /**
+   * Row height in pixels.
+   */
+  height: defaultRowHeight,
+  marginBottom: 2,
+  fillColor: '#252526',
+  /**
+   * Style for the all keyframes in a current row.
+   * Individual keyframe can have own style.
+   */
+  keyframesStyle: defaultTimelineKeyframeStyle,
+  /**
+   * Style of the groups.
+   */
+  groupsStyle: defaultGroupStyle,
+} as TimelineRowStyle;

+ 22 - 0
src/settings/defaults/defaultTimelineStyle.ts

@@ -0,0 +1,22 @@
+import { TimelineCapShape } from '../../enums/timelineCapShape';
+import { TimelineCursorType } from '../../enums/timelineCursorType';
+import { TimelineStyle } from '../styles/timelineStyle';
+
+export const defaultTimelineStyle = {
+  width: 2,
+  marginTop: 15,
+  marginBottom: 0,
+  strokeColor: 'DarkOrange',
+  fillColor: 'DarkOrange',
+  capStyle: {
+    width: 4,
+    height: 10,
+    /**
+     * Draw timeline rectangular cap.
+     */
+    capType: TimelineCapShape.Rect,
+    strokeColor: 'DarkOrange',
+    fillColor: 'DarkOrange',
+  },
+  cursor: TimelineCursorType.EWResize,
+} as TimelineStyle;

+ 27 - 0
src/settings/styles/timelineCapStyle.ts

@@ -0,0 +1,27 @@
+import { TimelineCapShape } from '../../enums/timelineCapShape';
+
+/**
+ * Timeline active/current value indicator style.
+ */
+export interface TimelineCapStyle {
+  /**
+   * Cap style width in pixels.
+   */
+  width?: number;
+  /**
+   * Cap style height in pixels.
+   */
+  height?: number;
+  /**
+   * Cap stroke color.
+   */
+  strokeColor: string;
+  /**
+   * Cap fill color.
+   */
+  fillColor: string;
+  /**
+   * Cap type
+   */
+  capType?: TimelineCapShape;
+}

+ 33 - 0
src/settings/styles/timelineGroupStyle.ts

@@ -0,0 +1,33 @@
+import { TimelineCursorType } from '../../enums/timelineCursorType';
+import { TimelineKeyframeStyle } from '../styles/timelineKeyframeStyle';
+
+/**
+ * Timeline group style.
+ */
+export interface TimelineGroupStyle {
+  /**
+   * Keyframes style height in pixels.
+   * 'auto' to automatically calculate.
+   */
+  height?: number | string;
+  /**
+   * Group stroke color.
+   */
+  strokeColor: string;
+  /**
+   * Group fill color.
+   */
+  fillColor: string;
+  /**
+   * Group mouse over cursor style.
+   */
+  cursor?: TimelineCursorType;
+  /**
+   * Margin top in px or 'auto' to center element.
+   */
+  marginTop?: number | string;
+  /**
+   * Style for all the keyframes in the current group.
+   */
+  keyframesStyle: TimelineKeyframeStyle;
+}

+ 18 - 4
src/settings/styles/timelineKeyframeStyle.ts

@@ -1,10 +1,15 @@
+import { TimelineCursorType } from '../../enums/timelineCursorType';
 import { TimelineKeyframeShape } from '../../enums/timelineKeyframeShape';
 
 export interface TimelineKeyframeStyle {
-  cursor?: string;
+  /**
+   * Timeline cursor style.
+   */
+  cursor?: TimelineCursorType;
+  /**
+   * Timeline keyframe shape
+   */
   shape?: TimelineKeyframeShape;
-  draggable?: boolean;
-  hidden?: boolean;
   /**
    * keyframe size, number or text 'auto'
    */
@@ -18,10 +23,19 @@ export interface TimelineKeyframeStyle {
    */
   fillColor?: string | null;
   /**
-   * Keyframe selected  fill color.
+   * Keyframe selected fill color.
    */
   selectedFillColor?: string | null;
+  /**
+   * Keyframe stroke color.
+   */
   strokeColor?: string | null;
+  /**
+   * Keyframe selected stroke color.
+   */
   selectedStrokeColor?: string | null;
+  /**
+   * Keyframe stroke Thickness.
+   */
   strokeThickness?: number | null;
 }

+ 17 - 13
src/settings/styles/timelineRowStyle.ts

@@ -1,25 +1,29 @@
+import { TimelineGroupStyle } from './timelineGroupStyle';
 import { TimelineKeyframeStyle } from './timelineKeyframeStyle';
+
+/**
+ * Style of the row.
+ */
 export interface TimelineRowStyle {
   /**
-   * Size of the row in pixels, can be set to 'auto'
+   * Size of the row in pixels.
    */
-  height?: string | number;
-  hidden?: boolean;
-  color?: string;
-  selectedColor?: string;
-  marginBottom?: number;
+  height?: number;
   /**
-   * Keyframes bounds group height.
-   * 'auto' to automatically calculate.
-   * number in pixels.
+   * Track fill color.
    */
-  groupHeight?: number | string;
+  fillColor?: string;
   /**
-   * Keyframes bounds group color. Default is used when undefined.
+   * Row margin bottom in pixels between tracks/rows.
    */
-  groupFillColor?: string;
+  marginBottom?: number;
   /**
-   * Style of all keyframes in a current row.
+   * Style for the all keyframes in a current row.
+   * Individual keyframe can have own style.
    */
   keyframesStyle?: TimelineKeyframeStyle;
+  /**
+   * Style of the groups. Keyframe groups can be also styles separately.
+   */
+  groupsStyle?: TimelineGroupStyle;
 }

+ 24 - 9
src/settings/styles/timelineStyle.ts

@@ -1,18 +1,33 @@
-import { TimelineCapShape } from '../../enums/timelineCapShape';
+import { TimelineCursorType } from '../../enums/timelineCursorType';
+import { TimelineCapStyle } from './timelineCapStyle';
 
 /**
- * Timeline indicator style
+ * Timeline active/current value indicator style.
  */
 export interface TimelineStyle {
   width?: number;
+  /**
+   * Margin top in pixels.
+   */
   marginTop?: number;
-  capWidth?: number;
-  capHeight?: number;
   /**
-   * Cap type
+   * Margin bottom in pixels.
+   */
+  marginBottom?: number;
+  /**
+   * Timeline top cap style.
+   */
+  capStyle?: TimelineCapStyle;
+  /**
+   * Timeline indicator stroke color.
+   */
+  strokeColor?: string;
+  /**
+   * Timeline fill color.
+   */
+  fillColor?: string;
+  /**
+   * Timeline cursor.
    */
-  capType?: TimelineCapShape;
-  timelineColor?: string;
-  strokeColor: string;
-  fillColor: string;
+  cursor?: TimelineCursorType;
 }

+ 17 - 0
src/settings/timelineConsts.ts

@@ -1,3 +1,7 @@
+/**
+ * Internal components consts.
+ * Still can be changed thru private property _consts but this is discouraged.
+ */
 export interface TimelineConsts {
   /**
    * Auto pan speed.
@@ -27,4 +31,17 @@ export interface TimelineConsts {
    * Click threshold
    */
   clickThreshold: number;
+
+  /**
+   * Click min radius for the elements detection.
+   */
+  clickDetectionMinRadius: number;
+  /**
+   * Default auto size for the group. It's percents.
+   */
+  autoPanSpeedLimit: number;
+  /**
+   * Default auto size for the group. It's percents.
+   */
+  defaultGroupHeight: number;
 }

+ 17 - 13
src/settings/timelineOptions.ts

@@ -1,6 +1,6 @@
 import { TimelineRowStyle } from './styles/timelineRowStyle';
 import { TimelineStyle } from './styles/timelineStyle';
-import { TimelineRanged } from '../timelineRanged';
+import { TimelineRanged } from '../models/timelineRanged';
 
 export interface TimelineOptions extends TimelineRanged {
   /**
@@ -12,11 +12,11 @@ export interface TimelineOptions extends TimelineRanged {
    */
   snapEnabled?: boolean;
   /**
-   *  Snap all selected keyframes as a bundle during the drag.
+   *  Snap all selected keyframes as one bundle during the drag.
    */
   snapAllKeyframesOnMove?: boolean;
   /**
-   * approximate step for the timeline in pixels for 1 second
+   * Approximate step for the timeline in pixels for 1 second
    */
   stepPx?: number;
   /**
@@ -40,6 +40,9 @@ export interface TimelineOptions extends TimelineRanged {
    * Component background color.
    */
   fillColor?: string;
+  /**
+   * Header labels color.
+   */
   labelsColor?: string;
   /**
    * Header gauge tick color.
@@ -50,15 +53,6 @@ export interface TimelineOptions extends TimelineRanged {
    */
   selectionColor?: string;
 
-  /**
-   * Default rows style.
-   * Can be overridden by setting style individually for each row.
-   */
-  rowsStyle?: TimelineRowStyle;
-  /**
-   * Timeline indicator style.
-   */
-  timelineStyle?: TimelineStyle;
   /**
    * Header height in pixels
    */
@@ -91,6 +85,16 @@ export interface TimelineOptions extends TimelineRanged {
    * Access the scroll container via this class for e.g. scroll bar styling.
    */
   scrollContainerClass?: string;
+  /**
+   * Default rows style.
+   * Can be overridden by setting style individually for each row.
+   */
+  rowsStyle?: TimelineRowStyle;
+  /**
+   * Timeline indicator style.
+   */
+  timelineStyle?: TimelineStyle;
+
   /**
    * keyframes group is draggable. Default: true
    */
@@ -102,5 +106,5 @@ export interface TimelineOptions extends TimelineRanged {
   /**
    * Timeline can be dragged or position can be changed by user interaction. Default: true
    */
-  timelineInteractive?: boolean;
+  timelineDraggable?: boolean;
 }

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 261 - 193
src/timeline.ts


+ 28 - 10
src/timelineEventsEmitter.ts

@@ -1,44 +1,62 @@
 /* eslint-disable  @typescript-eslint/no-explicit-any */
-interface Event {
+interface TimelineEvent {
   topic: string;
   callback: (args: any) => void;
 }
 
+/**
+ * Timeline events emitter.
+ */
 export class TimelineEventsEmitter {
-  protected _subscriptions: Array<Event> = [];
+  /**
+   * Active events subscriptions.
+   */
+  _subscriptions: TimelineEvent[] = [];
 
-  // on event.
-  on(topic: string, callback: (args: any) => void): void {
+  /**
+   * Subscribe event.
+   * @param topic event name.
+   * @param callback callback to be added.
+   */
+  on<T>(topic: string, callback: (args: T) => void): boolean {
     if (!callback) {
-      return;
+      return false;
     }
 
     this._subscriptions.push({
       topic: topic,
       callback: callback,
-    });
+    } as TimelineEvent);
+    return true;
   }
   /**
    * Remove an event from the subscriptions list.
    */
-  off(topic: string, callback: (args: any) => void): void {
+  off<T>(topic: string, callback: (args: T) => void): boolean {
+    const before = this._subscriptions.length;
     this._subscriptions = this._subscriptions.filter((event) => {
       return event && event.callback != callback && event.topic != topic;
     });
+    return before !== this._subscriptions.length;
   }
 
   /**
    * Unsubscribe all
    */
   offAll(): void {
+    // Remove all callbacks from array.
     this._subscriptions.length = 0;
   }
 
-  // emit event.
+  /**
+   * Emit event.
+   * @param topic Event name.
+   * @param args Event arguments.
+   */
   // eslint-disable-next-line @typescript-eslint/no-explicit-any
-  emit(topic: string, args: any): void {
+  emit<T>(topic: string, args: T): void {
     this._subscriptions.forEach((event) => {
-      if (event && event.topic == topic && event.callback) {
+      if (event?.topic === topic && event?.callback) {
         event.callback(args);
       }
     });

+ 0 - 13
src/timelineKeyframe.ts

@@ -1,13 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import { TimelineKeyframeStyle } from './settings/styles/timelineKeyframeStyle';
-import { Selectable } from './utils/selectable';
-import { TimelineRanged } from './timelineRanged';
-
-export interface TimelineKeyframe extends TimelineKeyframeStyle, Selectable, TimelineRanged {
-  val: number;
-  /**
-   * Related keyframe group.
-   * Timeline keyframes groups are rendered as one bundle.
-   */
-  group?: any;
-}

+ 0 - 19
src/timelineRanged.ts

@@ -1,19 +0,0 @@
-export interface TimelineRanged {
-  /**
-   * min
-   */
-  min?: number | null;
-  /**
-   * max.
-   */
-  max?: number | null;
-
-  /**
-   * Allow to calculate min.
-   */
-  getMin?: () => number;
-  /**
-   * Allow to calculate max.
-   */
-  getMax?: () => number;
-}

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно