@mtph9/heehee.js 1.0.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/LICENSE.txt ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) [2026] [mtph9]
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # heehee.js
2
+
3
+ A lightweight JavaScript library that adds Michael Jackson's iconic "grunts" and sounds to your web elements when they are hovered over.
4
+
5
+ [**Demo / GitHub Pages**](https://merlin-1d.github.io/heehee.js/)
6
+
7
+ `heehee.js` provides a fun and simple way to add sound effects to your website. It listens for `mouseover` events on specified elements and plays one of the 31 available Michael Jackson grunts. By default, it targets elements with the class `.heehee` or the attribute `data-heehee`.
8
+
9
+ ## Features
10
+
11
+ - **31 unique sounds**: A wide variety of iconic Michael Jackson grunts.
12
+ - **Random or Specific sounds**: Hovering over a default element plays a random sound, but you can specify which sound to play using the `data-heehee` attribute (e.g., `data-heehee="5"` for grunt 6, as it's 0-indexed).
13
+ - **Simple implementation**: Import and call `initHeeHee()`.
14
+
15
+ ## Setup & Run
16
+
17
+ ### 1. Install
18
+ ```bash
19
+ npm install heehee.js
20
+ ```
21
+
22
+ ### 2. Usage
23
+ Add `heehee` class or `data-heehee` attribute to your HTML elements:
24
+
25
+ ```html
26
+ <div class="heehee">Hover over me!</div>
27
+ <div data-heehee="7">Play specific sound (grunt-7.mp3)</div>
28
+ ```
29
+
30
+ Initialize in your JS:
31
+ ```javascript
32
+ import { initHeeHee } from '@mtph9/heehee.js';
33
+ initHeeHee();
34
+ ```
35
+
36
+ ## Configuration Options
37
+
38
+ You can pass an options object to `initHeeHee()`:
39
+
40
+ - `selector`: (String) CSS selector for elements (default: `.heehee, [data-heehee]`)
41
+ - `basePath`: (String) Custom path to the grunts directory (must end with `/`)
42
+ - `showUnlockButton`: (Boolean) Whether to show the "unlock sound" button if audio playback is blocked by the browser (default: `true`)
43
+
44
+ Example:
45
+ ```javascript
46
+ initHeeHee({
47
+ selector: '.my-custom-class',
48
+ basePath: 'https://unpkg.com/heehee.js/grunts/'
49
+ });
50
+ ```
51
+
52
+ ## License
53
+
54
+ This project is licensed under the **ISC License**. See the `LICENSE.txt` file for more details.
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/heehee.css ADDED
@@ -0,0 +1,44 @@
1
+ @keyframes heehee-scroll-in {
2
+ 0% { transform: translateY(100px) scale(0); opacity: 0; }
3
+ 60% { transform: translateY(-10px) scale(1.1); opacity: 1; }
4
+ 100% { transform: translateY(0) scale(1); opacity: 1; }
5
+ }
6
+
7
+ @keyframes heehee-shake {
8
+ 0%, 100% { transform: scale(1) rotate(0); }
9
+ 10%, 30%, 50%, 70%, 90% { transform: scale(1.1) rotate(-5deg); }
10
+ 20%, 40%, 60%, 80% { transform: scale(1.1) rotate(5deg); }
11
+ }
12
+
13
+ .heehee-unlock-icon {
14
+ position: fixed;
15
+ bottom: 20px;
16
+ right: 20px;
17
+ width: 48px;
18
+ height: 48px;
19
+ background-color: #ff0055;
20
+ color: white;
21
+ border-radius: 50%;
22
+ display: flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ cursor: pointer;
26
+ box-shadow: 0 4px 12px rgba(0,0,0,0.3);
27
+ z-index: 9999;
28
+ transition: transform 0.2s, background-color 0.2s;
29
+ animation: heehee-scroll-in 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards,
30
+ heehee-shake 2s ease-in-out infinite 2s;
31
+ }
32
+
33
+ .heehee-unlock-icon:hover {
34
+ animation-play-state: paused;
35
+ transform: scale(1.2) !important;
36
+ }
37
+
38
+ @media (prefers-reduced-motion: reduce) {
39
+ .heehee-unlock-icon {
40
+ animation: none !important;
41
+ opacity: 1;
42
+ transform: none;
43
+ }
44
+ }
package/heehee.js ADDED
@@ -0,0 +1,83 @@
1
+ let soundsBasePath = new URL('./grunts/', import.meta.url).href;
2
+ let unlockIcon = null;
3
+ let showUnlockButtonEnabled = true;
4
+
5
+ const sounds = Array.from({ length: 31 }, (_, i) => `grunt-${i + 1}.mp3`);
6
+
7
+ function showUnlockIcon() {
8
+ if (unlockIcon) return;
9
+
10
+ unlockIcon = document.createElement('div');
11
+ unlockIcon.className = 'heehee-unlock-icon';
12
+ unlockIcon.innerHTML = `
13
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
14
+ <path d="M11 5L6 9H2v6h4l5 4V5z"></path>
15
+ <line x1="23" y1="9" x2="17" y2="15"></line>
16
+ <line x1="17" y1="9" x2="23" y2="15"></line>
17
+ </svg>
18
+ `;
19
+
20
+ unlockIcon.addEventListener('click', () => {
21
+ const audio = new Audio(new URL(`./grunts/${sounds[0]}`, import.meta.url).href);
22
+ audio.play().then(() => {
23
+ unlockIcon.remove();
24
+ unlockIcon = null;
25
+ }).catch(err => {
26
+ console.debug('HeeHee: Still blocked.', err);
27
+ });
28
+ });
29
+
30
+ document.body.appendChild(unlockIcon);
31
+ }
32
+
33
+ function playSound(index, options = {}) {
34
+ const parsedIndex = parseInt(index);
35
+ const soundIndex = (!isNaN(parsedIndex) && parsedIndex >= 1 && parsedIndex <= sounds.length)
36
+ ? parsedIndex - 1
37
+ : Math.floor(Math.random() * sounds.length);
38
+
39
+ const audioUrl = options.basePath
40
+ ? new URL(sounds[soundIndex], soundsBasePath).href
41
+ : new URL(`./grunts/${sounds[soundIndex]}`, import.meta.url).href;
42
+
43
+ new Audio(audioUrl).play().then(() => {
44
+ if (unlockIcon) {
45
+ unlockIcon.remove();
46
+ unlockIcon = null;
47
+ }
48
+ }).catch(err => {
49
+ if (err.name === 'NotAllowedError' && showUnlockButtonEnabled) {
50
+ showUnlockIcon();
51
+ }
52
+ console.debug('HeeHee: Audio playback failed.', err);
53
+ });
54
+ }
55
+
56
+ export function initHeeHee(options = {}) {
57
+ const selector = typeof options === 'string' ? options : (options.selector || '.heehee, [data-heehee]');
58
+
59
+ if (options.basePath) {
60
+ soundsBasePath = options.basePath.endsWith('/') ? options.basePath : options.basePath + '/';
61
+ }
62
+
63
+ if (options.showUnlockButton !== undefined) {
64
+ showUnlockButtonEnabled = !!options.showUnlockButton;
65
+ }
66
+
67
+ document.addEventListener('mouseover', (event) => {
68
+ const target = event.target.closest(selector);
69
+
70
+ if (target && !target.dataset.heeheeActive) {
71
+ target.dataset.heeheeActive = 'true';
72
+
73
+ const soundAttr = target.getAttribute('data-heehee');
74
+ playSound(soundAttr, options);
75
+
76
+ const onMouseLeave = () => {
77
+ delete target.dataset.heeheeActive;
78
+ target.removeEventListener('mouseleave', onMouseLeave);
79
+ };
80
+ target.addEventListener('mouseleave', onMouseLeave);
81
+ }
82
+ });
83
+ }
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@mtph9/heehee.js",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "heehee.js",
6
+ "repository": "https://github.com/mtph9/heehee.js",
7
+ "files": [
8
+ "heehee.js",
9
+ "heehee.css",
10
+ "grunts/"
11
+ ],
12
+ "exports": {
13
+ ".": "./heehee.js",
14
+ "./heehee.css": "./heehee.css",
15
+ "./grunts/*": "./grunts/*"
16
+ },
17
+ "keywords": [],
18
+ "author": "mtph9 <mtph9.dev@gmail.com>",
19
+ "license": "ISC",
20
+ "type": "module"
21
+ }