@jjlmoya/utils-tools 1.9.0 → 1.11.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 (34) hide show
  1. package/package.json +5 -3
  2. package/scripts/postinstall.mjs +27 -0
  3. package/src/tool/date-diff-calculator/component.astro +0 -200
  4. package/src/tool/date-diff-calculator/date-difference-calculator.css +198 -0
  5. package/src/tool/drive-direct-link/component.astro +0 -173
  6. package/src/tool/drive-direct-link/google-drive-direct-download-link.css +171 -0
  7. package/src/tool/email-list-cleaner/component.astro +0 -204
  8. package/src/tool/email-list-cleaner/email-list-cleaner.css +202 -0
  9. package/src/tool/env-badge-spain/component.astro +0 -156
  10. package/src/tool/env-badge-spain/components/BadgeForm.astro +0 -151
  11. package/src/tool/env-badge-spain/components/BadgeResult.astro +0 -101
  12. package/src/tool/env-badge-spain/environmental-badge-simulator-spain.css +405 -0
  13. package/src/tool/morse-beacon/component.astro +0 -298
  14. package/src/tool/morse-beacon/morse-beacon.css +296 -0
  15. package/src/tool/password-generator/component.astro +0 -88
  16. package/src/tool/password-generator/components/Config.astro +0 -170
  17. package/src/tool/password-generator/components/Display.astro +0 -117
  18. package/src/tool/password-generator/components/Strength.astro +0 -52
  19. package/src/tool/password-generator/password-generator.css +424 -0
  20. package/src/tool/routes/component.astro +0 -254
  21. package/src/tool/routes/optimal-routes.css +252 -0
  22. package/src/tool/rule-of-three/component.astro +0 -249
  23. package/src/tool/rule-of-three/rule-of-three.css +247 -0
  24. package/src/tool/seo-content-optimizer/component.astro +0 -278
  25. package/src/tool/seo-content-optimizer/seo-content-optimizer.css +276 -0
  26. package/src/tool/speed-reader/component.astro +0 -400
  27. package/src/tool/speed-reader/speed-reader.css +398 -0
  28. package/src/tool/text-pixel-calculator/component.astro +0 -96
  29. package/src/tool/text-pixel-calculator/components/Editor.astro +0 -145
  30. package/src/tool/text-pixel-calculator/components/Preview.astro +0 -115
  31. package/src/tool/text-pixel-calculator/components/Stats.astro +0 -62
  32. package/src/tool/text-pixel-calculator/text-pixel-width-calculator.css +407 -0
  33. package/src/tool/whatsapp-link/component.astro +0 -264
  34. package/src/tool/whatsapp-link/whatsapp-link-generator.css +262 -0
@@ -0,0 +1,398 @@
1
+ .sr-root {
2
+ --sr-accent: #4f46e5;
3
+ --sr-accent-hover: #4338ca;
4
+ --sr-violet: #7c3aed;
5
+ --sr-pivot-color: #ef4444;
6
+ --sr-panel-bg: #fff;
7
+ --sr-panel-border: #f1f5f9;
8
+ --sr-field-bg: #f8fafc;
9
+ --sr-field-border: #e2e8f0;
10
+ --sr-field-focus: #4f46e5;
11
+ --sr-text-main: #1e293b;
12
+ --sr-text-label: #64748b;
13
+ --sr-text-hint: #94a3b8;
14
+ --sr-text-muted: #475569;
15
+ --sr-btn-shadow: rgba(79, 70, 229, 0.35);
16
+ --sr-badge-bg: rgba(15, 23, 42, 0.8);
17
+ --sr-badge-border: #334155;
18
+ --sr-led-idle: #22c55e;
19
+ --sr-led-active: #f59e0b;
20
+ --sr-guide-color: rgba(71, 85, 105, 0.3);
21
+ --sr-word-color: #e2e8f0;
22
+ --sr-word-muted: #475569;
23
+ --sr-clear-color: #f87171;
24
+ --sr-clear-hover: #fee2e2;
25
+
26
+ width: 100%;
27
+ max-width: 56rem;
28
+ margin: 0 auto;
29
+ display: flex;
30
+ flex-direction: column;
31
+ gap: 1rem;
32
+ }
33
+
34
+ :global(.theme-dark) .sr-root {
35
+ --sr-panel-bg: #0f172a;
36
+ --sr-panel-border: #1e293b;
37
+ --sr-field-bg: rgba(30, 41, 59, 0.5);
38
+ --sr-field-border: #334155;
39
+ --sr-text-main: #e2e8f0;
40
+ --sr-text-label: #94a3b8;
41
+ --sr-text-hint: #64748b;
42
+ --sr-text-muted: #64748b;
43
+ --sr-word-muted: #64748b;
44
+ }
45
+
46
+ .sr-stage {
47
+ position: relative;
48
+ background: #0f172a;
49
+ border-radius: 1.5rem;
50
+ height: 22rem;
51
+ display: flex;
52
+ align-items: center;
53
+ justify-content: center;
54
+ overflow: hidden;
55
+ border: 1px solid #1e293b;
56
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
57
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
58
+ }
59
+
60
+ :global(.sr-stage-active) {
61
+ transform: scale(1.02);
62
+ border-color: rgba(79, 70, 229, 0.4);
63
+ }
64
+
65
+ .sr-badge {
66
+ position: absolute;
67
+ top: 1.25rem;
68
+ right: 1.25rem;
69
+ display: flex;
70
+ align-items: center;
71
+ gap: 0.375rem;
72
+ background: var(--sr-badge-bg);
73
+ border: 1px solid var(--sr-badge-border);
74
+ border-radius: 9999px;
75
+ padding: 0.25rem 0.75rem;
76
+ font-size: 0.75rem;
77
+ color: #cbd5e1;
78
+ z-index: 20;
79
+ backdrop-filter: blur(4px);
80
+ }
81
+
82
+ .sr-badge > span:first-child {
83
+ font-weight: 700;
84
+ color: #f1f5f9;
85
+ }
86
+
87
+ .sr-badge-label {
88
+ color: #64748b;
89
+ text-transform: uppercase;
90
+ letter-spacing: 0.05em;
91
+ }
92
+
93
+ .sr-led {
94
+ width: 0.5rem;
95
+ height: 0.5rem;
96
+ border-radius: 50%;
97
+ background: var(--sr-led-idle);
98
+ transition: background 0.2s;
99
+ }
100
+
101
+ :global(.sr-led-active) {
102
+ background: var(--sr-led-active);
103
+ animation: sr-pulse 1s ease-in-out infinite;
104
+ }
105
+
106
+ @keyframes sr-pulse {
107
+ 0%, 100% { opacity: 1; }
108
+ 50% { opacity: 0.5; }
109
+ }
110
+
111
+ .sr-guide-v {
112
+ position: absolute;
113
+ top: 0;
114
+ bottom: 0;
115
+ left: 50%;
116
+ width: 1px;
117
+ background: rgba(71, 85, 105, 0.25);
118
+ transform: translateX(-50%);
119
+ pointer-events: none;
120
+ }
121
+
122
+ .sr-guide-h {
123
+ position: absolute;
124
+ top: 50%;
125
+ left: 50%;
126
+ width: 18rem;
127
+ height: 4.5rem;
128
+ transform: translate(-50%, -60%);
129
+ border-top: 1px solid rgba(71, 85, 105, 0.2);
130
+ border-bottom: 1px solid rgba(71, 85, 105, 0.2);
131
+ border-radius: 0.5rem;
132
+ pointer-events: none;
133
+ }
134
+
135
+ .sr-word {
136
+ position: relative;
137
+ z-index: 10;
138
+ display: grid;
139
+ grid-template-columns: 1fr auto 1fr;
140
+ align-items: center;
141
+ width: 100%;
142
+ max-width: 36rem;
143
+ padding: 0 2rem;
144
+ font-size: clamp(2rem, 6vw, 3.5rem);
145
+ font-weight: 700;
146
+ user-select: none;
147
+ }
148
+
149
+ .sr-word-left {
150
+ text-align: right;
151
+ color: var(--sr-word-muted);
152
+ white-space: nowrap;
153
+ }
154
+
155
+ .sr-word-pivot {
156
+ position: relative;
157
+ display: flex;
158
+ justify-content: center;
159
+ flex-shrink: 0;
160
+ min-width: 1ch;
161
+ margin: 0 1px;
162
+ }
163
+
164
+ .sr-word-pivot > span {
165
+ color: var(--sr-pivot-color);
166
+ font-weight: 900;
167
+ position: relative;
168
+ z-index: 2;
169
+ }
170
+
171
+ .sr-pivot-beam {
172
+ position: absolute;
173
+ top: 50%;
174
+ left: 50%;
175
+ transform: translate(-50%, -50%);
176
+ width: 2px;
177
+ height: 4rem;
178
+ background: rgba(239, 68, 68, 0.15);
179
+ border-radius: 9999px;
180
+ }
181
+
182
+ .sr-word-right {
183
+ text-align: left;
184
+ color: var(--sr-word-muted);
185
+ white-space: nowrap;
186
+ }
187
+
188
+ .sr-panel {
189
+ background: var(--sr-panel-bg);
190
+ border: 1px solid var(--sr-panel-border);
191
+ border-radius: 1.5rem;
192
+ padding: 1.5rem;
193
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.04);
194
+ display: flex;
195
+ flex-direction: column;
196
+ gap: 1.5rem;
197
+ }
198
+
199
+ .sr-playrow {
200
+ display: flex;
201
+ align-items: center;
202
+ gap: 1.25rem;
203
+ }
204
+
205
+ .sr-play-btn {
206
+ flex-shrink: 0;
207
+ width: 3.75rem;
208
+ height: 3.75rem;
209
+ background: var(--sr-accent);
210
+ color: #fff;
211
+ border: none;
212
+ border-radius: 1rem;
213
+ display: flex;
214
+ align-items: center;
215
+ justify-content: center;
216
+ cursor: pointer;
217
+ box-shadow: 0 4px 14px var(--sr-btn-shadow);
218
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
219
+ }
220
+
221
+ .sr-play-btn:hover {
222
+ background: var(--sr-accent-hover);
223
+ transform: scale(1.05);
224
+ }
225
+
226
+ .sr-play-btn:active {
227
+ transform: scale(0.95);
228
+ }
229
+
230
+ :global(.sr-play-btn-active) {
231
+ background: #1e293b;
232
+ box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
233
+ }
234
+
235
+ :global(.sr-play-btn-active):hover {
236
+ background: #0f172a;
237
+ }
238
+
239
+ .sr-play-icon {
240
+ width: 1.75rem;
241
+ height: 1.75rem;
242
+ }
243
+
244
+ .sr-progress-wrap {
245
+ flex: 1;
246
+ display: flex;
247
+ flex-direction: column;
248
+ gap: 0.5rem;
249
+ }
250
+
251
+ .sr-progress-header {
252
+ display: flex;
253
+ justify-content: space-between;
254
+ align-items: center;
255
+ font-size: 0.7rem;
256
+ font-weight: 700;
257
+ text-transform: uppercase;
258
+ letter-spacing: 0.08em;
259
+ color: var(--sr-text-hint);
260
+ padding: 0 0.25rem;
261
+ }
262
+
263
+ .sr-progress-pct {
264
+ color: var(--sr-accent);
265
+ }
266
+
267
+ .sr-slider {
268
+ width: 100%;
269
+ cursor: pointer;
270
+ accent-color: var(--sr-accent);
271
+ }
272
+
273
+ .sr-config {
274
+ display: grid;
275
+ grid-template-columns: 1fr;
276
+ gap: 1.5rem;
277
+ border-top: 1px solid var(--sr-panel-border);
278
+ padding-top: 1.5rem;
279
+ }
280
+
281
+ @media (min-width: 640px) {
282
+ .sr-config { grid-template-columns: 1fr 1fr; }
283
+ }
284
+
285
+ .sr-config-label {
286
+ display: block;
287
+ font-size: 1rem;
288
+ font-weight: 900;
289
+ color: var(--sr-text-main);
290
+ }
291
+
292
+ .sr-speed-section {
293
+ display: flex;
294
+ flex-direction: column;
295
+ gap: 0.75rem;
296
+ }
297
+
298
+ .sr-speed-header {
299
+ display: flex;
300
+ justify-content: space-between;
301
+ align-items: center;
302
+ }
303
+
304
+ .sr-wpm-badge {
305
+ background: rgba(79, 70, 229, 0.08);
306
+ color: var(--sr-accent);
307
+ border: 1px solid rgba(79, 70, 229, 0.2);
308
+ border-radius: 9999px;
309
+ padding: 0.2rem 0.75rem;
310
+ font-size: 0.8rem;
311
+ font-weight: 700;
312
+ }
313
+
314
+ .sr-speed-labels {
315
+ display: flex;
316
+ justify-content: space-between;
317
+ font-size: 0.7rem;
318
+ font-weight: 700;
319
+ color: var(--sr-text-hint);
320
+ letter-spacing: 0.08em;
321
+ }
322
+
323
+ .sr-speed-hint {
324
+ font-size: 0.8rem;
325
+ color: var(--sr-text-hint);
326
+ line-height: 1.5;
327
+ margin: 0;
328
+ }
329
+
330
+ .sr-text-section {
331
+ display: flex;
332
+ flex-direction: column;
333
+ gap: 0.5rem;
334
+ }
335
+
336
+ .sr-textarea-wrap {
337
+ position: relative;
338
+ }
339
+
340
+ .sr-textarea {
341
+ width: 100%;
342
+ height: 9rem;
343
+ background: var(--sr-field-bg);
344
+ border: 1px solid var(--sr-field-border);
345
+ border-radius: 0.75rem;
346
+ padding: 0.875rem 1rem 2.5rem;
347
+ font-size: 0.85rem;
348
+ color: var(--sr-text-main);
349
+ line-height: 1.6;
350
+ resize: none;
351
+ outline: none;
352
+ transition: border-color 0.2s;
353
+ box-sizing: border-box;
354
+ }
355
+
356
+ .sr-textarea::placeholder {
357
+ color: var(--sr-text-hint);
358
+ }
359
+
360
+ .sr-textarea:focus {
361
+ border-color: var(--sr-field-focus);
362
+ }
363
+
364
+ .sr-textarea-footer {
365
+ position: absolute;
366
+ bottom: 0.625rem;
367
+ right: 0.625rem;
368
+ display: flex;
369
+ align-items: center;
370
+ gap: 0.5rem;
371
+ }
372
+
373
+ .sr-word-count {
374
+ font-size: 0.7rem;
375
+ font-weight: 700;
376
+ color: var(--sr-text-hint);
377
+ background: var(--sr-panel-bg);
378
+ border: 1px solid var(--sr-panel-border);
379
+ padding: 0.2rem 0.5rem;
380
+ border-radius: 0.375rem;
381
+ }
382
+
383
+ .sr-clear-btn {
384
+ font-size: 0.7rem;
385
+ font-weight: 700;
386
+ color: var(--sr-clear-color);
387
+ background: transparent;
388
+ border: none;
389
+ cursor: pointer;
390
+ padding: 0.2rem 0.375rem;
391
+ border-radius: 0.375rem;
392
+ transition: background 0.15s;
393
+ letter-spacing: 0.05em;
394
+ }
395
+
396
+ .sr-clear-btn:hover {
397
+ background: var(--sr-clear-hover);
398
+ }
@@ -41,102 +41,6 @@ const t = (ui ?? {}) as TextPixelCalculatorUI;
41
41
 
42
42
  <div class="tpc-toast" id="tpc-toast">{t.copyDone}</div>
43
43
 
44
- <style>
45
- .tpc-root {
46
- --tpc-cyan: #06b6d4;
47
- --tpc-cyan-dark: #0891b2;
48
- --tpc-cyan-focus: rgba(6, 182, 212, 0.15);
49
- --tpc-purple: #8b5cf6;
50
- --tpc-card-bg: #fff;
51
- --tpc-card-border: rgba(0, 0, 0, 0.05);
52
- --tpc-field-bg: #f8fafc;
53
- --tpc-field-border: #e2e8f0;
54
- --tpc-text-main: #1e293b;
55
- --tpc-text-label: #64748b;
56
- --tpc-canvas-bg: #f1f5f9;
57
- --tpc-btn-secondary-bg: #f1f5f9;
58
- --tpc-btn-secondary-color: #475569;
59
- --tpc-checkbox-border: #cbd5e1;
60
- --tpc-checkbox-bg: #fff;
61
- --tpc-toast-bg: #1e293b;
62
-
63
- width: 100%;
64
- max-width: 1000px;
65
- margin: 0 auto;
66
- }
67
-
68
- :global(.theme-dark) .tpc-root {
69
- --tpc-card-bg: #1e293b;
70
- --tpc-card-border: rgba(255, 255, 255, 0.05);
71
- --tpc-field-bg: #0f172a;
72
- --tpc-field-border: #334155;
73
- --tpc-text-main: #f1f5f9;
74
- --tpc-text-label: #94a3b8;
75
- --tpc-canvas-bg: #0f172a;
76
- --tpc-btn-secondary-bg: #334155;
77
- --tpc-btn-secondary-color: #e2e8f0;
78
- --tpc-checkbox-border: #475569;
79
- --tpc-checkbox-bg: #0f172a;
80
- --tpc-toast-bg: #06b6d4;
81
- }
82
-
83
- .tpc-main-card {
84
- background: var(--tpc-card-bg);
85
- border: 1px solid var(--tpc-card-border);
86
- border-radius: 2.5rem;
87
- padding: 2.5rem;
88
- display: flex;
89
- gap: 3rem;
90
- box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.1);
91
- }
92
-
93
- .tpc-left {
94
- flex: 1.2;
95
- display: flex;
96
- flex-direction: column;
97
- }
98
-
99
- .tpc-right {
100
- flex: 1;
101
- border-left: 1px solid var(--tpc-field-border);
102
- padding-left: 3rem;
103
- }
104
-
105
- @media (max-width: 900px) {
106
- .tpc-main-card {
107
- flex-direction: column;
108
- padding: 1.5rem;
109
- gap: 2rem;
110
- }
111
- .tpc-right {
112
- border-left: none;
113
- padding-left: 0;
114
- border-top: 1px solid var(--tpc-field-border);
115
- padding-top: 2rem;
116
- }
117
- }
118
-
119
- .tpc-toast {
120
- position: fixed;
121
- bottom: 2rem;
122
- left: 50%;
123
- transform: translateX(-50%) translateY(100px);
124
- background: var(--tpc-toast-bg);
125
- color: #fff;
126
- padding: 1rem 2rem;
127
- border-radius: 100px;
128
- font-size: 0.875rem;
129
- font-weight: 700;
130
- transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
131
- z-index: 1000;
132
- box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.3);
133
- pointer-events: none;
134
- }
135
-
136
- .tpc-toast-show {
137
- transform: translateX(-50%) translateY(0);
138
- }
139
- </style>
140
44
 
141
45
  <script>
142
46
  import type { TextPixelCalculatorUI } from './ui';
@@ -93,148 +93,3 @@ const systemFonts = [
93
93
  </div>
94
94
  </div>
95
95
 
96
- <style>
97
- .tpc-editor {
98
- display: flex;
99
- flex-direction: column;
100
- gap: 1.5rem;
101
- }
102
-
103
- .tpc-field {
104
- display: flex;
105
- flex-direction: column;
106
- gap: 0.625rem;
107
- }
108
-
109
- .tpc-label {
110
- font-size: 0.75rem;
111
- font-weight: 700;
112
- color: var(--tpc-text-label);
113
- text-transform: uppercase;
114
- letter-spacing: 0.06em;
115
- }
116
-
117
- .tpc-textarea {
118
- width: 100%;
119
- background: var(--tpc-field-bg);
120
- border: 1px solid var(--tpc-field-border);
121
- border-radius: 1rem;
122
- padding: 1.25rem;
123
- font-size: 1.125rem;
124
- color: var(--tpc-text-main);
125
- line-height: 1.6;
126
- resize: none;
127
- outline: none;
128
- transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
129
- box-sizing: border-box;
130
- }
131
-
132
- .tpc-textarea:focus {
133
- border-color: var(--tpc-cyan);
134
- box-shadow: 0 0 0 4px var(--tpc-cyan-focus);
135
- background: #fff;
136
- }
137
-
138
- :global(.theme-dark) .tpc-textarea:focus {
139
- background: var(--tpc-field-bg);
140
- }
141
-
142
- .tpc-config-grid {
143
- display: grid;
144
- grid-template-columns: repeat(2, 1fr);
145
- gap: 1.25rem;
146
- }
147
-
148
- .tpc-input {
149
- width: 100%;
150
- background: var(--tpc-field-bg);
151
- border: 1px solid var(--tpc-field-border);
152
- border-radius: 0.875rem;
153
- padding: 0.75rem 1rem;
154
- font-size: 0.9375rem;
155
- color: var(--tpc-text-main);
156
- outline: none;
157
- transition: all 0.2s ease;
158
- box-sizing: border-box;
159
- appearance: none;
160
- }
161
-
162
- .tpc-input:focus {
163
- border-color: var(--tpc-cyan);
164
- box-shadow: 0 0 0 4px var(--tpc-cyan-focus);
165
- }
166
-
167
- .tpc-select-wrapper {
168
- position: relative;
169
- width: 100%;
170
- }
171
-
172
- .tpc-select-arrow {
173
- position: absolute;
174
- right: 1rem;
175
- top: 50%;
176
- transform: translateY(-50%);
177
- pointer-events: none;
178
- color: var(--tpc-text-label);
179
- width: 1.25rem;
180
- height: 1.25rem;
181
- }
182
-
183
- .tpc-checkbox-label {
184
- display: flex;
185
- align-items: center;
186
- gap: 0.75rem;
187
- cursor: pointer;
188
- user-select: none;
189
- height: 100%;
190
- padding-top: 1.5rem;
191
- }
192
-
193
- .tpc-checkbox-input {
194
- display: none;
195
- }
196
-
197
- .tpc-checkbox-box {
198
- width: 1.5rem;
199
- height: 1.5rem;
200
- border: 2px solid var(--tpc-checkbox-border);
201
- background: var(--tpc-checkbox-bg);
202
- border-radius: 0.5rem;
203
- position: relative;
204
- flex-shrink: 0;
205
- transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
206
- }
207
-
208
- :global(.tpc-checked) .tpc-checkbox-box {
209
- background: var(--tpc-cyan);
210
- border-color: var(--tpc-cyan);
211
- transform: scale(1.05);
212
- }
213
-
214
- :global(.tpc-checked) .tpc-checkbox-box::after {
215
- content: '';
216
- position: absolute;
217
- left: 50%;
218
- top: 45%;
219
- width: 6px;
220
- height: 11px;
221
- border: solid #fff;
222
- border-width: 0 2.5px 2.5px 0;
223
- transform: translate(-50%, -50%) rotate(45deg);
224
- }
225
-
226
- .tpc-italic-text {
227
- font-size: 0.9375rem;
228
- font-weight: 600;
229
- color: var(--tpc-text-main);
230
- }
231
-
232
- @media (max-width: 480px) {
233
- .tpc-config-grid {
234
- grid-template-columns: 1fr;
235
- }
236
- .tpc-field-italic {
237
- padding-top: 0;
238
- }
239
- }
240
- </style>