anime-cursor 2.1.2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
 
8
8
 
9
- [[简体中文]](#animecursorsc)
9
+ [[简体中文]](#sc)
10
10
 
11
11
  ## [Visit the official website](https://shuninyu.github.io/anime-cursor/) for more informations
12
12
 
@@ -185,6 +185,7 @@ Because v2 uses native CSS `cursor` property and CSS animations, there is no Jav
185
185
 
186
186
  ---
187
187
 
188
+ <span id="sc"></span>
188
189
  # AnimeCursor v2
189
190
 
190
191
  <div align="center">
@@ -1,5 +1,5 @@
1
1
  // AnimeCursor by github@ShuninYu
2
- // v2.1.2
2
+ // v2.1.3
3
3
 
4
4
  let _instance = null;
5
5
 
@@ -51,16 +51,15 @@ class AnimeCursor {
51
51
  enableTouch: false,
52
52
  fallbackCursor: 'auto',
53
53
  excludeSelectors: 'input, textarea, [contenteditable]',
54
- combineAnimations: false, // 是否自动组合用户动画
54
+ combineAnimations: false,
55
55
  ...options
56
56
  };
57
57
 
58
58
  this.disabled = false;
59
59
  this.cursors = this.options.cursors || {};
60
- this.cursorAnimationStrings = {}; // 存储每个光标类型的动画字符串
61
- this.combinedRules = new Map(); // 存储已生成的组合类名
60
+ this.cursorAnimationStrings = {};
61
+ this.combinedRules = new Map();
62
62
 
63
- // 检查是否应启用(触摸设备且未强制启用则禁用)
64
63
  if (!this.options.enableTouch && !this.isMouseLikeDevice()) {
65
64
  this.disabled = true;
66
65
  if (this.options.debug) {
@@ -71,6 +70,7 @@ class AnimeCursor {
71
70
 
72
71
  this.styleEl = null;
73
72
  this.debugEl = null;
73
+ this.crosshairEl = null;
74
74
  this._onMouseMove = null;
75
75
 
76
76
  this._validateOptions();
@@ -97,7 +97,6 @@ class AnimeCursor {
97
97
  throw new Error(`[AnimeCursor] Cursor "${name}" missing required setting: image`);
98
98
  }
99
99
 
100
- // 处理 frames 和 duration
101
100
  if (cfg.frames !== undefined && cfg.duration !== undefined) {
102
101
  const framesType = typeof cfg.frames;
103
102
  const durationType = typeof cfg.duration;
@@ -244,7 +243,6 @@ class AnimeCursor {
244
243
  }
245
244
  }
246
245
 
247
- // 核心注入样式
248
246
  _injectStyles() {
249
247
  if (this.disabled) return;
250
248
  this.combinedRules.clear();
@@ -253,14 +251,12 @@ class AnimeCursor {
253
251
  style.id = 'animecursor-styles';
254
252
  let css = '';
255
253
 
256
- // 如果有默认光标,生成全局规则
257
254
  if (this.defaultCursorName) {
258
255
  const defaultCfg = this.cursors[this.defaultCursorName];
259
256
  const defaultCursorDef = this._buildCursorCss(this.defaultCursorName, defaultCfg);
260
257
  css += `* { ${defaultCursorDef} }\n`;
261
258
  }
262
259
 
263
- // 为每个光标生成独立的类和关键帧
264
260
  for (const [name, cfg] of Object.entries(this.cursors)) {
265
261
  const className = `.ac-cursor-${name}`;
266
262
  const offset = cfg.offset || [0, 0];
@@ -292,7 +288,6 @@ class AnimeCursor {
292
288
  cursorAnimation = animation;
293
289
  css += `${className} { cursor: url("${frameUrls[0]}") ${offset[0]} ${offset[1]}, ${fallback}; animation: ${animation}; }\n`;
294
290
  } else {
295
- // 静态光标:生成一帧动画,只播放一次,结束后保持最后一帧
296
291
  const staticKeyframeName = `ac_anim_${name}_static`;
297
292
  css += `@keyframes ${staticKeyframeName} {\n`;
298
293
  css += ` 0%, 100% { cursor: url("${frameUrls[0]}") ${offset[0]} ${offset[1]}, ${fallback}; }\n`;
@@ -304,7 +299,6 @@ class AnimeCursor {
304
299
 
305
300
  this.cursorAnimationStrings[name] = cursorAnimation;
306
301
 
307
- // 标签和 data-cursor 规则
308
302
  if (cfg.tags && cfg.tags.length) {
309
303
  const selector = cfg.tags.join(', ');
310
304
  css += `${selector} { ${this._buildCursorCss(name, cfg)} }\n`;
@@ -316,7 +310,6 @@ class AnimeCursor {
316
310
  css += `${this.options.excludeSelectors} { cursor: text !important; animation: none !important; }\n`;
317
311
  }
318
312
 
319
- // 自动组合动画
320
313
  if (this.options.combineAnimations) {
321
314
  const elements = document.querySelectorAll('[data-ac-animation]');
322
315
  for (const el of elements) {
@@ -348,7 +341,6 @@ class AnimeCursor {
348
341
  this.styleEl = style;
349
342
  }
350
343
 
351
- // 获取元素对应的光标类型(复用 debug 逻辑)
352
344
  _getCursorTypeForElement(el) {
353
345
  if (el.dataset.cursor && this.cursors[el.dataset.cursor]) {
354
346
  return el.dataset.cursor;
@@ -358,7 +350,7 @@ class AnimeCursor {
358
350
  return name;
359
351
  }
360
352
  }
361
- return this.defaultCursorName; // 可能为 null
353
+ return this.defaultCursorName;
362
354
  }
363
355
 
364
356
  _buildKeyframes(cfg, frameUrls) {
@@ -411,7 +403,6 @@ class AnimeCursor {
411
403
  const totalDuration = Array.isArray(cfg.duration) ? cfg.duration.reduce((a, b) => a + b, 0) : cfg.duration;
412
404
  css += ` animation: ac_anim_${name} ${totalDuration}s steps(1) infinite ${cfg.pingpong ? 'alternate' : ''};`;
413
405
  } else {
414
- // 静态光标:一帧动画,只播放一次,结束后保持
415
406
  css += ` animation: ac_anim_${name}_static 0.001s forwards steps(1);`;
416
407
  }
417
408
  return css;
@@ -428,27 +419,82 @@ class AnimeCursor {
428
419
  }
429
420
 
430
421
  _initDebug() {
422
+ // 创建左上角信息浮层(现有 debug 面板)
431
423
  const debugDiv = document.createElement('div');
432
424
  debugDiv.className = 'animecursor-debug';
433
425
  debugDiv.style.cssText = `
434
- position: fixed;
435
- top: 0;
436
- left: 0;
437
- background: rgba(0,0,0,0.7);
438
- color: #0f0;
439
- padding: 4px 8px;
440
- font-family: monospace;
441
- font-size: 12px;
442
- z-index: 2147483647;
443
- pointer-events: none;
444
- white-space: nowrap;
445
- `;
426
+ position: fixed;
427
+ top: 0;
428
+ left: 0;
429
+ background: rgba(0,0,0,0.7);
430
+ color: #0f0;
431
+ padding: 4px 8px;
432
+ font-family: monospace;
433
+ font-size: 12px;
434
+ z-index: 2147483647;
435
+ pointer-events: auto;
436
+ white-space: nowrap;
437
+ transition: opacity 0.2s ease;
438
+ `;
439
+ // hover 时半透明,便于查看被遮挡内容
440
+ debugDiv.addEventListener('mouseenter', () => { debugDiv.style.opacity = '0.5'; });
441
+ debugDiv.addEventListener('mouseleave', () => { debugDiv.style.opacity = '1'; });
446
442
  document.body.appendChild(debugDiv);
447
443
  this.debugEl = debugDiv;
448
444
 
445
+ // 创建跟随鼠标的十字辅助线层(横竖双色线)
446
+ const crosshair = document.createElement('div');
447
+ crosshair.className = 'animecursor-crosshair';
448
+ crosshair.style.cssText = `
449
+ position: fixed;
450
+ top: 0;
451
+ left: 0;
452
+ width: 0;
453
+ height: 0;
454
+ pointer-events: none;
455
+ z-index: 2147483646;
456
+ `;
457
+ // 横线
458
+ const hLine = document.createElement('div');
459
+ hLine.className = 'ac-crosshair-h';
460
+ hLine.style.cssText = `
461
+ position: fixed;
462
+ left: 0;
463
+ width: 100%;
464
+ height: 1px;
465
+ background-color: rgba(255,0,0,0.6);
466
+ pointer-events: none;
467
+ transform: translateY(-0.5px);
468
+ `;
469
+ // 竖线
470
+ const vLine = document.createElement('div');
471
+ vLine.className = 'ac-crosshair-v';
472
+ vLine.style.cssText = `
473
+ position: fixed;
474
+ top: 0;
475
+ width: 1px;
476
+ height: 100%;
477
+ background-color: rgba(255,0,0,0.6);
478
+ pointer-events: none;
479
+ transform: translateX(-0.5px);
480
+ `;
481
+ crosshair.appendChild(hLine);
482
+ crosshair.appendChild(vLine);
483
+ document.body.appendChild(crosshair);
484
+ this.crosshairEl = { container: crosshair, hLine, vLine };
485
+
449
486
  let lastCursor = '';
450
487
  this._onMouseMove = (e) => {
451
- const target = document.elementFromPoint(e.clientX, e.clientY);
488
+ const x = e.clientX;
489
+ const y = e.clientY;
490
+
491
+ // 更新十字线位置
492
+ if (this.crosshairEl) {
493
+ this.crosshairEl.hLine.style.top = y + 'px';
494
+ this.crosshairEl.vLine.style.left = x + 'px';
495
+ }
496
+
497
+ const target = document.elementFromPoint(x, y);
452
498
  let cursorType = null;
453
499
  if (target) {
454
500
  if (target.dataset.cursor && this.cursors[target.dataset.cursor]) {
@@ -469,9 +515,9 @@ class AnimeCursor {
469
515
  }
470
516
  if (cursorType !== lastCursor) {
471
517
  lastCursor = cursorType;
472
- debugDiv.textContent = `🎯 ${cursorType} @ (${e.clientX}, ${e.clientY})`;
518
+ debugDiv.textContent = `${cursorType} @ (${x}, ${y})`;
473
519
  } else {
474
- debugDiv.textContent = `🎯 ${cursorType} @ (${e.clientX}, ${e.clientY})`;
520
+ debugDiv.textContent = `${cursorType} @ (${x}, ${y})`;
475
521
  }
476
522
  };
477
523
  document.addEventListener('mousemove', this._onMouseMove);
@@ -484,6 +530,7 @@ class AnimeCursor {
484
530
  this._injectStyles();
485
531
  if (this.options.debug) {
486
532
  if (this.debugEl) this.debugEl.remove();
533
+ if (this.crosshairEl) this.crosshairEl.container.remove();
487
534
  this._initDebug();
488
535
  }
489
536
  console.log('[AnimeCursor] Refresh complete');
@@ -493,6 +540,7 @@ class AnimeCursor {
493
540
  if (this.disabled) return;
494
541
  if (this.styleEl) this.styleEl.remove();
495
542
  if (this.debugEl) this.debugEl.remove();
543
+ if (this.crosshairEl) this.crosshairEl.container.remove();
496
544
  if (this._onMouseMove) {
497
545
  document.removeEventListener('mousemove', this._onMouseMove);
498
546
  }
@@ -503,16 +551,18 @@ class AnimeCursor {
503
551
 
504
552
  disable() {
505
553
  if (this.disabled) return;
506
- // 移除样式表
507
554
  if (this.styleEl) {
508
555
  this.styleEl.remove();
509
556
  this.styleEl = null;
510
557
  }
511
- // 移除 debug 相关
512
558
  if (this.debugEl) {
513
559
  this.debugEl.remove();
514
560
  this.debugEl = null;
515
561
  }
562
+ if (this.crosshairEl) {
563
+ this.crosshairEl.container.remove();
564
+ this.crosshairEl = null;
565
+ }
516
566
  if (this._onMouseMove) {
517
567
  document.removeEventListener('mousemove', this._onMouseMove);
518
568
  this._onMouseMove = null;
@@ -524,9 +574,7 @@ class AnimeCursor {
524
574
  enable() {
525
575
  if (!this.disabled) return;
526
576
  this.disabled = false;
527
- // 重新注入样式
528
577
  this._injectStyles();
529
- // 如果 debug 模式开启,重新初始化 debug
530
578
  if (this.options.debug) {
531
579
  this._initDebug();
532
580
  }
@@ -5,7 +5,7 @@
5
5
  })(this, (function () { 'use strict';
6
6
 
7
7
  // AnimeCursor by github@ShuninYu
8
- // v2.1.2
8
+ // v2.1.3
9
9
 
10
10
  let _instance = null;
11
11
 
@@ -57,16 +57,15 @@
57
57
  enableTouch: false,
58
58
  fallbackCursor: 'auto',
59
59
  excludeSelectors: 'input, textarea, [contenteditable]',
60
- combineAnimations: false, // 是否自动组合用户动画
60
+ combineAnimations: false,
61
61
  ...options
62
62
  };
63
63
 
64
64
  this.disabled = false;
65
65
  this.cursors = this.options.cursors || {};
66
- this.cursorAnimationStrings = {}; // 存储每个光标类型的动画字符串
67
- this.combinedRules = new Map(); // 存储已生成的组合类名
66
+ this.cursorAnimationStrings = {};
67
+ this.combinedRules = new Map();
68
68
 
69
- // 检查是否应启用(触摸设备且未强制启用则禁用)
70
69
  if (!this.options.enableTouch && !this.isMouseLikeDevice()) {
71
70
  this.disabled = true;
72
71
  if (this.options.debug) {
@@ -77,6 +76,7 @@
77
76
 
78
77
  this.styleEl = null;
79
78
  this.debugEl = null;
79
+ this.crosshairEl = null;
80
80
  this._onMouseMove = null;
81
81
 
82
82
  this._validateOptions();
@@ -103,7 +103,6 @@
103
103
  throw new Error(`[AnimeCursor] Cursor "${name}" missing required setting: image`);
104
104
  }
105
105
 
106
- // 处理 frames 和 duration
107
106
  if (cfg.frames !== undefined && cfg.duration !== undefined) {
108
107
  const framesType = typeof cfg.frames;
109
108
  const durationType = typeof cfg.duration;
@@ -250,7 +249,6 @@
250
249
  }
251
250
  }
252
251
 
253
- // 核心注入样式
254
252
  _injectStyles() {
255
253
  if (this.disabled) return;
256
254
  this.combinedRules.clear();
@@ -259,14 +257,12 @@
259
257
  style.id = 'animecursor-styles';
260
258
  let css = '';
261
259
 
262
- // 如果有默认光标,生成全局规则
263
260
  if (this.defaultCursorName) {
264
261
  const defaultCfg = this.cursors[this.defaultCursorName];
265
262
  const defaultCursorDef = this._buildCursorCss(this.defaultCursorName, defaultCfg);
266
263
  css += `* { ${defaultCursorDef} }\n`;
267
264
  }
268
265
 
269
- // 为每个光标生成独立的类和关键帧
270
266
  for (const [name, cfg] of Object.entries(this.cursors)) {
271
267
  const className = `.ac-cursor-${name}`;
272
268
  const offset = cfg.offset || [0, 0];
@@ -298,7 +294,6 @@
298
294
  cursorAnimation = animation;
299
295
  css += `${className} { cursor: url("${frameUrls[0]}") ${offset[0]} ${offset[1]}, ${fallback}; animation: ${animation}; }\n`;
300
296
  } else {
301
- // 静态光标:生成一帧动画,只播放一次,结束后保持最后一帧
302
297
  const staticKeyframeName = `ac_anim_${name}_static`;
303
298
  css += `@keyframes ${staticKeyframeName} {\n`;
304
299
  css += ` 0%, 100% { cursor: url("${frameUrls[0]}") ${offset[0]} ${offset[1]}, ${fallback}; }\n`;
@@ -310,7 +305,6 @@
310
305
 
311
306
  this.cursorAnimationStrings[name] = cursorAnimation;
312
307
 
313
- // 标签和 data-cursor 规则
314
308
  if (cfg.tags && cfg.tags.length) {
315
309
  const selector = cfg.tags.join(', ');
316
310
  css += `${selector} { ${this._buildCursorCss(name, cfg)} }\n`;
@@ -322,7 +316,6 @@
322
316
  css += `${this.options.excludeSelectors} { cursor: text !important; animation: none !important; }\n`;
323
317
  }
324
318
 
325
- // 自动组合动画
326
319
  if (this.options.combineAnimations) {
327
320
  const elements = document.querySelectorAll('[data-ac-animation]');
328
321
  for (const el of elements) {
@@ -354,7 +347,6 @@
354
347
  this.styleEl = style;
355
348
  }
356
349
 
357
- // 获取元素对应的光标类型(复用 debug 逻辑)
358
350
  _getCursorTypeForElement(el) {
359
351
  if (el.dataset.cursor && this.cursors[el.dataset.cursor]) {
360
352
  return el.dataset.cursor;
@@ -364,7 +356,7 @@
364
356
  return name;
365
357
  }
366
358
  }
367
- return this.defaultCursorName; // 可能为 null
359
+ return this.defaultCursorName;
368
360
  }
369
361
 
370
362
  _buildKeyframes(cfg, frameUrls) {
@@ -417,7 +409,6 @@
417
409
  const totalDuration = Array.isArray(cfg.duration) ? cfg.duration.reduce((a, b) => a + b, 0) : cfg.duration;
418
410
  css += ` animation: ac_anim_${name} ${totalDuration}s steps(1) infinite ${cfg.pingpong ? 'alternate' : ''};`;
419
411
  } else {
420
- // 静态光标:一帧动画,只播放一次,结束后保持
421
412
  css += ` animation: ac_anim_${name}_static 0.001s forwards steps(1);`;
422
413
  }
423
414
  return css;
@@ -434,27 +425,82 @@
434
425
  }
435
426
 
436
427
  _initDebug() {
428
+ // 创建左上角信息浮层(现有 debug 面板)
437
429
  const debugDiv = document.createElement('div');
438
430
  debugDiv.className = 'animecursor-debug';
439
431
  debugDiv.style.cssText = `
440
- position: fixed;
441
- top: 0;
442
- left: 0;
443
- background: rgba(0,0,0,0.7);
444
- color: #0f0;
445
- padding: 4px 8px;
446
- font-family: monospace;
447
- font-size: 12px;
448
- z-index: 2147483647;
449
- pointer-events: none;
450
- white-space: nowrap;
451
- `;
432
+ position: fixed;
433
+ top: 0;
434
+ left: 0;
435
+ background: rgba(0,0,0,0.7);
436
+ color: #0f0;
437
+ padding: 4px 8px;
438
+ font-family: monospace;
439
+ font-size: 12px;
440
+ z-index: 2147483647;
441
+ pointer-events: auto;
442
+ white-space: nowrap;
443
+ transition: opacity 0.2s ease;
444
+ `;
445
+ // hover 时半透明,便于查看被遮挡内容
446
+ debugDiv.addEventListener('mouseenter', () => { debugDiv.style.opacity = '0.5'; });
447
+ debugDiv.addEventListener('mouseleave', () => { debugDiv.style.opacity = '1'; });
452
448
  document.body.appendChild(debugDiv);
453
449
  this.debugEl = debugDiv;
454
450
 
451
+ // 创建跟随鼠标的十字辅助线层(横竖双色线)
452
+ const crosshair = document.createElement('div');
453
+ crosshair.className = 'animecursor-crosshair';
454
+ crosshair.style.cssText = `
455
+ position: fixed;
456
+ top: 0;
457
+ left: 0;
458
+ width: 0;
459
+ height: 0;
460
+ pointer-events: none;
461
+ z-index: 2147483646;
462
+ `;
463
+ // 横线
464
+ const hLine = document.createElement('div');
465
+ hLine.className = 'ac-crosshair-h';
466
+ hLine.style.cssText = `
467
+ position: fixed;
468
+ left: 0;
469
+ width: 100%;
470
+ height: 1px;
471
+ background-color: rgba(255,0,0,0.6);
472
+ pointer-events: none;
473
+ transform: translateY(-0.5px);
474
+ `;
475
+ // 竖线
476
+ const vLine = document.createElement('div');
477
+ vLine.className = 'ac-crosshair-v';
478
+ vLine.style.cssText = `
479
+ position: fixed;
480
+ top: 0;
481
+ width: 1px;
482
+ height: 100%;
483
+ background-color: rgba(255,0,0,0.6);
484
+ pointer-events: none;
485
+ transform: translateX(-0.5px);
486
+ `;
487
+ crosshair.appendChild(hLine);
488
+ crosshair.appendChild(vLine);
489
+ document.body.appendChild(crosshair);
490
+ this.crosshairEl = { container: crosshair, hLine, vLine };
491
+
455
492
  let lastCursor = '';
456
493
  this._onMouseMove = (e) => {
457
- const target = document.elementFromPoint(e.clientX, e.clientY);
494
+ const x = e.clientX;
495
+ const y = e.clientY;
496
+
497
+ // 更新十字线位置
498
+ if (this.crosshairEl) {
499
+ this.crosshairEl.hLine.style.top = y + 'px';
500
+ this.crosshairEl.vLine.style.left = x + 'px';
501
+ }
502
+
503
+ const target = document.elementFromPoint(x, y);
458
504
  let cursorType = null;
459
505
  if (target) {
460
506
  if (target.dataset.cursor && this.cursors[target.dataset.cursor]) {
@@ -475,9 +521,9 @@
475
521
  }
476
522
  if (cursorType !== lastCursor) {
477
523
  lastCursor = cursorType;
478
- debugDiv.textContent = `🎯 ${cursorType} @ (${e.clientX}, ${e.clientY})`;
524
+ debugDiv.textContent = `${cursorType} @ (${x}, ${y})`;
479
525
  } else {
480
- debugDiv.textContent = `🎯 ${cursorType} @ (${e.clientX}, ${e.clientY})`;
526
+ debugDiv.textContent = `${cursorType} @ (${x}, ${y})`;
481
527
  }
482
528
  };
483
529
  document.addEventListener('mousemove', this._onMouseMove);
@@ -490,6 +536,7 @@
490
536
  this._injectStyles();
491
537
  if (this.options.debug) {
492
538
  if (this.debugEl) this.debugEl.remove();
539
+ if (this.crosshairEl) this.crosshairEl.container.remove();
493
540
  this._initDebug();
494
541
  }
495
542
  console.log('[AnimeCursor] Refresh complete');
@@ -499,6 +546,7 @@
499
546
  if (this.disabled) return;
500
547
  if (this.styleEl) this.styleEl.remove();
501
548
  if (this.debugEl) this.debugEl.remove();
549
+ if (this.crosshairEl) this.crosshairEl.container.remove();
502
550
  if (this._onMouseMove) {
503
551
  document.removeEventListener('mousemove', this._onMouseMove);
504
552
  }
@@ -509,16 +557,18 @@
509
557
 
510
558
  disable() {
511
559
  if (this.disabled) return;
512
- // 移除样式表
513
560
  if (this.styleEl) {
514
561
  this.styleEl.remove();
515
562
  this.styleEl = null;
516
563
  }
517
- // 移除 debug 相关
518
564
  if (this.debugEl) {
519
565
  this.debugEl.remove();
520
566
  this.debugEl = null;
521
567
  }
568
+ if (this.crosshairEl) {
569
+ this.crosshairEl.container.remove();
570
+ this.crosshairEl = null;
571
+ }
522
572
  if (this._onMouseMove) {
523
573
  document.removeEventListener('mousemove', this._onMouseMove);
524
574
  this._onMouseMove = null;
@@ -530,9 +580,7 @@
530
580
  enable() {
531
581
  if (!this.disabled) return;
532
582
  this.disabled = false;
533
- // 重新注入样式
534
583
  this._injectStyles();
535
- // 如果 debug 模式开启,重新初始化 debug
536
584
  if (this.options.debug) {
537
585
  this._initDebug();
538
586
  }
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).AnimeCursor=t()}(this,function(){"use strict";let e=null;return class{static get instance(){return e}static destroy(){return!!e&&(e.destroy(),!0)}static refresh(){return!!e&&(e.refresh(),!0)}static disable(){return!!e&&(e.disable(),!0)}static enable(){return!!e&&(e.enable(),!0)}constructor(t={}){return e?(console.warn("[AnimeCursor] Instance already exists, returning existing one"),e):(this.options={debug:!1,enableTouch:!1,fallbackCursor:"auto",excludeSelectors:"input, textarea, [contenteditable]",combineAnimations:!1,...t},this.disabled=!1,this.cursors=this.options.cursors||{},this.cursorAnimationStrings={},this.combinedRules=new Map,this.options.enableTouch||this.isMouseLikeDevice()?(this.styleEl=null,this.debugEl=null,this._onMouseMove=null,this._validateOptions(),this._preloadImages(),this._checkDomLoad(),void(e=this)):(this.disabled=!0,void(this.options.debug&&console.warn("[AnimeCursor] Touch device detected, cursor animations disabled"))))}isMouseLikeDevice(){return window.matchMedia("(pointer: fine)").matches}_validateOptions(){if(this.disabled)return;if(!this.cursors||0===Object.keys(this.cursors).length)throw new Error("[AnimeCursor] At least one cursor must be defined");let e=!1;for(const[t,s]of Object.entries(this.cursors)){if(!s.image)throw new Error(`[AnimeCursor] Cursor "${t}" missing required setting: image`);if(void 0!==s.frames&&void 0!==s.duration){if(typeof s.frames!==typeof s.duration)console.warn(`[AnimeCursor] Cursor "${t}" has mismatched types for frames and duration, treating as static cursor`),delete s.frames,delete s.duration;else if(Array.isArray(s.frames)&&Array.isArray(s.duration))if(s.frames.length!==s.duration.length)console.warn(`[AnimeCursor] Cursor "${t}" frames and duration arrays have different lengths, treating as static cursor`),delete s.frames,delete s.duration;else{for(let e of s.frames)if(!Number.isInteger(e)||e<=0){console.warn(`[AnimeCursor] Cursor "${t}" frames array contains invalid value, treating as static cursor`),delete s.frames,delete s.duration;break}for(let e of s.duration)if("number"!=typeof e||e<=0){console.warn(`[AnimeCursor] Cursor "${t}" duration array contains invalid value, treating as static cursor`),delete s.frames,delete s.duration;break}}else"number"==typeof s.frames&&"number"==typeof s.duration?(s.frames<=0||s.duration<=0)&&(console.warn(`[AnimeCursor] Cursor "${t}" frames or duration <= 0, treating as static cursor`),delete s.frames,delete s.duration):(console.warn(`[AnimeCursor] Cursor "${t}" frames and duration must be both numbers or both arrays, treating as static cursor`),delete s.frames,delete s.duration)}else void 0===s.frames&&void 0===s.duration||(console.warn(`[AnimeCursor] Cursor "${t}" has only frames or duration defined, treating as static cursor`),delete s.frames,delete s.duration);if(s.tags&&!Array.isArray(s.tags))throw new Error(`[AnimeCursor] Cursor "${t}" tags must be an array`);if(s.default){if(e)throw new Error("[AnimeCursor] Only one default cursor allowed");e=!0}if(s.offset&&(!Array.isArray(s.offset)||2!==s.offset.length))throw new Error(`[AnimeCursor] Cursor "${t}" offset must be [x, y] array`)}this.defaultCursorName=e?Object.keys(this.cursors).find(e=>this.cursors[e].default):null}_preloadImages(){const e=new Set;for(const t of Object.values(this.cursors)){this._getFrameUrls(t).forEach(t=>e.add(t))}e.forEach(e=>{const t=document.createElement("link");t.rel="preload",t.as="image",t.href=e,e.startsWith("http")&&!e.startsWith(window.location.origin)&&(t.crossOrigin="anonymous"),document.head.appendChild(t)}),this.options.debug&&e.size&&console.info(`[AnimeCursor] Preloaded ${e.size} cursor images`)}_getFrameUrls(e){let t=1;void 0!==e.frames&&(Array.isArray(e.frames)?t=e.frames.reduce((e,t)=>e+t,0):"number"==typeof e.frames&&(t=e.frames));const{image:s}=e;if(1===t)return[s];const{prefix:r,suffix:o,startNum:i,numFormat:n,ext:a}=this._parseImagePattern(s),u=[];for(let e=0;e<t;e++){const t=i+e,s=`${r}${n?this._formatNumber(t,n):t}${o}${a}`;u.push(s)}return u}_parseImagePattern(e){const t=e.match(/\.[^.]+$/),s=t?t[0]:"",r=e.slice(0,-s.length),o=r.match(/(\d+)(?!.*\d)/);if(!o)return{prefix:r+"_",suffix:"",startNum:1,numFormat:null,ext:s};const i=o[0],n=parseInt(i,10),a=i.length;return{prefix:r.slice(0,o.index),suffix:r.slice(o.index+i.length),startNum:n,numFormat:a,ext:s}}_formatNumber(e,t){return String(e).padStart(t,"0")}_checkDomLoad(){const e=()=>{this._injectStyles(),this.options.debug&&this._initDebug(),console.log("[AnimeCursor] Initialization complete")};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()}_injectStyles(){if(this.disabled)return;this.combinedRules.clear();const e=document.createElement("style");e.id="animecursor-styles";let t="";if(this.defaultCursorName){const e=this.cursors[this.defaultCursorName];t+=`* { ${this._buildCursorCss(this.defaultCursorName,e)} }\n`}for(const[e,s]of Object.entries(this.cursors)){const r=`.ac-cursor-${e}`,o=s.offset||[0,0],i=s.fallback||this.options.fallbackCursor,n=this._getFrameUrls(s),a=n.length;let u="";if(void 0!==s.frames&&void 0!==s.duration&&(Array.isArray(s.frames)&&Array.isArray(s.duration)||"number"==typeof s.frames&&"number"==typeof s.duration)&&a>1){const a=`ac_anim_${e}`;let l=`@keyframes ${a} {\n`;const d=this._buildKeyframes(s,n);for(const e of d){let t=(100*e.percent).toFixed(5);1===e.percent&&(t="100");l+=` ${t}% { ${`cursor: url("${e.url}") ${o[0]} ${o[1]}, ${i};`} }\n`}l+="}\n",t+=l;const c=`${a} ${Array.isArray(s.duration)?s.duration.reduce((e,t)=>e+t,0):s.duration}s steps(1) infinite ${s.pingpong?"alternate":""}`;u=c,t+=`${r} { cursor: url("${n[0]}") ${o[0]} ${o[1]}, ${i}; animation: ${c}; }\n`}else{const s=`ac_anim_${e}_static`;t+=`@keyframes ${s} {\n`,t+=` 0%, 100% { cursor: url("${n[0]}") ${o[0]} ${o[1]}, ${i}; }\n`,t+="}\n";const a=`${s} 0.001s forwards steps(1)`;u=a,t+=`${r} { cursor: url("${n[0]}") ${o[0]} ${o[1]}, ${i}; animation: ${a}; }\n`}if(this.cursorAnimationStrings[e]=u,s.tags&&s.tags.length){t+=`${s.tags.join(", ")} { ${this._buildCursorCss(e,s)} }\n`}t+=`[data-cursor="${e}"] { ${this._buildCursorCss(e,s)} }\n`}if(this.options.excludeSelectors&&(t+=`${this.options.excludeSelectors} { cursor: text !important; animation: none !important; }\n`),this.options.combineAnimations){const e=document.querySelectorAll("[data-ac-animation]");for(const s of e){const e=s.getAttribute("data-ac-animation");if(!e)continue;let r=this._getCursorTypeForElement(s);if(!r)continue;const o=this.cursorAnimationStrings[r];if(!o)continue;const i=`${r}:${e}`;if(!this.combinedRules.has(i)){const s=`ac-combined-${this._simpleHash(i)}`;t+=`.${s} { animation: ${o}, ${e}; }\n`,this.combinedRules.set(i,s)}const n=this.combinedRules.get(i);s.classList.add(n)}}t+="body.animecursor-disabled * { cursor: auto !important; animation: none !important; }\n",e.textContent=t,document.head.appendChild(e),this.styleEl=e}_getCursorTypeForElement(e){if(e.dataset.cursor&&this.cursors[e.dataset.cursor])return e.dataset.cursor;for(const[t,s]of Object.entries(this.cursors))if(s.tags&&s.tags.some(t=>e.matches(t)))return t;return this.defaultCursorName}_buildKeyframes(e,t){let s=e.frames,r=e.duration;const o=t.length;if("number"==typeof s){const e=r/s;s=new Array(s).fill(1),r=new Array(s.length).fill(e)}const i=[];let n=r.reduce((e,t)=>e+t,0),a=0,u=0;for(let e=0;e<s.length;e++){const o=s[e],l=r[e]/o;for(let e=0;e<o;e++){const e=a/n;i.push({percent:e,url:t[u]}),a+=l,u++}}return i.push({percent:1,url:t[o-1]}),i}_buildCursorCss(e,t){const s=this._getFrameUrls(t),r=t.offset||[0,0],o=t.fallback||this.options.fallbackCursor;let i=`cursor: url("${s[0]}") ${r[0]} ${r[1]}, ${o};`;if(void 0!==t.frames&&void 0!==t.duration&&(Array.isArray(t.frames)&&Array.isArray(t.duration)||"number"==typeof t.frames&&"number"==typeof t.duration)&&s.length>1){i+=` animation: ac_anim_${e} ${Array.isArray(t.duration)?t.duration.reduce((e,t)=>e+t,0):t.duration}s steps(1) infinite ${t.pingpong?"alternate":""};`}else i+=` animation: ac_anim_${e}_static 0.001s forwards steps(1);`;return i}_simpleHash(e){let t=0;for(let s=0;s<e.length;s++){t=(t<<5)-t+e.charCodeAt(s),t|=0}return Math.abs(t).toString(36)}_initDebug(){const e=document.createElement("div");e.className="animecursor-debug",e.style.cssText="\n position: fixed;\n top: 0;\n left: 0;\n background: rgba(0,0,0,0.7);\n color: #0f0;\n padding: 4px 8px;\n font-family: monospace;\n font-size: 12px;\n z-index: 2147483647;\n pointer-events: none;\n white-space: nowrap;\n ",document.body.appendChild(e),this.debugEl=e;let t="";this._onMouseMove=s=>{const r=document.elementFromPoint(s.clientX,s.clientY);let o=null;if(r)if(r.dataset.cursor&&this.cursors[r.dataset.cursor])o=r.dataset.cursor;else for(const[e,t]of Object.entries(this.cursors))if(t.tags&&t.tags.some(e=>r.matches(e))){o=e;break}o||this.defaultCursorName?!o&&this.defaultCursorName&&(o=this.defaultCursorName):o="native",o!==t?(t=o,e.textContent=`🎯 ${o} @ (${s.clientX}, ${s.clientY})`):e.textContent=`🎯 ${o} @ (${s.clientX}, ${s.clientY})`},document.addEventListener("mousemove",this._onMouseMove)}refresh(){this.disabled||(this.styleEl&&this.styleEl.remove(),this.combinedRules.clear(),this._injectStyles(),this.options.debug&&(this.debugEl&&this.debugEl.remove(),this._initDebug()),console.log("[AnimeCursor] Refresh complete"))}destroy(){this.disabled||(this.styleEl&&this.styleEl.remove(),this.debugEl&&this.debugEl.remove(),this._onMouseMove&&document.removeEventListener("mousemove",this._onMouseMove),document.body.classList.remove("animecursor-disabled"),e=null,console.log("[AnimeCursor] Destroyed"))}disable(){this.disabled||(this.styleEl&&(this.styleEl.remove(),this.styleEl=null),this.debugEl&&(this.debugEl.remove(),this.debugEl=null),this._onMouseMove&&(document.removeEventListener("mousemove",this._onMouseMove),this._onMouseMove=null),this.disabled=!0,this.options.debug&&console.log("[AnimeCursor] Disabled"))}enable(){this.disabled&&(this.disabled=!1,this._injectStyles(),this.options.debug&&this._initDebug(),this.options.debug&&console.log("[AnimeCursor] Enabled"))}}});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).AnimeCursor=t()}(this,function(){"use strict";let e=null;return class{static get instance(){return e}static destroy(){return!!e&&(e.destroy(),!0)}static refresh(){return!!e&&(e.refresh(),!0)}static disable(){return!!e&&(e.disable(),!0)}static enable(){return!!e&&(e.enable(),!0)}constructor(t={}){return e?(console.warn("[AnimeCursor] Instance already exists, returning existing one"),e):(this.options={debug:!1,enableTouch:!1,fallbackCursor:"auto",excludeSelectors:"input, textarea, [contenteditable]",combineAnimations:!1,...t},this.disabled=!1,this.cursors=this.options.cursors||{},this.cursorAnimationStrings={},this.combinedRules=new Map,this.options.enableTouch||this.isMouseLikeDevice()?(this.styleEl=null,this.debugEl=null,this.crosshairEl=null,this._onMouseMove=null,this._validateOptions(),this._preloadImages(),this._checkDomLoad(),void(e=this)):(this.disabled=!0,void(this.options.debug&&console.warn("[AnimeCursor] Touch device detected, cursor animations disabled"))))}isMouseLikeDevice(){return window.matchMedia("(pointer: fine)").matches}_validateOptions(){if(this.disabled)return;if(!this.cursors||0===Object.keys(this.cursors).length)throw new Error("[AnimeCursor] At least one cursor must be defined");let e=!1;for(const[t,s]of Object.entries(this.cursors)){if(!s.image)throw new Error(`[AnimeCursor] Cursor "${t}" missing required setting: image`);if(void 0!==s.frames&&void 0!==s.duration){if(typeof s.frames!==typeof s.duration)console.warn(`[AnimeCursor] Cursor "${t}" has mismatched types for frames and duration, treating as static cursor`),delete s.frames,delete s.duration;else if(Array.isArray(s.frames)&&Array.isArray(s.duration))if(s.frames.length!==s.duration.length)console.warn(`[AnimeCursor] Cursor "${t}" frames and duration arrays have different lengths, treating as static cursor`),delete s.frames,delete s.duration;else{for(let e of s.frames)if(!Number.isInteger(e)||e<=0){console.warn(`[AnimeCursor] Cursor "${t}" frames array contains invalid value, treating as static cursor`),delete s.frames,delete s.duration;break}for(let e of s.duration)if("number"!=typeof e||e<=0){console.warn(`[AnimeCursor] Cursor "${t}" duration array contains invalid value, treating as static cursor`),delete s.frames,delete s.duration;break}}else"number"==typeof s.frames&&"number"==typeof s.duration?(s.frames<=0||s.duration<=0)&&(console.warn(`[AnimeCursor] Cursor "${t}" frames or duration <= 0, treating as static cursor`),delete s.frames,delete s.duration):(console.warn(`[AnimeCursor] Cursor "${t}" frames and duration must be both numbers or both arrays, treating as static cursor`),delete s.frames,delete s.duration)}else void 0===s.frames&&void 0===s.duration||(console.warn(`[AnimeCursor] Cursor "${t}" has only frames or duration defined, treating as static cursor`),delete s.frames,delete s.duration);if(s.tags&&!Array.isArray(s.tags))throw new Error(`[AnimeCursor] Cursor "${t}" tags must be an array`);if(s.default){if(e)throw new Error("[AnimeCursor] Only one default cursor allowed");e=!0}if(s.offset&&(!Array.isArray(s.offset)||2!==s.offset.length))throw new Error(`[AnimeCursor] Cursor "${t}" offset must be [x, y] array`)}this.defaultCursorName=e?Object.keys(this.cursors).find(e=>this.cursors[e].default):null}_preloadImages(){const e=new Set;for(const t of Object.values(this.cursors)){this._getFrameUrls(t).forEach(t=>e.add(t))}e.forEach(e=>{const t=document.createElement("link");t.rel="preload",t.as="image",t.href=e,e.startsWith("http")&&!e.startsWith(window.location.origin)&&(t.crossOrigin="anonymous"),document.head.appendChild(t)}),this.options.debug&&e.size&&console.info(`[AnimeCursor] Preloaded ${e.size} cursor images`)}_getFrameUrls(e){let t=1;void 0!==e.frames&&(Array.isArray(e.frames)?t=e.frames.reduce((e,t)=>e+t,0):"number"==typeof e.frames&&(t=e.frames));const{image:s}=e;if(1===t)return[s];const{prefix:r,suffix:o,startNum:n,numFormat:i,ext:a}=this._parseImagePattern(s),u=[];for(let e=0;e<t;e++){const t=n+e,s=`${r}${i?this._formatNumber(t,i):t}${o}${a}`;u.push(s)}return u}_parseImagePattern(e){const t=e.match(/\.[^.]+$/),s=t?t[0]:"",r=e.slice(0,-s.length),o=r.match(/(\d+)(?!.*\d)/);if(!o)return{prefix:r+"_",suffix:"",startNum:1,numFormat:null,ext:s};const n=o[0],i=parseInt(n,10),a=n.length;return{prefix:r.slice(0,o.index),suffix:r.slice(o.index+n.length),startNum:i,numFormat:a,ext:s}}_formatNumber(e,t){return String(e).padStart(t,"0")}_checkDomLoad(){const e=()=>{this._injectStyles(),this.options.debug&&this._initDebug(),console.log("[AnimeCursor] Initialization complete")};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",e):e()}_injectStyles(){if(this.disabled)return;this.combinedRules.clear();const e=document.createElement("style");e.id="animecursor-styles";let t="";if(this.defaultCursorName){const e=this.cursors[this.defaultCursorName];t+=`* { ${this._buildCursorCss(this.defaultCursorName,e)} }\n`}for(const[e,s]of Object.entries(this.cursors)){const r=`.ac-cursor-${e}`,o=s.offset||[0,0],n=s.fallback||this.options.fallbackCursor,i=this._getFrameUrls(s),a=i.length;let u="";if(void 0!==s.frames&&void 0!==s.duration&&(Array.isArray(s.frames)&&Array.isArray(s.duration)||"number"==typeof s.frames&&"number"==typeof s.duration)&&a>1){const a=`ac_anim_${e}`;let l=`@keyframes ${a} {\n`;const c=this._buildKeyframes(s,i);for(const e of c){let t=(100*e.percent).toFixed(5);1===e.percent&&(t="100");l+=` ${t}% { ${`cursor: url("${e.url}") ${o[0]} ${o[1]}, ${n};`} }\n`}l+="}\n",t+=l;const d=`${a} ${Array.isArray(s.duration)?s.duration.reduce((e,t)=>e+t,0):s.duration}s steps(1) infinite ${s.pingpong?"alternate":""}`;u=d,t+=`${r} { cursor: url("${i[0]}") ${o[0]} ${o[1]}, ${n}; animation: ${d}; }\n`}else{const s=`ac_anim_${e}_static`;t+=`@keyframes ${s} {\n`,t+=` 0%, 100% { cursor: url("${i[0]}") ${o[0]} ${o[1]}, ${n}; }\n`,t+="}\n";const a=`${s} 0.001s forwards steps(1)`;u=a,t+=`${r} { cursor: url("${i[0]}") ${o[0]} ${o[1]}, ${n}; animation: ${a}; }\n`}if(this.cursorAnimationStrings[e]=u,s.tags&&s.tags.length){t+=`${s.tags.join(", ")} { ${this._buildCursorCss(e,s)} }\n`}t+=`[data-cursor="${e}"] { ${this._buildCursorCss(e,s)} }\n`}if(this.options.excludeSelectors&&(t+=`${this.options.excludeSelectors} { cursor: text !important; animation: none !important; }\n`),this.options.combineAnimations){const e=document.querySelectorAll("[data-ac-animation]");for(const s of e){const e=s.getAttribute("data-ac-animation");if(!e)continue;let r=this._getCursorTypeForElement(s);if(!r)continue;const o=this.cursorAnimationStrings[r];if(!o)continue;const n=`${r}:${e}`;if(!this.combinedRules.has(n)){const s=`ac-combined-${this._simpleHash(n)}`;t+=`.${s} { animation: ${o}, ${e}; }\n`,this.combinedRules.set(n,s)}const i=this.combinedRules.get(n);s.classList.add(i)}}t+="body.animecursor-disabled * { cursor: auto !important; animation: none !important; }\n",e.textContent=t,document.head.appendChild(e),this.styleEl=e}_getCursorTypeForElement(e){if(e.dataset.cursor&&this.cursors[e.dataset.cursor])return e.dataset.cursor;for(const[t,s]of Object.entries(this.cursors))if(s.tags&&s.tags.some(t=>e.matches(t)))return t;return this.defaultCursorName}_buildKeyframes(e,t){let s=e.frames,r=e.duration;const o=t.length;if("number"==typeof s){const e=r/s;s=new Array(s).fill(1),r=new Array(s.length).fill(e)}const n=[];let i=r.reduce((e,t)=>e+t,0),a=0,u=0;for(let e=0;e<s.length;e++){const o=s[e],l=r[e]/o;for(let e=0;e<o;e++){const e=a/i;n.push({percent:e,url:t[u]}),a+=l,u++}}return n.push({percent:1,url:t[o-1]}),n}_buildCursorCss(e,t){const s=this._getFrameUrls(t),r=t.offset||[0,0],o=t.fallback||this.options.fallbackCursor;let n=`cursor: url("${s[0]}") ${r[0]} ${r[1]}, ${o};`;if(void 0!==t.frames&&void 0!==t.duration&&(Array.isArray(t.frames)&&Array.isArray(t.duration)||"number"==typeof t.frames&&"number"==typeof t.duration)&&s.length>1){n+=` animation: ac_anim_${e} ${Array.isArray(t.duration)?t.duration.reduce((e,t)=>e+t,0):t.duration}s steps(1) infinite ${t.pingpong?"alternate":""};`}else n+=` animation: ac_anim_${e}_static 0.001s forwards steps(1);`;return n}_simpleHash(e){let t=0;for(let s=0;s<e.length;s++){t=(t<<5)-t+e.charCodeAt(s),t|=0}return Math.abs(t).toString(36)}_initDebug(){const e=document.createElement("div");e.className="animecursor-debug",e.style.cssText="\n position: fixed;\n top: 0;\n left: 0;\n background: rgba(0,0,0,0.7);\n color: #0f0;\n padding: 4px 8px;\n font-family: monospace;\n font-size: 12px;\n z-index: 2147483647;\n pointer-events: auto;\n white-space: nowrap;\n transition: opacity 0.2s ease;\n ",e.addEventListener("mouseenter",()=>{e.style.opacity="0.5"}),e.addEventListener("mouseleave",()=>{e.style.opacity="1"}),document.body.appendChild(e),this.debugEl=e;const t=document.createElement("div");t.className="animecursor-crosshair",t.style.cssText="\n position: fixed;\n top: 0;\n left: 0;\n width: 0;\n height: 0;\n pointer-events: none;\n z-index: 2147483646;\n ";const s=document.createElement("div");s.className="ac-crosshair-h",s.style.cssText="\n position: fixed;\n left: 0;\n width: 100%;\n height: 1px;\n background-color: rgba(255,0,0,0.6);\n pointer-events: none;\n transform: translateY(-0.5px);\n ";const r=document.createElement("div");r.className="ac-crosshair-v",r.style.cssText="\n position: fixed;\n top: 0;\n width: 1px;\n height: 100%;\n background-color: rgba(255,0,0,0.6);\n pointer-events: none;\n transform: translateX(-0.5px);\n ",t.appendChild(s),t.appendChild(r),document.body.appendChild(t),this.crosshairEl={container:t,hLine:s,vLine:r};let o="";this._onMouseMove=t=>{const s=t.clientX,r=t.clientY;this.crosshairEl&&(this.crosshairEl.hLine.style.top=r+"px",this.crosshairEl.vLine.style.left=s+"px");const n=document.elementFromPoint(s,r);let i=null;if(n)if(n.dataset.cursor&&this.cursors[n.dataset.cursor])i=n.dataset.cursor;else for(const[e,t]of Object.entries(this.cursors))if(t.tags&&t.tags.some(e=>n.matches(e))){i=e;break}i||this.defaultCursorName?!i&&this.defaultCursorName&&(i=this.defaultCursorName):i="native",i!==o?(o=i,e.textContent=`${i} @ (${s}, ${r})`):e.textContent=`${i} @ (${s}, ${r})`},document.addEventListener("mousemove",this._onMouseMove)}refresh(){this.disabled||(this.styleEl&&this.styleEl.remove(),this.combinedRules.clear(),this._injectStyles(),this.options.debug&&(this.debugEl&&this.debugEl.remove(),this.crosshairEl&&this.crosshairEl.container.remove(),this._initDebug()),console.log("[AnimeCursor] Refresh complete"))}destroy(){this.disabled||(this.styleEl&&this.styleEl.remove(),this.debugEl&&this.debugEl.remove(),this.crosshairEl&&this.crosshairEl.container.remove(),this._onMouseMove&&document.removeEventListener("mousemove",this._onMouseMove),document.body.classList.remove("animecursor-disabled"),e=null,console.log("[AnimeCursor] Destroyed"))}disable(){this.disabled||(this.styleEl&&(this.styleEl.remove(),this.styleEl=null),this.debugEl&&(this.debugEl.remove(),this.debugEl=null),this.crosshairEl&&(this.crosshairEl.container.remove(),this.crosshairEl=null),this._onMouseMove&&(document.removeEventListener("mousemove",this._onMouseMove),this._onMouseMove=null),this.disabled=!0,this.options.debug&&console.log("[AnimeCursor] Disabled"))}enable(){this.disabled&&(this.disabled=!1,this._injectStyles(),this.options.debug&&this._initDebug(),this.options.debug&&console.log("[AnimeCursor] Enabled"))}}});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anime-cursor",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
4
4
  "description": "A lightweight JavaScript library for animated custom cursors",
5
5
  "main": "dist/anime-cursor.umd.js",
6
6
  "module": "dist/anime-cursor.esm.js",