@jithinaji/typeit 1.0.0 → 1.1.0

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/README.md CHANGED
@@ -14,6 +14,7 @@ A lightweight, zero-dependency JavaScript typing animation library with natural
14
14
 
15
15
  - **Zero dependencies**: Weighs only ~1 KB minified and gzipped.
16
16
  - **Natural typing effect**: Configurable typing speed and random speed variation to mimic human typing.
17
+ - **Auto-scrolling**: Automatically scrolls parent container to bottom as content grows via `ResizeObserver`.
17
18
  - **Chainable API**: Fluent queueing with `.type()`, `.clear()`, and speed adjustments.
18
19
  - **Universal compatibility**: Shipped in ESM (`.mjs`), CommonJS (`.cjs`), and browser standalone bundle (`.min.js`).
19
20
  - **Interactive demo**: Included directly in the repository to preview and experiment.
@@ -44,10 +45,10 @@ Include directly via jsDelivr or unpkg:
44
45
 
45
46
  ```html
46
47
  <!-- jsDelivr -->
47
- <script src="https://cdn.jsdelivr.net/npm/@jithinaji/typeit@1.0.0/dist/typeit.min.js"></script>
48
+ <script src="https://cdn.jsdelivr.net/npm/@jithinaji/typeit@1.1.0/dist/typeit.min.js"></script>
48
49
 
49
50
  <!-- unpkg -->
50
- <script src="https://unpkg.com/@jithinaji/typeit@1.0.0/dist/typeit.min.js"></script>
51
+ <script src="https://unpkg.com/@jithinaji/typeit@1.1.0/dist/typeit.min.js"></script>
51
52
  ```
52
53
 
53
54
  When loaded via a `<script>` tag, the `TypeIt` class is available globally on `window.TypeIt`.
@@ -66,7 +67,8 @@ const target = document.getElementById("header-title");
66
67
  const typist = new TypeIt({
67
68
  element: target,
68
69
  typingSpeed: 120, // Base speed in milliseconds per character
69
- speedVariation: 40 // Random variation (+/- ms) for natural typing rhythm
70
+ speedVariation: 40, // Random variation (+/- ms) for natural typing rhythm
71
+ autoScroll: true // Automatically scroll parent container (default: true)
70
72
  });
71
73
 
72
74
  typist
@@ -107,7 +109,7 @@ Creates a new `TypeIt` instance.
107
109
 
108
110
  #### Parameters:
109
111
  `data` can be either:
110
- 1. A DOM `Element` (defaults to `typingSpeed: 150`, `speedVariation: 50`):
112
+ 1. A DOM `Element` (defaults to `typingSpeed: 150`, `speedVariation: 50`, `autoScroll: true`):
111
113
  ```javascript
112
114
  const typist = new TypeIt(document.querySelector("#demo"));
113
115
  ```
@@ -116,7 +118,8 @@ Creates a new `TypeIt` instance.
116
118
  const typist = new TypeIt({
117
119
  element: document.querySelector("#demo"), // Required DOM Element
118
120
  typingSpeed: 150, // Optional: default 150ms
119
- speedVariation: 50 // Optional: default 50ms
121
+ speedVariation: 50, // Optional: default 50ms
122
+ autoScroll: true // Optional: default true
120
123
  });
121
124
  ```
122
125
 
package/dist/index.cjs CHANGED
@@ -29,14 +29,21 @@ var TypeIt = function(data) {
29
29
  this.settings.element = data;
30
30
  this.settings.typingSpeed = 150;
31
31
  this.settings.speedVariation = 50;
32
+ this.settings.autoScroll = true;
32
33
  } else {
33
34
  this.settings.element = data.element;
34
35
  this.settings.typingSpeed = data.typingSpeed ?? 150;
35
36
  this.settings.speedVariation = data.speedVariation ?? 50;
37
+ this.settings.autoScroll = data.autoScroll ?? true;
38
+ }
39
+ if (!(this.settings.element instanceof Element)) {
40
+ throw new Error("Initialize with an html element");
36
41
  }
37
42
  this.timer = null;
38
43
  this.queue = [];
39
44
  this.isTyping = false;
45
+ this.events = {};
46
+ this.observer = null;
40
47
  };
41
48
  TypeIt.prototype.type = function(content) {
42
49
  this.queue.push(content);
@@ -48,13 +55,37 @@ TypeIt.prototype.type = function(content) {
48
55
  TypeIt.prototype.next = function() {
49
56
  if (this.queue.length === 0) {
50
57
  this.isTyping = false;
58
+ this.emit("complete");
59
+ if (this.observer) {
60
+ this.observer.disconnect();
61
+ this.observer = null;
62
+ }
51
63
  return;
52
64
  }
53
65
  this.isTyping = true;
54
- const content = this.queue.shift();
55
- const settings = this.settings;
56
- const element = settings.element;
57
- let index = 0;
66
+ var content = this.queue.shift();
67
+ var settings = this.settings;
68
+ var element = settings.element;
69
+ var parentElement = element.parentElement || null;
70
+ if (settings.autoScroll && parentElement) {
71
+ let scrollToBottom = function() {
72
+ var currentHeight = parentElement.scrollHeight;
73
+ if (currentHeight > previousHeight) {
74
+ parentElement.scrollTo({
75
+ top: parentElement.scrollHeight,
76
+ behavior: "smooth"
77
+ });
78
+ previousHeight = currentHeight;
79
+ }
80
+ };
81
+ if (this.observer) {
82
+ this.observer.disconnect();
83
+ }
84
+ var previousHeight = parentElement.scrollHeight;
85
+ this.observer = new ResizeObserver(scrollToBottom);
86
+ this.observer.observe(parentElement);
87
+ }
88
+ var index = 0;
58
89
  const addContent = () => {
59
90
  if (index >= content.length) {
60
91
  this.next();
@@ -62,8 +93,8 @@ TypeIt.prototype.next = function() {
62
93
  }
63
94
  element.textContent += content[index];
64
95
  index++;
65
- const variation = (Math.random() * 2 - 1) * settings.speedVariation;
66
- const delay = Math.max(0, settings.typingSpeed + variation);
96
+ var variation = (Math.random() * 2 - 1) * settings.speedVariation;
97
+ var delay = Math.max(0, settings.typingSpeed + variation);
67
98
  this.timer = setTimeout(addContent, delay);
68
99
  };
69
100
  addContent();
@@ -82,10 +113,10 @@ TypeIt.prototype.setVariationSpeed = function(speed) {
82
113
  return this;
83
114
  };
84
115
  TypeIt.prototype.clear = function(options = {}) {
85
- const settings = this.settings;
86
- const element = settings.element;
87
- const animated = options.animated ?? true;
88
- const count = Math.max(
116
+ var settings = this.settings;
117
+ var element = settings.element;
118
+ var animated = options.animated ?? true;
119
+ var count = Math.max(
89
120
  0,
90
121
  Math.floor(options.count ?? element.textContent.length)
91
122
  );
@@ -94,29 +125,68 @@ TypeIt.prototype.clear = function(options = {}) {
94
125
  }
95
126
  clearTimeout(this.timer);
96
127
  this.timer = null;
128
+ if (this.observer) {
129
+ this.observer.disconnect();
130
+ this.observer = null;
131
+ }
97
132
  this.queue = [];
98
133
  this.isTyping = false;
99
134
  if (!animated) {
100
135
  element.textContent = Array.from(element.textContent).slice(0, -count).join("");
136
+ this.emit("clear");
101
137
  return this;
102
138
  }
103
- let deleted = 0;
104
- const removeContent = () => {
139
+ var deleted = 0;
140
+ function removeContent() {
105
141
  if (deleted >= count || !element.textContent.length) {
106
142
  this.timer = null;
107
143
  this.isTyping = false;
144
+ this.emit("clear");
108
145
  return;
109
146
  }
110
147
  element.textContent = Array.from(element.textContent).slice(0, -1).join("");
111
148
  deleted++;
112
- const variation = (Math.random() * 2 - 1) * settings.speedVariation;
113
- const delay = Math.max(0, settings.typingSpeed + variation);
149
+ var variation = (Math.random() * 2 - 1) * settings.speedVariation;
150
+ var delay = Math.max(0, settings.typingSpeed + variation);
114
151
  this.timer = setTimeout(removeContent, delay);
115
- };
152
+ }
116
153
  this.isTyping = true;
117
154
  removeContent();
118
155
  return this;
119
156
  };
157
+ TypeIt.prototype.on = function(event, callback) {
158
+ if (typeof callback !== "function") {
159
+ return this;
160
+ }
161
+ if (!this.events[event]) {
162
+ this.events[event] = [];
163
+ }
164
+ this.events[event].push(callback);
165
+ return this;
166
+ };
167
+ TypeIt.prototype.off = function(event, callback) {
168
+ if (!this.events[event]) {
169
+ return this;
170
+ }
171
+ if (typeof callback === "function") {
172
+ this.events[event] = this.events[event].filter(function(cb) {
173
+ return cb !== callback;
174
+ });
175
+ } else {
176
+ delete this.events[event];
177
+ }
178
+ return this;
179
+ };
180
+ TypeIt.prototype.emit = function(event, ...args) {
181
+ const callbacks = this.events[event];
182
+ if (!callbacks || callbacks.length === 0) {
183
+ return this;
184
+ }
185
+ callbacks.slice().forEach(function(callback) {
186
+ callback.apply(this, args);
187
+ }, this);
188
+ return this;
189
+ };
120
190
  var index_default = TypeIt;
121
191
  module.exports = TypeIt; module.exports.default = TypeIt;
122
192
  //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js"],
4
- "sourcesContent": ["\"use strict\"\n\nconst TypeIt = function (data) {\n this.settings = {};\n if(data instanceof Element) {\n this.settings.element = data;\n this.settings.typingSpeed = 150;\n this.settings.speedVariation = 50;\n }\n else {\n this.settings.element = data.element;\n this.settings.typingSpeed = data.typingSpeed ?? 150;\n this.settings.speedVariation = data.speedVariation ?? 50;\n }\n\n this.timer = null;\n this.queue = [];\n this.isTyping = false;\n\n}\n\nTypeIt.prototype.type = function (content) {\n this.queue.push(content);\n\n if(!this.isTyping) {\n this.next();\n }\n\n return this;\n}\n\n\nTypeIt.prototype.next = function () {\n if(this.queue.length === 0) {\n this.isTyping = false;\n return;\n }\n\n this.isTyping = true;\n\n const content = this.queue.shift();\n const settings = this.settings;\n const element = settings.element;\n\n\n let index = 0;\n\n const addContent = () => {\n if(index >= content.length) {\n this.next();\n return;\n }\n\n element.textContent += content[index];\n index++;\n\n const variation = (Math.random() * 2 -1) * settings.speedVariation;\n\n const delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(addContent, delay);\n \n }\n\n addContent();\n return this;\n}\n\nTypeIt.prototype.setTypingSpeed = function (speed) {\n if(typeof speed == \"number\") {\n this.settings.typingSpeed = speed;\n }\n return this;\n}\n\nTypeIt.prototype.setVariationSpeed = function (speed) {\n if(typeof speed == \"number\") {\n this.settings.speedVariation = speed;\n }\n return this;\n}\n\nTypeIt.prototype.clear = function (options = {}) {\n const settings = this.settings;\n const element = settings.element;\n\n const animated = options.animated ?? true;\n const count = Math.max(\n 0,\n Math.floor(options.count ?? element.textContent.length)\n ) \n\n if(count <= 0) {\n return this;\n }\n\n clearTimeout(this.timer);\n this.timer = null;\n\n this.queue = [];\n this.isTyping = false;\n\n if(!animated) {\n element.textContent = Array.from(element.textContent)\n .slice(0, -count)\n .join(\"\");\n\n return this;\n }\n\n let deleted = 0;\n\n const removeContent = () => {\n if(deleted >= count || !element.textContent.length) {\n this.timer = null;\n this.isTyping = false;\n return;\n }\n\n element.textContent = Array.from(element.textContent)\n .slice(0, -1)\n .join(\"\");\n\n deleted++;\n\n const variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n const delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(removeContent, delay);\n }\n\n this.isTyping = true;\n removeContent();\n\n return this;\n}\n\nexport default TypeIt;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,IAAM,SAAS,SAAU,MAAM;AAC7B,OAAK,WAAW,CAAC;AACjB,MAAG,gBAAgB,SAAS;AAC1B,SAAK,SAAS,UAAU;AACxB,SAAK,SAAS,cAAc;AAC5B,SAAK,SAAS,iBAAiB;AAAA,EACjC,OACK;AACH,SAAK,SAAS,UAAU,KAAK;AAC7B,SAAK,SAAS,cAAc,KAAK,eAAe;AAChD,SAAK,SAAS,iBAAiB,KAAK,kBAAkB;AAAA,EACxD;AAEA,OAAK,QAAQ;AACb,OAAK,QAAQ,CAAC;AACd,OAAK,WAAW;AAElB;AAEA,OAAO,UAAU,OAAO,SAAU,SAAS;AACzC,OAAK,MAAM,KAAK,OAAO;AAEvB,MAAG,CAAC,KAAK,UAAU;AACjB,SAAK,KAAK;AAAA,EACZ;AAEA,SAAO;AACT;AAGA,OAAO,UAAU,OAAO,WAAY;AAClC,MAAG,KAAK,MAAM,WAAW,GAAG;AAC1B,SAAK,WAAW;AAChB;AAAA,EACF;AAEA,OAAK,WAAW;AAEhB,QAAM,UAAU,KAAK,MAAM,MAAM;AACjC,QAAM,WAAW,KAAK;AACtB,QAAM,UAAU,SAAS;AAGzB,MAAI,QAAQ;AAEZ,QAAM,aAAa,MAAM;AACvB,QAAG,SAAS,QAAQ,QAAQ;AAC1B,WAAK,KAAK;AACV;AAAA,IACF;AAEA,YAAQ,eAAe,QAAQ,KAAK;AACpC;AAEA,UAAM,aAAa,KAAK,OAAO,IAAI,IAAG,KAAK,SAAS;AAEpD,UAAM,QAAQ,KAAK,IAAI,GAAG,SAAS,cAAc,SAAS;AAE1D,SAAK,QAAQ,WAAW,YAAY,KAAK;AAAA,EAE3C;AAEA,aAAW;AACX,SAAO;AACT;AAEA,OAAO,UAAU,iBAAiB,SAAU,OAAO;AACjD,MAAG,OAAO,SAAS,UAAU;AAC3B,SAAK,SAAS,cAAc;AAAA,EAC9B;AACA,SAAO;AACT;AAEA,OAAO,UAAU,oBAAoB,SAAU,OAAO;AACpD,MAAG,OAAO,SAAS,UAAU;AAC3B,SAAK,SAAS,iBAAiB;AAAA,EACjC;AACA,SAAO;AACT;AAEA,OAAO,UAAU,QAAQ,SAAU,UAAU,CAAC,GAAG;AAC/C,QAAM,WAAW,KAAK;AACtB,QAAM,UAAU,SAAS;AAEzB,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,QAAQ,KAAK;AAAA,IACjB;AAAA,IACA,KAAK,MAAM,QAAQ,SAAS,QAAQ,YAAY,MAAM;AAAA,EACxD;AAEA,MAAG,SAAS,GAAG;AACb,WAAO;AAAA,EACT;AAEA,eAAa,KAAK,KAAK;AACvB,OAAK,QAAQ;AAEb,OAAK,QAAQ,CAAC;AACd,OAAK,WAAW;AAEhB,MAAG,CAAC,UAAU;AACZ,YAAQ,cAAc,MAAM,KAAK,QAAQ,WAAW,EAC3B,MAAM,GAAG,CAAC,KAAK,EACf,KAAK,EAAE;AAEhC,WAAO;AAAA,EACT;AAEA,MAAI,UAAU;AAEd,QAAM,gBAAgB,MAAM;AAC1B,QAAG,WAAW,SAAS,CAAC,QAAQ,YAAY,QAAQ;AAClD,WAAK,QAAQ;AACb,WAAK,WAAW;AAChB;AAAA,IACF;AAEA,YAAQ,cAAc,MAAM,KAAK,QAAQ,WAAW,EACzB,MAAM,GAAG,EAAE,EACX,KAAK,EAAE;AAElC;AAEA,UAAM,aAAa,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS;AAErD,UAAM,QAAQ,KAAK,IAAI,GAAG,SAAS,cAAc,SAAS;AAE1D,SAAK,QAAQ,WAAW,eAAe,KAAK;AAAA,EAC9C;AAEA,OAAK,WAAW;AAChB,gBAAc;AAEd,SAAO;AACT;AAEA,IAAO,gBAAQ;",
4
+ "sourcesContent": ["\"use strict\"\n\nconst TypeIt = function (data) {\n this.settings = {};\n if (data instanceof Element) {\n this.settings.element = data;\n this.settings.typingSpeed = 150;\n this.settings.speedVariation = 50;\n this.settings.autoScroll = true;\n }\n else {\n this.settings.element = data.element;\n this.settings.typingSpeed = data.typingSpeed ?? 150;\n this.settings.speedVariation = data.speedVariation ?? 50;\n this.settings.autoScroll = data.autoScroll ?? true;\n }\n\n if (!(this.settings.element instanceof Element)) {\n throw new Error(\"Initialize with an html element\")\n }\n\n this.timer = null;\n this.queue = [];\n this.isTyping = false;\n\n this.events = {};\n this.observer = null;\n}\n\nTypeIt.prototype.type = function (content) {\n this.queue.push(content);\n\n if (!this.isTyping) {\n this.next();\n }\n\n return this;\n}\n\n\nTypeIt.prototype.next = function () {\n if (this.queue.length === 0) {\n this.isTyping = false;\n this.emit(\"complete\");\n\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n\n return;\n }\n\n this.isTyping = true;\n\n var content = this.queue.shift();\n var settings = this.settings;\n var element = settings.element;\n var parentElement = element.parentElement || null;\n\n if (settings.autoScroll && parentElement) {\n if (this.observer) {\n this.observer.disconnect();\n }\n\n var previousHeight = parentElement.scrollHeight;\n\n this.observer = new ResizeObserver(scrollToBottom);\n this.observer.observe(parentElement);\n\n function scrollToBottom() {\n var currentHeight = parentElement.scrollHeight;\n\n if (currentHeight > previousHeight) {\n parentElement.scrollTo({\n top: parentElement.scrollHeight,\n behavior: \"smooth\",\n });\n\n previousHeight = currentHeight;\n }\n }\n }\n\n var index = 0;\n\n const addContent = () => {\n if (index >= content.length) {\n this.next();\n return;\n }\n\n element.textContent += content[index];\n index++;\n\n var variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n var delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(addContent, delay);\n\n }\n\n addContent();\n return this;\n}\n\nTypeIt.prototype.setTypingSpeed = function (speed) {\n if (typeof speed == \"number\") {\n this.settings.typingSpeed = speed;\n }\n return this;\n}\n\nTypeIt.prototype.setVariationSpeed = function (speed) {\n if (typeof speed == \"number\") {\n this.settings.speedVariation = speed;\n }\n return this;\n}\n\nTypeIt.prototype.clear = function (options = {}) {\n var settings = this.settings;\n var element = settings.element;\n\n var animated = options.animated ?? true;\n var count = Math.max(\n 0,\n Math.floor(options.count ?? element.textContent.length)\n )\n\n if (count <= 0) {\n return this;\n }\n\n clearTimeout(this.timer);\n this.timer = null;\n\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n\n this.queue = [];\n this.isTyping = false;\n\n if (!animated) {\n element.textContent = Array.from(element.textContent)\n .slice(0, -count)\n .join(\"\");\n\n this.emit(\"clear\");\n\n return this;\n }\n\n var deleted = 0;\n\n function removeContent() {\n if (deleted >= count || !element.textContent.length) {\n this.timer = null;\n this.isTyping = false;\n\n this.emit(\"clear\");\n\n return;\n }\n\n element.textContent = Array.from(element.textContent)\n .slice(0, -1)\n .join(\"\");\n\n deleted++;\n\n var variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n var delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(removeContent, delay);\n }\n\n this.isTyping = true;\n removeContent();\n\n return this;\n}\n\nTypeIt.prototype.on = function (event, callback) {\n if (typeof callback !== \"function\") {\n return this;\n }\n\n if (!this.events[event]) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n}\n\nTypeIt.prototype.off = function (event, callback) {\n if (!this.events[event]) {\n return this;\n }\n\n if (typeof callback === \"function\") {\n this.events[event] = this.events[event].filter(function (cb) {\n return cb !== callback;\n });\n } else {\n delete this.events[event];\n }\n\n return this;\n}\n\nTypeIt.prototype.emit = function (event, ...args) {\n const callbacks = this.events[event];\n\n if (!callbacks || callbacks.length === 0) {\n return this;\n }\n\n callbacks.slice().forEach(function (callback) {\n callback.apply(this, args);\n }, this);\n\n return this;\n}\n\nexport default TypeIt;\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,IAAM,SAAS,SAAU,MAAM;AAC7B,OAAK,WAAW,CAAC;AACjB,MAAI,gBAAgB,SAAS;AAC3B,SAAK,SAAS,UAAU;AACxB,SAAK,SAAS,cAAc;AAC5B,SAAK,SAAS,iBAAiB;AAC/B,SAAK,SAAS,aAAa;AAAA,EAC7B,OACK;AACH,SAAK,SAAS,UAAU,KAAK;AAC7B,SAAK,SAAS,cAAc,KAAK,eAAe;AAChD,SAAK,SAAS,iBAAiB,KAAK,kBAAkB;AACtD,SAAK,SAAS,aAAa,KAAK,cAAc;AAAA,EAChD;AAEA,MAAI,EAAE,KAAK,SAAS,mBAAmB,UAAU;AAC/C,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AAEA,OAAK,QAAQ;AACb,OAAK,QAAQ,CAAC;AACd,OAAK,WAAW;AAEhB,OAAK,SAAS,CAAC;AACf,OAAK,WAAW;AAClB;AAEA,OAAO,UAAU,OAAO,SAAU,SAAS;AACzC,OAAK,MAAM,KAAK,OAAO;AAEvB,MAAI,CAAC,KAAK,UAAU;AAClB,SAAK,KAAK;AAAA,EACZ;AAEA,SAAO;AACT;AAGA,OAAO,UAAU,OAAO,WAAY;AAClC,MAAI,KAAK,MAAM,WAAW,GAAG;AAC3B,SAAK,WAAW;AAChB,SAAK,KAAK,UAAU;AAEpB,QAAI,KAAK,UAAU;AACjB,WAAK,SAAS,WAAW;AACzB,WAAK,WAAW;AAAA,IAClB;AAEA;AAAA,EACF;AAEA,OAAK,WAAW;AAEhB,MAAI,UAAU,KAAK,MAAM,MAAM;AAC/B,MAAI,WAAW,KAAK;AACpB,MAAI,UAAU,SAAS;AACvB,MAAI,gBAAgB,QAAQ,iBAAiB;AAE7C,MAAI,SAAS,cAAc,eAAe;AAUxC,QAAS,iBAAT,WAA0B;AACxB,UAAI,gBAAgB,cAAc;AAElC,UAAI,gBAAgB,gBAAgB;AAClC,sBAAc,SAAS;AAAA,UACrB,KAAK,cAAc;AAAA,UACnB,UAAU;AAAA,QACZ,CAAC;AAED,yBAAiB;AAAA,MACnB;AAAA,IACF;AApBA,QAAI,KAAK,UAAU;AACjB,WAAK,SAAS,WAAW;AAAA,IAC3B;AAEA,QAAI,iBAAiB,cAAc;AAEnC,SAAK,WAAW,IAAI,eAAe,cAAc;AACjD,SAAK,SAAS,QAAQ,aAAa;AAAA,EAcrC;AAEA,MAAI,QAAQ;AAEZ,QAAM,aAAa,MAAM;AACvB,QAAI,SAAS,QAAQ,QAAQ;AAC3B,WAAK,KAAK;AACV;AAAA,IACF;AAEA,YAAQ,eAAe,QAAQ,KAAK;AACpC;AAEA,QAAI,aAAa,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS;AAEnD,QAAI,QAAQ,KAAK,IAAI,GAAG,SAAS,cAAc,SAAS;AAExD,SAAK,QAAQ,WAAW,YAAY,KAAK;AAAA,EAE3C;AAEA,aAAW;AACX,SAAO;AACT;AAEA,OAAO,UAAU,iBAAiB,SAAU,OAAO;AACjD,MAAI,OAAO,SAAS,UAAU;AAC5B,SAAK,SAAS,cAAc;AAAA,EAC9B;AACA,SAAO;AACT;AAEA,OAAO,UAAU,oBAAoB,SAAU,OAAO;AACpD,MAAI,OAAO,SAAS,UAAU;AAC5B,SAAK,SAAS,iBAAiB;AAAA,EACjC;AACA,SAAO;AACT;AAEA,OAAO,UAAU,QAAQ,SAAU,UAAU,CAAC,GAAG;AAC/C,MAAI,WAAW,KAAK;AACpB,MAAI,UAAU,SAAS;AAEvB,MAAI,WAAW,QAAQ,YAAY;AACnC,MAAI,QAAQ,KAAK;AAAA,IACf;AAAA,IACA,KAAK,MAAM,QAAQ,SAAS,QAAQ,YAAY,MAAM;AAAA,EACxD;AAEA,MAAI,SAAS,GAAG;AACd,WAAO;AAAA,EACT;AAEA,eAAa,KAAK,KAAK;AACvB,OAAK,QAAQ;AAEb,MAAI,KAAK,UAAU;AACjB,SAAK,SAAS,WAAW;AACzB,SAAK,WAAW;AAAA,EAClB;AAEA,OAAK,QAAQ,CAAC;AACd,OAAK,WAAW;AAEhB,MAAI,CAAC,UAAU;AACb,YAAQ,cAAc,MAAM,KAAK,QAAQ,WAAW,EACjD,MAAM,GAAG,CAAC,KAAK,EACf,KAAK,EAAE;AAEV,SAAK,KAAK,OAAO;AAEjB,WAAO;AAAA,EACT;AAEA,MAAI,UAAU;AAEd,WAAS,gBAAgB;AACvB,QAAI,WAAW,SAAS,CAAC,QAAQ,YAAY,QAAQ;AACnD,WAAK,QAAQ;AACb,WAAK,WAAW;AAEhB,WAAK,KAAK,OAAO;AAEjB;AAAA,IACF;AAEA,YAAQ,cAAc,MAAM,KAAK,QAAQ,WAAW,EACjD,MAAM,GAAG,EAAE,EACX,KAAK,EAAE;AAEV;AAEA,QAAI,aAAa,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS;AAEnD,QAAI,QAAQ,KAAK,IAAI,GAAG,SAAS,cAAc,SAAS;AAExD,SAAK,QAAQ,WAAW,eAAe,KAAK;AAAA,EAC9C;AAEA,OAAK,WAAW;AAChB,gBAAc;AAEd,SAAO;AACT;AAEA,OAAO,UAAU,KAAK,SAAU,OAAO,UAAU;AAC/C,MAAI,OAAO,aAAa,YAAY;AAClC,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,KAAK,OAAO,KAAK,GAAG;AACvB,SAAK,OAAO,KAAK,IAAI,CAAC;AAAA,EACxB;AAEA,OAAK,OAAO,KAAK,EAAE,KAAK,QAAQ;AAEhC,SAAO;AACT;AAEA,OAAO,UAAU,MAAM,SAAU,OAAO,UAAU;AAChD,MAAI,CAAC,KAAK,OAAO,KAAK,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,aAAa,YAAY;AAClC,SAAK,OAAO,KAAK,IAAI,KAAK,OAAO,KAAK,EAAE,OAAO,SAAU,IAAI;AAC3D,aAAO,OAAO;AAAA,IAChB,CAAC;AAAA,EACH,OAAO;AACL,WAAO,KAAK,OAAO,KAAK;AAAA,EAC1B;AAEA,SAAO;AACT;AAEA,OAAO,UAAU,OAAO,SAAU,UAAU,MAAM;AAChD,QAAM,YAAY,KAAK,OAAO,KAAK;AAEnC,MAAI,CAAC,aAAa,UAAU,WAAW,GAAG;AACxC,WAAO;AAAA,EACT;AAEA,YAAU,MAAM,EAAE,QAAQ,SAAU,UAAU;AAC5C,aAAS,MAAM,MAAM,IAAI;AAAA,EAC3B,GAAG,IAAI;AAEP,SAAO;AACT;AAEA,IAAO,gBAAQ;",
6
6
  "names": []
7
7
  }
package/dist/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export interface TypeItOptions {
5
5
  typingSpeed?: number;
6
6
  /** Speed variation in milliseconds for human-like random variance (default: 50) */
7
7
  speedVariation?: number;
8
+ /** Whether the parent container automatically scrolls to bottom as text grows (default: true) */
9
+ autoScroll?: boolean;
8
10
  }
9
11
 
10
12
  export interface ClearOptions {
@@ -25,6 +27,7 @@ export class TypeIt {
25
27
  element: Element;
26
28
  typingSpeed: number;
27
29
  speedVariation: number;
30
+ autoScroll: boolean;
28
31
  };
29
32
  timer: ReturnType<typeof setTimeout> | null;
30
33
  queue: string[];
@@ -53,11 +56,34 @@ export class TypeIt {
53
56
  */
54
57
  setVariationSpeed(speed: number): this;
55
58
 
59
+ events: Record<string, ((...args: any[]) => void)[]>;
60
+
56
61
  /**
57
62
  * Clears characters from the element.
58
63
  * @param options Configuration options for deletion.
59
64
  */
60
65
  clear(options?: ClearOptions): this;
66
+
67
+ /**
68
+ * Registers an event listener callback.
69
+ * @param event The event name to listen to.
70
+ * @param callback The function to execute when the event is emitted.
71
+ */
72
+ on(event: string, callback: (...args: any[]) => void): this;
73
+
74
+ /**
75
+ * Removes a specific event listener or all listeners for an event.
76
+ * @param event The event name.
77
+ * @param callback The specific callback to remove. If omitted, removes all callbacks for the event.
78
+ */
79
+ off(event: string, callback?: (...args: any[]) => void): this;
80
+
81
+ /**
82
+ * Emits an event to all registered listeners.
83
+ * @param event The event name to emit.
84
+ * @param args Arguments to pass to the callbacks.
85
+ */
86
+ emit(event: string, ...args: any[]): this;
61
87
  }
62
88
 
63
89
  export default TypeIt;
@@ -29,14 +29,21 @@ var TypeIt = (() => {
29
29
  this.settings.element = data;
30
30
  this.settings.typingSpeed = 150;
31
31
  this.settings.speedVariation = 50;
32
+ this.settings.autoScroll = true;
32
33
  } else {
33
34
  this.settings.element = data.element;
34
35
  this.settings.typingSpeed = data.typingSpeed ?? 150;
35
36
  this.settings.speedVariation = data.speedVariation ?? 50;
37
+ this.settings.autoScroll = data.autoScroll ?? true;
38
+ }
39
+ if (!(this.settings.element instanceof Element)) {
40
+ throw new Error("Initialize with an html element");
36
41
  }
37
42
  this.timer = null;
38
43
  this.queue = [];
39
44
  this.isTyping = false;
45
+ this.events = {};
46
+ this.observer = null;
40
47
  };
41
48
  TypeIt.prototype.type = function(content) {
42
49
  this.queue.push(content);
@@ -48,13 +55,37 @@ var TypeIt = (() => {
48
55
  TypeIt.prototype.next = function() {
49
56
  if (this.queue.length === 0) {
50
57
  this.isTyping = false;
58
+ this.emit("complete");
59
+ if (this.observer) {
60
+ this.observer.disconnect();
61
+ this.observer = null;
62
+ }
51
63
  return;
52
64
  }
53
65
  this.isTyping = true;
54
- const content = this.queue.shift();
55
- const settings = this.settings;
56
- const element = settings.element;
57
- let index = 0;
66
+ var content = this.queue.shift();
67
+ var settings = this.settings;
68
+ var element = settings.element;
69
+ var parentElement = element.parentElement || null;
70
+ if (settings.autoScroll && parentElement) {
71
+ let scrollToBottom = function() {
72
+ var currentHeight = parentElement.scrollHeight;
73
+ if (currentHeight > previousHeight) {
74
+ parentElement.scrollTo({
75
+ top: parentElement.scrollHeight,
76
+ behavior: "smooth"
77
+ });
78
+ previousHeight = currentHeight;
79
+ }
80
+ };
81
+ if (this.observer) {
82
+ this.observer.disconnect();
83
+ }
84
+ var previousHeight = parentElement.scrollHeight;
85
+ this.observer = new ResizeObserver(scrollToBottom);
86
+ this.observer.observe(parentElement);
87
+ }
88
+ var index = 0;
58
89
  const addContent = () => {
59
90
  if (index >= content.length) {
60
91
  this.next();
@@ -62,8 +93,8 @@ var TypeIt = (() => {
62
93
  }
63
94
  element.textContent += content[index];
64
95
  index++;
65
- const variation = (Math.random() * 2 - 1) * settings.speedVariation;
66
- const delay = Math.max(0, settings.typingSpeed + variation);
96
+ var variation = (Math.random() * 2 - 1) * settings.speedVariation;
97
+ var delay = Math.max(0, settings.typingSpeed + variation);
67
98
  this.timer = setTimeout(addContent, delay);
68
99
  };
69
100
  addContent();
@@ -82,10 +113,10 @@ var TypeIt = (() => {
82
113
  return this;
83
114
  };
84
115
  TypeIt.prototype.clear = function(options = {}) {
85
- const settings = this.settings;
86
- const element = settings.element;
87
- const animated = options.animated ?? true;
88
- const count = Math.max(
116
+ var settings = this.settings;
117
+ var element = settings.element;
118
+ var animated = options.animated ?? true;
119
+ var count = Math.max(
89
120
  0,
90
121
  Math.floor(options.count ?? element.textContent.length)
91
122
  );
@@ -94,29 +125,68 @@ var TypeIt = (() => {
94
125
  }
95
126
  clearTimeout(this.timer);
96
127
  this.timer = null;
128
+ if (this.observer) {
129
+ this.observer.disconnect();
130
+ this.observer = null;
131
+ }
97
132
  this.queue = [];
98
133
  this.isTyping = false;
99
134
  if (!animated) {
100
135
  element.textContent = Array.from(element.textContent).slice(0, -count).join("");
136
+ this.emit("clear");
101
137
  return this;
102
138
  }
103
- let deleted = 0;
104
- const removeContent = () => {
139
+ var deleted = 0;
140
+ function removeContent() {
105
141
  if (deleted >= count || !element.textContent.length) {
106
142
  this.timer = null;
107
143
  this.isTyping = false;
144
+ this.emit("clear");
108
145
  return;
109
146
  }
110
147
  element.textContent = Array.from(element.textContent).slice(0, -1).join("");
111
148
  deleted++;
112
- const variation = (Math.random() * 2 - 1) * settings.speedVariation;
113
- const delay = Math.max(0, settings.typingSpeed + variation);
149
+ var variation = (Math.random() * 2 - 1) * settings.speedVariation;
150
+ var delay = Math.max(0, settings.typingSpeed + variation);
114
151
  this.timer = setTimeout(removeContent, delay);
115
- };
152
+ }
116
153
  this.isTyping = true;
117
154
  removeContent();
118
155
  return this;
119
156
  };
157
+ TypeIt.prototype.on = function(event, callback) {
158
+ if (typeof callback !== "function") {
159
+ return this;
160
+ }
161
+ if (!this.events[event]) {
162
+ this.events[event] = [];
163
+ }
164
+ this.events[event].push(callback);
165
+ return this;
166
+ };
167
+ TypeIt.prototype.off = function(event, callback) {
168
+ if (!this.events[event]) {
169
+ return this;
170
+ }
171
+ if (typeof callback === "function") {
172
+ this.events[event] = this.events[event].filter(function(cb) {
173
+ return cb !== callback;
174
+ });
175
+ } else {
176
+ delete this.events[event];
177
+ }
178
+ return this;
179
+ };
180
+ TypeIt.prototype.emit = function(event, ...args) {
181
+ const callbacks = this.events[event];
182
+ if (!callbacks || callbacks.length === 0) {
183
+ return this;
184
+ }
185
+ callbacks.slice().forEach(function(callback) {
186
+ callback.apply(this, args);
187
+ }, this);
188
+ return this;
189
+ };
120
190
  var index_default = TypeIt;
121
191
  return __toCommonJS(index_exports);
122
192
  })();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js"],
4
- "sourcesContent": ["\"use strict\"\n\nconst TypeIt = function (data) {\n this.settings = {};\n if(data instanceof Element) {\n this.settings.element = data;\n this.settings.typingSpeed = 150;\n this.settings.speedVariation = 50;\n }\n else {\n this.settings.element = data.element;\n this.settings.typingSpeed = data.typingSpeed ?? 150;\n this.settings.speedVariation = data.speedVariation ?? 50;\n }\n\n this.timer = null;\n this.queue = [];\n this.isTyping = false;\n\n}\n\nTypeIt.prototype.type = function (content) {\n this.queue.push(content);\n\n if(!this.isTyping) {\n this.next();\n }\n\n return this;\n}\n\n\nTypeIt.prototype.next = function () {\n if(this.queue.length === 0) {\n this.isTyping = false;\n return;\n }\n\n this.isTyping = true;\n\n const content = this.queue.shift();\n const settings = this.settings;\n const element = settings.element;\n\n\n let index = 0;\n\n const addContent = () => {\n if(index >= content.length) {\n this.next();\n return;\n }\n\n element.textContent += content[index];\n index++;\n\n const variation = (Math.random() * 2 -1) * settings.speedVariation;\n\n const delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(addContent, delay);\n \n }\n\n addContent();\n return this;\n}\n\nTypeIt.prototype.setTypingSpeed = function (speed) {\n if(typeof speed == \"number\") {\n this.settings.typingSpeed = speed;\n }\n return this;\n}\n\nTypeIt.prototype.setVariationSpeed = function (speed) {\n if(typeof speed == \"number\") {\n this.settings.speedVariation = speed;\n }\n return this;\n}\n\nTypeIt.prototype.clear = function (options = {}) {\n const settings = this.settings;\n const element = settings.element;\n\n const animated = options.animated ?? true;\n const count = Math.max(\n 0,\n Math.floor(options.count ?? element.textContent.length)\n ) \n\n if(count <= 0) {\n return this;\n }\n\n clearTimeout(this.timer);\n this.timer = null;\n\n this.queue = [];\n this.isTyping = false;\n\n if(!animated) {\n element.textContent = Array.from(element.textContent)\n .slice(0, -count)\n .join(\"\");\n\n return this;\n }\n\n let deleted = 0;\n\n const removeContent = () => {\n if(deleted >= count || !element.textContent.length) {\n this.timer = null;\n this.isTyping = false;\n return;\n }\n\n element.textContent = Array.from(element.textContent)\n .slice(0, -1)\n .join(\"\");\n\n deleted++;\n\n const variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n const delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(removeContent, delay);\n }\n\n this.isTyping = true;\n removeContent();\n\n return this;\n}\n\nexport default TypeIt;\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAEA,MAAM,SAAS,SAAU,MAAM;AAC7B,SAAK,WAAW,CAAC;AACjB,QAAG,gBAAgB,SAAS;AAC1B,WAAK,SAAS,UAAU;AACxB,WAAK,SAAS,cAAc;AAC5B,WAAK,SAAS,iBAAiB;AAAA,IACjC,OACK;AACH,WAAK,SAAS,UAAU,KAAK;AAC7B,WAAK,SAAS,cAAc,KAAK,eAAe;AAChD,WAAK,SAAS,iBAAiB,KAAK,kBAAkB;AAAA,IACxD;AAEA,SAAK,QAAQ;AACb,SAAK,QAAQ,CAAC;AACd,SAAK,WAAW;AAAA,EAElB;AAEA,SAAO,UAAU,OAAO,SAAU,SAAS;AACzC,SAAK,MAAM,KAAK,OAAO;AAEvB,QAAG,CAAC,KAAK,UAAU;AACjB,WAAK,KAAK;AAAA,IACZ;AAEA,WAAO;AAAA,EACT;AAGA,SAAO,UAAU,OAAO,WAAY;AAClC,QAAG,KAAK,MAAM,WAAW,GAAG;AAC1B,WAAK,WAAW;AAChB;AAAA,IACF;AAEA,SAAK,WAAW;AAEhB,UAAM,UAAU,KAAK,MAAM,MAAM;AACjC,UAAM,WAAW,KAAK;AACtB,UAAM,UAAU,SAAS;AAGzB,QAAI,QAAQ;AAEZ,UAAM,aAAa,MAAM;AACvB,UAAG,SAAS,QAAQ,QAAQ;AAC1B,aAAK,KAAK;AACV;AAAA,MACF;AAEA,cAAQ,eAAe,QAAQ,KAAK;AACpC;AAEA,YAAM,aAAa,KAAK,OAAO,IAAI,IAAG,KAAK,SAAS;AAEpD,YAAM,QAAQ,KAAK,IAAI,GAAG,SAAS,cAAc,SAAS;AAE1D,WAAK,QAAQ,WAAW,YAAY,KAAK;AAAA,IAE3C;AAEA,eAAW;AACX,WAAO;AAAA,EACT;AAEA,SAAO,UAAU,iBAAiB,SAAU,OAAO;AACjD,QAAG,OAAO,SAAS,UAAU;AAC3B,WAAK,SAAS,cAAc;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AAEA,SAAO,UAAU,oBAAoB,SAAU,OAAO;AACpD,QAAG,OAAO,SAAS,UAAU;AAC3B,WAAK,SAAS,iBAAiB;AAAA,IACjC;AACA,WAAO;AAAA,EACT;AAEA,SAAO,UAAU,QAAQ,SAAU,UAAU,CAAC,GAAG;AAC/C,UAAM,WAAW,KAAK;AACtB,UAAM,UAAU,SAAS;AAEzB,UAAM,WAAW,QAAQ,YAAY;AACrC,UAAM,QAAQ,KAAK;AAAA,MACjB;AAAA,MACA,KAAK,MAAM,QAAQ,SAAS,QAAQ,YAAY,MAAM;AAAA,IACxD;AAEA,QAAG,SAAS,GAAG;AACb,aAAO;AAAA,IACT;AAEA,iBAAa,KAAK,KAAK;AACvB,SAAK,QAAQ;AAEb,SAAK,QAAQ,CAAC;AACd,SAAK,WAAW;AAEhB,QAAG,CAAC,UAAU;AACZ,cAAQ,cAAc,MAAM,KAAK,QAAQ,WAAW,EAC3B,MAAM,GAAG,CAAC,KAAK,EACf,KAAK,EAAE;AAEhC,aAAO;AAAA,IACT;AAEA,QAAI,UAAU;AAEd,UAAM,gBAAgB,MAAM;AAC1B,UAAG,WAAW,SAAS,CAAC,QAAQ,YAAY,QAAQ;AAClD,aAAK,QAAQ;AACb,aAAK,WAAW;AAChB;AAAA,MACF;AAEA,cAAQ,cAAc,MAAM,KAAK,QAAQ,WAAW,EACzB,MAAM,GAAG,EAAE,EACX,KAAK,EAAE;AAElC;AAEA,YAAM,aAAa,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS;AAErD,YAAM,QAAQ,KAAK,IAAI,GAAG,SAAS,cAAc,SAAS;AAE1D,WAAK,QAAQ,WAAW,eAAe,KAAK;AAAA,IAC9C;AAEA,SAAK,WAAW;AAChB,kBAAc;AAEd,WAAO;AAAA,EACT;AAEA,MAAO,gBAAQ;",
4
+ "sourcesContent": ["\"use strict\"\n\nconst TypeIt = function (data) {\n this.settings = {};\n if (data instanceof Element) {\n this.settings.element = data;\n this.settings.typingSpeed = 150;\n this.settings.speedVariation = 50;\n this.settings.autoScroll = true;\n }\n else {\n this.settings.element = data.element;\n this.settings.typingSpeed = data.typingSpeed ?? 150;\n this.settings.speedVariation = data.speedVariation ?? 50;\n this.settings.autoScroll = data.autoScroll ?? true;\n }\n\n if (!(this.settings.element instanceof Element)) {\n throw new Error(\"Initialize with an html element\")\n }\n\n this.timer = null;\n this.queue = [];\n this.isTyping = false;\n\n this.events = {};\n this.observer = null;\n}\n\nTypeIt.prototype.type = function (content) {\n this.queue.push(content);\n\n if (!this.isTyping) {\n this.next();\n }\n\n return this;\n}\n\n\nTypeIt.prototype.next = function () {\n if (this.queue.length === 0) {\n this.isTyping = false;\n this.emit(\"complete\");\n\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n\n return;\n }\n\n this.isTyping = true;\n\n var content = this.queue.shift();\n var settings = this.settings;\n var element = settings.element;\n var parentElement = element.parentElement || null;\n\n if (settings.autoScroll && parentElement) {\n if (this.observer) {\n this.observer.disconnect();\n }\n\n var previousHeight = parentElement.scrollHeight;\n\n this.observer = new ResizeObserver(scrollToBottom);\n this.observer.observe(parentElement);\n\n function scrollToBottom() {\n var currentHeight = parentElement.scrollHeight;\n\n if (currentHeight > previousHeight) {\n parentElement.scrollTo({\n top: parentElement.scrollHeight,\n behavior: \"smooth\",\n });\n\n previousHeight = currentHeight;\n }\n }\n }\n\n var index = 0;\n\n const addContent = () => {\n if (index >= content.length) {\n this.next();\n return;\n }\n\n element.textContent += content[index];\n index++;\n\n var variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n var delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(addContent, delay);\n\n }\n\n addContent();\n return this;\n}\n\nTypeIt.prototype.setTypingSpeed = function (speed) {\n if (typeof speed == \"number\") {\n this.settings.typingSpeed = speed;\n }\n return this;\n}\n\nTypeIt.prototype.setVariationSpeed = function (speed) {\n if (typeof speed == \"number\") {\n this.settings.speedVariation = speed;\n }\n return this;\n}\n\nTypeIt.prototype.clear = function (options = {}) {\n var settings = this.settings;\n var element = settings.element;\n\n var animated = options.animated ?? true;\n var count = Math.max(\n 0,\n Math.floor(options.count ?? element.textContent.length)\n )\n\n if (count <= 0) {\n return this;\n }\n\n clearTimeout(this.timer);\n this.timer = null;\n\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n\n this.queue = [];\n this.isTyping = false;\n\n if (!animated) {\n element.textContent = Array.from(element.textContent)\n .slice(0, -count)\n .join(\"\");\n\n this.emit(\"clear\");\n\n return this;\n }\n\n var deleted = 0;\n\n function removeContent() {\n if (deleted >= count || !element.textContent.length) {\n this.timer = null;\n this.isTyping = false;\n\n this.emit(\"clear\");\n\n return;\n }\n\n element.textContent = Array.from(element.textContent)\n .slice(0, -1)\n .join(\"\");\n\n deleted++;\n\n var variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n var delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(removeContent, delay);\n }\n\n this.isTyping = true;\n removeContent();\n\n return this;\n}\n\nTypeIt.prototype.on = function (event, callback) {\n if (typeof callback !== \"function\") {\n return this;\n }\n\n if (!this.events[event]) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n}\n\nTypeIt.prototype.off = function (event, callback) {\n if (!this.events[event]) {\n return this;\n }\n\n if (typeof callback === \"function\") {\n this.events[event] = this.events[event].filter(function (cb) {\n return cb !== callback;\n });\n } else {\n delete this.events[event];\n }\n\n return this;\n}\n\nTypeIt.prototype.emit = function (event, ...args) {\n const callbacks = this.events[event];\n\n if (!callbacks || callbacks.length === 0) {\n return this;\n }\n\n callbacks.slice().forEach(function (callback) {\n callback.apply(this, args);\n }, this);\n\n return this;\n}\n\nexport default TypeIt;\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/index.mjs CHANGED
@@ -5,14 +5,21 @@ var TypeIt = function(data) {
5
5
  this.settings.element = data;
6
6
  this.settings.typingSpeed = 150;
7
7
  this.settings.speedVariation = 50;
8
+ this.settings.autoScroll = true;
8
9
  } else {
9
10
  this.settings.element = data.element;
10
11
  this.settings.typingSpeed = data.typingSpeed ?? 150;
11
12
  this.settings.speedVariation = data.speedVariation ?? 50;
13
+ this.settings.autoScroll = data.autoScroll ?? true;
14
+ }
15
+ if (!(this.settings.element instanceof Element)) {
16
+ throw new Error("Initialize with an html element");
12
17
  }
13
18
  this.timer = null;
14
19
  this.queue = [];
15
20
  this.isTyping = false;
21
+ this.events = {};
22
+ this.observer = null;
16
23
  };
17
24
  TypeIt.prototype.type = function(content) {
18
25
  this.queue.push(content);
@@ -24,13 +31,37 @@ TypeIt.prototype.type = function(content) {
24
31
  TypeIt.prototype.next = function() {
25
32
  if (this.queue.length === 0) {
26
33
  this.isTyping = false;
34
+ this.emit("complete");
35
+ if (this.observer) {
36
+ this.observer.disconnect();
37
+ this.observer = null;
38
+ }
27
39
  return;
28
40
  }
29
41
  this.isTyping = true;
30
- const content = this.queue.shift();
31
- const settings = this.settings;
32
- const element = settings.element;
33
- let index = 0;
42
+ var content = this.queue.shift();
43
+ var settings = this.settings;
44
+ var element = settings.element;
45
+ var parentElement = element.parentElement || null;
46
+ if (settings.autoScroll && parentElement) {
47
+ let scrollToBottom = function() {
48
+ var currentHeight = parentElement.scrollHeight;
49
+ if (currentHeight > previousHeight) {
50
+ parentElement.scrollTo({
51
+ top: parentElement.scrollHeight,
52
+ behavior: "smooth"
53
+ });
54
+ previousHeight = currentHeight;
55
+ }
56
+ };
57
+ if (this.observer) {
58
+ this.observer.disconnect();
59
+ }
60
+ var previousHeight = parentElement.scrollHeight;
61
+ this.observer = new ResizeObserver(scrollToBottom);
62
+ this.observer.observe(parentElement);
63
+ }
64
+ var index = 0;
34
65
  const addContent = () => {
35
66
  if (index >= content.length) {
36
67
  this.next();
@@ -38,8 +69,8 @@ TypeIt.prototype.next = function() {
38
69
  }
39
70
  element.textContent += content[index];
40
71
  index++;
41
- const variation = (Math.random() * 2 - 1) * settings.speedVariation;
42
- const delay = Math.max(0, settings.typingSpeed + variation);
72
+ var variation = (Math.random() * 2 - 1) * settings.speedVariation;
73
+ var delay = Math.max(0, settings.typingSpeed + variation);
43
74
  this.timer = setTimeout(addContent, delay);
44
75
  };
45
76
  addContent();
@@ -58,10 +89,10 @@ TypeIt.prototype.setVariationSpeed = function(speed) {
58
89
  return this;
59
90
  };
60
91
  TypeIt.prototype.clear = function(options = {}) {
61
- const settings = this.settings;
62
- const element = settings.element;
63
- const animated = options.animated ?? true;
64
- const count = Math.max(
92
+ var settings = this.settings;
93
+ var element = settings.element;
94
+ var animated = options.animated ?? true;
95
+ var count = Math.max(
65
96
  0,
66
97
  Math.floor(options.count ?? element.textContent.length)
67
98
  );
@@ -70,29 +101,68 @@ TypeIt.prototype.clear = function(options = {}) {
70
101
  }
71
102
  clearTimeout(this.timer);
72
103
  this.timer = null;
104
+ if (this.observer) {
105
+ this.observer.disconnect();
106
+ this.observer = null;
107
+ }
73
108
  this.queue = [];
74
109
  this.isTyping = false;
75
110
  if (!animated) {
76
111
  element.textContent = Array.from(element.textContent).slice(0, -count).join("");
112
+ this.emit("clear");
77
113
  return this;
78
114
  }
79
- let deleted = 0;
80
- const removeContent = () => {
115
+ var deleted = 0;
116
+ function removeContent() {
81
117
  if (deleted >= count || !element.textContent.length) {
82
118
  this.timer = null;
83
119
  this.isTyping = false;
120
+ this.emit("clear");
84
121
  return;
85
122
  }
86
123
  element.textContent = Array.from(element.textContent).slice(0, -1).join("");
87
124
  deleted++;
88
- const variation = (Math.random() * 2 - 1) * settings.speedVariation;
89
- const delay = Math.max(0, settings.typingSpeed + variation);
125
+ var variation = (Math.random() * 2 - 1) * settings.speedVariation;
126
+ var delay = Math.max(0, settings.typingSpeed + variation);
90
127
  this.timer = setTimeout(removeContent, delay);
91
- };
128
+ }
92
129
  this.isTyping = true;
93
130
  removeContent();
94
131
  return this;
95
132
  };
133
+ TypeIt.prototype.on = function(event, callback) {
134
+ if (typeof callback !== "function") {
135
+ return this;
136
+ }
137
+ if (!this.events[event]) {
138
+ this.events[event] = [];
139
+ }
140
+ this.events[event].push(callback);
141
+ return this;
142
+ };
143
+ TypeIt.prototype.off = function(event, callback) {
144
+ if (!this.events[event]) {
145
+ return this;
146
+ }
147
+ if (typeof callback === "function") {
148
+ this.events[event] = this.events[event].filter(function(cb) {
149
+ return cb !== callback;
150
+ });
151
+ } else {
152
+ delete this.events[event];
153
+ }
154
+ return this;
155
+ };
156
+ TypeIt.prototype.emit = function(event, ...args) {
157
+ const callbacks = this.events[event];
158
+ if (!callbacks || callbacks.length === 0) {
159
+ return this;
160
+ }
161
+ callbacks.slice().forEach(function(callback) {
162
+ callback.apply(this, args);
163
+ }, this);
164
+ return this;
165
+ };
96
166
  var index_default = TypeIt;
97
167
  export {
98
168
  index_default as default
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js"],
4
- "sourcesContent": ["\"use strict\"\n\nconst TypeIt = function (data) {\n this.settings = {};\n if(data instanceof Element) {\n this.settings.element = data;\n this.settings.typingSpeed = 150;\n this.settings.speedVariation = 50;\n }\n else {\n this.settings.element = data.element;\n this.settings.typingSpeed = data.typingSpeed ?? 150;\n this.settings.speedVariation = data.speedVariation ?? 50;\n }\n\n this.timer = null;\n this.queue = [];\n this.isTyping = false;\n\n}\n\nTypeIt.prototype.type = function (content) {\n this.queue.push(content);\n\n if(!this.isTyping) {\n this.next();\n }\n\n return this;\n}\n\n\nTypeIt.prototype.next = function () {\n if(this.queue.length === 0) {\n this.isTyping = false;\n return;\n }\n\n this.isTyping = true;\n\n const content = this.queue.shift();\n const settings = this.settings;\n const element = settings.element;\n\n\n let index = 0;\n\n const addContent = () => {\n if(index >= content.length) {\n this.next();\n return;\n }\n\n element.textContent += content[index];\n index++;\n\n const variation = (Math.random() * 2 -1) * settings.speedVariation;\n\n const delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(addContent, delay);\n \n }\n\n addContent();\n return this;\n}\n\nTypeIt.prototype.setTypingSpeed = function (speed) {\n if(typeof speed == \"number\") {\n this.settings.typingSpeed = speed;\n }\n return this;\n}\n\nTypeIt.prototype.setVariationSpeed = function (speed) {\n if(typeof speed == \"number\") {\n this.settings.speedVariation = speed;\n }\n return this;\n}\n\nTypeIt.prototype.clear = function (options = {}) {\n const settings = this.settings;\n const element = settings.element;\n\n const animated = options.animated ?? true;\n const count = Math.max(\n 0,\n Math.floor(options.count ?? element.textContent.length)\n ) \n\n if(count <= 0) {\n return this;\n }\n\n clearTimeout(this.timer);\n this.timer = null;\n\n this.queue = [];\n this.isTyping = false;\n\n if(!animated) {\n element.textContent = Array.from(element.textContent)\n .slice(0, -count)\n .join(\"\");\n\n return this;\n }\n\n let deleted = 0;\n\n const removeContent = () => {\n if(deleted >= count || !element.textContent.length) {\n this.timer = null;\n this.isTyping = false;\n return;\n }\n\n element.textContent = Array.from(element.textContent)\n .slice(0, -1)\n .join(\"\");\n\n deleted++;\n\n const variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n const delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(removeContent, delay);\n }\n\n this.isTyping = true;\n removeContent();\n\n return this;\n}\n\nexport default TypeIt;\n"],
5
- "mappings": ";AAEA,IAAM,SAAS,SAAU,MAAM;AAC7B,OAAK,WAAW,CAAC;AACjB,MAAG,gBAAgB,SAAS;AAC1B,SAAK,SAAS,UAAU;AACxB,SAAK,SAAS,cAAc;AAC5B,SAAK,SAAS,iBAAiB;AAAA,EACjC,OACK;AACH,SAAK,SAAS,UAAU,KAAK;AAC7B,SAAK,SAAS,cAAc,KAAK,eAAe;AAChD,SAAK,SAAS,iBAAiB,KAAK,kBAAkB;AAAA,EACxD;AAEA,OAAK,QAAQ;AACb,OAAK,QAAQ,CAAC;AACd,OAAK,WAAW;AAElB;AAEA,OAAO,UAAU,OAAO,SAAU,SAAS;AACzC,OAAK,MAAM,KAAK,OAAO;AAEvB,MAAG,CAAC,KAAK,UAAU;AACjB,SAAK,KAAK;AAAA,EACZ;AAEA,SAAO;AACT;AAGA,OAAO,UAAU,OAAO,WAAY;AAClC,MAAG,KAAK,MAAM,WAAW,GAAG;AAC1B,SAAK,WAAW;AAChB;AAAA,EACF;AAEA,OAAK,WAAW;AAEhB,QAAM,UAAU,KAAK,MAAM,MAAM;AACjC,QAAM,WAAW,KAAK;AACtB,QAAM,UAAU,SAAS;AAGzB,MAAI,QAAQ;AAEZ,QAAM,aAAa,MAAM;AACvB,QAAG,SAAS,QAAQ,QAAQ;AAC1B,WAAK,KAAK;AACV;AAAA,IACF;AAEA,YAAQ,eAAe,QAAQ,KAAK;AACpC;AAEA,UAAM,aAAa,KAAK,OAAO,IAAI,IAAG,KAAK,SAAS;AAEpD,UAAM,QAAQ,KAAK,IAAI,GAAG,SAAS,cAAc,SAAS;AAE1D,SAAK,QAAQ,WAAW,YAAY,KAAK;AAAA,EAE3C;AAEA,aAAW;AACX,SAAO;AACT;AAEA,OAAO,UAAU,iBAAiB,SAAU,OAAO;AACjD,MAAG,OAAO,SAAS,UAAU;AAC3B,SAAK,SAAS,cAAc;AAAA,EAC9B;AACA,SAAO;AACT;AAEA,OAAO,UAAU,oBAAoB,SAAU,OAAO;AACpD,MAAG,OAAO,SAAS,UAAU;AAC3B,SAAK,SAAS,iBAAiB;AAAA,EACjC;AACA,SAAO;AACT;AAEA,OAAO,UAAU,QAAQ,SAAU,UAAU,CAAC,GAAG;AAC/C,QAAM,WAAW,KAAK;AACtB,QAAM,UAAU,SAAS;AAEzB,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,QAAQ,KAAK;AAAA,IACjB;AAAA,IACA,KAAK,MAAM,QAAQ,SAAS,QAAQ,YAAY,MAAM;AAAA,EACxD;AAEA,MAAG,SAAS,GAAG;AACb,WAAO;AAAA,EACT;AAEA,eAAa,KAAK,KAAK;AACvB,OAAK,QAAQ;AAEb,OAAK,QAAQ,CAAC;AACd,OAAK,WAAW;AAEhB,MAAG,CAAC,UAAU;AACZ,YAAQ,cAAc,MAAM,KAAK,QAAQ,WAAW,EAC3B,MAAM,GAAG,CAAC,KAAK,EACf,KAAK,EAAE;AAEhC,WAAO;AAAA,EACT;AAEA,MAAI,UAAU;AAEd,QAAM,gBAAgB,MAAM;AAC1B,QAAG,WAAW,SAAS,CAAC,QAAQ,YAAY,QAAQ;AAClD,WAAK,QAAQ;AACb,WAAK,WAAW;AAChB;AAAA,IACF;AAEA,YAAQ,cAAc,MAAM,KAAK,QAAQ,WAAW,EACzB,MAAM,GAAG,EAAE,EACX,KAAK,EAAE;AAElC;AAEA,UAAM,aAAa,KAAK,OAAO,IAAI,IAAI,KAAK,SAAS;AAErD,UAAM,QAAQ,KAAK,IAAI,GAAG,SAAS,cAAc,SAAS;AAE1D,SAAK,QAAQ,WAAW,eAAe,KAAK;AAAA,EAC9C;AAEA,OAAK,WAAW;AAChB,gBAAc;AAEd,SAAO;AACT;AAEA,IAAO,gBAAQ;",
4
+ "sourcesContent": ["\"use strict\"\n\nconst TypeIt = function (data) {\n this.settings = {};\n if (data instanceof Element) {\n this.settings.element = data;\n this.settings.typingSpeed = 150;\n this.settings.speedVariation = 50;\n this.settings.autoScroll = true;\n }\n else {\n this.settings.element = data.element;\n this.settings.typingSpeed = data.typingSpeed ?? 150;\n this.settings.speedVariation = data.speedVariation ?? 50;\n this.settings.autoScroll = data.autoScroll ?? true;\n }\n\n if (!(this.settings.element instanceof Element)) {\n throw new Error(\"Initialize with an html element\")\n }\n\n this.timer = null;\n this.queue = [];\n this.isTyping = false;\n\n this.events = {};\n this.observer = null;\n}\n\nTypeIt.prototype.type = function (content) {\n this.queue.push(content);\n\n if (!this.isTyping) {\n this.next();\n }\n\n return this;\n}\n\n\nTypeIt.prototype.next = function () {\n if (this.queue.length === 0) {\n this.isTyping = false;\n this.emit(\"complete\");\n\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n\n return;\n }\n\n this.isTyping = true;\n\n var content = this.queue.shift();\n var settings = this.settings;\n var element = settings.element;\n var parentElement = element.parentElement || null;\n\n if (settings.autoScroll && parentElement) {\n if (this.observer) {\n this.observer.disconnect();\n }\n\n var previousHeight = parentElement.scrollHeight;\n\n this.observer = new ResizeObserver(scrollToBottom);\n this.observer.observe(parentElement);\n\n function scrollToBottom() {\n var currentHeight = parentElement.scrollHeight;\n\n if (currentHeight > previousHeight) {\n parentElement.scrollTo({\n top: parentElement.scrollHeight,\n behavior: \"smooth\",\n });\n\n previousHeight = currentHeight;\n }\n }\n }\n\n var index = 0;\n\n const addContent = () => {\n if (index >= content.length) {\n this.next();\n return;\n }\n\n element.textContent += content[index];\n index++;\n\n var variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n var delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(addContent, delay);\n\n }\n\n addContent();\n return this;\n}\n\nTypeIt.prototype.setTypingSpeed = function (speed) {\n if (typeof speed == \"number\") {\n this.settings.typingSpeed = speed;\n }\n return this;\n}\n\nTypeIt.prototype.setVariationSpeed = function (speed) {\n if (typeof speed == \"number\") {\n this.settings.speedVariation = speed;\n }\n return this;\n}\n\nTypeIt.prototype.clear = function (options = {}) {\n var settings = this.settings;\n var element = settings.element;\n\n var animated = options.animated ?? true;\n var count = Math.max(\n 0,\n Math.floor(options.count ?? element.textContent.length)\n )\n\n if (count <= 0) {\n return this;\n }\n\n clearTimeout(this.timer);\n this.timer = null;\n\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n\n this.queue = [];\n this.isTyping = false;\n\n if (!animated) {\n element.textContent = Array.from(element.textContent)\n .slice(0, -count)\n .join(\"\");\n\n this.emit(\"clear\");\n\n return this;\n }\n\n var deleted = 0;\n\n function removeContent() {\n if (deleted >= count || !element.textContent.length) {\n this.timer = null;\n this.isTyping = false;\n\n this.emit(\"clear\");\n\n return;\n }\n\n element.textContent = Array.from(element.textContent)\n .slice(0, -1)\n .join(\"\");\n\n deleted++;\n\n var variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n var delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(removeContent, delay);\n }\n\n this.isTyping = true;\n removeContent();\n\n return this;\n}\n\nTypeIt.prototype.on = function (event, callback) {\n if (typeof callback !== \"function\") {\n return this;\n }\n\n if (!this.events[event]) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n}\n\nTypeIt.prototype.off = function (event, callback) {\n if (!this.events[event]) {\n return this;\n }\n\n if (typeof callback === \"function\") {\n this.events[event] = this.events[event].filter(function (cb) {\n return cb !== callback;\n });\n } else {\n delete this.events[event];\n }\n\n return this;\n}\n\nTypeIt.prototype.emit = function (event, ...args) {\n const callbacks = this.events[event];\n\n if (!callbacks || callbacks.length === 0) {\n return this;\n }\n\n callbacks.slice().forEach(function (callback) {\n callback.apply(this, args);\n }, this);\n\n return this;\n}\n\nexport default TypeIt;\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,3 +1,3 @@
1
- "use strict";var TypeIt=(()=>{var u=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var m=(t,e)=>{for(var i in e)u(t,i,{get:e[i],enumerable:!0})},f=(t,e,i,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of g(e))!c.call(t,n)&&n!==i&&u(t,n,{get:()=>e[n],enumerable:!(s=l(e,n))||s.enumerable});return t};var y=t=>f(u({},"__esModule",{value:!0}),t);var x={};m(x,{default:()=>d});var o=function(t){this.settings={},t instanceof Element?(this.settings.element=t,this.settings.typingSpeed=150,this.settings.speedVariation=50):(this.settings.element=t.element,this.settings.typingSpeed=t.typingSpeed??150,this.settings.speedVariation=t.speedVariation??50),this.timer=null,this.queue=[],this.isTyping=!1};o.prototype.type=function(t){return this.queue.push(t),this.isTyping||this.next(),this};o.prototype.next=function(){if(this.queue.length===0){this.isTyping=!1;return}this.isTyping=!0;let t=this.queue.shift(),e=this.settings,i=e.element,s=0,n=()=>{if(s>=t.length){this.next();return}i.textContent+=t[s],s++;let r=(Math.random()*2-1)*e.speedVariation,h=Math.max(0,e.typingSpeed+r);this.timer=setTimeout(n,h)};return n(),this};o.prototype.setTypingSpeed=function(t){return typeof t=="number"&&(this.settings.typingSpeed=t),this};o.prototype.setVariationSpeed=function(t){return typeof t=="number"&&(this.settings.speedVariation=t),this};o.prototype.clear=function(t={}){let e=this.settings,i=e.element,s=t.animated??!0,n=Math.max(0,Math.floor(t.count??i.textContent.length));if(n<=0)return this;if(clearTimeout(this.timer),this.timer=null,this.queue=[],this.isTyping=!1,!s)return i.textContent=Array.from(i.textContent).slice(0,-n).join(""),this;let r=0,h=()=>{if(r>=n||!i.textContent.length){this.timer=null,this.isTyping=!1;return}i.textContent=Array.from(i.textContent).slice(0,-1).join(""),r++;let p=(Math.random()*2-1)*e.speedVariation,a=Math.max(0,e.typingSpeed+p);this.timer=setTimeout(h,a)};return this.isTyping=!0,h(),this};var d=o;return y(x);})();
1
+ "use strict";var TypeIt=(()=>{var a=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var m=(t,e)=>{for(var i in e)a(t,i,{get:e[i],enumerable:!0})},g=(t,e,i,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of f(e))!c.call(t,s)&&s!==i&&a(t,s,{get:()=>e[s],enumerable:!(n=p(e,s))||n.enumerable});return t};var v=t=>g(a({},"__esModule",{value:!0}),t);var d={};m(d,{default:()=>y});var r=function(t){if(this.settings={},t instanceof Element?(this.settings.element=t,this.settings.typingSpeed=150,this.settings.speedVariation=50,this.settings.autoScroll=!0):(this.settings.element=t.element,this.settings.typingSpeed=t.typingSpeed??150,this.settings.speedVariation=t.speedVariation??50,this.settings.autoScroll=t.autoScroll??!0),!(this.settings.element instanceof Element))throw new Error("Initialize with an html element");this.timer=null,this.queue=[],this.isTyping=!1,this.events={},this.observer=null};r.prototype.type=function(t){return this.queue.push(t),this.isTyping||this.next(),this};r.prototype.next=function(){if(this.queue.length===0){this.isTyping=!1,this.emit("complete"),this.observer&&(this.observer.disconnect(),this.observer=null);return}this.isTyping=!0;var t=this.queue.shift(),e=this.settings,i=e.element,n=i.parentElement||null;if(e.autoScroll&&n){let u=function(){var h=n.scrollHeight;h>s&&(n.scrollTo({top:n.scrollHeight,behavior:"smooth"}),s=h)};this.observer&&this.observer.disconnect();var s=n.scrollHeight;this.observer=new ResizeObserver(u),this.observer.observe(n)}var o=0;let l=()=>{if(o>=t.length){this.next();return}i.textContent+=t[o],o++;var u=(Math.random()*2-1)*e.speedVariation,h=Math.max(0,e.typingSpeed+u);this.timer=setTimeout(l,h)};return l(),this};r.prototype.setTypingSpeed=function(t){return typeof t=="number"&&(this.settings.typingSpeed=t),this};r.prototype.setVariationSpeed=function(t){return typeof t=="number"&&(this.settings.speedVariation=t),this};r.prototype.clear=function(t={}){var e=this.settings,i=e.element,n=t.animated??!0,s=Math.max(0,Math.floor(t.count??i.textContent.length));if(s<=0)return this;if(clearTimeout(this.timer),this.timer=null,this.observer&&(this.observer.disconnect(),this.observer=null),this.queue=[],this.isTyping=!1,!n)return i.textContent=Array.from(i.textContent).slice(0,-s).join(""),this.emit("clear"),this;var o=0;function l(){if(o>=s||!i.textContent.length){this.timer=null,this.isTyping=!1,this.emit("clear");return}i.textContent=Array.from(i.textContent).slice(0,-1).join(""),o++;var u=(Math.random()*2-1)*e.speedVariation,h=Math.max(0,e.typingSpeed+u);this.timer=setTimeout(l,h)}return this.isTyping=!0,l(),this};r.prototype.on=function(t,e){return typeof e!="function"?this:(this.events[t]||(this.events[t]=[]),this.events[t].push(e),this)};r.prototype.off=function(t,e){return this.events[t]?(typeof e=="function"?this.events[t]=this.events[t].filter(function(i){return i!==e}):delete this.events[t],this):this};r.prototype.emit=function(t,...e){let i=this.events[t];return!i||i.length===0?this:(i.slice().forEach(function(n){n.apply(this,e)},this),this)};var y=r;return v(d);})();
2
2
  if (typeof TypeIt !== "undefined" && TypeIt.default) TypeIt = TypeIt.default;
3
3
  //# sourceMappingURL=typeit.min.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js"],
4
- "sourcesContent": ["\"use strict\"\n\nconst TypeIt = function (data) {\n this.settings = {};\n if(data instanceof Element) {\n this.settings.element = data;\n this.settings.typingSpeed = 150;\n this.settings.speedVariation = 50;\n }\n else {\n this.settings.element = data.element;\n this.settings.typingSpeed = data.typingSpeed ?? 150;\n this.settings.speedVariation = data.speedVariation ?? 50;\n }\n\n this.timer = null;\n this.queue = [];\n this.isTyping = false;\n\n}\n\nTypeIt.prototype.type = function (content) {\n this.queue.push(content);\n\n if(!this.isTyping) {\n this.next();\n }\n\n return this;\n}\n\n\nTypeIt.prototype.next = function () {\n if(this.queue.length === 0) {\n this.isTyping = false;\n return;\n }\n\n this.isTyping = true;\n\n const content = this.queue.shift();\n const settings = this.settings;\n const element = settings.element;\n\n\n let index = 0;\n\n const addContent = () => {\n if(index >= content.length) {\n this.next();\n return;\n }\n\n element.textContent += content[index];\n index++;\n\n const variation = (Math.random() * 2 -1) * settings.speedVariation;\n\n const delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(addContent, delay);\n \n }\n\n addContent();\n return this;\n}\n\nTypeIt.prototype.setTypingSpeed = function (speed) {\n if(typeof speed == \"number\") {\n this.settings.typingSpeed = speed;\n }\n return this;\n}\n\nTypeIt.prototype.setVariationSpeed = function (speed) {\n if(typeof speed == \"number\") {\n this.settings.speedVariation = speed;\n }\n return this;\n}\n\nTypeIt.prototype.clear = function (options = {}) {\n const settings = this.settings;\n const element = settings.element;\n\n const animated = options.animated ?? true;\n const count = Math.max(\n 0,\n Math.floor(options.count ?? element.textContent.length)\n ) \n\n if(count <= 0) {\n return this;\n }\n\n clearTimeout(this.timer);\n this.timer = null;\n\n this.queue = [];\n this.isTyping = false;\n\n if(!animated) {\n element.textContent = Array.from(element.textContent)\n .slice(0, -count)\n .join(\"\");\n\n return this;\n }\n\n let deleted = 0;\n\n const removeContent = () => {\n if(deleted >= count || !element.textContent.length) {\n this.timer = null;\n this.isTyping = false;\n return;\n }\n\n element.textContent = Array.from(element.textContent)\n .slice(0, -1)\n .join(\"\");\n\n deleted++;\n\n const variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n const delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(removeContent, delay);\n }\n\n this.isTyping = true;\n removeContent();\n\n return this;\n}\n\nexport default TypeIt;\n"],
5
- "mappings": "0bAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,IAEA,IAAMC,EAAS,SAAUC,EAAM,CAC7B,KAAK,SAAW,CAAC,EACdA,aAAgB,SACjB,KAAK,SAAS,QAAUA,EACxB,KAAK,SAAS,YAAc,IAC5B,KAAK,SAAS,eAAiB,KAG/B,KAAK,SAAS,QAAUA,EAAK,QAC7B,KAAK,SAAS,YAAcA,EAAK,aAAe,IAChD,KAAK,SAAS,eAAiBA,EAAK,gBAAkB,IAGxD,KAAK,MAAQ,KACb,KAAK,MAAQ,CAAC,EACd,KAAK,SAAW,EAElB,EAEAD,EAAO,UAAU,KAAO,SAAUE,EAAS,CACzC,YAAK,MAAM,KAAKA,CAAO,EAEnB,KAAK,UACP,KAAK,KAAK,EAGL,IACT,EAGAF,EAAO,UAAU,KAAO,UAAY,CAClC,GAAG,KAAK,MAAM,SAAW,EAAG,CAC1B,KAAK,SAAW,GAChB,MACF,CAEA,KAAK,SAAW,GAEhB,IAAME,EAAU,KAAK,MAAM,MAAM,EAC3BC,EAAW,KAAK,SAChBC,EAAUD,EAAS,QAGrBE,EAAQ,EAENC,EAAa,IAAM,CACvB,GAAGD,GAASH,EAAQ,OAAQ,CAC1B,KAAK,KAAK,EACV,MACF,CAEAE,EAAQ,aAAeF,EAAQG,CAAK,EACpCA,IAEA,IAAME,GAAa,KAAK,OAAO,EAAI,EAAG,GAAKJ,EAAS,eAE9CK,EAAQ,KAAK,IAAI,EAAGL,EAAS,YAAcI,CAAS,EAE1D,KAAK,MAAQ,WAAWD,EAAYE,CAAK,CAE3C,EAEA,OAAAF,EAAW,EACJ,IACT,EAEAN,EAAO,UAAU,eAAiB,SAAUS,EAAO,CACjD,OAAG,OAAOA,GAAS,WACjB,KAAK,SAAS,YAAcA,GAEvB,IACT,EAEAT,EAAO,UAAU,kBAAoB,SAAUS,EAAO,CACpD,OAAG,OAAOA,GAAS,WACjB,KAAK,SAAS,eAAiBA,GAE1B,IACT,EAEAT,EAAO,UAAU,MAAQ,SAAUU,EAAU,CAAC,EAAG,CAC/C,IAAMP,EAAW,KAAK,SAChBC,EAAUD,EAAS,QAEnBQ,EAAWD,EAAQ,UAAY,GAC/BE,EAAQ,KAAK,IACjB,EACA,KAAK,MAAMF,EAAQ,OAASN,EAAQ,YAAY,MAAM,CACxD,EAEA,GAAGQ,GAAS,EACV,OAAO,KAST,GANA,aAAa,KAAK,KAAK,EACvB,KAAK,MAAQ,KAEb,KAAK,MAAQ,CAAC,EACd,KAAK,SAAW,GAEb,CAACD,EACF,OAAAP,EAAQ,YAAc,MAAM,KAAKA,EAAQ,WAAW,EAC3B,MAAM,EAAG,CAACQ,CAAK,EACf,KAAK,EAAE,EAEzB,KAGT,IAAIC,EAAU,EAERC,EAAgB,IAAM,CAC1B,GAAGD,GAAWD,GAAS,CAACR,EAAQ,YAAY,OAAQ,CAClD,KAAK,MAAQ,KACb,KAAK,SAAW,GAChB,MACF,CAEAA,EAAQ,YAAc,MAAM,KAAKA,EAAQ,WAAW,EACzB,MAAM,EAAG,EAAE,EACX,KAAK,EAAE,EAElCS,IAEA,IAAMN,GAAa,KAAK,OAAO,EAAI,EAAI,GAAKJ,EAAS,eAE/CK,EAAQ,KAAK,IAAI,EAAGL,EAAS,YAAcI,CAAS,EAE1D,KAAK,MAAQ,WAAWO,EAAeN,CAAK,CAC9C,EAEA,YAAK,SAAW,GAChBM,EAAc,EAEP,IACT,EAEA,IAAOf,EAAQC",
6
- "names": ["index_exports", "__export", "index_default", "TypeIt", "data", "content", "settings", "element", "index", "addContent", "variation", "delay", "speed", "options", "animated", "count", "deleted", "removeContent"]
4
+ "sourcesContent": ["\"use strict\"\n\nconst TypeIt = function (data) {\n this.settings = {};\n if (data instanceof Element) {\n this.settings.element = data;\n this.settings.typingSpeed = 150;\n this.settings.speedVariation = 50;\n this.settings.autoScroll = true;\n }\n else {\n this.settings.element = data.element;\n this.settings.typingSpeed = data.typingSpeed ?? 150;\n this.settings.speedVariation = data.speedVariation ?? 50;\n this.settings.autoScroll = data.autoScroll ?? true;\n }\n\n if (!(this.settings.element instanceof Element)) {\n throw new Error(\"Initialize with an html element\")\n }\n\n this.timer = null;\n this.queue = [];\n this.isTyping = false;\n\n this.events = {};\n this.observer = null;\n}\n\nTypeIt.prototype.type = function (content) {\n this.queue.push(content);\n\n if (!this.isTyping) {\n this.next();\n }\n\n return this;\n}\n\n\nTypeIt.prototype.next = function () {\n if (this.queue.length === 0) {\n this.isTyping = false;\n this.emit(\"complete\");\n\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n\n return;\n }\n\n this.isTyping = true;\n\n var content = this.queue.shift();\n var settings = this.settings;\n var element = settings.element;\n var parentElement = element.parentElement || null;\n\n if (settings.autoScroll && parentElement) {\n if (this.observer) {\n this.observer.disconnect();\n }\n\n var previousHeight = parentElement.scrollHeight;\n\n this.observer = new ResizeObserver(scrollToBottom);\n this.observer.observe(parentElement);\n\n function scrollToBottom() {\n var currentHeight = parentElement.scrollHeight;\n\n if (currentHeight > previousHeight) {\n parentElement.scrollTo({\n top: parentElement.scrollHeight,\n behavior: \"smooth\",\n });\n\n previousHeight = currentHeight;\n }\n }\n }\n\n var index = 0;\n\n const addContent = () => {\n if (index >= content.length) {\n this.next();\n return;\n }\n\n element.textContent += content[index];\n index++;\n\n var variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n var delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(addContent, delay);\n\n }\n\n addContent();\n return this;\n}\n\nTypeIt.prototype.setTypingSpeed = function (speed) {\n if (typeof speed == \"number\") {\n this.settings.typingSpeed = speed;\n }\n return this;\n}\n\nTypeIt.prototype.setVariationSpeed = function (speed) {\n if (typeof speed == \"number\") {\n this.settings.speedVariation = speed;\n }\n return this;\n}\n\nTypeIt.prototype.clear = function (options = {}) {\n var settings = this.settings;\n var element = settings.element;\n\n var animated = options.animated ?? true;\n var count = Math.max(\n 0,\n Math.floor(options.count ?? element.textContent.length)\n )\n\n if (count <= 0) {\n return this;\n }\n\n clearTimeout(this.timer);\n this.timer = null;\n\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n\n this.queue = [];\n this.isTyping = false;\n\n if (!animated) {\n element.textContent = Array.from(element.textContent)\n .slice(0, -count)\n .join(\"\");\n\n this.emit(\"clear\");\n\n return this;\n }\n\n var deleted = 0;\n\n function removeContent() {\n if (deleted >= count || !element.textContent.length) {\n this.timer = null;\n this.isTyping = false;\n\n this.emit(\"clear\");\n\n return;\n }\n\n element.textContent = Array.from(element.textContent)\n .slice(0, -1)\n .join(\"\");\n\n deleted++;\n\n var variation = (Math.random() * 2 - 1) * settings.speedVariation;\n\n var delay = Math.max(0, settings.typingSpeed + variation);\n\n this.timer = setTimeout(removeContent, delay);\n }\n\n this.isTyping = true;\n removeContent();\n\n return this;\n}\n\nTypeIt.prototype.on = function (event, callback) {\n if (typeof callback !== \"function\") {\n return this;\n }\n\n if (!this.events[event]) {\n this.events[event] = [];\n }\n\n this.events[event].push(callback);\n\n return this;\n}\n\nTypeIt.prototype.off = function (event, callback) {\n if (!this.events[event]) {\n return this;\n }\n\n if (typeof callback === \"function\") {\n this.events[event] = this.events[event].filter(function (cb) {\n return cb !== callback;\n });\n } else {\n delete this.events[event];\n }\n\n return this;\n}\n\nTypeIt.prototype.emit = function (event, ...args) {\n const callbacks = this.events[event];\n\n if (!callbacks || callbacks.length === 0) {\n return this;\n }\n\n callbacks.slice().forEach(function (callback) {\n callback.apply(this, args);\n }, this);\n\n return this;\n}\n\nexport default TypeIt;\n"],
5
+ "mappings": "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",
6
+ "names": ["index_exports", "__export", "index_default", "TypeIt", "data", "content", "settings", "element", "parentElement", "scrollToBottom", "currentHeight", "previousHeight", "index", "addContent", "variation", "delay", "speed", "options", "animated", "count", "deleted", "removeContent", "event", "callback", "cb", "args", "callbacks"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jithinaji/typeit",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A lightweight JavaScript typing animation library with natural speed variation and chaining support.",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
package/src/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export interface TypeItOptions {
5
5
  typingSpeed?: number;
6
6
  /** Speed variation in milliseconds for human-like random variance (default: 50) */
7
7
  speedVariation?: number;
8
+ /** Whether the parent container automatically scrolls to bottom as text grows (default: true) */
9
+ autoScroll?: boolean;
8
10
  }
9
11
 
10
12
  export interface ClearOptions {
@@ -25,6 +27,7 @@ export class TypeIt {
25
27
  element: Element;
26
28
  typingSpeed: number;
27
29
  speedVariation: number;
30
+ autoScroll: boolean;
28
31
  };
29
32
  timer: ReturnType<typeof setTimeout> | null;
30
33
  queue: string[];
@@ -53,11 +56,34 @@ export class TypeIt {
53
56
  */
54
57
  setVariationSpeed(speed: number): this;
55
58
 
59
+ events: Record<string, ((...args: any[]) => void)[]>;
60
+
56
61
  /**
57
62
  * Clears characters from the element.
58
63
  * @param options Configuration options for deletion.
59
64
  */
60
65
  clear(options?: ClearOptions): this;
66
+
67
+ /**
68
+ * Registers an event listener callback.
69
+ * @param event The event name to listen to.
70
+ * @param callback The function to execute when the event is emitted.
71
+ */
72
+ on(event: string, callback: (...args: any[]) => void): this;
73
+
74
+ /**
75
+ * Removes a specific event listener or all listeners for an event.
76
+ * @param event The event name.
77
+ * @param callback The specific callback to remove. If omitted, removes all callbacks for the event.
78
+ */
79
+ off(event: string, callback?: (...args: any[]) => void): this;
80
+
81
+ /**
82
+ * Emits an event to all registered listeners.
83
+ * @param event The event name to emit.
84
+ * @param args Arguments to pass to the callbacks.
85
+ */
86
+ emit(event: string, ...args: any[]): this;
61
87
  }
62
88
 
63
89
  export default TypeIt;
package/src/index.js CHANGED
@@ -2,27 +2,35 @@
2
2
 
3
3
  const TypeIt = function (data) {
4
4
  this.settings = {};
5
- if(data instanceof Element) {
5
+ if (data instanceof Element) {
6
6
  this.settings.element = data;
7
7
  this.settings.typingSpeed = 150;
8
8
  this.settings.speedVariation = 50;
9
+ this.settings.autoScroll = true;
9
10
  }
10
11
  else {
11
12
  this.settings.element = data.element;
12
13
  this.settings.typingSpeed = data.typingSpeed ?? 150;
13
14
  this.settings.speedVariation = data.speedVariation ?? 50;
15
+ this.settings.autoScroll = data.autoScroll ?? true;
16
+ }
17
+
18
+ if (!(this.settings.element instanceof Element)) {
19
+ throw new Error("Initialize with an html element")
14
20
  }
15
21
 
16
22
  this.timer = null;
17
23
  this.queue = [];
18
24
  this.isTyping = false;
19
25
 
26
+ this.events = {};
27
+ this.observer = null;
20
28
  }
21
29
 
22
30
  TypeIt.prototype.type = function (content) {
23
31
  this.queue.push(content);
24
32
 
25
- if(!this.isTyping) {
33
+ if (!this.isTyping) {
26
34
  this.next();
27
35
  }
28
36
 
@@ -31,22 +39,53 @@ TypeIt.prototype.type = function (content) {
31
39
 
32
40
 
33
41
  TypeIt.prototype.next = function () {
34
- if(this.queue.length === 0) {
42
+ if (this.queue.length === 0) {
35
43
  this.isTyping = false;
44
+ this.emit("complete");
45
+
46
+ if (this.observer) {
47
+ this.observer.disconnect();
48
+ this.observer = null;
49
+ }
50
+
36
51
  return;
37
52
  }
38
53
 
39
54
  this.isTyping = true;
40
55
 
41
- const content = this.queue.shift();
42
- const settings = this.settings;
43
- const element = settings.element;
56
+ var content = this.queue.shift();
57
+ var settings = this.settings;
58
+ var element = settings.element;
59
+ var parentElement = element.parentElement || null;
60
+
61
+ if (settings.autoScroll && parentElement) {
62
+ if (this.observer) {
63
+ this.observer.disconnect();
64
+ }
65
+
66
+ var previousHeight = parentElement.scrollHeight;
67
+
68
+ this.observer = new ResizeObserver(scrollToBottom);
69
+ this.observer.observe(parentElement);
70
+
71
+ function scrollToBottom() {
72
+ var currentHeight = parentElement.scrollHeight;
73
+
74
+ if (currentHeight > previousHeight) {
75
+ parentElement.scrollTo({
76
+ top: parentElement.scrollHeight,
77
+ behavior: "smooth",
78
+ });
44
79
 
80
+ previousHeight = currentHeight;
81
+ }
82
+ }
83
+ }
45
84
 
46
- let index = 0;
85
+ var index = 0;
47
86
 
48
87
  const addContent = () => {
49
- if(index >= content.length) {
88
+ if (index >= content.length) {
50
89
  this.next();
51
90
  return;
52
91
  }
@@ -54,12 +93,12 @@ TypeIt.prototype.next = function () {
54
93
  element.textContent += content[index];
55
94
  index++;
56
95
 
57
- const variation = (Math.random() * 2 -1) * settings.speedVariation;
96
+ var variation = (Math.random() * 2 - 1) * settings.speedVariation;
58
97
 
59
- const delay = Math.max(0, settings.typingSpeed + variation);
98
+ var delay = Math.max(0, settings.typingSpeed + variation);
60
99
 
61
100
  this.timer = setTimeout(addContent, delay);
62
-
101
+
63
102
  }
64
103
 
65
104
  addContent();
@@ -67,65 +106,75 @@ TypeIt.prototype.next = function () {
67
106
  }
68
107
 
69
108
  TypeIt.prototype.setTypingSpeed = function (speed) {
70
- if(typeof speed == "number") {
109
+ if (typeof speed == "number") {
71
110
  this.settings.typingSpeed = speed;
72
111
  }
73
112
  return this;
74
113
  }
75
114
 
76
115
  TypeIt.prototype.setVariationSpeed = function (speed) {
77
- if(typeof speed == "number") {
116
+ if (typeof speed == "number") {
78
117
  this.settings.speedVariation = speed;
79
118
  }
80
119
  return this;
81
120
  }
82
121
 
83
122
  TypeIt.prototype.clear = function (options = {}) {
84
- const settings = this.settings;
85
- const element = settings.element;
123
+ var settings = this.settings;
124
+ var element = settings.element;
86
125
 
87
- const animated = options.animated ?? true;
88
- const count = Math.max(
126
+ var animated = options.animated ?? true;
127
+ var count = Math.max(
89
128
  0,
90
129
  Math.floor(options.count ?? element.textContent.length)
91
- )
130
+ )
92
131
 
93
- if(count <= 0) {
132
+ if (count <= 0) {
94
133
  return this;
95
134
  }
96
135
 
97
136
  clearTimeout(this.timer);
98
137
  this.timer = null;
99
138
 
139
+ if (this.observer) {
140
+ this.observer.disconnect();
141
+ this.observer = null;
142
+ }
143
+
100
144
  this.queue = [];
101
145
  this.isTyping = false;
102
146
 
103
- if(!animated) {
147
+ if (!animated) {
104
148
  element.textContent = Array.from(element.textContent)
105
- .slice(0, -count)
106
- .join("");
149
+ .slice(0, -count)
150
+ .join("");
151
+
152
+ this.emit("clear");
107
153
 
108
154
  return this;
109
155
  }
110
156
 
111
- let deleted = 0;
157
+ var deleted = 0;
112
158
 
113
- const removeContent = () => {
114
- if(deleted >= count || !element.textContent.length) {
159
+ function removeContent() {
160
+ if (deleted >= count || !element.textContent.length) {
115
161
  this.timer = null;
116
162
  this.isTyping = false;
163
+
164
+ this.emit("clear");
165
+
117
166
  return;
118
167
  }
119
168
 
120
169
  element.textContent = Array.from(element.textContent)
121
- .slice(0, -1)
122
- .join("");
170
+ .slice(0, -1)
171
+ .join("");
123
172
 
124
173
  deleted++;
125
174
 
126
- const variation = (Math.random() * 2 - 1) * settings.speedVariation;
175
+ var variation = (Math.random() * 2 - 1) * settings.speedVariation;
127
176
 
128
- const delay = Math.max(0, settings.typingSpeed + variation);
177
+ var delay = Math.max(0, settings.typingSpeed + variation);
129
178
 
130
179
  this.timer = setTimeout(removeContent, delay);
131
180
  }
@@ -136,4 +185,48 @@ TypeIt.prototype.clear = function (options = {}) {
136
185
  return this;
137
186
  }
138
187
 
188
+ TypeIt.prototype.on = function (event, callback) {
189
+ if (typeof callback !== "function") {
190
+ return this;
191
+ }
192
+
193
+ if (!this.events[event]) {
194
+ this.events[event] = [];
195
+ }
196
+
197
+ this.events[event].push(callback);
198
+
199
+ return this;
200
+ }
201
+
202
+ TypeIt.prototype.off = function (event, callback) {
203
+ if (!this.events[event]) {
204
+ return this;
205
+ }
206
+
207
+ if (typeof callback === "function") {
208
+ this.events[event] = this.events[event].filter(function (cb) {
209
+ return cb !== callback;
210
+ });
211
+ } else {
212
+ delete this.events[event];
213
+ }
214
+
215
+ return this;
216
+ }
217
+
218
+ TypeIt.prototype.emit = function (event, ...args) {
219
+ const callbacks = this.events[event];
220
+
221
+ if (!callbacks || callbacks.length === 0) {
222
+ return this;
223
+ }
224
+
225
+ callbacks.slice().forEach(function (callback) {
226
+ callback.apply(this, args);
227
+ }, this);
228
+
229
+ return this;
230
+ }
231
+
139
232
  export default TypeIt;
@@ -0,0 +1,72 @@
1
+ export interface TypeItOptions {
2
+ /** The target DOM element where the typing animation will be rendered */
3
+ element: Element;
4
+ /** Base typing speed in milliseconds per character (default: 150) */
5
+ typingSpeed?: number;
6
+ /** Speed variation in milliseconds for human-like random variance (default: 50) */
7
+ speedVariation?: number;
8
+ /** Whether the parent container automatically scrolls to bottom as text grows (default: true) */
9
+ autoScroll?: boolean;
10
+ }
11
+
12
+ export interface ClearOptions {
13
+ /** Number of characters to delete. Defaults to the entire text length. */
14
+ count?: number;
15
+ /** Whether the deletion should be animated (default: true). Set false for instant clear. */
16
+ animated?: boolean;
17
+ }
18
+
19
+ export class TypeIt {
20
+ /**
21
+ * Initializes a new TypeIt instance.
22
+ * @param data Either a DOM Element or an options configuration object.
23
+ */
24
+ constructor(data: Element | TypeItOptions);
25
+
26
+ settings: {
27
+ element: Element;
28
+ typingSpeed: number;
29
+ speedVariation: number;
30
+ autoScroll: boolean;
31
+ };
32
+ timer: ReturnType<typeof setTimeout> | null;
33
+ queue: string[];
34
+ isTyping: boolean;
35
+
36
+ /**
37
+ * Queues a string to be typed into the element.
38
+ * @param content The text string to type.
39
+ */
40
+ type(content: string): this;
41
+
42
+ /**
43
+ * Processes the next item in the typing queue.
44
+ */
45
+ next(): this;
46
+
47
+ /**
48
+ * Dynamically updates the base typing speed.
49
+ * @param speed Speed in milliseconds per character.
50
+ */
51
+ setTypingSpeed(speed: number): this;
52
+
53
+ /**
54
+ * Dynamically updates the speed variation range.
55
+ * @param speed Variation range in milliseconds.
56
+ */
57
+ setVariationSpeed(speed: number): this;
58
+
59
+ /**
60
+ * Clears characters from the element.
61
+ * @param options Configuration options for deletion.
62
+ */
63
+ clear(options?: ClearOptions): this;
64
+ }
65
+
66
+ declare global {
67
+ interface Window {
68
+ TypeIt: typeof TypeIt;
69
+ }
70
+ }
71
+
72
+ export default TypeIt;
package/src/typeit.js ADDED
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+
3
+ (function (global) {
4
+ const TypeIt = function (data) {
5
+ this.settings = {};
6
+ if (data instanceof Element) {
7
+ this.settings.element = data;
8
+ this.settings.typingSpeed = 150;
9
+ this.settings.speedVariation = 50;
10
+ } else {
11
+ this.settings.element = data.element;
12
+ this.settings.typingSpeed = data.typingSpeed ?? 150;
13
+ this.settings.speedVariation = data.speedVariation ?? 50;
14
+ }
15
+
16
+ this.timer = null;
17
+ this.queue = [];
18
+ this.isTyping = false;
19
+ };
20
+
21
+ TypeIt.prototype.type = function (content) {
22
+ this.queue.push(content);
23
+
24
+ if (!this.isTyping) {
25
+ this.next();
26
+ }
27
+
28
+ return this;
29
+ };
30
+
31
+ TypeIt.prototype.next = function () {
32
+ if (this.queue.length === 0) {
33
+ this.isTyping = false;
34
+ return;
35
+ }
36
+
37
+ this.isTyping = true;
38
+
39
+ const content = this.queue.shift();
40
+ const settings = this.settings;
41
+ const element = settings.element;
42
+
43
+ let index = 0;
44
+
45
+ const addContent = () => {
46
+ if (index >= content.length) {
47
+ this.next();
48
+ return;
49
+ }
50
+
51
+ element.textContent += content[index];
52
+ index++;
53
+
54
+ const variation = (Math.random() * 2 - 1) * settings.speedVariation;
55
+ const delay = Math.max(0, settings.typingSpeed + variation);
56
+
57
+ this.timer = setTimeout(addContent, delay);
58
+ };
59
+
60
+ addContent();
61
+ return this;
62
+ };
63
+
64
+ TypeIt.prototype.setTypingSpeed = function (speed) {
65
+ if (typeof speed === "number") {
66
+ this.settings.typingSpeed = speed;
67
+ }
68
+ return this;
69
+ };
70
+
71
+ TypeIt.prototype.setVariationSpeed = function (speed) {
72
+ if (typeof speed === "number") {
73
+ this.settings.speedVariation = speed;
74
+ }
75
+ return this;
76
+ };
77
+
78
+ TypeIt.prototype.clear = function (options = {}) {
79
+ const settings = this.settings;
80
+ const element = settings.element;
81
+
82
+ const animated = options.animated ?? true;
83
+ const count = Math.max(
84
+ 0,
85
+ Math.floor(options.count ?? element.textContent.length)
86
+ );
87
+
88
+ if (count <= 0) {
89
+ return this;
90
+ }
91
+
92
+ clearTimeout(this.timer);
93
+ this.timer = null;
94
+
95
+ this.queue = [];
96
+ this.isTyping = false;
97
+
98
+ if (!animated) {
99
+ element.textContent = Array.from(element.textContent)
100
+ .slice(0, -count)
101
+ .join("");
102
+
103
+ return this;
104
+ }
105
+
106
+ let deleted = 0;
107
+
108
+ const removeContent = () => {
109
+ if (deleted >= count || !element.textContent.length) {
110
+ this.timer = null;
111
+ this.isTyping = false;
112
+ return;
113
+ }
114
+
115
+ element.textContent = Array.from(element.textContent)
116
+ .slice(0, -1)
117
+ .join("");
118
+
119
+ deleted++;
120
+
121
+ const variation = (Math.random() * 2 - 1) * settings.speedVariation;
122
+ const delay = Math.max(0, settings.typingSpeed + variation);
123
+
124
+ this.timer = setTimeout(removeContent, delay);
125
+ };
126
+
127
+ this.isTyping = true;
128
+ removeContent();
129
+
130
+ return this;
131
+ };
132
+
133
+ // Expose to window / globalThis in browser
134
+ global.TypeIt = TypeIt;
135
+
136
+ // Optional CommonJS export
137
+ if (typeof module !== "undefined" && module.exports) {
138
+ module.exports = TypeIt;
139
+ }
140
+ })(typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : this);