@jjlmoya/utils-diy 1.14.0 → 1.16.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 (46) hide show
  1. package/package.json +1 -1
  2. package/src/entries.ts +3 -1
  3. package/src/index.ts +2 -0
  4. package/src/tests/locale_completeness.test.ts +2 -2
  5. package/src/tests/tool_validation.test.ts +2 -2
  6. package/src/tool/pythagoreanRightAngleCalculator/component.astro +16 -11
  7. package/src/tool/pythagoreanRightAngleCalculator/i18n/de.ts +2 -0
  8. package/src/tool/pythagoreanRightAngleCalculator/i18n/es.ts +2 -0
  9. package/src/tool/pythagoreanRightAngleCalculator/i18n/fr.ts +2 -0
  10. package/src/tool/pythagoreanRightAngleCalculator/i18n/id.ts +2 -0
  11. package/src/tool/pythagoreanRightAngleCalculator/i18n/it.ts +3 -1
  12. package/src/tool/pythagoreanRightAngleCalculator/i18n/ja.ts +2 -0
  13. package/src/tool/pythagoreanRightAngleCalculator/i18n/nl.ts +2 -0
  14. package/src/tool/pythagoreanRightAngleCalculator/i18n/pl.ts +2 -0
  15. package/src/tool/pythagoreanRightAngleCalculator/i18n/pt.ts +3 -1
  16. package/src/tool/pythagoreanRightAngleCalculator/i18n/ru.ts +2 -0
  17. package/src/tool/pythagoreanRightAngleCalculator/i18n/sv.ts +2 -0
  18. package/src/tool/pythagoreanRightAngleCalculator/i18n/tr.ts +2 -0
  19. package/src/tool/pythagoreanRightAngleCalculator/i18n/zh.ts +2 -0
  20. package/src/tool/pythagoreanRightAngleCalculator/logic.ts +37 -31
  21. package/src/tool/pythagoreanRightAngleCalculator/pythagorean-right-angle-calculator.css +13 -4
  22. package/src/tool/twoStrokeMixtureCalculator/bibliography.astro +6 -0
  23. package/src/tool/twoStrokeMixtureCalculator/bibliography.ts +12 -0
  24. package/src/tool/twoStrokeMixtureCalculator/component.astro +266 -0
  25. package/src/tool/twoStrokeMixtureCalculator/entry.ts +24 -0
  26. package/src/tool/twoStrokeMixtureCalculator/i18n/de.ts +194 -0
  27. package/src/tool/twoStrokeMixtureCalculator/i18n/en.ts +194 -0
  28. package/src/tool/twoStrokeMixtureCalculator/i18n/es.ts +194 -0
  29. package/src/tool/twoStrokeMixtureCalculator/i18n/fr.ts +194 -0
  30. package/src/tool/twoStrokeMixtureCalculator/i18n/id.ts +194 -0
  31. package/src/tool/twoStrokeMixtureCalculator/i18n/it.ts +194 -0
  32. package/src/tool/twoStrokeMixtureCalculator/i18n/ja.ts +194 -0
  33. package/src/tool/twoStrokeMixtureCalculator/i18n/ko.ts +194 -0
  34. package/src/tool/twoStrokeMixtureCalculator/i18n/nl.ts +194 -0
  35. package/src/tool/twoStrokeMixtureCalculator/i18n/pl.ts +194 -0
  36. package/src/tool/twoStrokeMixtureCalculator/i18n/pt.ts +194 -0
  37. package/src/tool/twoStrokeMixtureCalculator/i18n/ru.ts +194 -0
  38. package/src/tool/twoStrokeMixtureCalculator/i18n/sv.ts +194 -0
  39. package/src/tool/twoStrokeMixtureCalculator/i18n/tr.ts +194 -0
  40. package/src/tool/twoStrokeMixtureCalculator/i18n/zh.ts +194 -0
  41. package/src/tool/twoStrokeMixtureCalculator/index.ts +11 -0
  42. package/src/tool/twoStrokeMixtureCalculator/logic.ts +92 -0
  43. package/src/tool/twoStrokeMixtureCalculator/seo.astro +15 -0
  44. package/src/tool/twoStrokeMixtureCalculator/two-stroke-fuel-mixture-calculator.css +405 -0
  45. package/src/tool/twoStrokeMixtureCalculator/ui.ts +81 -0
  46. package/src/tools.ts +2 -1
@@ -0,0 +1,405 @@
1
+ :root {
2
+ --tsmc-primary: #ea580c;
3
+ --tsmc-secondary: #fbbf24;
4
+ --tsmc-accent-oil: #dc2626;
5
+ --tsmc-neutral: #1e293b;
6
+ --tsmc-neutral-light: #64748b;
7
+ --tsmc-border: #e2e8f0;
8
+ --tsmc-bg: #fff;
9
+ --tsmc-bg-light: #f8fafc;
10
+ }
11
+
12
+ :root.theme-dark {
13
+ --tsmc-primary: #f97316;
14
+ --tsmc-secondary: #fcd34d;
15
+ --tsmc-accent-oil: #ef4444;
16
+ --tsmc-neutral: #f1f5f9;
17
+ --tsmc-neutral-light: #9ca3af;
18
+ --tsmc-border: rgba(255, 255, 255, 0.1);
19
+ --tsmc-bg: #0f172a;
20
+ --tsmc-bg-light: rgba(15, 23, 42, 0.8);
21
+ }
22
+
23
+ .tsmc-root {
24
+ width: 100%;
25
+ color: var(--tsmc-neutral);
26
+ -webkit-font-smoothing: antialiased;
27
+ -moz-osx-font-smoothing: grayscale;
28
+ background: var(--tsmc-bg);
29
+ }
30
+
31
+ .tsmc-mission-selector {
32
+ display: grid;
33
+ grid-template-columns: 1fr 1fr;
34
+ gap: 0.4rem;
35
+ padding: 0.75rem;
36
+ background: var(--tsmc-bg-light);
37
+ border-bottom: 2px solid var(--tsmc-primary);
38
+ }
39
+
40
+ .tsmc-mission-btn {
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ gap: 0.4rem;
45
+ padding: 0.6rem;
46
+ border: 2px solid var(--tsmc-border);
47
+ border-radius: 0.5rem;
48
+ background: var(--tsmc-bg);
49
+ color: var(--tsmc-neutral-light);
50
+ font-weight: 700;
51
+ font-size: 0.85rem;
52
+ cursor: pointer;
53
+ transition: all 150ms ease;
54
+ }
55
+
56
+ .tsmc-mission-btn.active {
57
+ border-color: var(--tsmc-primary);
58
+ background: var(--tsmc-primary);
59
+ color: #fff;
60
+ box-shadow: 0 4px 8px rgba(234, 88, 12, 0.25);
61
+ }
62
+
63
+ .tsmc-mission-btn svg {
64
+ width: 18px;
65
+ height: 18px;
66
+ }
67
+
68
+ .tsmc-container {
69
+ display: flex;
70
+ flex-direction: column;
71
+ gap: 1rem;
72
+ padding: 1rem;
73
+ max-width: 100%;
74
+ transition: background-color 300ms ease;
75
+ }
76
+
77
+ .tsmc-container.tsmc-oil-mode {
78
+ background: linear-gradient(135deg, rgba(34, 197, 94, 0.08) 0%, rgba(34, 197, 94, 0.04) 100%);
79
+ }
80
+
81
+ .tsmc-oil-mode .tsmc-mission-selector {
82
+ background: rgba(34, 197, 94, 0.1);
83
+ border-bottom-color: #22c55e;
84
+ }
85
+
86
+ .tsmc-oil-mode .tsmc-mission-btn.active {
87
+ background: #22c55e;
88
+ border-color: #22c55e;
89
+ box-shadow: 0 4px 8px rgba(34, 197, 94, 0.25);
90
+ }
91
+
92
+ .tsmc-oil-mode .tsmc-slider {
93
+ background: linear-gradient(to right, #86efac, #22c55e);
94
+ }
95
+
96
+ .tsmc-oil-mode .tsmc-slider::-webkit-slider-thumb {
97
+ background: #22c55e;
98
+ box-shadow: 0 2px 6px rgba(34, 197, 94, 0.4);
99
+ }
100
+
101
+ .tsmc-oil-mode .tsmc-slider::-moz-range-thumb {
102
+ background: #22c55e;
103
+ box-shadow: 0 2px 6px rgba(34, 197, 94, 0.4);
104
+ }
105
+
106
+ .tsmc-oil-mode .tsmc-slider-value-display {
107
+ color: #22c55e;
108
+ }
109
+
110
+ .tsmc-oil-mode .tsmc-quick-btn.active {
111
+ background: #22c55e;
112
+ border-color: #22c55e;
113
+ box-shadow: 0 3px 8px rgba(34, 197, 94, 0.25);
114
+ }
115
+
116
+ .tsmc-oil-mode .tsmc-mega-result {
117
+ border-color: #22c55e;
118
+ background: linear-gradient(135deg, rgba(34, 197, 94, 0.12) 0%, rgba(34, 197, 94, 0.06) 100%);
119
+ }
120
+
121
+ .tsmc-oil-mode .tsmc-result-label,
122
+ .tsmc-oil-mode .tsmc-result-big {
123
+ color: #22c55e;
124
+ }
125
+
126
+ .tsmc-oil-mode .tsmc-reset-btn {
127
+ border-color: #22c55e;
128
+ color: #22c55e;
129
+ }
130
+
131
+ .tsmc-oil-mode .tsmc-reset-btn:hover {
132
+ background: #22c55e;
133
+ color: #fff;
134
+ }
135
+
136
+ .tsmc-input-section,
137
+ .tsmc-ratio-section {
138
+ display: flex;
139
+ flex-direction: column;
140
+ gap: 0.6rem;
141
+ }
142
+
143
+ .tsmc-section-label {
144
+ font-size: 0.65rem;
145
+ font-weight: 800;
146
+ color: var(--tsmc-neutral);
147
+ text-transform: uppercase;
148
+ letter-spacing: 0.6px;
149
+ }
150
+
151
+ .tsmc-slider-container {
152
+ display: flex;
153
+ flex-direction: column;
154
+ gap: 0.6rem;
155
+ }
156
+
157
+ .tsmc-slider {
158
+ width: 100%;
159
+ height: 10px;
160
+ border-radius: 5px;
161
+ background: linear-gradient(to right, #fcd34d, #f97316);
162
+ outline: none;
163
+ -webkit-appearance: none;
164
+ appearance: none;
165
+ cursor: pointer;
166
+ }
167
+
168
+ .tsmc-slider::-webkit-slider-thumb {
169
+ -webkit-appearance: none;
170
+ appearance: none;
171
+ width: 24px;
172
+ height: 24px;
173
+ border-radius: 50%;
174
+ background: var(--tsmc-primary);
175
+ cursor: grab;
176
+ box-shadow: 0 2px 6px rgba(234, 88, 12, 0.4);
177
+ border: 2px solid var(--tsmc-bg);
178
+ }
179
+
180
+ .tsmc-slider::-moz-range-thumb {
181
+ width: 24px;
182
+ height: 24px;
183
+ border-radius: 50%;
184
+ background: var(--tsmc-primary);
185
+ cursor: grab;
186
+ box-shadow: 0 2px 6px rgba(234, 88, 12, 0.4);
187
+ border: 2px solid var(--tsmc-bg);
188
+ }
189
+
190
+ .tsmc-slider-value-display {
191
+ text-align: center;
192
+ font-size: 1.8rem;
193
+ font-weight: 800;
194
+ color: var(--tsmc-primary);
195
+ line-height: 1;
196
+ }
197
+
198
+ .tsmc-unit {
199
+ font-size: 1rem;
200
+ margin-left: 0.3rem;
201
+ color: var(--tsmc-neutral);
202
+ }
203
+
204
+ .tsmc-quick-buttons {
205
+ display: grid;
206
+ grid-template-columns: 1fr 1fr 1fr;
207
+ gap: 0.4rem;
208
+ }
209
+
210
+ .tsmc-quick-btn {
211
+ padding: 0.6rem 0.5rem;
212
+ border: 2px solid var(--tsmc-border);
213
+ border-radius: 0.4rem;
214
+ background: var(--tsmc-bg-light);
215
+ color: var(--tsmc-neutral);
216
+ font-weight: 700;
217
+ font-size: 0.8rem;
218
+ cursor: pointer;
219
+ transition: all 120ms ease;
220
+ }
221
+
222
+ .tsmc-quick-btn:active {
223
+ transform: scale(0.95);
224
+ }
225
+
226
+ .tsmc-quick-btn.active {
227
+ background: var(--tsmc-primary);
228
+ color: #fff;
229
+ border-color: var(--tsmc-primary);
230
+ box-shadow: 0 3px 8px rgba(234, 88, 12, 0.25);
231
+ }
232
+
233
+ .tsmc-quick-btn.hidden {
234
+ display: none;
235
+ }
236
+
237
+ .tsmc-ratio-cards {
238
+ display: grid;
239
+ grid-template-columns: 1fr 1fr;
240
+ gap: 0.5rem;
241
+ }
242
+
243
+ .tsmc-ratio-card {
244
+ padding: 0.75rem;
245
+ border: 2px solid var(--tsmc-border);
246
+ border-radius: 0.5rem;
247
+ background: var(--tsmc-bg-light);
248
+ color: var(--tsmc-neutral);
249
+ cursor: pointer;
250
+ transition: all 150ms ease;
251
+ display: flex;
252
+ flex-direction: column;
253
+ gap: 0.3rem;
254
+ align-items: center;
255
+ text-align: center;
256
+ }
257
+
258
+ .tsmc-ratio-card:hover {
259
+ border-color: var(--tsmc-primary);
260
+ background: var(--tsmc-bg);
261
+ }
262
+
263
+ .tsmc-ratio-card.active {
264
+ background: var(--tsmc-primary);
265
+ color: #fff;
266
+ border-color: var(--tsmc-primary);
267
+ box-shadow: 0 4px 10px rgba(234, 88, 12, 0.25);
268
+ }
269
+
270
+ .tsmc-ratio-value {
271
+ font-size: 1rem;
272
+ font-weight: 800;
273
+ }
274
+
275
+ .tsmc-ratio-desc {
276
+ font-size: 0.7rem;
277
+ font-weight: 700;
278
+ opacity: 0.9;
279
+ line-height: 1.3;
280
+ }
281
+
282
+ .tsmc-mega-result {
283
+ background: linear-gradient(135deg, rgba(234, 88, 12, 0.12) 0%, rgba(251, 191, 36, 0.06) 100%);
284
+ border: 2.5px solid var(--tsmc-primary);
285
+ border-radius: 0.75rem;
286
+ padding: 1rem;
287
+ display: flex;
288
+ flex-direction: column;
289
+ gap: 0.8rem;
290
+ align-items: center;
291
+ text-align: center;
292
+ }
293
+
294
+ .tsmc-result-label {
295
+ font-size: 0.65rem;
296
+ font-weight: 800;
297
+ color: var(--tsmc-primary);
298
+ text-transform: uppercase;
299
+ letter-spacing: 0.5px;
300
+ }
301
+
302
+ .tsmc-result-display {
303
+ display: flex;
304
+ align-items: baseline;
305
+ justify-content: center;
306
+ gap: 0.3rem;
307
+ }
308
+
309
+ .tsmc-result-big {
310
+ font-size: 2.8rem;
311
+ font-weight: 900;
312
+ color: var(--tsmc-primary);
313
+ line-height: 1;
314
+ letter-spacing: -1px;
315
+ }
316
+
317
+ .tsmc-result-unit {
318
+ font-size: 1rem;
319
+ font-weight: 700;
320
+ color: var(--tsmc-neutral);
321
+ }
322
+
323
+ .tsmc-container-visual {
324
+ width: 100%;
325
+ max-width: 120px;
326
+ height: auto;
327
+ }
328
+
329
+ .tsmc-share-btn {
330
+ padding: 0.6rem;
331
+ border: 2px solid var(--tsmc-primary);
332
+ border-radius: 0.4rem;
333
+ background: var(--tsmc-bg);
334
+ color: var(--tsmc-primary);
335
+ cursor: pointer;
336
+ transition: all 150ms ease;
337
+ width: 100%;
338
+ display: flex;
339
+ align-items: center;
340
+ justify-content: center;
341
+ }
342
+
343
+ .tsmc-share-btn:hover {
344
+ background: var(--tsmc-primary);
345
+ color: #fff;
346
+ }
347
+
348
+ .tsmc-share-btn svg {
349
+ width: 20px;
350
+ height: 20px;
351
+ }
352
+
353
+ .tsmc-oil-mode .tsmc-share-btn {
354
+ border-color: #22c55e;
355
+ color: #22c55e;
356
+ }
357
+
358
+ .tsmc-oil-mode .tsmc-share-btn:hover {
359
+ background: #22c55e;
360
+ color: #fff;
361
+ }
362
+
363
+ .tsmc-checklist {
364
+ display: flex;
365
+ flex-direction: column;
366
+ gap: 0.5rem;
367
+ padding: 0.75rem;
368
+ background: var(--tsmc-bg-light);
369
+ border-radius: 0.5rem;
370
+ border: 1.5px solid var(--tsmc-border);
371
+ }
372
+
373
+ .tsmc-checklist-item {
374
+ display: flex;
375
+ align-items: center;
376
+ gap: 0.6rem;
377
+ font-weight: 600;
378
+ font-size: 0.8rem;
379
+ color: var(--tsmc-neutral);
380
+ }
381
+
382
+ .tsmc-checklist-item svg {
383
+ width: 18px;
384
+ height: 18px;
385
+ color: var(--tsmc-primary);
386
+ flex-shrink: 0;
387
+ }
388
+
389
+ @media (min-width: 480px) {
390
+ .tsmc-quick-buttons {
391
+ grid-template-columns: repeat(5, 1fr);
392
+ }
393
+ }
394
+
395
+ @media (min-width: 768px) {
396
+ .tsmc-container {
397
+ padding: 1.5rem;
398
+ max-width: 500px;
399
+ margin: 0 auto;
400
+ }
401
+
402
+ .tsmc-ratio-cards {
403
+ grid-template-columns: repeat(4, 1fr);
404
+ }
405
+ }
@@ -0,0 +1,81 @@
1
+ export interface TwoStrokeMixtureCalculatorUI extends Record<string, string> {
2
+ titleMain: string;
3
+ labelFuelVolume: string;
4
+ labelRatio: string;
5
+ labelOilRequired: string;
6
+ labelTotalMixture: string;
7
+ labelRichness: string;
8
+ labelPresets: string;
9
+ labelCustomRatio: string;
10
+ btnClear: string;
11
+ btnCopyResults: string;
12
+ btnSwitchMode: string;
13
+ unitLiters: string;
14
+ unitMilliliters: string;
15
+ richLean: string;
16
+ richBalanced: string;
17
+ richRich: string;
18
+ msgReady: string;
19
+ msgMixtureReady: string;
20
+ tooltipFuelVolume: string;
21
+ tooltipRatio: string;
22
+ recipientLabel: string;
23
+ oilPercentage: string;
24
+ labelVolume: string;
25
+ labelRatioShort: string;
26
+ labelOilTip: string;
27
+ labelMixingTips: string;
28
+ labelMixingTipsDesc: string;
29
+ recipePrefix: string;
30
+ recipeAt: string;
31
+ recipeAdd: string;
32
+ recipeOfOil: string;
33
+ copyTextPrefix: string;
34
+ copyTextFuel: string;
35
+ copyTextOil: string;
36
+ ratio25Desc: string;
37
+ ratio33Desc: string;
38
+ ratio40Desc: string;
39
+ ratio50Desc: string;
40
+ }
41
+
42
+ export const twoStrokeMixtureCalculatorUI: TwoStrokeMixtureCalculatorUI = {
43
+ titleMain: 'Two Stroke Fuel Mixture Calculator',
44
+ labelFuelVolume: 'Fuel Volume',
45
+ labelRatio: 'Mix Ratio',
46
+ labelOilRequired: 'Oil Required',
47
+ labelTotalMixture: 'Total Mixture',
48
+ labelRichness: 'Mixture Richness',
49
+ labelPresets: 'Common Ratios',
50
+ labelCustomRatio: 'Custom Ratio (1:X)',
51
+ btnClear: 'Clear',
52
+ btnCopyResults: 'Copy Results',
53
+ btnSwitchMode: 'Switch Mode',
54
+ unitLiters: 'L',
55
+ unitMilliliters: 'ml',
56
+ richLean: 'Lean (less oil, risk of seizure)',
57
+ richBalanced: 'Balanced (standard mix)',
58
+ richRich: 'Rich (more oil, more smoke, engine protection)',
59
+ msgReady: 'Ready',
60
+ msgMixtureReady: 'Mixture calculated',
61
+ tooltipFuelVolume: 'Enter the amount of gasoline',
62
+ tooltipRatio: 'Enter ratio as 25, 33, 40, or 50 (for 1:25, 1:33, etc.)',
63
+ recipientLabel: 'Mixture Container',
64
+ oilPercentage: 'Oil %',
65
+ labelVolume: 'Volume',
66
+ labelRatioShort: 'Ratio',
67
+ labelOilTip: '2% oil mix = 1:50 ratio',
68
+ labelMixingTips: 'Mixing Tips',
69
+ labelMixingTipsDesc: 'Mix in a clean container—gasoline first, add measured oil, then remaining fuel. Shake well (1-2 minutes) for homogeneous blend. Label with date and ratio.',
70
+ recipePrefix: 'For',
71
+ recipeAt: 'of fuel at',
72
+ recipeAdd: 'add exactly',
73
+ recipeOfOil: 'of 2-stroke oil.',
74
+ copyTextPrefix: '2-Stroke Mix',
75
+ copyTextFuel: 'fuel',
76
+ copyTextOil: 'oil',
77
+ ratio25Desc: 'Old machines',
78
+ ratio33Desc: 'Classic models',
79
+ ratio40Desc: 'Standard recommended',
80
+ ratio50Desc: 'Modern chainsaws',
81
+ };
package/src/tools.ts CHANGED
@@ -15,6 +15,7 @@ import { STAIR_CALCULATOR_TOOL } from './tool/stairCalculator/index';
15
15
  import { DRILL_SHARPENER_TOOL } from './tool/drillSharpener/index';
16
16
  import { WORKSHOP_FRACTION_CONVERTER_TOOL } from './tool/workshopFractionConverter/index';
17
17
  import { PYTHAGOREAN_RIGHT_ANGLE_CALCULATOR_TOOL } from './tool/pythagoreanRightAngleCalculator/index';
18
+ import { TWO_STROKE_MIXTURE_CALCULATOR_TOOL } from './tool/twoStrokeMixtureCalculator/index';
18
19
 
19
- export const ALL_TOOLS: ToolDefinition[] = [CLAY_CALCULATOR_TOOL, EPOXY_CALCULATOR_TOOL, BALUSTER_CALCULATOR_TOOL, MORTAR_CALCULATOR_TOOL, PASSEPARTOUT_CALCULATOR_TOOL, CONCRETE_CALCULATOR_TOOL, CUT_OPTIMIZER_TOOL, VOLTAGE_DROP_CALCULATOR_TOOL, FURNITURE_FIT_TOOL, THERMAL_EXPANSION_CALCULATOR_TOOL, DRILL_CALCULATOR_TOOL, STAIR_CALCULATOR_TOOL, DRILL_SHARPENER_TOOL, WORKSHOP_FRACTION_CONVERTER_TOOL, PYTHAGOREAN_RIGHT_ANGLE_CALCULATOR_TOOL];
20
+ export const ALL_TOOLS: ToolDefinition[] = [CLAY_CALCULATOR_TOOL, EPOXY_CALCULATOR_TOOL, BALUSTER_CALCULATOR_TOOL, MORTAR_CALCULATOR_TOOL, PASSEPARTOUT_CALCULATOR_TOOL, CONCRETE_CALCULATOR_TOOL, CUT_OPTIMIZER_TOOL, VOLTAGE_DROP_CALCULATOR_TOOL, FURNITURE_FIT_TOOL, THERMAL_EXPANSION_CALCULATOR_TOOL, DRILL_CALCULATOR_TOOL, STAIR_CALCULATOR_TOOL, DRILL_SHARPENER_TOOL, WORKSHOP_FRACTION_CONVERTER_TOOL, PYTHAGOREAN_RIGHT_ANGLE_CALCULATOR_TOOL, TWO_STROKE_MIXTURE_CALCULATOR_TOOL];
20
21