@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.
@@ -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="../docs/COMPONENTS_REFERENCE.md"><i class="fas fa-book"></i> Docs</a></li>
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="../docs/COMPONENTS_REFERENCE.md"><i class="fas fa-list"></i> Component Reference</a>
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>
@@ -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="../docs/COMPONENTS_REFERENCE.md"><i class="fas fa-book"></i> Docs</a></li>
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="../docs/COMPONENTS_REFERENCE.md"><i class="fas fa-book"></i> Docs</a></li>
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="../docs/COMPONENTS_REFERENCE.md#nikke-components" style="color: var(--accent); text-decoration: none;">Documentation</a>
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="../docs/COMPONENTS_REFERENCE.md"><i class="fas fa-book"></i> Docs</a></li>
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="../docs/COMPONENTS_REFERENCE.md#customization" class="link">Customization</a> •
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>
@@ -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="../docs/COMPONENTS_REFERENCE.md"><i class="fas fa-book"></i> Docs</a></li>
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="../docs/COMPONENTS_REFERENCE.md#customization" class="link">Customization</a> •
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.4",
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
+ }