@jjlmoya/utils-tools 1.8.0 → 1.10.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 (52) hide show
  1. package/package.json +7 -4
  2. package/scripts/postinstall.mjs +27 -0
  3. package/src/entries.ts +26 -0
  4. package/src/tool/date-diff-calculator/component.astro +0 -200
  5. package/src/tool/date-diff-calculator/date-difference-calculator.css +198 -0
  6. package/src/tool/date-diff-calculator/entry.ts +24 -0
  7. package/src/tool/date-diff-calculator/index.ts +2 -25
  8. package/src/tool/drive-direct-link/component.astro +0 -173
  9. package/src/tool/drive-direct-link/entry.ts +24 -0
  10. package/src/tool/drive-direct-link/google-drive-direct-download-link.css +171 -0
  11. package/src/tool/drive-direct-link/index.ts +2 -25
  12. package/src/tool/email-list-cleaner/component.astro +0 -204
  13. package/src/tool/email-list-cleaner/email-list-cleaner.css +202 -0
  14. package/src/tool/email-list-cleaner/entry.ts +24 -0
  15. package/src/tool/email-list-cleaner/index.ts +2 -25
  16. package/src/tool/env-badge-spain/component.astro +0 -156
  17. package/src/tool/env-badge-spain/entry.ts +24 -0
  18. package/src/tool/env-badge-spain/environmental-badge-simulator-spain.css +154 -0
  19. package/src/tool/env-badge-spain/index.ts +2 -25
  20. package/src/tool/morse-beacon/component.astro +0 -298
  21. package/src/tool/morse-beacon/entry.ts +24 -0
  22. package/src/tool/morse-beacon/index.ts +2 -25
  23. package/src/tool/morse-beacon/morse-beacon.css +296 -0
  24. package/src/tool/password-generator/component.astro +0 -88
  25. package/src/tool/password-generator/entry.ts +24 -0
  26. package/src/tool/password-generator/index.ts +2 -25
  27. package/src/tool/password-generator/password-generator.css +86 -0
  28. package/src/tool/routes/component.astro +0 -254
  29. package/src/tool/routes/entry.ts +24 -0
  30. package/src/tool/routes/index.ts +2 -25
  31. package/src/tool/routes/optimal-routes.css +252 -0
  32. package/src/tool/rule-of-three/component.astro +0 -249
  33. package/src/tool/rule-of-three/entry.ts +24 -0
  34. package/src/tool/rule-of-three/index.ts +2 -25
  35. package/src/tool/rule-of-three/rule-of-three.css +247 -0
  36. package/src/tool/seo-content-optimizer/component.astro +0 -278
  37. package/src/tool/seo-content-optimizer/entry.ts +24 -0
  38. package/src/tool/seo-content-optimizer/index.ts +2 -25
  39. package/src/tool/seo-content-optimizer/seo-content-optimizer.css +276 -0
  40. package/src/tool/speed-reader/component.astro +0 -400
  41. package/src/tool/speed-reader/entry.ts +24 -0
  42. package/src/tool/speed-reader/index.ts +2 -25
  43. package/src/tool/speed-reader/speed-reader.css +398 -0
  44. package/src/tool/text-pixel-calculator/component.astro +0 -96
  45. package/src/tool/text-pixel-calculator/entry.ts +24 -0
  46. package/src/tool/text-pixel-calculator/index.ts +2 -25
  47. package/src/tool/text-pixel-calculator/text-pixel-width-calculator.css +94 -0
  48. package/src/tool/whatsapp-link/component.astro +0 -264
  49. package/src/tool/whatsapp-link/entry.ts +24 -0
  50. package/src/tool/whatsapp-link/index.ts +2 -25
  51. package/src/tool/whatsapp-link/whatsapp-link-generator.css +262 -0
  52. package/src/tools.ts +1 -1
@@ -39,94 +39,6 @@ const t = (ui ?? {}) as PasswordGeneratorUI;
39
39
  </div>
40
40
  </div>
41
41
 
42
- <style>
43
- .pg-app-container {
44
- width: 100%;
45
- max-width: 640px;
46
- margin: 0 auto;
47
- padding: 1rem;
48
- perspective: 1000px;
49
- }
50
-
51
- .pg-card {
52
- position: relative;
53
- border-radius: 2rem;
54
- padding: 2px;
55
- background: linear-gradient(
56
- 135deg,
57
- rgba(255, 255, 255, 0.1),
58
- rgba(255, 255, 255, 0.05)
59
- );
60
- box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.15);
61
- transition: transform 0.3s ease;
62
- }
63
-
64
- :global(.theme-dark) .pg-card {
65
- background: linear-gradient(
66
- 135deg,
67
- rgba(255, 255, 255, 0.05),
68
- rgba(0, 0, 0, 0.2)
69
- );
70
- }
71
-
72
- .pg-card-glow {
73
- position: absolute;
74
- inset: 0;
75
- border-radius: 2rem;
76
- background: linear-gradient(135deg, #10b981 0%, #3b82f6 100%);
77
- opacity: 0.1;
78
- filter: blur(20px);
79
- z-index: -1;
80
- }
81
-
82
- .pg-card-content {
83
- background: #fff;
84
- border-radius: calc(2rem - 2px);
85
- padding: 1.5rem;
86
- display: flex;
87
- flex-direction: column;
88
- }
89
-
90
- :global(.theme-dark) .pg-card-content {
91
- background: #0f172a;
92
- }
93
-
94
- .pg-divider {
95
- height: 1px;
96
- background: linear-gradient(
97
- to right,
98
- transparent,
99
- rgba(0, 0, 0, 0.05),
100
- transparent
101
- );
102
- margin: 1.5rem 0;
103
- }
104
-
105
- :global(.theme-dark) .pg-divider {
106
- background: linear-gradient(
107
- to right,
108
- transparent,
109
- rgba(255, 255, 255, 0.05),
110
- transparent
111
- );
112
- }
113
-
114
- @keyframes pulse-success {
115
- 0% {
116
- transform: scale(1);
117
- }
118
- 50% {
119
- transform: scale(1.05);
120
- }
121
- 100% {
122
- transform: scale(1);
123
- }
124
- }
125
-
126
- :global(.pg-copied-anim) {
127
- animation: pulse-success 0.3s ease-out;
128
- }
129
- </style>
130
42
 
131
43
  <script>
132
44
  const root = document.querySelector(
@@ -0,0 +1,24 @@
1
+ import type { ToolsToolEntry } from '../../types';
2
+ import type { PasswordGeneratorUI } from './ui';
3
+
4
+ export const passwordGenerator: ToolsToolEntry<PasswordGeneratorUI> = {
5
+ id: 'password-generator',
6
+ icons: { bg: 'mdi:shield-key', fg: 'mdi:lock-reset' },
7
+ i18n: {
8
+ de: () => import('./i18n/de').then((m) => m.content),
9
+ en: () => import('./i18n/en').then((m) => m.content),
10
+ es: () => import('./i18n/es').then((m) => m.content),
11
+ fr: () => import('./i18n/fr').then((m) => m.content),
12
+ id: () => import('./i18n/id').then((m) => m.content),
13
+ it: () => import('./i18n/it').then((m) => m.content),
14
+ ja: () => import('./i18n/ja').then((m) => m.content),
15
+ ko: () => import('./i18n/ko').then((m) => m.content),
16
+ nl: () => import('./i18n/nl').then((m) => m.content),
17
+ pl: () => import('./i18n/pl').then((m) => m.content),
18
+ pt: () => import('./i18n/pt').then((m) => m.content),
19
+ ru: () => import('./i18n/ru').then((m) => m.content),
20
+ sv: () => import('./i18n/sv').then((m) => m.content),
21
+ tr: () => import('./i18n/tr').then((m) => m.content),
22
+ zh: () => import('./i18n/zh').then((m) => m.content),
23
+ },
24
+ };
@@ -1,28 +1,5 @@
1
- import type { ToolDefinition, ToolsToolEntry } from '../../types';
2
- import type { PasswordGeneratorUI } from './ui';
3
-
4
- export const passwordGenerator: ToolsToolEntry<PasswordGeneratorUI> = {
5
- id: 'password-generator',
6
- icons: { bg: 'mdi:shield-key', fg: 'mdi:lock-reset' },
7
- i18n: {
8
- de: () => import('./i18n/de').then((m) => m.content),
9
- en: () => import('./i18n/en').then((m) => m.content),
10
- es: () => import('./i18n/es').then((m) => m.content),
11
- fr: () => import('./i18n/fr').then((m) => m.content),
12
- id: () => import('./i18n/id').then((m) => m.content),
13
- it: () => import('./i18n/it').then((m) => m.content),
14
- ja: () => import('./i18n/ja').then((m) => m.content),
15
- ko: () => import('./i18n/ko').then((m) => m.content),
16
- nl: () => import('./i18n/nl').then((m) => m.content),
17
- pl: () => import('./i18n/pl').then((m) => m.content),
18
- pt: () => import('./i18n/pt').then((m) => m.content),
19
- ru: () => import('./i18n/ru').then((m) => m.content),
20
- sv: () => import('./i18n/sv').then((m) => m.content),
21
- tr: () => import('./i18n/tr').then((m) => m.content),
22
- zh: () => import('./i18n/zh').then((m) => m.content),
23
- },
24
- };
25
-
1
+ import { passwordGenerator } from './entry';
2
+ export * from './entry';
26
3
  export const PASSWORD_GENERATOR_TOOL: ToolDefinition = {
27
4
  entry: passwordGenerator,
28
5
  Component: () => import('./component.astro'),
@@ -0,0 +1,86 @@
1
+ .pg-app-container {
2
+ width: 100%;
3
+ max-width: 640px;
4
+ margin: 0 auto;
5
+ padding: 1rem;
6
+ perspective: 1000px;
7
+ }
8
+
9
+ .pg-card {
10
+ position: relative;
11
+ border-radius: 2rem;
12
+ padding: 2px;
13
+ background: linear-gradient(
14
+ 135deg,
15
+ rgba(255, 255, 255, 0.1),
16
+ rgba(255, 255, 255, 0.05)
17
+ );
18
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.15);
19
+ transition: transform 0.3s ease;
20
+ }
21
+
22
+ :global(.theme-dark) .pg-card {
23
+ background: linear-gradient(
24
+ 135deg,
25
+ rgba(255, 255, 255, 0.05),
26
+ rgba(0, 0, 0, 0.2)
27
+ );
28
+ }
29
+
30
+ .pg-card-glow {
31
+ position: absolute;
32
+ inset: 0;
33
+ border-radius: 2rem;
34
+ background: linear-gradient(135deg, #10b981 0%, #3b82f6 100%);
35
+ opacity: 0.1;
36
+ filter: blur(20px);
37
+ z-index: -1;
38
+ }
39
+
40
+ .pg-card-content {
41
+ background: #fff;
42
+ border-radius: calc(2rem - 2px);
43
+ padding: 1.5rem;
44
+ display: flex;
45
+ flex-direction: column;
46
+ }
47
+
48
+ :global(.theme-dark) .pg-card-content {
49
+ background: #0f172a;
50
+ }
51
+
52
+ .pg-divider {
53
+ height: 1px;
54
+ background: linear-gradient(
55
+ to right,
56
+ transparent,
57
+ rgba(0, 0, 0, 0.05),
58
+ transparent
59
+ );
60
+ margin: 1.5rem 0;
61
+ }
62
+
63
+ :global(.theme-dark) .pg-divider {
64
+ background: linear-gradient(
65
+ to right,
66
+ transparent,
67
+ rgba(255, 255, 255, 0.05),
68
+ transparent
69
+ );
70
+ }
71
+
72
+ @keyframes pulse-success {
73
+ 0% {
74
+ transform: scale(1);
75
+ }
76
+ 50% {
77
+ transform: scale(1.05);
78
+ }
79
+ 100% {
80
+ transform: scale(1);
81
+ }
82
+ }
83
+
84
+ :global(.pg-copied-anim) {
85
+ animation: pulse-success 0.3s ease-out;
86
+ }
@@ -60,260 +60,6 @@ const t = (ui ?? {}) as RoutesUI;
60
60
  </div>
61
61
  </div>
62
62
 
63
- <style>
64
- .rut-root {
65
- --rut-accent: #06b6d4;
66
- --rut-accent-hover: #0891b2;
67
- --rut-sidebar-bg: #f8fafc;
68
- --rut-sidebar-border: #e2e8f0;
69
- --rut-map-bg: #f1f5f9;
70
- --rut-text-main: #1e293b;
71
- --rut-text-muted: #64748b;
72
- --rut-item-bg: #fff;
73
- --rut-item-border: #f1f5f9;
74
- --rut-item-hover-border: rgba(6, 182, 212, 0.5);
75
- --rut-badge-bg: rgba(207, 250, 254, 1);
76
- --rut-badge-border: #a5f3fc;
77
- --rut-badge-text: #0e7490;
78
- --rut-stats-bg: rgba(236, 254, 255, 1);
79
- --rut-stats-border: #a5f3fc;
80
- --rut-stats-label: #164e63;
81
- --rut-stats-value: #0891b2;
82
- --rut-btn-clear-bg: #fff;
83
- --rut-btn-clear-text: #334155;
84
- --rut-btn-clear-border: #e2e8f0;
85
- --rut-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
86
- }
87
-
88
- :global(.theme-dark) .rut-root {
89
- --rut-sidebar-bg: rgba(15, 23, 42, 0.5);
90
- --rut-sidebar-border: #1e293b;
91
- --rut-map-bg: #1e293b;
92
- --rut-text-main: #f1f5f9;
93
- --rut-text-muted: #94a3b8;
94
- --rut-item-bg: #1e293b;
95
- --rut-item-border: #334155;
96
- --rut-badge-bg: rgba(8, 145, 178, 0.3);
97
- --rut-badge-border: #164e63;
98
- --rut-badge-text: #67e8f9;
99
- --rut-stats-bg: rgba(8, 145, 178, 0.2);
100
- --rut-stats-border: rgba(8, 145, 178, 0.3);
101
- --rut-stats-label: #a5f3fc;
102
- --rut-stats-value: #22d3ee;
103
- --rut-btn-clear-bg: #1e293b;
104
- --rut-btn-clear-text: #cbd5e1;
105
- --rut-btn-clear-border: #334155;
106
- --rut-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
107
- }
108
-
109
- .rut-layout {
110
- display: flex;
111
- flex-direction: column;
112
- height: calc(100vh - 100px);
113
- min-height: 500px;
114
- max-height: 800px;
115
- }
116
-
117
- @media (min-width: 1024px) {
118
- .rut-layout {
119
- display: grid;
120
- grid-template-columns: 320px 1fr;
121
- flex-direction: unset;
122
- }
123
- }
124
-
125
- .rut-sidebar {
126
- display: flex;
127
- flex-direction: column;
128
- padding: 1.5rem;
129
- background: var(--rut-sidebar-bg);
130
- border-bottom: 1px solid var(--rut-sidebar-border);
131
- overflow: hidden;
132
- height: 50%;
133
- }
134
-
135
- @media (min-width: 1024px) {
136
- .rut-sidebar {
137
- height: 100%;
138
- border-bottom: none;
139
- border-right: 1px solid var(--rut-sidebar-border);
140
- order: 1;
141
- }
142
- }
143
-
144
- .rut-sidebar-header {
145
- margin-bottom: 1.25rem;
146
- }
147
-
148
- .rut-sidebar-title {
149
- font-size: 1.2rem;
150
- font-weight: 700;
151
- color: var(--rut-text-main);
152
- margin: 0 0 0.375rem;
153
- }
154
-
155
- .rut-sidebar-desc {
156
- font-size: 0.875rem;
157
- color: var(--rut-text-muted);
158
- margin: 0;
159
- }
160
-
161
- .rut-list-wrapper {
162
- flex: 1;
163
- overflow-y: auto;
164
- min-height: 0;
165
- margin-bottom: 1rem;
166
- padding-right: 0.25rem;
167
- }
168
-
169
- .rut-list-wrapper::-webkit-scrollbar {
170
- width: 6px;
171
- }
172
-
173
- .rut-list-wrapper::-webkit-scrollbar-track {
174
- background: transparent;
175
- }
176
-
177
- .rut-list-wrapper::-webkit-scrollbar-thumb {
178
- background-color: rgba(156, 163, 175, 0.5);
179
- border-radius: 20px;
180
- }
181
-
182
- .rut-points-list {
183
- list-style: none;
184
- margin: 0;
185
- padding: 0;
186
- display: flex;
187
- flex-direction: column;
188
- gap: 0.5rem;
189
- }
190
-
191
- .rut-empty-state {
192
- text-align: center;
193
- padding: 2rem 1rem;
194
- color: var(--rut-text-muted);
195
- border: 2px dashed var(--rut-sidebar-border);
196
- border-radius: 0.5rem;
197
- font-size: 0.875rem;
198
- }
199
-
200
- .rut-actions {
201
- margin-top: auto;
202
- padding-top: 1rem;
203
- border-top: 1px solid var(--rut-sidebar-border);
204
- display: flex;
205
- flex-direction: column;
206
- gap: 0.75rem;
207
- }
208
-
209
- .rut-btn-primary {
210
- width: 100%;
211
- padding: 0.75rem 1rem;
212
- background: var(--rut-accent-hover);
213
- color: #fff;
214
- border: none;
215
- border-radius: 0.5rem;
216
- font-size: 0.9rem;
217
- font-weight: 600;
218
- cursor: pointer;
219
- display: flex;
220
- align-items: center;
221
- justify-content: center;
222
- gap: 0.5rem;
223
- transition: background 0.15s;
224
- box-shadow: 0 4px 6px -1px rgba(8, 145, 178, 0.2);
225
- }
226
-
227
- .rut-btn-primary:hover:not(:disabled) {
228
- background: var(--rut-accent);
229
- }
230
-
231
- .rut-btn-primary:disabled {
232
- opacity: 0.5;
233
- cursor: not-allowed;
234
- }
235
-
236
- .rut-btn-secondary {
237
- width: 100%;
238
- padding: 0.5rem 1rem;
239
- background: var(--rut-btn-clear-bg);
240
- color: var(--rut-btn-clear-text);
241
- border: 1px solid var(--rut-btn-clear-border);
242
- border-radius: 0.5rem;
243
- font-size: 0.875rem;
244
- font-weight: 500;
245
- cursor: pointer;
246
- transition: opacity 0.15s;
247
- }
248
-
249
- .rut-btn-secondary:hover {
250
- opacity: 0.8;
251
- }
252
-
253
- .rut-btn-icon {
254
- flex-shrink: 0;
255
- }
256
-
257
- .rut-icon-spin {
258
- display: none;
259
- animation: rut-spin 1s linear infinite;
260
- }
261
-
262
- @keyframes rut-spin {
263
- to { transform: rotate(360deg); }
264
- }
265
-
266
- .rut-btn-primary[data-loading] .rut-icon-chart {
267
- display: none;
268
- }
269
-
270
- .rut-btn-primary[data-loading] .rut-icon-spin {
271
- display: block;
272
- }
273
-
274
- .rut-stats-panel {
275
- margin-top: 1rem;
276
- padding: 1rem;
277
- background: var(--rut-stats-bg);
278
- border: 1px solid var(--rut-stats-border);
279
- border-radius: 0.5rem;
280
- }
281
-
282
- .rut-stats-label {
283
- font-size: 0.875rem;
284
- font-weight: 500;
285
- color: var(--rut-stats-label);
286
- }
287
-
288
- .rut-stats-value {
289
- font-size: 1.5rem;
290
- font-weight: 700;
291
- color: var(--rut-stats-value);
292
- }
293
-
294
- .rut-map-area {
295
- position: relative;
296
- height: 50%;
297
- order: 0;
298
- }
299
-
300
- @media (min-width: 1024px) {
301
- .rut-map-area {
302
- height: 100%;
303
- order: 2;
304
- }
305
- }
306
-
307
- .rut-map {
308
- width: 100%;
309
- height: 100%;
310
- background: var(--rut-map-bg);
311
- }
312
-
313
- :global(.rut-hidden) {
314
- display: none;
315
- }
316
- </style>
317
63
 
318
64
  <style is:global>
319
65
  .rut-icon-container {
@@ -0,0 +1,24 @@
1
+ import type { ToolsToolEntry } from '../../types';
2
+ import type { RoutesUI } from './ui';
3
+
4
+ export const routes: ToolsToolEntry<RoutesUI> = {
5
+ id: 'routes',
6
+ icons: { bg: 'mdi:map-marker-path', fg: 'mdi:map-search' },
7
+ i18n: {
8
+ de: () => import('./i18n/de').then((m) => m.content),
9
+ en: () => import('./i18n/en').then((m) => m.content),
10
+ es: () => import('./i18n/es').then((m) => m.content),
11
+ fr: () => import('./i18n/fr').then((m) => m.content),
12
+ id: () => import('./i18n/id').then((m) => m.content),
13
+ it: () => import('./i18n/it').then((m) => m.content),
14
+ ja: () => import('./i18n/ja').then((m) => m.content),
15
+ ko: () => import('./i18n/ko').then((m) => m.content),
16
+ nl: () => import('./i18n/nl').then((m) => m.content),
17
+ pl: () => import('./i18n/pl').then((m) => m.content),
18
+ pt: () => import('./i18n/pt').then((m) => m.content),
19
+ ru: () => import('./i18n/ru').then((m) => m.content),
20
+ sv: () => import('./i18n/sv').then((m) => m.content),
21
+ tr: () => import('./i18n/tr').then((m) => m.content),
22
+ zh: () => import('./i18n/zh').then((m) => m.content),
23
+ },
24
+ };
@@ -1,28 +1,5 @@
1
- import type { ToolDefinition, ToolsToolEntry } from '../../types';
2
- import type { RoutesUI } from './ui';
3
-
4
- export const routes: ToolsToolEntry<RoutesUI> = {
5
- id: 'routes',
6
- icons: { bg: 'mdi:map-marker-path', fg: 'mdi:map-search' },
7
- i18n: {
8
- de: () => import('./i18n/de').then((m) => m.content),
9
- en: () => import('./i18n/en').then((m) => m.content),
10
- es: () => import('./i18n/es').then((m) => m.content),
11
- fr: () => import('./i18n/fr').then((m) => m.content),
12
- id: () => import('./i18n/id').then((m) => m.content),
13
- it: () => import('./i18n/it').then((m) => m.content),
14
- ja: () => import('./i18n/ja').then((m) => m.content),
15
- ko: () => import('./i18n/ko').then((m) => m.content),
16
- nl: () => import('./i18n/nl').then((m) => m.content),
17
- pl: () => import('./i18n/pl').then((m) => m.content),
18
- pt: () => import('./i18n/pt').then((m) => m.content),
19
- ru: () => import('./i18n/ru').then((m) => m.content),
20
- sv: () => import('./i18n/sv').then((m) => m.content),
21
- tr: () => import('./i18n/tr').then((m) => m.content),
22
- zh: () => import('./i18n/zh').then((m) => m.content),
23
- },
24
- };
25
-
1
+ import { routes } from './entry';
2
+ export * from './entry';
26
3
  export const ROUTES_TOOL: ToolDefinition = {
27
4
  entry: routes,
28
5
  Component: () => import('./component.astro'),