@twick/timeline 0.14.2 → 0.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -4,13 +4,19 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import React, { useState, createContext, useContext, useRef, useMemo, useEffect } from "react";
6
6
  const PLAYER_STATE = {
7
+ /** Player is refreshing/reloading content */
7
8
  REFRESH: "Refresh",
9
+ /** Player is actively playing content */
8
10
  PLAYING: "Playing",
11
+ /** Player is paused */
9
12
  PAUSED: "Paused"
10
13
  };
11
14
  const CAPTION_STYLE = {
15
+ /** Highlights background of each word */
12
16
  WORD_BG_HIGHLIGHT: "highlight_bg",
17
+ /** Animates text word by word */
13
18
  WORD_BY_WORD: "word_by_word",
19
+ /** Animates text word by word with background highlighting */
14
20
  WORD_BY_WORD_WITH_BG: "word_by_word_with_bg"
15
21
  };
16
22
  const CAPTION_STYLE_OPTIONS = {
@@ -28,34 +34,54 @@ const CAPTION_STYLE_OPTIONS = {
28
34
  }
29
35
  };
30
36
  const CAPTION_FONT = {
37
+ /** Font size in pixels */
31
38
  size: 40
32
39
  };
33
40
  const CAPTION_COLOR = {
41
+ /** Text color in hex format */
34
42
  text: "#ffffff",
43
+ /** Highlight color in hex format */
35
44
  highlight: "#ff4081",
45
+ /** Background color in hex format */
36
46
  bgColor: "#8C52FF"
37
47
  };
38
48
  const WORDS_PER_PHRASE = 4;
39
49
  const TIMELINE_ACTION = {
50
+ /** No action being performed */
40
51
  NONE: "none",
52
+ /** Setting the player state (play/pause) */
41
53
  SET_PLAYER_STATE: "setPlayerState",
54
+ /** Updating player data */
42
55
  UPDATE_PLAYER_DATA: "updatePlayerData",
56
+ /** Player has been updated */
43
57
  ON_PLAYER_UPDATED: "onPlayerUpdated"
44
58
  };
45
59
  const TIMELINE_ELEMENT_TYPE = {
60
+ /** Video element type */
46
61
  VIDEO: "video",
62
+ /** Caption element type */
47
63
  CAPTION: "caption",
64
+ /** Image element type */
48
65
  IMAGE: "image",
66
+ /** Audio element type */
49
67
  AUDIO: "audio",
68
+ /** Text element type */
50
69
  TEXT: "text",
70
+ /** Rectangle element type */
51
71
  RECT: "rect",
72
+ /** Circle element type */
52
73
  CIRCLE: "circle",
74
+ /** Icon element type */
53
75
  ICON: "icon"
54
76
  };
55
77
  const PROCESS_STATE = {
78
+ /** Process is idle */
56
79
  IDLE: "Idle",
80
+ /** Process is currently running */
57
81
  PROCESSING: "Processing",
82
+ /** Process has completed successfully */
58
83
  COMPLETED: "Completed",
84
+ /** Process has failed */
59
85
  FAILED: "Failed"
60
86
  };
61
87
  const imageDimensionsCache = {};
@@ -1682,6 +1708,18 @@ class TrackFriend {
1682
1708
  }
1683
1709
  }
1684
1710
  class Track {
1711
+ /**
1712
+ * Creates a new Track instance.
1713
+ *
1714
+ * @param name - The display name for the track
1715
+ * @param id - Optional unique identifier (auto-generated if not provided)
1716
+ *
1717
+ * @example
1718
+ * ```js
1719
+ * const track = new Track("My Video Track");
1720
+ * const trackWithId = new Track("Audio Track", "audio-track-1");
1721
+ * ```
1722
+ */
1685
1723
  constructor(name, id) {
1686
1724
  __publicField(this, "id");
1687
1725
  __publicField(this, "name");
@@ -1695,66 +1733,210 @@ class Track {
1695
1733
  this.validator = new ElementValidator();
1696
1734
  }
1697
1735
  /**
1698
- * Create a friend instance for explicit access to protected methods
1699
- * This implements the Friend Class Pattern
1700
- * @returns TrackFriend instance
1736
+ * Creates a friend instance for explicit access to protected methods.
1737
+ * This implements the Friend Class Pattern to allow controlled access
1738
+ * to protected methods while maintaining encapsulation.
1739
+ *
1740
+ * @returns TrackFriend instance that can access protected methods
1741
+ *
1742
+ * @example
1743
+ * ```js
1744
+ * const track = new Track("My Track");
1745
+ * const friend = track.createFriend();
1746
+ *
1747
+ * // Use friend to add elements
1748
+ * const element = new VideoElement({ src: "video.mp4", start: 0, end: 10 });
1749
+ * friend.addElement(element);
1750
+ * ```
1701
1751
  */
1702
1752
  createFriend() {
1703
1753
  return new TrackFriend(this);
1704
1754
  }
1705
1755
  /**
1706
- * Friend method to add element (called by TrackFriend)
1707
- * @param element The element to add
1708
- * @param skipValidation If true, skips validation
1756
+ * Friend method to add element (called by TrackFriend).
1757
+ * Provides controlled access to the protected addElement method.
1758
+ *
1759
+ * @param element - The element to add to the track
1760
+ * @param skipValidation - If true, skips validation (use with caution)
1709
1761
  * @returns true if element was added successfully
1762
+ *
1763
+ * @example
1764
+ * ```js
1765
+ * const track = new Track("My Track");
1766
+ * const friend = track.createFriend();
1767
+ * const element = new VideoElement({ src: "video.mp4", start: 0, end: 10 });
1768
+ *
1769
+ * const success = track.addElementViaFriend(element);
1770
+ * // success = true if element was added successfully
1771
+ * ```
1710
1772
  */
1711
1773
  addElementViaFriend(element, skipValidation = false) {
1712
1774
  return this.addElement(element, skipValidation);
1713
1775
  }
1714
1776
  /**
1715
- * Friend method to remove element (called by TrackFriend)
1716
- * @param element The element to remove
1777
+ * Friend method to remove element (called by TrackFriend).
1778
+ * Provides controlled access to the protected removeElement method.
1779
+ *
1780
+ * @param element - The element to remove from the track
1781
+ *
1782
+ * @example
1783
+ * ```js
1784
+ * const track = new Track("My Track");
1785
+ * const element = new VideoElement({ src: "video.mp4", start: 0, end: 10 });
1786
+ *
1787
+ * track.removeElementViaFriend(element);
1788
+ * // Element is removed from the track
1789
+ * ```
1717
1790
  */
1718
1791
  removeElementViaFriend(element) {
1719
1792
  this.removeElement(element);
1720
1793
  }
1721
1794
  /**
1722
- * Friend method to update element (called by TrackFriend)
1723
- * @param element The element to update
1795
+ * Friend method to update element (called by TrackFriend).
1796
+ * Provides controlled access to the protected updateElement method.
1797
+ *
1798
+ * @param element - The updated element to replace the existing one
1724
1799
  * @returns true if element was updated successfully
1800
+ *
1801
+ * @example
1802
+ * ```js
1803
+ * const track = new Track("My Track");
1804
+ * const element = new VideoElement({ src: "video.mp4", start: 0, end: 10 });
1805
+ *
1806
+ * // Update the element
1807
+ * element.setEnd(15);
1808
+ * const success = track.updateElementViaFriend(element);
1809
+ * // success = true if element was updated successfully
1810
+ * ```
1725
1811
  */
1726
1812
  updateElementViaFriend(element) {
1727
1813
  return this.updateElement(element);
1728
1814
  }
1815
+ /**
1816
+ * Gets the unique identifier of the track.
1817
+ *
1818
+ * @returns The track's unique ID string
1819
+ *
1820
+ * @example
1821
+ * ```js
1822
+ * const track = new Track("My Track", "track-123");
1823
+ * const id = track.getId(); // "track-123"
1824
+ * ```
1825
+ */
1729
1826
  getId() {
1730
1827
  return this.id;
1731
1828
  }
1829
+ /**
1830
+ * Gets the display name of the track.
1831
+ *
1832
+ * @returns The track's display name
1833
+ *
1834
+ * @example
1835
+ * ```js
1836
+ * const track = new Track("Video Track");
1837
+ * const name = track.getName(); // "Video Track"
1838
+ * ```
1839
+ */
1732
1840
  getName() {
1733
1841
  return this.name;
1734
1842
  }
1843
+ /**
1844
+ * Gets the type of the track.
1845
+ *
1846
+ * @returns The track's type string
1847
+ *
1848
+ * @example
1849
+ * ```js
1850
+ * const track = new Track("My Track");
1851
+ * const type = track.getType(); // "element"
1852
+ * ```
1853
+ */
1735
1854
  getType() {
1736
1855
  return this.type;
1737
1856
  }
1857
+ /**
1858
+ * Gets a read-only array of all elements in the track.
1859
+ * Returns a copy of the elements array to prevent external modification.
1860
+ *
1861
+ * @returns Read-only array of track elements
1862
+ *
1863
+ * @example
1864
+ * ```js
1865
+ * const track = new Track("My Track");
1866
+ * const elements = track.getElements();
1867
+ * // elements is a read-only array of TrackElement instances
1868
+ *
1869
+ * elements.forEach(element => {
1870
+ * console.log(`Element: ${element.getId()}, Duration: ${element.getEnd() - element.getStart()}`);
1871
+ * });
1872
+ * ```
1873
+ */
1738
1874
  getElements() {
1739
1875
  return [...this.elements];
1740
1876
  }
1741
1877
  /**
1742
- * Validates an element
1743
- * @param element The element to validate
1878
+ * Validates a single element using the track's validator.
1879
+ * Checks if the element meets all validation requirements.
1880
+ *
1881
+ * @param element - The element to validate
1744
1882
  * @returns true if valid, throws ValidationError if invalid
1883
+ *
1884
+ * @example
1885
+ * ```js
1886
+ * const track = new Track("My Track");
1887
+ * const element = new VideoElement({ src: "video.mp4", start: 0, end: 10 });
1888
+ *
1889
+ * try {
1890
+ * const isValid = track.validateElement(element);
1891
+ * console.log('Element is valid:', isValid);
1892
+ * } catch (error) {
1893
+ * if (error instanceof ValidationError) {
1894
+ * console.log('Validation failed:', error.errors);
1895
+ * }
1896
+ * }
1897
+ * ```
1745
1898
  */
1746
1899
  validateElement(element) {
1747
1900
  return element.accept(this.validator);
1748
1901
  }
1902
+ /**
1903
+ * Gets the total duration of the track.
1904
+ * Calculates the duration based on the end time of the last element.
1905
+ *
1906
+ * @returns The total duration of the track in seconds
1907
+ *
1908
+ * @example
1909
+ * ```js
1910
+ * const track = new Track("My Track");
1911
+ * const duration = track.getTrackDuration(); // 0 if no elements
1912
+ *
1913
+ * // After adding elements
1914
+ * const element = new VideoElement({ src: "video.mp4", start: 0, end: 30 });
1915
+ * track.createFriend().addElement(element);
1916
+ * const newDuration = track.getTrackDuration(); // 30
1917
+ * ```
1918
+ */
1749
1919
  getTrackDuration() {
1750
1920
  var _a;
1751
1921
  return ((_a = this.elements) == null ? void 0 : _a.length) ? this.elements[this.elements.length - 1].getEnd() : 0;
1752
1922
  }
1753
1923
  /**
1754
- * Adds an element to the track with validation
1755
- * @param element The element to add
1756
- * @param skipValidation If true, skips validation (use with caution)
1924
+ * Adds an element to the track with validation.
1925
+ * Protected method that should be accessed through TrackFriend.
1926
+ *
1927
+ * @param element - The element to add to the track
1928
+ * @param skipValidation - If true, skips validation (use with caution)
1757
1929
  * @returns true if element was added successfully, throws ValidationError if validation fails
1930
+ *
1931
+ * @example
1932
+ * ```js
1933
+ * const track = new Track("My Track");
1934
+ * const element = new VideoElement({ src: "video.mp4", start: 0, end: 10 });
1935
+ *
1936
+ * // Use friend to access this protected method
1937
+ * const friend = track.createFriend();
1938
+ * const success = friend.addElement(element);
1939
+ * ```
1758
1940
  */
1759
1941
  addElement(element, skipValidation = false) {
1760
1942
  element.setTrackId(this.id);
@@ -1776,6 +1958,22 @@ class Track {
1776
1958
  }
1777
1959
  return false;
1778
1960
  }
1961
+ /**
1962
+ * Removes an element from the track.
1963
+ * Protected method that should be accessed through TrackFriend.
1964
+ *
1965
+ * @param element - The element to remove from the track
1966
+ *
1967
+ * @example
1968
+ * ```js
1969
+ * const track = new Track("My Track");
1970
+ * const element = new VideoElement({ src: "video.mp4", start: 0, end: 10 });
1971
+ *
1972
+ * // Use friend to access this protected method
1973
+ * const friend = track.createFriend();
1974
+ * friend.removeElement(element);
1975
+ * ```
1976
+ */
1779
1977
  removeElement(element) {
1780
1978
  const index = this.elements.findIndex((e2) => e2.getId() === element.getId());
1781
1979
  if (index !== -1) {
@@ -1783,9 +1981,22 @@ class Track {
1783
1981
  }
1784
1982
  }
1785
1983
  /**
1786
- * Updates an element in the track with validation
1787
- * @param element The element to update
1984
+ * Updates an element in the track with validation.
1985
+ * Protected method that should be accessed through TrackFriend.
1986
+ *
1987
+ * @param element - The updated element to replace the existing one
1788
1988
  * @returns true if element was updated successfully, throws ValidationError if validation fails
1989
+ *
1990
+ * @example
1991
+ * ```js
1992
+ * const track = new Track("My Track");
1993
+ * const element = new VideoElement({ src: "video.mp4", start: 0, end: 10 });
1994
+ *
1995
+ * // Use friend to access this protected method
1996
+ * const friend = track.createFriend();
1997
+ * element.setEnd(15);
1998
+ * const success = friend.updateElement(element);
1999
+ * ```
1789
2000
  */
1790
2001
  updateElement(element) {
1791
2002
  try {
@@ -1807,14 +2018,55 @@ class Track {
1807
2018
  }
1808
2019
  return false;
1809
2020
  }
2021
+ /**
2022
+ * Finds an element in the track by its ID.
2023
+ *
2024
+ * @param id - The unique identifier of the element to find
2025
+ * @returns The found element or undefined if not found
2026
+ *
2027
+ * @example
2028
+ * ```js
2029
+ * const track = new Track("My Track");
2030
+ * const element = new VideoElement({ src: "video.mp4", start: 0, end: 10 });
2031
+ * track.createFriend().addElement(element);
2032
+ *
2033
+ * const foundElement = track.getElementById(element.getId());
2034
+ * // foundElement is the same element instance
2035
+ * ```
2036
+ */
1810
2037
  getElementById(id) {
1811
2038
  const element = this.elements.find((e2) => e2.getId() === id);
1812
2039
  if (!element) return void 0;
1813
2040
  return element;
1814
2041
  }
1815
2042
  /**
1816
- * Validates all elements in the track and returns combined result and per-element status
2043
+ * Validates all elements in the track and returns combined result and per-element status.
2044
+ * Provides detailed validation information for each element including errors and warnings.
2045
+ *
1817
2046
  * @returns Object with overall isValid and array of per-element validation results
2047
+ *
2048
+ * @example
2049
+ * ```js
2050
+ * const track = new Track("My Track");
2051
+ * const element1 = new VideoElement({ src: "video.mp4", start: 0, end: 10 });
2052
+ * const element2 = new TextElement({ text: "Hello", start: 5, end: 15 });
2053
+ *
2054
+ * track.createFriend().addElement(element1);
2055
+ * track.createFriend().addElement(element2);
2056
+ *
2057
+ * const validation = track.validateAllElements();
2058
+ * console.log('Overall valid:', validation.isValid);
2059
+ *
2060
+ * validation.results.forEach(result => {
2061
+ * console.log(`Element ${result.element.getId()}: ${result.isValid ? 'Valid' : 'Invalid'}`);
2062
+ * if (result.errors) {
2063
+ * console.log('Errors:', result.errors);
2064
+ * }
2065
+ * if (result.warnings) {
2066
+ * console.log('Warnings:', result.warnings);
2067
+ * }
2068
+ * });
2069
+ * ```
1818
2070
  */
1819
2071
  validateAllElements() {
1820
2072
  let validResult = true;
@@ -1844,6 +2096,30 @@ class Track {
1844
2096
  });
1845
2097
  return { isValid: validResult, results };
1846
2098
  }
2099
+ /**
2100
+ * Serializes the track and all its elements to JSON format.
2101
+ * Converts the track structure to a format that can be stored or transmitted.
2102
+ *
2103
+ * @returns TrackJSON object representing the track and its elements
2104
+ *
2105
+ * @example
2106
+ * ```js
2107
+ * const track = new Track("My Track");
2108
+ * const element = new VideoElement({ src: "video.mp4", start: 0, end: 10 });
2109
+ * track.createFriend().addElement(element);
2110
+ *
2111
+ * const trackData = track.serialize();
2112
+ * // trackData = {
2113
+ * // id: "t-abc123",
2114
+ * // name: "My Track",
2115
+ * // type: "element",
2116
+ * // elements: [{ ... }]
2117
+ * // }
2118
+ *
2119
+ * // Save to localStorage
2120
+ * localStorage.setItem('track-data', JSON.stringify(trackData));
2121
+ * ```
2122
+ */
1847
2123
  serialize() {
1848
2124
  const serializer = new ElementSerializer();
1849
2125
  return {
@@ -1855,6 +2131,35 @@ class Track {
1855
2131
  )
1856
2132
  };
1857
2133
  }
2134
+ /**
2135
+ * Creates a Track instance from JSON data.
2136
+ * Static factory method for deserializing track data.
2137
+ *
2138
+ * @param json - JSON object containing track data
2139
+ * @returns New Track instance with loaded data
2140
+ *
2141
+ * @example
2142
+ * ```js
2143
+ * const trackData = {
2144
+ * id: "t-abc123",
2145
+ * name: "My Track",
2146
+ * type: "element",
2147
+ * elements: [
2148
+ * {
2149
+ * id: "e-def456",
2150
+ * type: "video",
2151
+ * src: "video.mp4",
2152
+ * start: 0,
2153
+ * end: 10
2154
+ * }
2155
+ * ]
2156
+ * };
2157
+ *
2158
+ * const track = Track.fromJSON(trackData);
2159
+ * console.log(track.getName()); // "My Track"
2160
+ * console.log(track.getElements().length); // 1
2161
+ * ```
2162
+ */
1858
2163
  static fromJSON(json) {
1859
2164
  const track = new Track(json.name, json.id);
1860
2165
  track.type = json.type;
@@ -1934,12 +2239,37 @@ __publicField(_TimelineContextStore, "instance");
1934
2239
  let TimelineContextStore = _TimelineContextStore;
1935
2240
  const timelineContextStore = TimelineContextStore.getInstance();
1936
2241
  class ElementAdder {
2242
+ /**
2243
+ * Creates a new ElementAdder instance for the specified track.
2244
+ *
2245
+ * @param track - The track to add elements to
2246
+ *
2247
+ * @example
2248
+ * ```js
2249
+ * const adder = new ElementAdder(track);
2250
+ * const success = await adder.visitVideoElement(videoElement);
2251
+ * ```
2252
+ */
1937
2253
  constructor(track) {
1938
2254
  __publicField(this, "track");
1939
2255
  __publicField(this, "trackFriend");
1940
2256
  this.track = track;
1941
2257
  this.trackFriend = track.createFriend();
1942
2258
  }
2259
+ /**
2260
+ * Adds a video element to the track.
2261
+ * Updates video metadata and calculates appropriate start/end times
2262
+ * based on existing track elements.
2263
+ *
2264
+ * @param element - The video element to add
2265
+ * @returns Promise resolving to true if element was added successfully
2266
+ *
2267
+ * @example
2268
+ * ```js
2269
+ * const success = await adder.visitVideoElement(videoElement);
2270
+ * // success = true if element was added successfully
2271
+ * ```
2272
+ */
1943
2273
  async visitVideoElement(element) {
1944
2274
  await element.updateVideoMeta();
1945
2275
  const elements = this.track.getElements();
@@ -1952,6 +2282,20 @@ class ElementAdder {
1952
2282
  }
1953
2283
  return this.trackFriend.addElement(element);
1954
2284
  }
2285
+ /**
2286
+ * Adds an audio element to the track.
2287
+ * Updates audio metadata and calculates appropriate start/end times
2288
+ * based on existing track elements.
2289
+ *
2290
+ * @param element - The audio element to add
2291
+ * @returns Promise resolving to true if element was added successfully
2292
+ *
2293
+ * @example
2294
+ * ```js
2295
+ * const success = await adder.visitAudioElement(audioElement);
2296
+ * // success = true if element was added successfully
2297
+ * ```
2298
+ */
1955
2299
  async visitAudioElement(element) {
1956
2300
  await element.updateAudioMeta();
1957
2301
  const elements = this.track.getElements();
@@ -1964,6 +2308,20 @@ class ElementAdder {
1964
2308
  }
1965
2309
  return this.trackFriend.addElement(element);
1966
2310
  }
2311
+ /**
2312
+ * Adds an image element to the track.
2313
+ * Updates image metadata and calculates appropriate start/end times
2314
+ * based on existing track elements.
2315
+ *
2316
+ * @param element - The image element to add
2317
+ * @returns Promise resolving to true if element was added successfully
2318
+ *
2319
+ * @example
2320
+ * ```js
2321
+ * const success = await adder.visitImageElement(imageElement);
2322
+ * // success = true if element was added successfully
2323
+ * ```
2324
+ */
1967
2325
  async visitImageElement(element) {
1968
2326
  await element.updateImageMeta();
1969
2327
  const elements = this.track.getElements();
@@ -1976,6 +2334,19 @@ class ElementAdder {
1976
2334
  }
1977
2335
  return this.trackFriend.addElement(element);
1978
2336
  }
2337
+ /**
2338
+ * Adds a text element to the track.
2339
+ * Calculates appropriate start/end times based on existing track elements.
2340
+ *
2341
+ * @param element - The text element to add
2342
+ * @returns Promise resolving to true if element was added successfully
2343
+ *
2344
+ * @example
2345
+ * ```js
2346
+ * const success = await adder.visitTextElement(textElement);
2347
+ * // success = true if element was added successfully
2348
+ * ```
2349
+ */
1979
2350
  async visitTextElement(element) {
1980
2351
  const elements = this.track.getElements();
1981
2352
  const lastEndtime = (elements == null ? void 0 : elements.length) ? elements[elements.length - 1].getEnd() : 0;
@@ -1987,6 +2358,19 @@ class ElementAdder {
1987
2358
  }
1988
2359
  return this.trackFriend.addElement(element);
1989
2360
  }
2361
+ /**
2362
+ * Adds a caption element to the track.
2363
+ * Calculates appropriate start/end times based on existing track elements.
2364
+ *
2365
+ * @param element - The caption element to add
2366
+ * @returns Promise resolving to true if element was added successfully
2367
+ *
2368
+ * @example
2369
+ * ```js
2370
+ * const success = await adder.visitCaptionElement(captionElement);
2371
+ * // success = true if element was added successfully
2372
+ * ```
2373
+ */
1990
2374
  async visitCaptionElement(element) {
1991
2375
  const elements = this.track.getElements();
1992
2376
  const lastEndtime = (elements == null ? void 0 : elements.length) ? elements[elements.length - 1].getEnd() : 0;
@@ -1998,6 +2382,19 @@ class ElementAdder {
1998
2382
  }
1999
2383
  return this.trackFriend.addElement(element);
2000
2384
  }
2385
+ /**
2386
+ * Adds an icon element to the track.
2387
+ * Calculates appropriate start/end times based on existing track elements.
2388
+ *
2389
+ * @param element - The icon element to add
2390
+ * @returns Promise resolving to true if element was added successfully
2391
+ *
2392
+ * @example
2393
+ * ```js
2394
+ * const success = await adder.visitIconElement(iconElement);
2395
+ * // success = true if element was added successfully
2396
+ * ```
2397
+ */
2001
2398
  async visitIconElement(element) {
2002
2399
  const elements = this.track.getElements();
2003
2400
  const lastEndtime = (elements == null ? void 0 : elements.length) ? elements[elements.length - 1].getEnd() : 0;
@@ -2009,6 +2406,19 @@ class ElementAdder {
2009
2406
  }
2010
2407
  return this.trackFriend.addElement(element);
2011
2408
  }
2409
+ /**
2410
+ * Adds a circle element to the track.
2411
+ * Calculates appropriate start/end times based on existing track elements.
2412
+ *
2413
+ * @param element - The circle element to add
2414
+ * @returns Promise resolving to true if element was added successfully
2415
+ *
2416
+ * @example
2417
+ * ```js
2418
+ * const success = await adder.visitCircleElement(circleElement);
2419
+ * // success = true if element was added successfully
2420
+ * ```
2421
+ */
2012
2422
  async visitCircleElement(element) {
2013
2423
  const elements = this.track.getElements();
2014
2424
  const lastEndtime = (elements == null ? void 0 : elements.length) ? elements[elements.length - 1].getEnd() : 0;
@@ -2020,6 +2430,19 @@ class ElementAdder {
2020
2430
  }
2021
2431
  return this.trackFriend.addElement(element);
2022
2432
  }
2433
+ /**
2434
+ * Adds a rectangle element to the track.
2435
+ * Calculates appropriate start/end times based on existing track elements.
2436
+ *
2437
+ * @param element - The rectangle element to add
2438
+ * @returns Promise resolving to true if element was added successfully
2439
+ *
2440
+ * @example
2441
+ * ```js
2442
+ * const success = await adder.visitRectElement(rectElement);
2443
+ * // success = true if element was added successfully
2444
+ * ```
2445
+ */
2023
2446
  async visitRectElement(element) {
2024
2447
  const elements = this.track.getElements();
2025
2448
  const lastEndtime = (elements == null ? void 0 : elements.length) ? elements[elements.length - 1].getEnd() : 0;