@whykusanagi/corrupted-theme 0.1.4 → 0.1.5
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/CHANGELOG.md +21 -7
- package/README.md +79 -15
- package/examples/advanced/nsfw-corruption.html +348 -0
- package/examples/basic/corrupted-text.html +254 -0
- package/examples/basic/typing-animation.html +344 -0
- package/examples/button.html +1 -1
- package/examples/card.html +1 -1
- package/examples/extensions-showcase.html +1 -1
- package/examples/form.html +1 -1
- package/examples/index.html +29 -3
- package/examples/layout.html +1 -1
- package/examples/nikke-team-builder.html +2 -2
- package/examples/showcase-complete.html +2 -2
- package/examples/showcase.html +2 -2
- package/package.json +1 -1
- package/src/core/corrupted-text.js +280 -0
- package/src/core/corruption-phrases.js +285 -0
- package/src/core/typing-animation.js +390 -0
package/examples/index.html
CHANGED
|
@@ -463,7 +463,7 @@
|
|
|
463
463
|
<a href="layout.html"><i class="fas fa-columns"></i> Layouts</a>
|
|
464
464
|
</div>
|
|
465
465
|
</li>
|
|
466
|
-
<li><a href="../
|
|
466
|
+
<li><a href="../showcase-complete.html"><i class="fas fa-book"></i> Docs</a></li>
|
|
467
467
|
</ul>
|
|
468
468
|
</div>
|
|
469
469
|
</nav>
|
|
@@ -557,7 +557,7 @@
|
|
|
557
557
|
<span class="badge badge-primary">New</span>
|
|
558
558
|
</h3>
|
|
559
559
|
<p>
|
|
560
|
-
Production-tested modules: Gallery system with lightbox, NSFW content blur,
|
|
560
|
+
Production-tested modules: Gallery system with lightbox, NSFW content blur,
|
|
561
561
|
social links, countdown widgets, and more.
|
|
562
562
|
</p>
|
|
563
563
|
<div class="card-footer">
|
|
@@ -565,6 +565,24 @@
|
|
|
565
565
|
</div>
|
|
566
566
|
</a>
|
|
567
567
|
|
|
568
|
+
<!-- Corruption Components -->
|
|
569
|
+
<a href="basic/corrupted-text.html" class="category-card">
|
|
570
|
+
<div class="category-icon">
|
|
571
|
+
<i class="fas fa-terminal"></i>
|
|
572
|
+
</div>
|
|
573
|
+
<h3>
|
|
574
|
+
Corruption Effects
|
|
575
|
+
<span class="badge badge-primary">v1.1</span>
|
|
576
|
+
</h3>
|
|
577
|
+
<p>
|
|
578
|
+
Character-level glitch and phrase buffer corruption animations.
|
|
579
|
+
SFW mode (default) with optional NSFW mode. Neural network decoding aesthetic.
|
|
580
|
+
</p>
|
|
581
|
+
<div class="card-footer">
|
|
582
|
+
View examples <i class="fas fa-arrow-right"></i>
|
|
583
|
+
</div>
|
|
584
|
+
</a>
|
|
585
|
+
|
|
568
586
|
<!-- Glass Components -->
|
|
569
587
|
<a href="showcase-complete.html#glass" class="category-card">
|
|
570
588
|
<div class="category-icon">
|
|
@@ -667,6 +685,14 @@
|
|
|
667
685
|
<i class="fas fa-users"></i>
|
|
668
686
|
<span>Team Builder</span>
|
|
669
687
|
</a>
|
|
688
|
+
<a href="basic/corrupted-text.html" class="quick-link">
|
|
689
|
+
<i class="fas fa-terminal"></i>
|
|
690
|
+
<span>Character Corruption</span>
|
|
691
|
+
</a>
|
|
692
|
+
<a href="basic/typing-animation.html" class="quick-link">
|
|
693
|
+
<i class="fas fa-keyboard"></i>
|
|
694
|
+
<span>Buffer Corruption</span>
|
|
695
|
+
</a>
|
|
670
696
|
</div>
|
|
671
697
|
</section>
|
|
672
698
|
|
|
@@ -717,7 +743,7 @@
|
|
|
717
743
|
<div class="footer-content">
|
|
718
744
|
<div class="footer-links">
|
|
719
745
|
<a href="../README.md"><i class="fas fa-book"></i> Documentation</a>
|
|
720
|
-
<a href="../
|
|
746
|
+
<a href="../showcase-complete.html"><i class="fas fa-list"></i> Component Reference</a>
|
|
721
747
|
<a href="https://github.com/whykusanagi/corrupted-theme" target="_blank"><i class="fab fa-github"></i> GitHub</a>
|
|
722
748
|
<a href="https://www.npmjs.com/package/@whykusanagi/corrupted-theme" target="_blank"><i class="fab fa-npm"></i> npm</a>
|
|
723
749
|
</div>
|
package/examples/layout.html
CHANGED
|
@@ -189,7 +189,7 @@
|
|
|
189
189
|
<a href="layout.html" class="active"><i class="fas fa-columns"></i> Layouts</a>
|
|
190
190
|
</div>
|
|
191
191
|
</li>
|
|
192
|
-
<li><a href="../
|
|
192
|
+
<li><a href="../showcase-complete.html"><i class="fas fa-book"></i> Docs</a></li>
|
|
193
193
|
</ul>
|
|
194
194
|
</div>
|
|
195
195
|
</nav>
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
<a href="layout.html"><i class="fas fa-columns"></i> Layouts</a>
|
|
197
197
|
</div>
|
|
198
198
|
</li>
|
|
199
|
-
<li><a href="../
|
|
199
|
+
<li><a href="../showcase-complete.html"><i class="fas fa-book"></i> Docs</a></li>
|
|
200
200
|
</ul>
|
|
201
201
|
</div>
|
|
202
202
|
</nav>
|
|
@@ -566,7 +566,7 @@
|
|
|
566
566
|
<p>Nikke Team Builder Example • Corrupted Theme v0.1.4</p>
|
|
567
567
|
<p style="font-size: 0.875rem; margin-top: var(--spacing-md);">
|
|
568
568
|
<a href="index.html" style="color: var(--accent); text-decoration: none;">← Back to Showcase</a> •
|
|
569
|
-
<a href="../
|
|
569
|
+
<a href="../showcase-complete.html#nikke" style="color: var(--accent); text-decoration: none;">Documentation</a>
|
|
570
570
|
</p>
|
|
571
571
|
</footer>
|
|
572
572
|
</div>
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
<a href="layout.html"><i class="fas fa-columns"></i> Layouts</a>
|
|
150
150
|
</div>
|
|
151
151
|
</li>
|
|
152
|
-
<li><a href="../
|
|
152
|
+
<li><a href="../showcase-complete.html"><i class="fas fa-book"></i> Docs</a></li>
|
|
153
153
|
</ul>
|
|
154
154
|
</div>
|
|
155
155
|
</nav>
|
|
@@ -1697,7 +1697,7 @@ const theme = {
|
|
|
1697
1697
|
<p><strong>Corrupted Theme</strong> v0.1.4 • Built with <i class="fas fa-heart" style="color: var(--accent);"></i> by whykusanagi</p>
|
|
1698
1698
|
<p style="font-size: 0.875rem; margin-top: var(--spacing-md);">
|
|
1699
1699
|
<a href="../README.md" class="link">Documentation</a> •
|
|
1700
|
-
<a href="
|
|
1700
|
+
<a href="#customization" class="link">Customization</a> •
|
|
1701
1701
|
<a href="https://github.com/whykusanagi/corrupted-theme" class="link">GitHub</a>
|
|
1702
1702
|
</p>
|
|
1703
1703
|
</footer>
|
package/examples/showcase.html
CHANGED
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
<a href="layout.html"><i class="fas fa-columns"></i> Layouts</a>
|
|
152
152
|
</div>
|
|
153
153
|
</li>
|
|
154
|
-
<li><a href="../
|
|
154
|
+
<li><a href="../showcase-complete.html"><i class="fas fa-book"></i> Docs</a></li>
|
|
155
155
|
</ul>
|
|
156
156
|
</div>
|
|
157
157
|
</nav>
|
|
@@ -465,7 +465,7 @@ const theme = {
|
|
|
465
465
|
<p><strong>Corrupted Theme</strong> v0.1.4 • Built with <i class="fas fa-heart" style="color: var(--accent);"></i> by whykusanagi</p>
|
|
466
466
|
<p style="font-size: 0.875rem; margin-top: var(--spacing-md);">
|
|
467
467
|
<a href="../README.md" class="link">Documentation</a> •
|
|
468
|
-
<a href="
|
|
468
|
+
<a href="#customization" class="link">Customization</a> •
|
|
469
469
|
<a href="https://github.com/whykusanagi/corrupted-theme" class="link">GitHub</a>
|
|
470
470
|
</p>
|
|
471
471
|
</footer>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@whykusanagi/corrupted-theme",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A dark, glassmorphic design system with pink/purple accents. Perfect for creating modern, visually striking web applications.",
|
|
6
6
|
"main": "src/css/theme.css",
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Corrupted Text Animation
|
|
3
|
+
*
|
|
4
|
+
* Cycles through Japanese (hiragana/katakana/kanji), romaji, and English text variants
|
|
5
|
+
* with character-level corruption effects. The text progressively corrupts from one
|
|
6
|
+
* variant to another, creating a glitchy Matrix-style transformation effect.
|
|
7
|
+
*
|
|
8
|
+
* @class CorruptedText
|
|
9
|
+
* @version 1.0.0
|
|
10
|
+
* @author whykusanagi
|
|
11
|
+
* @license MIT
|
|
12
|
+
*
|
|
13
|
+
* @example Basic Usage (Auto-initialization via data attributes)
|
|
14
|
+
* ```html
|
|
15
|
+
* <span class="corrupted-multilang"
|
|
16
|
+
* data-english="Hello World"
|
|
17
|
+
* data-romaji="konnichiwa"
|
|
18
|
+
* data-hiragana="こんにちは"
|
|
19
|
+
* data-katakana="コンニチハ"
|
|
20
|
+
* data-kanji="今日は">
|
|
21
|
+
* </span>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example Manual Initialization
|
|
25
|
+
* ```javascript
|
|
26
|
+
* const element = document.querySelector('.my-text');
|
|
27
|
+
* const corrupted = new CorruptedText(element, {
|
|
28
|
+
* duration: 3000,
|
|
29
|
+
* cycleDelay: 100,
|
|
30
|
+
* loop: true
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Control playback
|
|
34
|
+
* corrupted.start();
|
|
35
|
+
* corrupted.stop();
|
|
36
|
+
* corrupted.restart();
|
|
37
|
+
* corrupted.settle('Final Text');
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @see https://github.com/whykusanagi/corrupted-theme
|
|
41
|
+
* @see CORRUPTED_THEME_SPEC.md - Character-by-Character Decoding pattern
|
|
42
|
+
*/
|
|
43
|
+
class CorruptedText {
|
|
44
|
+
/**
|
|
45
|
+
* Creates a new CorruptedText animation instance
|
|
46
|
+
*
|
|
47
|
+
* @param {HTMLElement} element - The DOM element to animate
|
|
48
|
+
* @param {Object} [options={}] - Configuration options
|
|
49
|
+
* @param {number} [options.duration=3000] - Total animation duration in milliseconds
|
|
50
|
+
* @param {number} [options.cycleDelay=100] - Delay between character corruption steps (ms)
|
|
51
|
+
* @param {number} [options.startDelay=0] - Initial delay before animation starts (ms)
|
|
52
|
+
* @param {boolean} [options.loop=true] - Whether to loop through variants continuously
|
|
53
|
+
* @param {string|null} [options.finalText=null] - Text to settle on after cycle (if loop=false)
|
|
54
|
+
*/
|
|
55
|
+
constructor(element, options = {}) {
|
|
56
|
+
this.element = element;
|
|
57
|
+
this.options = {
|
|
58
|
+
duration: options.duration || 3000,
|
|
59
|
+
cycleDelay: options.cycleDelay || 100,
|
|
60
|
+
startDelay: options.startDelay || 0,
|
|
61
|
+
loop: options.loop !== false,
|
|
62
|
+
finalText: options.finalText || null,
|
|
63
|
+
...options
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Get text variants from data attributes
|
|
67
|
+
this.variants = {
|
|
68
|
+
english: this.element.dataset.english || this.element.textContent.trim(),
|
|
69
|
+
romaji: this.element.dataset.romaji || null,
|
|
70
|
+
hiragana: this.element.dataset.hiragana || null,
|
|
71
|
+
katakana: this.element.dataset.katakana || null,
|
|
72
|
+
kanji: this.element.dataset.kanji || null
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Filter out null variants and create array of available variants
|
|
76
|
+
this.availableVariants = Object.entries(this.variants)
|
|
77
|
+
.filter(([_, value]) => value !== null)
|
|
78
|
+
.map(([key, value]) => ({ type: key, text: value }));
|
|
79
|
+
|
|
80
|
+
if (this.availableVariants.length === 0) {
|
|
81
|
+
console.warn('CorruptedText: No text variants found for element', element);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this.currentVariantIndex = 0;
|
|
86
|
+
this.isAnimating = false;
|
|
87
|
+
this.animationFrame = null;
|
|
88
|
+
|
|
89
|
+
this.init();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Initialize the corruption animation
|
|
94
|
+
* @private
|
|
95
|
+
*/
|
|
96
|
+
init() {
|
|
97
|
+
// Add corrupted class for styling
|
|
98
|
+
if (!this.element.classList.contains('corrupted-multilang')) {
|
|
99
|
+
this.element.classList.add('corrupted-multilang');
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Store original text
|
|
103
|
+
this.originalText = this.element.textContent.trim();
|
|
104
|
+
|
|
105
|
+
// Start animation after configured delay
|
|
106
|
+
if (this.options.startDelay > 0) {
|
|
107
|
+
setTimeout(() => this.start(), this.options.startDelay);
|
|
108
|
+
} else {
|
|
109
|
+
this.start();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Start the corruption animation
|
|
115
|
+
* @public
|
|
116
|
+
*/
|
|
117
|
+
start() {
|
|
118
|
+
if (this.isAnimating) return;
|
|
119
|
+
this.isAnimating = true;
|
|
120
|
+
this.animate();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Stop the corruption animation
|
|
125
|
+
* @public
|
|
126
|
+
*/
|
|
127
|
+
stop() {
|
|
128
|
+
this.isAnimating = false;
|
|
129
|
+
if (this.animationFrame) {
|
|
130
|
+
cancelAnimationFrame(this.animationFrame);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Main animation loop - cycles through text variants
|
|
136
|
+
* @private
|
|
137
|
+
*/
|
|
138
|
+
animate() {
|
|
139
|
+
if (!this.isAnimating) return;
|
|
140
|
+
|
|
141
|
+
const variant = this.availableVariants[this.currentVariantIndex];
|
|
142
|
+
this.corruptToText(variant.text, () => {
|
|
143
|
+
// Move to next variant in cycle
|
|
144
|
+
this.currentVariantIndex = (this.currentVariantIndex + 1) % this.availableVariants.length;
|
|
145
|
+
|
|
146
|
+
// Check if animation should stop
|
|
147
|
+
if (!this.options.loop && this.currentVariantIndex === 0) {
|
|
148
|
+
// One full cycle complete - settle on final text
|
|
149
|
+
const finalText = this.options.finalText || this.variants.english;
|
|
150
|
+
this.corruptToText(finalText, () => {
|
|
151
|
+
this.isAnimating = false;
|
|
152
|
+
});
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Continue animation to next variant
|
|
157
|
+
setTimeout(() => {
|
|
158
|
+
if (this.isAnimating) {
|
|
159
|
+
this.animate();
|
|
160
|
+
}
|
|
161
|
+
}, this.options.duration / this.availableVariants.length);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Corrupt the current text to a target text with progressive reveal
|
|
167
|
+
*
|
|
168
|
+
* @param {string} targetText - The text to reveal through corruption
|
|
169
|
+
* @param {Function} callback - Called when corruption is complete
|
|
170
|
+
* @private
|
|
171
|
+
*/
|
|
172
|
+
corruptToText(targetText, callback) {
|
|
173
|
+
const currentText = this.element.textContent.trim();
|
|
174
|
+
const maxLength = Math.max(currentText.length, targetText.length);
|
|
175
|
+
const steps = 20; // Number of corruption animation steps
|
|
176
|
+
let step = 0;
|
|
177
|
+
|
|
178
|
+
// Character sets for corruption effect (from CORRUPTED_THEME_SPEC.md)
|
|
179
|
+
const katakana = 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン';
|
|
180
|
+
const hiragana = 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをん';
|
|
181
|
+
const romaji = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
|
182
|
+
const symbols = '0123456789!@#$%^&*()_+-=[]{}|;:,.<>?~`';
|
|
183
|
+
|
|
184
|
+
// Combined corruption character set
|
|
185
|
+
const allCorruptChars = katakana + hiragana + romaji + symbols;
|
|
186
|
+
|
|
187
|
+
const corrupt = () => {
|
|
188
|
+
if (step >= steps) {
|
|
189
|
+
// Animation complete - set final text
|
|
190
|
+
this.element.textContent = targetText;
|
|
191
|
+
if (callback) callback();
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Generate corrupted text with progressive reveal
|
|
196
|
+
let corrupted = '';
|
|
197
|
+
for (let i = 0; i < maxLength; i++) {
|
|
198
|
+
if (i < targetText.length && step > steps * 0.7) {
|
|
199
|
+
// Last 30% of animation - start revealing target text
|
|
200
|
+
const revealProgress = (step - steps * 0.7) / (steps * 0.3);
|
|
201
|
+
if (Math.random() < revealProgress) {
|
|
202
|
+
corrupted += targetText[i];
|
|
203
|
+
} else {
|
|
204
|
+
corrupted += allCorruptChars[Math.floor(Math.random() * allCorruptChars.length)];
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
// First 70% - full random corruption
|
|
208
|
+
corrupted += allCorruptChars[Math.floor(Math.random() * allCorruptChars.length)];
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
this.element.textContent = corrupted;
|
|
213
|
+
step++;
|
|
214
|
+
|
|
215
|
+
// Schedule next corruption step
|
|
216
|
+
this.animationFrame = requestAnimationFrame(() => {
|
|
217
|
+
setTimeout(corrupt, this.options.cycleDelay);
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
corrupt();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Restart the animation from the beginning
|
|
226
|
+
* @public
|
|
227
|
+
*/
|
|
228
|
+
restart() {
|
|
229
|
+
this.stop();
|
|
230
|
+
this.currentVariantIndex = 0;
|
|
231
|
+
this.start();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Stop animation and settle on a specific text
|
|
236
|
+
*
|
|
237
|
+
* @param {string} [finalText] - Text to settle on (defaults to english variant)
|
|
238
|
+
* @public
|
|
239
|
+
*/
|
|
240
|
+
settle(finalText) {
|
|
241
|
+
this.stop();
|
|
242
|
+
this.corruptToText(finalText || this.variants.english, () => {
|
|
243
|
+
this.isAnimating = false;
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Auto-initialize all elements with the 'corrupted-multilang' class
|
|
250
|
+
*
|
|
251
|
+
* This function is automatically called on DOM ready and can be called
|
|
252
|
+
* manually to initialize dynamically added elements.
|
|
253
|
+
*
|
|
254
|
+
* @public
|
|
255
|
+
*/
|
|
256
|
+
function initCorruptedText() {
|
|
257
|
+
document.querySelectorAll('.corrupted-multilang').forEach(element => {
|
|
258
|
+
if (!element.corruptedTextInstance) {
|
|
259
|
+
element.corruptedTextInstance = new CorruptedText(element);
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Auto-initialize on DOM ready
|
|
265
|
+
if (document.readyState === 'loading') {
|
|
266
|
+
document.addEventListener('DOMContentLoaded', initCorruptedText);
|
|
267
|
+
} else {
|
|
268
|
+
initCorruptedText();
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Export for both ES6 modules and CommonJS
|
|
272
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
273
|
+
module.exports = { CorruptedText, initCorruptedText };
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Export for ES6 modules
|
|
277
|
+
if (typeof exports !== 'undefined') {
|
|
278
|
+
exports.CorruptedText = CorruptedText;
|
|
279
|
+
exports.initCorruptedText = initCorruptedText;
|
|
280
|
+
}
|