diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5d1f319
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+arrow.d.ts
+node_modules/
+*.tgz
\ No newline at end of file
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..759b777
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,4 @@
+node_modules
+.gitignore
+.vscode
+*.tgz
\ No newline at end of file
diff --git a/README.md b/README.md
index 73269e5..0010c60 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Following the issue of vis https://github.com/almende/vis/issues/1699, and thank
1 - Download the package
-```
+```bash
npm install timeline-arrows
```
@@ -20,8 +20,8 @@ npm install timeline-arrows
For instance:
-```
-const my_timeline = new vis.Timeline(container, items, groups, options);
+```bash
+const myTimeline = new vis.Timeline(container, items, groups, options);
```
@@ -35,8 +35,8 @@ And optionally:
For instance:
-```
-var arrows_array = [
+```javascript
+var arrowsSpecs = [
{ id: 2, id_item_1: 1, id_item_2: 2 },
{ id: 5, id_item_1: 3, id_item_2: 5, title:'Hello!!!' },
{ id: 7, id_item_1: 6, id_item_2: 7 },
@@ -48,8 +48,8 @@ var arrows_array = [
For instance:
-```
-const my_Arrow = new Arrow(my_timeline, arrows_array);
+```javascript
+const myArrows = new Arrow(myTimeline, arrowsSpecs);
```
That's it :)
@@ -59,13 +59,16 @@ That's it :)
Options can be used to customize the arrows. Options are defined as a JSON object. All options are optional.
-```
+```javascript
const options = {
followRelationships: true,
- color: "#039E00"
+ color: "#039E00",
+ tooltipConfig: (el, title) => {
+ // tooltip initialization
+ },
};
-const my_Arrow = new Arrow(my_timeline, arrows_array, options);
+const myArrows = new Arrow(myTimeline, arrowsSpecs, options);
```
**followRelationships** - defaults to false.
@@ -74,6 +77,11 @@ If true, arrows can point backwards and will follow the relationships set in the
**color** - defaults to "#9c0000".
Sets the arrows color.
+**strokeWidth** - defaults to 3 (px).
+Sets the arrows width in pixels.
+
+**tooltipConfig** - if arrows have a `title` property, the default behavior will add a title attribute that shows on hover. However, you might not want to use the title attribute, but instead your own tooltip configuration.
+This method takes two arguments, `el` - the arrow - and `title` - the content of the `title` property set in the arrow data.
## Methods
@@ -82,29 +90,33 @@ I have created the following methods:
**getArrow ( *arrow id* )** Returns the arrow whith this arrow_id.
For instance:
-```
-my_Arrow.getArrow (2);
+
+```javascript
+myArrow.getArrow(2);
```
**addArrow ( *arrow object* )** Inserts a new arrow.
For instance:
-```
-my_Arrow.addArrow ( { id: 13, id_item_1: 15, id_item_2: 16 } );
+
+```javascript
+myArrow.addArrow({ id: 13, id_item_1: 15, id_item_2: 16 });
```
-**removeArrow ( *arrow_Id* )** Removes the arrows with this arrow_Id.
+**removeArrow ( *arrow_Id* )** Removes the arrows with this arrow_Id.
For instance:
-```
-my_Arrow.removeArrow ( 10 );
+
+```javascript
+myArrow.removeArrow( 10 );
```
-**removeArrowbyItemId ( *item_Id* )** Removes the arrows connected with Items with this item_Id. Returns an array with the id's of the removed arrows.
+**removeItemArrows ( *item_Id* )** Removes the arrows connected with Items with this item_Id. Returns an array with the id's of the removed arrows.
For instance:
-```
-my_Arrow.removeArrowbyItemId ( 23 );
+
+```javascript
+myArrow.removeItemArrows( 23 );
```
## Examples
diff --git a/arrow.js b/arrow.js
index cfd1faf..e779adc 100644
--- a/arrow.js
+++ b/arrow.js
@@ -24,20 +24,62 @@
* timeline-arrows may be distributed under either license.
*/
+// @ts-check
+
+/**
+ * @typedef {(number | string)} VisIdType Timeline view item id. Equivalent to vis.IdType.
+ */
+
+/**
+ * @typedef {(number | string)} ArrowIdType arrow id.
+ */
+
+/**
+ * @typedef ArrowSpec Arrow specification
+ * @property {ArrowIdType} id arrow id
+ * @property {VisIdType} id_item_1 start timeline item id
+ * @property {VisIdType} id_item_2 end timeline item id
+ * @property {string} [title] optional arrow title
+ */
+
+/**
+ * @typedef ArrowOptions Arrow configuration options
+ * @property {boolean} [followRelationships] if true, arrows can point backwards and will follow the relationships set in the data
+ * @property {(el: SVGPathElement, title: string) => string } [tooltipConfig] if arrows have a `title` property, the default behavior will add a title attribute that shows on hover. However, you might not want to use the title attribute, but instead your own tooltip configuration.
+ This method takes two arguments, `el` - the arrow - and `title` - the content of the `title` property set in the arrow data.
+ * @property {string} [color] arrow color
+ * @property {number} [strokeWidth] arrow thickness in pixels
+ */
+
+/** Arrow set for a vis.js Timeline. */
export default class Arrow {
+ /**
+ * Creates arrows.
+ * @param {*} timeline timeline object
+ * @param {ArrowSpec[]} dependencies arrows
+ * @param {ArrowOptions} [options]
+ */
constructor(timeline, dependencies, options) {
this._svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
this._timeline = timeline;
+ /** @private @type {boolean | undefined} if true, arrows can point backwards and will follow the relationships set in the data */
this._followRelationships = options?.followRelationships;
+ /** @private @type {((el: SVGPathElement, title: string) => string) | undefined } */
+ this._tooltipConfig = options?.tooltipConfig;
+ /** @private @type {string} color */
this._arrowsColor = options?.color ? options.color : "#9c0000"
+ /** @private @type {number} arrow thickness in pixels */
+ this._arrowsStrokeWidth = options?.strokeWidth ?? 3;
+ /** @private @type {SVGMarkerElement} */
this._arrowHead = document.createElementNS(
"http://www.w3.org/2000/svg",
"marker"
);
+ /** @private @type {SVGPathElement} */
this._arrowHeadPath = document.createElementNS(
"http://www.w3.org/2000/svg",
"path"
@@ -45,6 +87,7 @@ export default class Arrow {
this._dependency = dependencies;
+ /** @private @type {SVGPathElement[]} */
this._dependencyPath = [];
this._initialize();
@@ -87,6 +130,7 @@ export default class Arrow {
}
+ /** @private */
_createPath(){
//Add a new path to array dependencyPath and to svg
let somePath = document.createElementNS(
@@ -95,7 +139,7 @@ export default class Arrow {
);
somePath.setAttribute("d", "M 0 0");
somePath.style.stroke = this._arrowsColor;
- somePath.style.strokeWidth = "3px";
+ somePath.style.strokeWidth = this._arrowsStrokeWidth + "px";
somePath.style.fill = "none";
somePath.style.pointerEvents = "auto";
this._dependencyPath.push(somePath);
@@ -103,7 +147,7 @@ export default class Arrow {
}
-
+ /** @private */
_drawDependencies() {
//Create paths for the started dependency array
for (let i = 0; i < this._dependency.length; i++) {
@@ -111,20 +155,21 @@ export default class Arrow {
}
}
+ /**
+ * @private
+ * @param {ArrowSpec} dep arrow specification
+ * @param {number} index arrow index
+ */
_drawArrows(dep, index) {
//Checks if both items exist
//if( (typeof this._timeline.itemsData._data[dep.id_item_1] !== "undefined") && (typeof this._timeline.itemsData._data[dep.id_item_2] !== "undefined") ) {
//debugger;
- if( (this._timeline.itemsData.get(dep.id_item_1) !== null) && (this._timeline.itemsData.get(dep.id_item_2) !== null) ) {
- var bothItemsExist = true;
- } else {
- var bothItemsExist = false;
- }
+ const bothItemsExist = (this._timeline.itemsData.get(dep.id_item_1) !== null) && (this._timeline.itemsData.get(dep.id_item_2) !== null);
//Checks if at least one item is visible in screen
- var oneItemVisible = false; //Iniciamos a false
+ let oneItemVisible = false; //Iniciamos a false
if (bothItemsExist) {
- var visibleItems = this._timeline.getVisibleItems();
+ const visibleItems = this._timeline.getVisibleItems();
for (let k = 0; k < visibleItems.length ; k++) {
if (dep.id_item_1 == visibleItems[k]) oneItemVisible = true;
if (dep.id_item_2 == visibleItems[k]) oneItemVisible = true;
@@ -212,7 +257,9 @@ export default class Arrow {
// Adding the title if property title has been added in the dependency
if (dep.hasOwnProperty("title")) {
- this._dependencyPath[index].innerHTML = "
" +dep.title +""
+ this._tooltipConfig
+ ? this._tooltipConfig(this._dependencyPath[index], dep.title ?? '')
+ : this._dependencyPath[index].innerHTML = "" + dep.title + "";
}
} else {
this._dependencyPath[index].setAttribute("marker-end", "");
@@ -221,7 +268,7 @@ export default class Arrow {
}
- //Función que recibe in Item y devuelve la posición en pantalla del item.
+ /** @private Función que recibe in Item y devuelve la posición en pantalla del item. */
_getItemPos (item) {
let left_x = item.left;
let top_y;
@@ -243,38 +290,52 @@ export default class Arrow {
}
- addArrow (dep) {
+ /**
+ * Adds arrow between two timeline items.
+ * @param {ArrowSpec} dep item dependency
+ */
+ addArrow(dep) {
this._dependency.push(dep);
this._createPath();
this._timeline.redraw();
}
- getArrow (id) {
- for (let i = 0; i < this._dependency.length; i++) {
- if (this._dependency[i].id == id) {
- return this._dependency[i];
- }
- }
- return null;
+ /**
+ * Get arrow by ID.
+ * @param {ArrowIdType} id arrow ID
+ * @returns {ArrowSpec | null} arrow spec, or null
+ */
+ getArrow(id) {
+ return this._dependency.find(dep => dep.id === id) ?? null;
}
- //Función que recibe el id de una flecha y la elimina.
+ /**
+ * Finds arrow with the given id and removes it.
+ * Función que recibe el id de una flecha y la elimina.
+ * @param {ArrowIdType} id arrow id
+ */
removeArrow(id) {
- for (let i = 0; i < this._dependency.length; i++) {
- if (this._dependency[i].id == id) var index = i;
- }
+ const index = this._dependency.findIndex(dep => dep.id === id);
- //var list = document.getElementsByTagName("path"); //FALTA QUE ESTA SELECCION LA HAGA PARA EL DOM DEL TIMELINE INSTANCIADO!!!!
- var list = document.querySelectorAll("#" +this._timeline.dom.container.id +" path");
+ if (index >= 0) {
- this._dependency.splice(index, 1); //Elimino del array dependency
- this._dependencyPath.splice(index, 1); //Elimino del array dependencyPath
+ //var list = document.getElementsByTagName("path"); //FALTA QUE ESTA SELECCION LA HAGA PARA EL DOM DEL TIMELINE INSTANCIADO!!!!
+ const list = document.querySelectorAll("#" + this._timeline.dom.container.id + " path");
+
+ this._dependency.splice(index, 1); //Elimino del array dependency
+ this._dependencyPath.splice(index, 1); //Elimino del array dependencyPath
- list[index + 1].parentNode.removeChild(list[index + 1]); //Lo elimino del dom
+ list[index + 1].parentNode.removeChild(list[index + 1]); //Lo elimino del dom
+ }
}
- //Función que recibe el id de un item y elimina la flecha.
- removeArrowbyItemId(id) {
+ /**
+ * Finds all arrows related to one view item and removes them all.
+ * Función que recibe el id de un item y elimina la flecha.
+ * @param {VisIdType} id view item id
+ * @returns {(ArrowIdType)[]} list of removed arrow ids
+ */
+ removeItemArrows(id) {
let listOfRemovedArrows = [];
for (let i = 0; i < this._dependency.length; i++) {
if ( (this._dependency[i].id_item_1 == id) || (this._dependency[i].id_item_2 == id) ) {
@@ -286,6 +347,12 @@ export default class Arrow {
return listOfRemovedArrows;
}
-
+ /**
+ * For backward compatibility
+ * @deprecated use the removeItemArrows method instead.
+ */
+ removeArrowbyItemId(id) {
+ this.removeItemArrows(id);
+ }
}
\ No newline at end of file
diff --git a/examples/2timelines.js b/examples/2timelines.js
index 494f2c9..30137e4 100644
--- a/examples/2timelines.js
+++ b/examples/2timelines.js
@@ -9,12 +9,12 @@
selectable: true,
editable: true,
groupTemplate: function(group) { //function to hide groups
- var container = document.createElement('div');
- var label = document.createElement('span');
+ const container = document.createElement('div');
+ const label = document.createElement('span');
label.innerHTML = group.content + ' ';
container.insertAdjacentElement('afterBegin',label);
- var hide = document.createElement('span');
+ const hide = document.createElement('span');
hide.setAttribute("class", "oi oi-eye");
hide.addEventListener('click',function(){
groups.update({id: group.id, visible: false});
@@ -25,23 +25,23 @@
};
// Generate some
- var now = vis.moment()
+ const now = vis.moment()
.minutes(0)
.seconds(0)
.milliseconds(0);
- var names = ["John", "Alston", "Lee", "Grant"];
- var itemCount = 20;
+ const names = ["John", "Alston", "Lee", "Grant"];
+ const itemCount = 20;
// create a data set with groups
- var groups = new vis.DataSet();
- for (var g = 0; g < names.length; g++) {
+ const groups = new vis.DataSet();
+ for (let g = 0; g < names.length; g++) {
groups.add({ id: g, content: names[g] });
}
// create a dataset with items
- var items = new vis.DataSet();
- for (var i = 0; i < itemCount; i++) {
- var start = now.clone().add(Math.random() * 200, "hours");
- var end = start + 100000000;
- var group = Math.floor(Math.random() * names.length);
+ const items = new vis.DataSet();
+ for (let i = 0; i < itemCount; i++) {
+ const start = now.clone().add(Math.random() * 200, "hours");
+ const end = start + 100000000;
+ const group = Math.floor(Math.random() * names.length);
items.add({
id: i,
group: group,
@@ -71,12 +71,12 @@
selectable: true,
editable: true,
groupTemplate: function(group) { //function to hide groups
- var container = document.createElement('div');
- var label = document.createElement('span');
+ const container = document.createElement('div');
+ const label = document.createElement('span');
label.innerHTML = group.content + ' ';
container.insertAdjacentElement('afterBegin',label);
- var hide = document.createElement('span');
+ const hide = document.createElement('span');
hide.setAttribute("class", "oi oi-eye");
hide.addEventListener('click',function(){
groups2.update({id: group.id, visible: false});
@@ -87,23 +87,23 @@
};
// Generate some
- var now2 = vis.moment()
+ const now2 = vis.moment()
.minutes(0)
.seconds(0)
.milliseconds(0);
- var names2 = ["Juan", "Alfredo", "Luis", "David"];
- var itemCount2 = 20;
+ const names2 = ["Juan", "Alfredo", "Luis", "David"];
+ const itemCount2 = 20;
// create a data set with groups
- var groups2 = new vis.DataSet();
- for (var g = 0; g < names2.length; g++) {
+ const groups2 = new vis.DataSet();
+ for (let g = 0; g < names2.length; g++) {
groups2.add({ id: g, content: names2[g] });
}
// create a dataset with items
- var items2 = new vis.DataSet();
- for (var i = 0; i < itemCount2; i++) {
- var start = now2.clone().add(Math.random() * 200, "hours");
- var end = start + 100000000;
- var group = Math.floor(Math.random() * names2.length);
+ const items2 = new vis.DataSet();
+ for (let i = 0; i < itemCount2; i++) {
+ const start = now2.clone().add(Math.random() * 200, "hours");
+ const end = start + 100000000;
+ const group = Math.floor(Math.random() * names2.length);
items2.add({
id: i,
group: group,
@@ -134,11 +134,11 @@
onrangechange1();
});
function onrangechange1() {
- var range = timelinevis.getWindow();
+ const range = timelinevis.getWindow();
timelinevis2.setWindow(range.start, range.end, {animation: false});
}
function onrangechange2() {
- var range = timelinevis2.getWindow();
+ const range = timelinevis2.getWindow();
timelinevis.setWindow(range.start, range.end, {animation: false});
}
@@ -147,7 +147,7 @@
/**
*CREATING 2 ARRAYS OF ARROWS
*/
- var dependency = [
+ const dependency = [
{
id: 2,
id_item_1: 1,
@@ -174,7 +174,7 @@
- var dependency2 = [
+ const dependency2 = [
{
id: 2,
id_item_1: 1,
@@ -219,7 +219,7 @@
/*ANOTHER FUNCTIONS (NO IMPORTANT)*/
const showVisibleItems = function () {
- var a = timelinevis.getVisibleItems();
+ const a = timelinevis.getVisibleItems();
document.getElementById("visibleItemsContainer").innerHTML = ""
document.getElementById("visibleItemsContainer").innerHTML += a;
};
diff --git a/examples/basic_example.js b/examples/basic_example.js
index 4c788cd..2ab4e71 100644
--- a/examples/basic_example.js
+++ b/examples/basic_example.js
@@ -9,12 +9,12 @@
editable: true,
// orientation: "top",
groupTemplate: function(group) { //function to hide groups
- var container = document.createElement('div');
- var label = document.createElement('span');
+ const container = document.createElement('div');
+ const label = document.createElement('span');
label.innerHTML = group.content + ' ';
container.insertAdjacentElement('afterBegin',label);
- var hide = document.createElement('span');
+ const hide = document.createElement('span');
hide.setAttribute("class", "oi oi-eye");
hide.addEventListener('click',function(){
groups.update({id: group.id, visible: false});
@@ -25,23 +25,23 @@
};
// Generate some
- var now = vis.moment()
+ const now = vis.moment()
.minutes(0)
.seconds(0)
.milliseconds(0);
- var names = ["John", "Alston", "Lee", "Grant"];
- var itemCount = 20;
+ const names = ["John", "Alston", "Lee", "Grant"];
+ const itemCount = 20;
// create a data set with groups
- var groups = new vis.DataSet();
- for (var g = 0; g < names.length; g++) {
+ const groups = new vis.DataSet();
+ for (let g = 0; g < names.length; g++) {
groups.add({ id: g, content: names[g] });
}
// create a dataset with items
- var items = new vis.DataSet();
- for (var i = 0; i < itemCount; i++) {
- var start = now.clone().add(Math.random() * 200, "hours");
- var end = start + 100000000;
- var group = Math.floor(Math.random() * names.length);
+ const items = new vis.DataSet();
+ for (let i = 0; i < itemCount; i++) {
+ const start = now.clone().add(Math.random() * 200, "hours");
+ const end = start + 100000000;
+ const group = Math.floor(Math.random() * names.length);
items.add({
id: i,
group: group,
@@ -68,7 +68,7 @@
/**
*CREATING THE ARROWS
*/
- var dependency = [
+ const dependency = [
{
id: 2,
id_item_1: 1,
@@ -116,7 +116,7 @@
/*ANOTHER FUNCTIONS (NO IMPORTANT)*/
const showVisibleItems = function () {
- var a = timelinevis.getVisibleItems();
+ const a = timelinevis.getVisibleItems();
document.getElementById("visibleItemsContainer").innerHTML = ""
document.getElementById("visibleItemsContainer").innerHTML += a;
};
diff --git a/examples/colorOption.js b/examples/colorOption.js
index a9def02..7c80943 100644
--- a/examples/colorOption.js
+++ b/examples/colorOption.js
@@ -8,12 +8,12 @@
selectable: true,
editable: true,
groupTemplate: function(group) { //function to hide groups
- var container = document.createElement('div');
- var label = document.createElement('span');
+ const container = document.createElement('div');
+ const label = document.createElement('span');
label.innerHTML = group.content + ' ';
container.insertAdjacentElement('afterBegin',label);
- var hide = document.createElement('span');
+ const hide = document.createElement('span');
hide.setAttribute("class", "oi oi-eye");
hide.addEventListener('click',function(){
groups.update({id: group.id, visible: false});
@@ -24,23 +24,23 @@
};
// Generate some
- var now = vis.moment()
+ const now = vis.moment()
.minutes(0)
.seconds(0)
.milliseconds(0);
- var names = ["John", "Alston", "Lee", "Grant"];
- var itemCount = 20;
+ const names = ["John", "Alston", "Lee", "Grant"];
+ const itemCount = 20;
// create a data set with groups
- var groups = new vis.DataSet();
- for (var g = 0; g < names.length; g++) {
+ const groups = new vis.DataSet();
+ for (let g = 0; g < names.length; g++) {
groups.add({ id: g, content: names[g] });
}
// create a dataset with items
- var items = new vis.DataSet();
- for (var i = 0; i < itemCount; i++) {
- var start = now.clone().add(Math.random() * 200, "hours");
- var end = start + 100000000;
- var group = Math.floor(Math.random() * names.length);
+ const items = new vis.DataSet();
+ for (let i = 0; i < itemCount; i++) {
+ const start = now.clone().add(Math.random() * 200, "hours");
+ const end = start + 100000000;
+ const group = Math.floor(Math.random() * names.length);
items.add({
id: i,
group: group,
@@ -67,7 +67,7 @@
/**
*CREATING THE ARROWS
*/
- var dependency = [
+ const dependency = [
{
id: 2,
id_item_1: 1,
@@ -119,7 +119,7 @@
/*ANOTHER FUNCTIONS (NO IMPORTANT)*/
const showVisibleItems = function () {
- var a = timelinevis.getVisibleItems();
+ const a = timelinevis.getVisibleItems();
document.getElementById("visibleItemsContainer").innerHTML = ""
document.getElementById("visibleItemsContainer").innerHTML += a;
};
diff --git a/examples/followRelationships_True.js b/examples/followRelationships_True.js
index dac73f7..339cef7 100644
--- a/examples/followRelationships_True.js
+++ b/examples/followRelationships_True.js
@@ -8,12 +8,12 @@
selectable: true,
editable: true,
groupTemplate: function(group) { //function to hide groups
- var container = document.createElement('div');
- var label = document.createElement('span');
+ const container = document.createElement('div');
+ const label = document.createElement('span');
label.innerHTML = group.content + ' ';
container.insertAdjacentElement('afterBegin',label);
- var hide = document.createElement('span');
+ const hide = document.createElement('span');
hide.setAttribute("class", "oi oi-eye");
hide.addEventListener('click',function(){
groups.update({id: group.id, visible: false});
@@ -24,23 +24,23 @@
};
// Generate some
- var now = vis.moment()
+ const now = vis.moment()
.minutes(0)
.seconds(0)
.milliseconds(0);
- var names = ["John", "Alston", "Lee", "Grant"];
- var itemCount = 20;
+ const names = ["John", "Alston", "Lee", "Grant"];
+ const itemCount = 20;
// create a data set with groups
- var groups = new vis.DataSet();
- for (var g = 0; g < names.length; g++) {
+ const groups = new vis.DataSet();
+ for (let g = 0; g < names.length; g++) {
groups.add({ id: g, content: names[g] });
}
// create a dataset with items
- var items = new vis.DataSet();
- for (var i = 0; i < itemCount; i++) {
- var start = now.clone().add(Math.random() * 200, "hours");
- var end = start + 100000000;
- var group = Math.floor(Math.random() * names.length);
+ const items = new vis.DataSet();
+ for (let i = 0; i < itemCount; i++) {
+ const start = now.clone().add(Math.random() * 200, "hours");
+ const end = start + 100000000;
+ const group = Math.floor(Math.random() * names.length);
items.add({
id: i,
group: group,
@@ -67,7 +67,7 @@
/**
*CREATING THE ARROWS
*/
- var dependency = [
+ const dependency = [
{
id: 2,
id_item_1: 1,
@@ -119,7 +119,7 @@
/*ANOTHER FUNCTIONS (NO IMPORTANT)*/
const showVisibleItems = function () {
- var a = timelinevis.getVisibleItems();
+ const a = timelinevis.getVisibleItems();
document.getElementById("visibleItemsContainer").innerHTML = ""
document.getElementById("visibleItemsContainer").innerHTML += a;
};
diff --git a/index.html b/index.html
index babafa9..951dc93 100644
--- a/index.html
+++ b/index.html
@@ -1,5 +1,5 @@
-
+
Timeline-arrows
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..c1c0b3b
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,29 @@
+{
+ "name": "timeline-arrows",
+ "version": "4.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "timeline-arrows",
+ "version": "4.1.0",
+ "license": "MIT",
+ "devDependencies": {
+ "typescript": "^5.0.4"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz",
+ "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=12.20"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
index 41f7296..d1b1420 100644
--- a/package.json
+++ b/package.json
@@ -3,8 +3,11 @@
"version": "4.1.1",
"description": "Package to easily draw lines to connect items in the vis Timeline module.",
"main": "arrow.js",
+ "types": "arrow.d.ts",
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "generateTypes": "tsc --allowJs -d --emitDeclarationOnly --lib es2015,dom arrow.js",
+ "prepack": "npm run generateTypes"
},
"repository": {
"type": "git",
@@ -19,5 +22,8 @@
"bugs": {
"url": "https://github.com/javdome/timeline-arrows/issues"
},
- "homepage": "https://github.com/javdome/timeline-arrows#readme"
+ "homepage": "https://github.com/javdome/timeline-arrows#readme",
+ "devDependencies": {
+ "typescript": "^5.0.4"
+ }
}