easter-egg-quest 1.0.1 โ†’ 1.0.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
@@ -1,23 +1,26 @@
1
1
  # ๐Ÿฅš Easter Egg Quest
2
2
 
3
- Drop a hidden Easter-themed mini-game onto **any website** with a single line of code. Users discover a secret entry point on your page and solve three poetic riddles โ€” *Stillness*, *Motion*, *Rhythm* โ€” to collect three symbolic eggs.
3
+ Something is hiding on your website. Your visitors don't know it yet.
4
4
 
5
- **Zero configuration required.** The game overlays your page without breaking layout. Fully self-contained โ€” Three.js 3D rendering is built in.
5
+ One line of code โ€” and your page holds a secret. A poetic journey disguised as ordinary text. Three riddles. Three eggs. One question: *will they notice?*
6
6
 
7
- ## Quick Start
7
+ No buttons. No banners. No hints. Just a quiet invitation woven into the fabric of your page.
8
8
 
9
- ### CDN (simplest)
9
+ Those who find it will never look at your website the same way again.
10
+
11
+ ---
12
+
13
+ ## Installation
14
+
15
+ ### One line (CDN)
10
16
 
11
17
  ```html
12
- <script src="https://unpkg.com/easter-egg-quest"></script>
13
- <script>
14
- EasterEggQuest.init();
15
- </script>
18
+ <script src="https://unpkg.com/easter-egg-quest/dist/easter-egg-quest.umd.js"></script>
16
19
  ```
17
20
 
18
- That's it. The game hides itself inside your page content and waits to be discovered.
21
+ Nothing else needed. The script activates itself after your page loads.
19
22
 
20
- ### npm
23
+ ### npm / yarn
21
24
 
22
25
  ```bash
23
26
  npm install easter-egg-quest
@@ -29,59 +32,50 @@ import { EasterEggQuest } from 'easter-egg-quest';
29
32
  EasterEggQuest.init();
30
33
  ```
31
34
 
32
- ## How It Works
35
+ ---
36
+
37
+ ## What happens next?
38
+
39
+ That's for your visitors to discover.
40
+
41
+ We'll only say this: the experience has three chapters, each asking something different. Something about stillness. Something about motion. Something about the space between.
33
42
 
34
- 1. **Hidden entry** โ€” the game injects a subtle "start hunt" trigger into existing text on your page
35
- 2. **Stage 1: Stillness** โ€” stop moving. The egg comes to those who wait
36
- 3. **Stage 2: Motion** โ€” keep moving. Be the river
37
- 4. **Stage 3: Rhythm** โ€” find the pulse. Breathe
38
- 5. **Finale** โ€” all three eggs appear in a 3D carousel with a "Happy Easter!" greeting
39
- 6. **Results** โ€” a personalized profile card based on your behavior (shareable as image)
43
+ The whole thing takes a few minutes. At the end, each person gets a unique result โ€” a portrait of how they moved through the unknown.
40
44
 
41
- The user clicks "finish" to close โ€” the game removes all traces of itself from the DOM.
45
+ ---
42
46
 
43
47
  ## Configuration
44
48
 
45
- All options are optional:
49
+ Everything works out of the box. But if you want control:
46
50
 
47
51
  ```js
48
52
  EasterEggQuest.init({
49
- // Lifecycle callbacks
50
53
  callbacks: {
51
- onInit: () => {},
52
- onEntryFound: () => {},
53
- onStageStart: (stage) => {},
54
- onEggFound: (eggIndex) => {},
55
- onComplete: (score) => {},
56
- onDestroy: () => {},
54
+ onComplete: (score) => {
55
+ // The visitor finished the quest
56
+ },
57
57
  },
58
58
 
59
- // Stage durations
60
59
  stageDurations: {
61
60
  stillnessMs: 20000,
62
61
  motionMs: 20000,
63
62
  rhythmCycles: 6,
64
63
  },
65
64
 
66
- // Rendering: 'auto' | '3d' | '2d'
67
- renderer: 'auto',
65
+ renderer: 'auto', // 'auto' | '3d' | '2d'
68
66
 
69
- // Accessibility
70
67
  accessibility: {
71
- reducedMotion: 'auto', // follows prefers-reduced-motion
72
- disableHiddenEntry: false, // shows a visible button instead
68
+ reducedMotion: 'auto',
69
+ disableHiddenEntry: false,
73
70
  },
74
71
 
75
- // Hidden entry targeting
76
72
  hiddenEntry: {
77
- selector: undefined, // CSS selector to limit entry candidates
78
- excludeSelectors: [], // selectors to exclude
73
+ selector: undefined,
74
+ excludeSelectors: [],
79
75
  },
80
76
 
81
- // Custom narrative text
82
77
  narrative: {
83
- // Override any dialogue array:
84
- // stage1Intro: ['your', 'custom', 'lines'],
78
+ // Your own words for any chapter
85
79
  },
86
80
  });
87
81
  ```
@@ -89,26 +83,26 @@ EasterEggQuest.init({
89
83
  ## API
90
84
 
91
85
  ```js
92
- EasterEggQuest.init(config?) // Start the game
93
- EasterEggQuest.pause() // Pause
94
- EasterEggQuest.resume() // Resume
95
- EasterEggQuest.destroy() // Remove everything, restore DOM
86
+ EasterEggQuest.init(config?) // Awaken the quest
87
+ EasterEggQuest.pause() // Freeze time
88
+ EasterEggQuest.resume() // Let it breathe again
89
+ EasterEggQuest.destroy() // Erase all traces
96
90
  ```
97
91
 
98
- ## Safety
92
+ ---
99
93
 
100
- Designed to be safe on production websites:
94
+ ## Safe by design
101
95
 
102
- - **No layout shifts** โ€” all UI is `position: fixed` overlay
103
- - **Shadow DOM isolation** โ€” CSS never collides with your styles
104
- - **Smart element filtering** โ€” hidden entry avoids Buy, Delete, Checkout, Submit buttons
105
- - **Clean destroy** โ€” removes all DOM elements, listeners, and WebGL resources
96
+ - Your layout stays untouched โ€” everything floats above
97
+ - Styles are sealed in Shadow DOM โ€” no collisions
98
+ - Dangerous buttons (Buy, Delete, Submit) are never used as entry points
99
+ - `destroy()` leaves your page exactly as it was
106
100
 
107
- ## Browser Support
101
+ ## Compatibility
108
102
 
109
- Chrome/Edge 90+ ยท Firefox 90+ ยท Safari 15+ ยท Mobile browsers
103
+ Chrome ยท Edge ยท Firefox ยท Safari ยท Mobile
110
104
 
111
- Falls back to CSS 2D rendering if WebGL is unavailable.
105
+ Falls back gracefully without WebGL.
112
106
 
113
107
  ## License
114
108
 
@@ -729,8 +729,8 @@ class HiddenEntry {
729
729
  this._injectShimmerStyles();
730
730
  this._createHintContainer();
731
731
  const hints = this.script.hiddenEntryHints;
732
- const FIRST_HINT_DELAY = 5e3;
733
- const HINT_INTERVAL = 3e3;
732
+ const FIRST_HINT_DELAY = 3e5;
733
+ const HINT_INTERVAL = 6e4;
734
734
  for (let i = 0; i < hints.length; i++) {
735
735
  const delay = FIRST_HINT_DELAY + i * HINT_INTERVAL;
736
736
  const timer = setTimeout(() => {
@@ -739,7 +739,7 @@ class HiddenEntry {
739
739
  }, delay);
740
740
  this.hintTimers.push(timer);
741
741
  }
742
- const shimmerDelay = 12e3;
742
+ const shimmerDelay = 42e4;
743
743
  const shimmerTimer = setTimeout(() => {
744
744
  if (this._destroyed || !this.targetElement) return;
745
745
  this.targetElement.classList.add("eeq-entry-target");
@@ -950,10 +950,10 @@ class NarrativeRenderer {
950
950
  this.currentLine = line;
951
951
  this.clearTimer = setTimeout(() => {
952
952
  this.clear();
953
- }, 5e3);
953
+ }, 12e3);
954
954
  }
955
955
  /** Show a sequence of lines with pauses. */
956
- async showSequence(lines, pauseMs = 1500) {
956
+ async showSequence(lines, pauseMs = 4500) {
957
957
  for (const line of lines) {
958
958
  this.showLine(line);
959
959
  await new Promise((r) => setTimeout(r, pauseMs));
@@ -3980,7 +3980,7 @@ class StillnessStage {
3980
3980
  const introLines = this.script.stage1Intro;
3981
3981
  for (let i = 0; i < introLines.length; i++) {
3982
3982
  this.bus.emit("narrative:show", introLines[i]);
3983
- await this._wait(1500);
3983
+ await this._wait(4500);
3984
3984
  }
3985
3985
  this.bus.emit("narrative:clear");
3986
3986
  await this._wait(1e3);
@@ -4020,7 +4020,7 @@ class StillnessStage {
4020
4020
  _handleBreak() {
4021
4021
  this._breaks++;
4022
4022
  const now = Date.now();
4023
- if (now - this._lastBreakNarrativeTime > 5e3) {
4023
+ if (now - this._lastBreakNarrativeTime > 6e4) {
4024
4024
  this._lastBreakNarrativeTime = now;
4025
4025
  const reactions = this.script.stage1Reactions;
4026
4026
  const line = reactions[this._narrativeIndex % reactions.length];
@@ -4060,7 +4060,7 @@ class MotionStage {
4060
4060
  const introLines = this.script.stage2Intro;
4061
4061
  for (let i = 0; i < introLines.length; i++) {
4062
4062
  this.bus.emit("narrative:show", introLines[i]);
4063
- await this._wait(1500);
4063
+ await this._wait(4500);
4064
4064
  }
4065
4065
  this.bus.emit("narrative:clear");
4066
4066
  await this._wait(1e3);
@@ -4115,7 +4115,7 @@ class MotionStage {
4115
4115
  // โ”€โ”€โ”€ Internal โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
4116
4116
  _handleFade() {
4117
4117
  const now = Date.now();
4118
- if (now - this._lastFadeNarrativeTime > 5e3) {
4118
+ if (now - this._lastFadeNarrativeTime > 6e4) {
4119
4119
  this._lastFadeNarrativeTime = now;
4120
4120
  const reactions = this.script.stage2Reactions;
4121
4121
  const line = reactions[this._narrativeIndex % reactions.length];
@@ -4159,7 +4159,7 @@ class RhythmStage {
4159
4159
  const introLines = this.script.stage3Intro;
4160
4160
  for (let i = 0; i < introLines.length; i++) {
4161
4161
  this.bus.emit("narrative:show", introLines[i]);
4162
- await this._wait(1500);
4162
+ await this._wait(4500);
4163
4163
  }
4164
4164
  this.bus.emit("narrative:clear");
4165
4165
  await this._wait(1e3);
@@ -4219,7 +4219,7 @@ class RhythmStage {
4219
4219
  }
4220
4220
  _showReaction() {
4221
4221
  const now = Date.now();
4222
- if (now - this._lastNarrativeTime > 5e3) {
4222
+ if (now - this._lastNarrativeTime > 6e4) {
4223
4223
  this._lastNarrativeTime = now;
4224
4224
  const reactions = this.script.stage3Reactions;
4225
4225
  const line = reactions[this._narrativeIndex % reactions.length];
@@ -4683,7 +4683,7 @@ class GameController {
4683
4683
  this.hiddenEntry = null;
4684
4684
  this._startAnticipationTremor();
4685
4685
  (_b2 = this.shrine) == null ? void 0 : _b2.show();
4686
- await ((_c = this.narrative) == null ? void 0 : _c.showSequence(this.script.entryConfirmation, 1500));
4686
+ await ((_c = this.narrative) == null ? void 0 : _c.showSequence(this.script.entryConfirmation, 4200));
4687
4687
  (_d = this.narrative) == null ? void 0 : _d.clear();
4688
4688
  this._stopAnticipationTremor();
4689
4689
  await this._wait(800);
@@ -4799,7 +4799,7 @@ class GameController {
4799
4799
  (_b2 = (_a2 = this.config.callbacks).onStageComplete) == null ? void 0 : _b2.call(_a2, this.fsm.state, result);
4800
4800
  }
4801
4801
  const successLines = eggIndex === 0 ? this.script.stage1Success : eggIndex === 1 ? this.script.stage2Success : this.script.stage3Success;
4802
- await ((_c = this.narrative) == null ? void 0 : _c.showSequence(successLines, 1500));
4802
+ await ((_c = this.narrative) == null ? void 0 : _c.showSequence(successLines, 4500));
4803
4803
  (_d = this.narrative) == null ? void 0 : _d.clear();
4804
4804
  await this._wait(800);
4805
4805
  if (this.threeRenderer) {
@@ -4880,7 +4880,7 @@ class GameController {
4880
4880
  (_c = this.shrine) == null ? void 0 : _c.hideAll();
4881
4881
  await this._wait(1e3);
4882
4882
  (_d = this.eggRenderer) == null ? void 0 : _d.startFinale();
4883
- await ((_e = this.narrative) == null ? void 0 : _e.showSequence(this.script.finale, 1500));
4883
+ await ((_e = this.narrative) == null ? void 0 : _e.showSequence(this.script.finale, 5e3));
4884
4884
  (_f = this.narrative) == null ? void 0 : _f.clear();
4885
4885
  await this._wait(4e3);
4886
4886
  this.fsm.transitionTo("results");