@jjlmoya/utils-creative 1.2.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.
Files changed (71) hide show
  1. package/package.json +64 -0
  2. package/src/category/i18n/en.ts +9 -0
  3. package/src/category/i18n/es.ts +9 -0
  4. package/src/category/i18n/fr.ts +9 -0
  5. package/src/category/index.ts +34 -0
  6. package/src/category/seo.astro +15 -0
  7. package/src/components/PreviewNavSidebar.astro +116 -0
  8. package/src/components/PreviewToolbar.astro +143 -0
  9. package/src/data.ts +6 -0
  10. package/src/env.d.ts +5 -0
  11. package/src/index.ts +27 -0
  12. package/src/layouts/PreviewLayout.astro +117 -0
  13. package/src/pages/[locale]/[slug].astro +146 -0
  14. package/src/pages/[locale].astro +251 -0
  15. package/src/pages/index.astro +4 -0
  16. package/src/tests/faq_count.test.ts +19 -0
  17. package/src/tests/locale_completeness.test.ts +42 -0
  18. package/src/tests/mocks/astro_mock.js +2 -0
  19. package/src/tests/no_h1_in_components.test.ts +48 -0
  20. package/src/tests/seo_length.test.ts +22 -0
  21. package/src/tests/tool_validation.test.ts +17 -0
  22. package/src/tool/bead-pattern-generator/bibliography.astro +18 -0
  23. package/src/tool/bead-pattern-generator/component.astro +372 -0
  24. package/src/tool/bead-pattern-generator/i18n/en.ts +61 -0
  25. package/src/tool/bead-pattern-generator/i18n/es.ts +68 -0
  26. package/src/tool/bead-pattern-generator/i18n/fr.ts +61 -0
  27. package/src/tool/bead-pattern-generator/index.ts +37 -0
  28. package/src/tool/bead-pattern-generator/seo.astro +14 -0
  29. package/src/tool/bead-pattern-generator/style.css +511 -0
  30. package/src/tool/dice-roller/bibliography.astro +17 -0
  31. package/src/tool/dice-roller/component.astro +230 -0
  32. package/src/tool/dice-roller/i18n/en.ts +87 -0
  33. package/src/tool/dice-roller/i18n/es.ts +89 -0
  34. package/src/tool/dice-roller/i18n/fr.ts +87 -0
  35. package/src/tool/dice-roller/index.ts +37 -0
  36. package/src/tool/dice-roller/seo.astro +14 -0
  37. package/src/tool/dice-roller/style.css +482 -0
  38. package/src/tool/excuse-generator/bibliography.astro +18 -0
  39. package/src/tool/excuse-generator/component.astro +140 -0
  40. package/src/tool/excuse-generator/i18n/en.ts +80 -0
  41. package/src/tool/excuse-generator/i18n/es.ts +84 -0
  42. package/src/tool/excuse-generator/i18n/fr.ts +80 -0
  43. package/src/tool/excuse-generator/index.ts +42 -0
  44. package/src/tool/excuse-generator/seo.astro +14 -0
  45. package/src/tool/excuse-generator/style.css +316 -0
  46. package/src/tool/fortune-cookie/bibliography.astro +18 -0
  47. package/src/tool/fortune-cookie/component.astro +299 -0
  48. package/src/tool/fortune-cookie/i18n/en.ts +85 -0
  49. package/src/tool/fortune-cookie/i18n/es.ts +90 -0
  50. package/src/tool/fortune-cookie/i18n/fr.ts +85 -0
  51. package/src/tool/fortune-cookie/index.ts +40 -0
  52. package/src/tool/fortune-cookie/seo.astro +14 -0
  53. package/src/tool/fortune-cookie/style.css +332 -0
  54. package/src/tool/synesthesia-painter/bibliography.astro +17 -0
  55. package/src/tool/synesthesia-painter/component.astro +110 -0
  56. package/src/tool/synesthesia-painter/i18n/en.ts +80 -0
  57. package/src/tool/synesthesia-painter/i18n/es.ts +82 -0
  58. package/src/tool/synesthesia-painter/i18n/fr.ts +80 -0
  59. package/src/tool/synesthesia-painter/index.ts +39 -0
  60. package/src/tool/synesthesia-painter/seo.astro +14 -0
  61. package/src/tool/synesthesia-painter/style.css +234 -0
  62. package/src/tool/zalgo-generator/bibliography.astro +18 -0
  63. package/src/tool/zalgo-generator/component.astro +195 -0
  64. package/src/tool/zalgo-generator/i18n/en.ts +60 -0
  65. package/src/tool/zalgo-generator/i18n/es.ts +67 -0
  66. package/src/tool/zalgo-generator/i18n/fr.ts +60 -0
  67. package/src/tool/zalgo-generator/index.ts +38 -0
  68. package/src/tool/zalgo-generator/seo.astro +14 -0
  69. package/src/tool/zalgo-generator/style.css +558 -0
  70. package/src/tools.ts +4 -0
  71. package/src/types.ts +72 -0
@@ -0,0 +1,511 @@
1
+ /* ── Bead Pattern Generator ─────────────────────────────── */
2
+ .bead-wrapper {
3
+ width: 100%;
4
+ max-width: 72rem;
5
+ margin: 0 auto;
6
+ padding: 1rem 2rem;
7
+ }
8
+
9
+ .bead-hidden {
10
+ display: none;
11
+ }
12
+
13
+ .bead-card {
14
+ position: relative;
15
+ background: rgba(255,255,255,0.85);
16
+ backdrop-filter: blur(16px);
17
+ border-radius: 1.5rem;
18
+ box-shadow: 0 25px 50px -12px rgba(0,0,0,0.15);
19
+ overflow: hidden;
20
+ border: 1px solid rgba(255,255,255,0.2);
21
+ }
22
+ .theme-dark .bead-card {
23
+ background: rgba(17,24,39,0.85);
24
+ border-color: rgba(55,65,81,0.3);
25
+ }
26
+
27
+ .bead-top-bar {
28
+ position: absolute;
29
+ top: 0;
30
+ left: 0;
31
+ width: 100%;
32
+ height: 0.5rem;
33
+ background: linear-gradient(to right, #ec4899, #a855f7, #6366f1);
34
+ }
35
+
36
+ .bead-inner {
37
+ padding: 2.5rem;
38
+ display: flex;
39
+ flex-direction: column;
40
+ gap: 2rem;
41
+ }
42
+
43
+ /* Header */
44
+ .bead-header {
45
+ display: flex;
46
+ flex-wrap: wrap;
47
+ gap: 1.5rem;
48
+ justify-content: space-between;
49
+ align-items: flex-end;
50
+ }
51
+ .bead-header-title h2 {
52
+ font-size: 1.5rem;
53
+ font-weight: 700;
54
+ color: #1f2937;
55
+ margin: 0;
56
+ }
57
+
58
+ .theme-dark .bead-header-title h2 {
59
+ color: #fff;
60
+ }
61
+
62
+ .bead-header-title p {
63
+ font-size: 0.875rem;
64
+ color: #6b7280;
65
+ margin: 0.25rem 0 0;
66
+ }
67
+
68
+ .theme-dark .bead-header-title p {
69
+ color: #9ca3af;
70
+ }
71
+
72
+ .bead-controls {
73
+ display: flex;
74
+ flex-wrap: wrap;
75
+ gap: 1rem;
76
+ align-items: flex-end;
77
+ }
78
+
79
+ .bead-control-group {
80
+ display: flex;
81
+ flex-direction: column;
82
+ gap: 0.25rem;
83
+ min-width: 9rem;
84
+ }
85
+
86
+ .bead-control-label {
87
+ font-size: 0.7rem;
88
+ font-weight: 700;
89
+ text-transform: uppercase;
90
+ color: #6b7280;
91
+ }
92
+
93
+ .bead-slider-row {
94
+ display: flex;
95
+ align-items: center;
96
+ gap: 0.5rem;
97
+ background: #f3f4f6;
98
+ padding: 0.5rem;
99
+ border-radius: 0.5rem;
100
+ border: 1px solid #e5e7eb;
101
+ }
102
+
103
+ .theme-dark .bead-slider-row {
104
+ background: #1f2937;
105
+ border-color: #374151;
106
+ }
107
+
108
+ .bead-slider {
109
+ flex: 1;
110
+ height: 0.5rem;
111
+ border-radius: 0.5rem;
112
+ appearance: none;
113
+ cursor: pointer;
114
+ background: #d1d5db;
115
+ }
116
+
117
+ .theme-dark .bead-slider {
118
+ background: #4b5563;
119
+ }
120
+
121
+ .bead-slider-pink {
122
+ accent-color: #ec4899;
123
+ }
124
+
125
+ .bead-slider-purple {
126
+ accent-color: #a855f7;
127
+ }
128
+
129
+ .bead-slider-val {
130
+ font-size: 0.875rem;
131
+ font-weight: 700;
132
+ width: 2rem;
133
+ text-align: center;
134
+ }
135
+ .bead-val-pink {
136
+ color: #ec4899;
137
+ }
138
+
139
+ .bead-val-purple {
140
+ color: #a855f7;
141
+ }
142
+
143
+ .bead-options-row {
144
+ display: flex;
145
+ align-items: center;
146
+ gap: 1rem;
147
+ height: 2.625rem;
148
+ background: #f3f4f6;
149
+ padding: 0.5rem 0.75rem;
150
+ border-radius: 0.5rem;
151
+ border: 1px solid #e5e7eb;
152
+ }
153
+
154
+ .theme-dark .bead-options-row {
155
+ background: #1f2937;
156
+ border-color: #374151;
157
+ }
158
+
159
+ .bead-checkbox-label {
160
+ display: flex;
161
+ align-items: center;
162
+ gap: 0.5rem;
163
+ cursor: pointer;
164
+ font-size: 0.875rem;
165
+ font-weight: 700;
166
+ color: #374151;
167
+ white-space: nowrap;
168
+ }
169
+
170
+ .theme-dark .bead-checkbox-label {
171
+ color: #d1d5db;
172
+ }
173
+
174
+ .bead-checkbox {
175
+ width: 1rem;
176
+ height: 1rem;
177
+ accent-color: #ec4899;
178
+ cursor: pointer;
179
+ }
180
+
181
+ .bead-divider {
182
+ width: 1px;
183
+ height: 100%;
184
+ background: #d1d5db;
185
+ }
186
+
187
+ .theme-dark .bead-divider {
188
+ background: #4b5563;
189
+ }
190
+
191
+ .bead-download-btn {
192
+ display: flex;
193
+ align-items: center;
194
+ gap: 0.5rem;
195
+ padding: 0.75rem 1.5rem;
196
+ background: #4f46e5;
197
+ color: #fff;
198
+ border: none;
199
+ border-radius: 0.75rem;
200
+ font-weight: 700;
201
+ cursor: pointer;
202
+ box-shadow: 0 4px 14px rgba(79,70,229,0.3);
203
+ transition: background 0.2s, box-shadow 0.2s;
204
+ white-space: nowrap;
205
+ }
206
+
207
+ .bead-download-btn:hover {
208
+ background: #4338ca;
209
+ }
210
+
211
+ .bead-download-btn:disabled {
212
+ opacity: 0.5;
213
+ box-shadow: none;
214
+ cursor: not-allowed;
215
+ }
216
+
217
+ /* Drop zone */
218
+ .bead-canvas-area {
219
+ position: relative;
220
+ min-height: 25rem;
221
+ display: flex;
222
+ flex-direction: column;
223
+ }
224
+
225
+ .bead-drop-zone {
226
+ position: relative;
227
+ display: flex;
228
+ flex-direction: column;
229
+ align-items: center;
230
+ justify-content: center;
231
+ border: 3px dashed #d1d5db;
232
+ border-radius: 1rem;
233
+ min-height: 25rem;
234
+ background: rgba(255,255,255,0.5);
235
+ backdrop-filter: blur(4px);
236
+ transition: border-color 0.2s, background 0.2s, transform 0.2s;
237
+ cursor: pointer;
238
+ }
239
+ .theme-dark .bead-drop-zone {
240
+ border-color: #374151;
241
+ background: rgba(31,41,55,0.5);
242
+ }
243
+
244
+ .bead-drop-zone:hover,
245
+ .bead-drop-active {
246
+ border-color: #ec4899;
247
+ background: rgba(236,72,153,0.04);
248
+ transform: scale(1.01);
249
+ }
250
+
251
+ .bead-file-input {
252
+ position: absolute;
253
+ inset: 0;
254
+ width: 100%;
255
+ height: 100%;
256
+ opacity: 0;
257
+ cursor: pointer;
258
+ z-index: 1;
259
+ }
260
+
261
+ .bead-drop-content {
262
+ text-align: center;
263
+ display: flex;
264
+ flex-direction: column;
265
+ align-items: center;
266
+ gap: 1rem;
267
+ pointer-events: none;
268
+ }
269
+
270
+ .bead-upload-icon {
271
+ display: flex;
272
+ align-items: center;
273
+ justify-content: center;
274
+ width: 5rem;
275
+ height: 5rem;
276
+ background: linear-gradient(135deg, #f472b6, #a855f7);
277
+ border-radius: 50%;
278
+ box-shadow: 0 8px 20px rgba(168,85,247,0.3);
279
+ color: #fff;
280
+ }
281
+
282
+ .bead-drop-content h3 {
283
+ font-size: 1.25rem;
284
+ font-weight: 700;
285
+ color: #374151;
286
+ margin: 0;
287
+ }
288
+
289
+ .theme-dark .bead-drop-content h3 {
290
+ color: #e5e7eb;
291
+ }
292
+
293
+ .bead-drop-content p {
294
+ color: #6b7280;
295
+ margin: 0;
296
+ }
297
+
298
+ /* Results */
299
+ .bead-result {
300
+ display: flex;
301
+ flex-direction: column;
302
+ gap: 2rem;
303
+ animation: bead-fade-in 0.5s ease;
304
+ }
305
+
306
+ @keyframes bead-fade-in {
307
+ from {
308
+ opacity: 0;
309
+ transform: scale(0.98);
310
+ }
311
+
312
+ to {
313
+ opacity: 1;
314
+ transform: scale(1);
315
+ }
316
+ }
317
+
318
+ .bead-result-inner {
319
+ display: flex;
320
+ gap: 2rem;
321
+ align-items: flex-start;
322
+ }
323
+
324
+ @media (max-width: 640px) {
325
+ .bead-result-inner {
326
+ flex-direction: column;
327
+ }
328
+ }
329
+
330
+ .bead-palette-col {
331
+ width: 12rem;
332
+ flex-shrink: 0;
333
+ }
334
+
335
+ .bead-palette-title {
336
+ font-size: 0.7rem;
337
+ font-weight: 700;
338
+ text-transform: uppercase;
339
+ letter-spacing: 0.05em;
340
+ color: #6b7280;
341
+ margin: 0 0 0.75rem;
342
+ }
343
+
344
+ .bead-palette-grid {
345
+ display: grid;
346
+ grid-template-columns: repeat(4, 1fr);
347
+ gap: 0.5rem;
348
+ }
349
+
350
+ .bead-palette-item {
351
+ display: flex;
352
+ flex-direction: column;
353
+ align-items: center;
354
+ }
355
+
356
+ .bead-color-swatch {
357
+ width: 100%;
358
+ aspect-ratio: 1;
359
+ border-radius: 50%;
360
+ box-shadow: 0 2px 6px rgba(0,0,0,0.15);
361
+ border: 2px solid #fff;
362
+ outline: 1px solid #e5e7eb;
363
+ display: flex;
364
+ align-items: center;
365
+ justify-content: center;
366
+ }
367
+
368
+ .theme-dark .bead-color-swatch {
369
+ border-color: #1f2937;
370
+ outline-color: #374151;
371
+ }
372
+
373
+ .bead-symbol {
374
+ font-size: 0.75rem;
375
+ font-weight: 700;
376
+ user-select: none;
377
+ }
378
+ .bead-symbol-dark {
379
+ color: #000;
380
+ }
381
+
382
+ .bead-symbol-light {
383
+ color: #fff;
384
+ }
385
+
386
+ .bead-reupload-btn {
387
+ margin-top: 1.5rem;
388
+ width: 100%;
389
+ padding: 0.5rem;
390
+ font-size: 0.875rem;
391
+ font-weight: 700;
392
+ color: #6b7280;
393
+ border: 1px solid #e5e7eb;
394
+ border-radius: 0.5rem;
395
+ background: transparent;
396
+ cursor: pointer;
397
+ display: flex;
398
+ align-items: center;
399
+ justify-content: center;
400
+ gap: 0.5rem;
401
+ transition: color 0.2s, border-color 0.2s;
402
+ }
403
+
404
+ .bead-reupload-btn:hover {
405
+ color: #ec4899;
406
+ border-color: #f9a8d4;
407
+ }
408
+
409
+ .bead-canvas-col {
410
+ flex: 1;
411
+ background: #f3f4f6;
412
+ padding: 1rem;
413
+ border-radius: 0.75rem;
414
+ border: 2px solid #e5e7eb;
415
+ box-shadow: inset 0 2px 8px rgba(0,0,0,0.06);
416
+ overflow-x: auto;
417
+ text-align: center;
418
+ }
419
+
420
+ .theme-dark .bead-canvas-col {
421
+ background: #030712;
422
+ border-color: #1f2937;
423
+ }
424
+
425
+ .bead-canvas {
426
+ display: inline-block;
427
+ max-width: 100%;
428
+ box-shadow: 0 20px 40px rgba(0,0,0,0.2);
429
+ cursor: crosshair;
430
+ image-rendering: pixelated;
431
+ }
432
+
433
+ /* Tunnel */
434
+ .bead-tunnel-bar {
435
+ display: flex;
436
+ align-items: center;
437
+ justify-content: space-between;
438
+ flex-wrap: wrap;
439
+ gap: 1rem;
440
+ padding: 1rem;
441
+ background: #eef2ff;
442
+ border: 1px solid #c7d2fe;
443
+ border-radius: 0.75rem;
444
+ }
445
+
446
+ .theme-dark .bead-tunnel-bar {
447
+ background: rgba(79,70,229,0.1);
448
+ border-color: rgba(99,102,241,0.3);
449
+ }
450
+
451
+ .bead-tunnel-title {
452
+ font-weight: 700;
453
+ color: #312e81;
454
+ margin: 0;
455
+ }
456
+
457
+ .theme-dark .bead-tunnel-title {
458
+ color: #c7d2fe;
459
+ }
460
+
461
+ .bead-tunnel-sub {
462
+ font-size: 0.875rem;
463
+ color: #4338ca;
464
+ margin: 0.25rem 0 0;
465
+ }
466
+
467
+ .theme-dark .bead-tunnel-sub {
468
+ color: #818cf8;
469
+ }
470
+
471
+ .bead-tunnel-controls {
472
+ display: flex;
473
+ gap: 0.5rem;
474
+ align-items: center;
475
+ }
476
+
477
+ .bead-tunnel-btn {
478
+ padding: 0.5rem;
479
+ border-radius: 0.5rem;
480
+ border: none;
481
+ background: #fff;
482
+ color: #4f46e5;
483
+ cursor: pointer;
484
+ transition: background 0.15s;
485
+ }
486
+
487
+ .bead-tunnel-btn:hover {
488
+ background: #e0e7ff;
489
+ }
490
+
491
+ .theme-dark .bead-tunnel-btn {
492
+ background: #1f2937;
493
+ color: #818cf8;
494
+ }
495
+
496
+ .bead-tunnel-display {
497
+ padding: 0.5rem 1rem;
498
+ background: #fff;
499
+ border-radius: 0.5rem;
500
+ font-weight: 700;
501
+ color: #4f46e5;
502
+ border: 1px solid #c7d2fe;
503
+ min-width: 3rem;
504
+ text-align: center;
505
+ }
506
+
507
+ .theme-dark .bead-tunnel-display {
508
+ background: #1f2937;
509
+ color: #818cf8;
510
+ border-color: rgba(99,102,241,0.3);
511
+ }
@@ -0,0 +1,17 @@
1
+ ---
2
+ import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
3
+ import { diceRoller } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'es' } = Astro.props;
11
+ const content = await diceRoller.i18n[locale]?.();
12
+ if (!content || !content.bibliography || content.bibliography.length === 0) return null;
13
+
14
+ const { bibliography, bibliographyTitle = 'Bibliografía' } = content;
15
+ ---
16
+
17
+ <SharedBibliography title={bibliographyTitle} links={bibliography} />