diff --git a/modules/internal/targets.js b/modules/internal/targets.js
index 8fe24d28..ae81f4e7 100644
--- a/modules/internal/targets.js
+++ b/modules/internal/targets.js
@@ -378,6 +378,10 @@ targets.setLastVersion = function (type, version) {
return '3.0.1';
} else if (type.startsWith('/spin.js/2.')) {
return '2.3.2';
+ } else if (type.startsWith('/spin.js/3.')) {
+ return '3.1.0';
+ } else if (type.startsWith('/spin.js/4.')) {
+ return '4.1.0';
} else if (type.startsWith('/stickyfill/1.')) {
return '1.1.4';
} else if (type.startsWith('/stickyfill/2.')) {
diff --git a/pages/updates/updates.html b/pages/updates/updates.html
index 4c933ab8..ff7177b5 100644
--- a/pages/updates/updates.html
+++ b/pages/updates/updates.html
@@ -78,6 +78,7 @@
Added: React v17.0.1
Updated: Rickshaw v1.6.6 -> v1.7.1
Added: Socket.IO v3.0.1
+ Added: spin.js v3.1.0, v4.1.0
diff --git a/resources/spin.js/3.1.0/spin.min.jsm b/resources/spin.js/3.1.0/spin.min.jsm
new file mode 100644
index 00000000..9eb42b2e
--- /dev/null
+++ b/resources/spin.js/3.1.0/spin.min.jsm
@@ -0,0 +1 @@
+var __assign=this&&this.__assign||Object.assign||function(t){for(var e,n=1,i=arguments.length;n1&&(r-=Math.floor(r)),o.el.childNodes.length===o.opts.lines)for(var a=0;a1)&&(i+=n.direction);var o=1-i/(n.trail/100);return o<0?n.opacity:o*(1-n.opacity)+n.opacity}function vendor(t,e){if(void 0!==t.style[e])return e;var n="ms"+e.charAt(0).toUpperCase()+e.slice(1);return void 0!==t.style[n]?n:""}function css(t,e){for(var n in e)t.style[vendor(t,n)||n]=e[n];return t}function getColor(t,e){return"string"==typeof t?t:t[e%t.length]}function drawLines(t,e){var n=Math.round(e.corners*e.width*500)/1e3+"px",i="none";!0===e.shadow?i="0 2px 4px #000":"string"==typeof e.shadow&&(i=e.shadow);for(var o=parseBoxShadow(i),r=0;r