@jjlmoya/utils-sports 1.29.0 → 1.30.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 (31) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -0
  3. package/src/entries.ts +4 -1
  4. package/src/tests/locale_completeness.test.ts +1 -1
  5. package/src/tests/tool_validation.test.ts +2 -2
  6. package/src/tool/baseballScoreKeeper/baseball-scorekeeper.css +419 -0
  7. package/src/tool/baseballScoreKeeper/bibliography.astro +6 -0
  8. package/src/tool/baseballScoreKeeper/bibliography.ts +10 -0
  9. package/src/tool/baseballScoreKeeper/component.astro +144 -0
  10. package/src/tool/baseballScoreKeeper/entry.ts +30 -0
  11. package/src/tool/baseballScoreKeeper/i18n/de.ts +198 -0
  12. package/src/tool/baseballScoreKeeper/i18n/en.ts +198 -0
  13. package/src/tool/baseballScoreKeeper/i18n/es.ts +198 -0
  14. package/src/tool/baseballScoreKeeper/i18n/fr.ts +198 -0
  15. package/src/tool/baseballScoreKeeper/i18n/id.ts +198 -0
  16. package/src/tool/baseballScoreKeeper/i18n/it.ts +198 -0
  17. package/src/tool/baseballScoreKeeper/i18n/ja.ts +198 -0
  18. package/src/tool/baseballScoreKeeper/i18n/ko.ts +198 -0
  19. package/src/tool/baseballScoreKeeper/i18n/nl.ts +198 -0
  20. package/src/tool/baseballScoreKeeper/i18n/pl.ts +198 -0
  21. package/src/tool/baseballScoreKeeper/i18n/pt.ts +198 -0
  22. package/src/tool/baseballScoreKeeper/i18n/ru.ts +198 -0
  23. package/src/tool/baseballScoreKeeper/i18n/sv.ts +198 -0
  24. package/src/tool/baseballScoreKeeper/i18n/tr.ts +198 -0
  25. package/src/tool/baseballScoreKeeper/i18n/zh.ts +198 -0
  26. package/src/tool/baseballScoreKeeper/index.ts +10 -0
  27. package/src/tool/baseballScoreKeeper/logic.ts +156 -0
  28. package/src/tool/baseballScoreKeeper/seo.astro +15 -0
  29. package/src/tool/baseballScoreKeeper/ui-init.ts +127 -0
  30. package/src/tool/baseballScoreKeeper/ui.ts +31 -0
  31. package/src/tools.ts +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jjlmoya/utils-sports",
3
- "version": "1.29.0",
3
+ "version": "1.30.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -7,6 +7,7 @@ import { gymTracker } from '../tool/gymTracker/index';
7
7
  import { reactionTester } from '../tool/reactionTester/index';
8
8
  import { pingPongScoreKeeper } from '../tool/pingPongScoreKeeper/index';
9
9
  import { rugbyScoreKeeper } from '../tool/rugbyScoreKeeper/index';
10
+ import { baseballScoreKeeper } from '../tool/baseballScoreKeeper/index';
10
11
 
11
12
  export const sportsCategory: SportsCategoryEntry = {
12
13
  icon: 'mdi:soccer',
@@ -19,6 +20,7 @@ export const sportsCategory: SportsCategoryEntry = {
19
20
  reactionTester,
20
21
  pingPongScoreKeeper,
21
22
  rugbyScoreKeeper,
23
+ baseballScoreKeeper,
22
24
  ] as unknown as SportsToolEntry<Record<string, string>>[],
23
25
  i18n: {
24
26
  es: () => import('./i18n/es').then((m) => m.content),
package/src/entries.ts CHANGED
@@ -26,6 +26,8 @@ export { snookerScoreKeeper } from './tool/snookerScoreKeeper/entry';
26
26
  export type { SnookerScoreKeeperLocaleContent } from './tool/snookerScoreKeeper/entry';
27
27
  export { rugbyScoreKeeper } from './tool/rugbyScoreKeeper/entry';
28
28
  export type { RugbyScoreKeeperLocaleContent } from './tool/rugbyScoreKeeper/entry';
29
+ export { baseballScoreKeeper } from './tool/baseballScoreKeeper/entry';
30
+ export type { BaseballScoreKeeperLocaleContent } from './tool/baseballScoreKeeper/entry';
29
31
  export { sportsCategory } from './category';
30
32
  import { basketScoreKeeper } from './tool/basketScoreKeeper/entry';
31
33
  import { footballScoreKeeper } from './tool/footballScoreKeeper/entry';
@@ -41,5 +43,6 @@ import { streetballScoreKeeper } from './tool/streetballScoreKeeper/entry';
41
43
  import { beachVolleyballScoreKeeper } from './tool/beachVolleyballScoreKeeper/entry';
42
44
  import { snookerScoreKeeper } from './tool/snookerScoreKeeper/entry';
43
45
  import { rugbyScoreKeeper } from './tool/rugbyScoreKeeper/entry';
44
- export const ALL_ENTRIES = [basketScoreKeeper, footballScoreKeeper, gymTracker, pingPongScoreKeeper, reactionTester, scoreKeeper, tournamentBracket, tennisScoreKeeper, dartsScoreKeeper, padelScoreKeeper, streetballScoreKeeper, beachVolleyballScoreKeeper, snookerScoreKeeper, rugbyScoreKeeper];
46
+ import { baseballScoreKeeper } from './tool/baseballScoreKeeper/entry';
47
+ export const ALL_ENTRIES = [basketScoreKeeper, footballScoreKeeper, gymTracker, pingPongScoreKeeper, reactionTester, scoreKeeper, tournamentBracket, tennisScoreKeeper, dartsScoreKeeper, padelScoreKeeper, streetballScoreKeeper, beachVolleyballScoreKeeper, snookerScoreKeeper, rugbyScoreKeeper, baseballScoreKeeper];
45
48
 
@@ -3,6 +3,6 @@ import { ALL_TOOLS } from '../tools';
3
3
 
4
4
  describe('Locale Completeness Validation', () => {
5
5
  it('all tools registered', () => {
6
- expect(ALL_TOOLS.length).toBe(14);
6
+ expect(ALL_TOOLS.length).toBe(15);
7
7
  });
8
8
  });
@@ -4,8 +4,8 @@ import { sportsCategory } from '../data';
4
4
 
5
5
  describe('Tool Validation Suite', () => {
6
6
  describe('Library Registration', () => {
7
- it('should have 14 tools in ALL_TOOLS', () => {
8
- expect(ALL_TOOLS.length).toBe(14);
7
+ it('should have 15 tools in ALL_TOOLS', () => {
8
+ expect(ALL_TOOLS.length).toBe(15);
9
9
  });
10
10
 
11
11
  it('sportsCategory should be defined', () => {
@@ -0,0 +1,419 @@
1
+ .bb-app {
2
+ --bb-bg-page: var(--bg-page);
3
+ --bb-bg-surface: var(--bg-surface);
4
+ --bb-bg-muted: var(--bg-muted);
5
+ --bb-border: var(--border-base);
6
+ --bb-text: var(--text-base);
7
+ --bb-text-dim: var(--text-muted);
8
+ --bb-clay: #c49a6c;
9
+ --bb-grass: #5a8f4a;
10
+ --bb-grass-bg: rgba(90, 143, 74, 0.12);
11
+ --bb-gold: #e3b341;
12
+ --bb-danger: #da3633;
13
+ --bb-strike: #da3633;
14
+ --bb-ball: #e3b341;
15
+ --bb-out: #636363;
16
+
17
+ background: var(--bb-bg-page);
18
+ color: var(--bb-text);
19
+ max-width: 780px;
20
+ margin: 0 auto;
21
+ padding: 16px;
22
+ position: relative;
23
+ overflow: hidden;
24
+ }
25
+
26
+ .bb-main-card {
27
+ background: var(--bb-bg-surface);
28
+ border: 1px solid var(--bb-border);
29
+ border-radius: 14px;
30
+ padding: 16px;
31
+ display: flex;
32
+ flex-direction: column;
33
+ gap: 14px;
34
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
35
+ }
36
+
37
+ .bb-strip {
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: space-between;
41
+ background: var(--bb-bg-muted);
42
+ border: 1px solid var(--bb-border);
43
+ border-radius: 12px;
44
+ padding: 12px 20px;
45
+ }
46
+
47
+ .bb-team {
48
+ text-align: center;
49
+ flex: 1;
50
+ }
51
+
52
+ .bb-name {
53
+ background: transparent;
54
+ border: none;
55
+ border-bottom: 2px solid var(--bb-border);
56
+ color: var(--bb-text);
57
+ font-size: 1rem;
58
+ text-align: center;
59
+ padding: 4px 8px;
60
+ outline: none;
61
+ width: 100%;
62
+ max-width: 130px;
63
+ }
64
+
65
+ .bb-name:focus {
66
+ border-color: var(--bb-gold);
67
+ }
68
+
69
+ .bb-score {
70
+ font-size: 2.8rem;
71
+ font-weight: 800;
72
+ color: var(--bb-gold);
73
+ line-height: 1;
74
+ margin-top: 4px;
75
+ }
76
+
77
+ .bb-divider {
78
+ text-align: center;
79
+ padding: 0 12px;
80
+ }
81
+
82
+ .bb-inning-badge {
83
+ font-size: 1rem;
84
+ font-weight: 700;
85
+ background: var(--bb-border);
86
+ color: var(--bb-text);
87
+ padding: 4px 14px;
88
+ border-radius: 6px;
89
+ }
90
+
91
+ .bb-diamond-wrap {
92
+ display: flex;
93
+ justify-content: center;
94
+ align-items: center;
95
+ background: var(--bb-bg-muted);
96
+ border: 1px solid var(--bb-border);
97
+ border-radius: 12px;
98
+ padding: 12px;
99
+ }
100
+
101
+ .bb-diamond-svg {
102
+ width: 100%;
103
+ max-width: 280px;
104
+ height: auto;
105
+ }
106
+
107
+ .bb-diamond-bg {
108
+ fill: var(--bb-grass);
109
+ stroke: var(--bb-clay);
110
+ stroke-width: 2;
111
+ }
112
+
113
+ .bb-base {
114
+ fill: var(--bb-clay);
115
+ stroke: var(--bb-border);
116
+ stroke-width: 2;
117
+ cursor: pointer;
118
+ transition: all 0.15s;
119
+ }
120
+
121
+ .bb-base:hover {
122
+ filter: brightness(1.15);
123
+ }
124
+
125
+ .bb-base-active {
126
+ fill: var(--bb-gold);
127
+ stroke: #d49a20;
128
+ filter: drop-shadow(0 0 10px rgba(227, 179, 65, 0.6));
129
+ }
130
+
131
+ .bb-base-label {
132
+ font-size: 11px;
133
+ font-weight: 800;
134
+ fill: var(--bb-text);
135
+ text-anchor: middle;
136
+ dominant-baseline: central;
137
+ pointer-events: none;
138
+ }
139
+
140
+ .bb-home-plate {
141
+ fill: var(--bb-clay);
142
+ stroke: var(--bb-border);
143
+ stroke-width: 2;
144
+ }
145
+
146
+ .bb-count-row {
147
+ display: flex;
148
+ justify-content: center;
149
+ gap: 32px;
150
+ background: var(--bb-bg-muted);
151
+ border: 1px solid var(--bb-border);
152
+ border-radius: 12px;
153
+ padding: 10px 16px;
154
+ }
155
+
156
+ .bb-count-item {
157
+ display: flex;
158
+ flex-direction: column;
159
+ align-items: center;
160
+ gap: 4px;
161
+ }
162
+
163
+ .bb-count-label {
164
+ font-size: 0.7rem;
165
+ font-weight: 700;
166
+ color: var(--bb-text-dim);
167
+ text-transform: uppercase;
168
+ letter-spacing: 0.05em;
169
+ }
170
+
171
+ .bb-dots {
172
+ display: flex;
173
+ gap: 6px;
174
+ }
175
+
176
+ .bb-dot {
177
+ width: 18px;
178
+ height: 18px;
179
+ border-radius: 50%;
180
+ border: 2px solid var(--bb-border);
181
+ background: transparent;
182
+ transition: all 0.2s;
183
+ }
184
+
185
+ .bb-rhe-wrap {
186
+ background: var(--bb-bg-muted);
187
+ border: 1px solid var(--bb-border);
188
+ border-radius: 12px;
189
+ padding: 10px 14px;
190
+ }
191
+
192
+ .bb-rhe-table {
193
+ width: 100%;
194
+ border-collapse: collapse;
195
+ font-size: 0.9rem;
196
+ }
197
+
198
+ .bb-rhe-table th {
199
+ text-align: center;
200
+ padding: 6px 10px;
201
+ border-bottom: 1px solid var(--bb-border);
202
+ color: var(--bb-text-dim);
203
+ font-weight: 700;
204
+ font-size: 0.75rem;
205
+ }
206
+
207
+ .bb-rhe-table td {
208
+ text-align: center;
209
+ padding: 6px 10px;
210
+ border-bottom: 1px solid var(--bb-border);
211
+ font-weight: 700;
212
+ font-size: 1.1rem;
213
+ }
214
+
215
+ .bb-rhe-team {
216
+ font-weight: 800;
217
+ text-align: left;
218
+ font-size: 0.9rem;
219
+ }
220
+
221
+ .bb-th-runs {
222
+ color: var(--bb-gold);
223
+ }
224
+
225
+ .bb-th-hits {
226
+ color: var(--bb-grass);
227
+ }
228
+
229
+ .bb-th-errors {
230
+ color: var(--bb-strike);
231
+ }
232
+
233
+ .bb-inning-scroll {
234
+ background: var(--bb-bg-muted);
235
+ border: 1px solid var(--bb-border);
236
+ border-radius: 12px;
237
+ padding: 8px 12px;
238
+ overflow-x: auto;
239
+ }
240
+
241
+ .bb-inning-header {
242
+ display: flex;
243
+ gap: 4px;
244
+ padding-bottom: 4px;
245
+ border-bottom: 1px solid var(--bb-border);
246
+ margin-bottom: 4px;
247
+ }
248
+
249
+ .bb-ih-team {
250
+ width: 44px;
251
+ flex-shrink: 0;
252
+ }
253
+
254
+ .bb-ih-cell {
255
+ width: 32px;
256
+ text-align: center;
257
+ font-size: 0.75rem;
258
+ font-weight: 700;
259
+ color: var(--bb-text-dim);
260
+ flex-shrink: 0;
261
+ }
262
+
263
+ .bb-inning-row {
264
+ display: flex;
265
+ gap: 4px;
266
+ align-items: center;
267
+ padding: 3px 0;
268
+ }
269
+
270
+ .bb-ir-team {
271
+ width: 44px;
272
+ font-size: 0.8rem;
273
+ font-weight: 700;
274
+ flex-shrink: 0;
275
+ }
276
+
277
+ .bb-inning-cell {
278
+ width: 32px;
279
+ text-align: center;
280
+ font-size: 0.85rem;
281
+ font-weight: 600;
282
+ padding: 2px 0;
283
+ flex-shrink: 0;
284
+ }
285
+
286
+ .bb-btn-row {
287
+ display: flex;
288
+ gap: 6px;
289
+ }
290
+
291
+ .bb-btn {
292
+ flex: 1;
293
+ padding: 12px 8px;
294
+ border: 1px solid var(--bb-border);
295
+ border-radius: 10px;
296
+ background: var(--bb-bg-surface);
297
+ color: var(--bb-text);
298
+ font-size: 0.85rem;
299
+ font-weight: 700;
300
+ cursor: pointer;
301
+ user-select: none;
302
+ text-align: center;
303
+ transition: transform 0.1s;
304
+ }
305
+
306
+ .bb-btn:hover {
307
+ transform: scale(1.04);
308
+ }
309
+
310
+ .bb-btn:active {
311
+ transform: scale(0.95);
312
+ }
313
+
314
+ .bb-btn-strike {
315
+ background: var(--bb-strike);
316
+ border-color: var(--bb-strike);
317
+ color: var(--text-on-accent);
318
+ }
319
+
320
+ .bb-btn-ball {
321
+ background: var(--bb-ball);
322
+ border-color: var(--bb-ball);
323
+ color: #0d1117;
324
+ }
325
+
326
+ .bb-btn-foul {
327
+ background: var(--bb-bg-surface);
328
+ border-color: var(--bb-border);
329
+ }
330
+
331
+ .bb-btn-hit {
332
+ background: var(--bb-grass);
333
+ border-color: var(--bb-grass);
334
+ color: var(--text-on-accent);
335
+ }
336
+
337
+ .bb-btn-out {
338
+ background: var(--bb-out);
339
+ border-color: var(--bb-out);
340
+ color: var(--text-on-accent);
341
+ }
342
+
343
+ .bb-btn-row-secondary {
344
+ margin-top: -8px;
345
+ }
346
+
347
+ .bb-btn-run {
348
+ background: var(--bb-gold);
349
+ border-color: var(--bb-gold);
350
+ color: #0d1117;
351
+ }
352
+
353
+ .bb-btn-error {
354
+ background: var(--bb-bg-surface);
355
+ border-color: var(--bb-strike);
356
+ color: var(--bb-strike);
357
+ }
358
+
359
+ .bb-btn-reset {
360
+ background: var(--bb-danger);
361
+ color: var(--text-on-accent);
362
+ padding: 12px 20px;
363
+ font-size: 0.9rem;
364
+ border-radius: 10px;
365
+ border: none;
366
+ cursor: pointer;
367
+ font-weight: 700;
368
+ }
369
+
370
+ .bb-reset-modal {
371
+ display: none;
372
+ position: fixed;
373
+ inset: 0;
374
+ background: rgba(0, 0, 0, 0.4);
375
+ align-items: center;
376
+ justify-content: center;
377
+ z-index: 200;
378
+ }
379
+
380
+ .bb-modal-content {
381
+ background: var(--bb-bg-surface);
382
+ border: 1px solid var(--bb-border);
383
+ border-radius: 12px;
384
+ padding: 24px;
385
+ max-width: 300px;
386
+ text-align: center;
387
+ }
388
+
389
+ .bb-modal-text {
390
+ margin-bottom: 18px;
391
+ font-size: 1rem;
392
+ line-height: 1.4;
393
+ }
394
+
395
+ .bb-modal-btns {
396
+ display: flex;
397
+ gap: 10px;
398
+ justify-content: center;
399
+ }
400
+
401
+ .bb-btn-modal-cancel {
402
+ background: var(--bb-bg-muted);
403
+ color: var(--bb-text);
404
+ border: none;
405
+ padding: 10px 20px;
406
+ border-radius: 8px;
407
+ font-weight: 600;
408
+ cursor: pointer;
409
+ }
410
+
411
+ .bb-btn-modal-confirm {
412
+ background: var(--bb-danger);
413
+ color: var(--text-on-accent);
414
+ border: none;
415
+ padding: 10px 20px;
416
+ border-radius: 8px;
417
+ font-weight: 600;
418
+ cursor: pointer;
419
+ }
@@ -0,0 +1,6 @@
1
+ ---
2
+ import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
3
+ import { bibliography } from './bibliography';
4
+ ---
5
+
6
+ <SharedBibliography links={bibliography} />
@@ -0,0 +1,10 @@
1
+ export const bibliography = [
2
+ {
3
+ name: 'Major League Baseball Official Rules',
4
+ url: 'https://img.mlbstatic.com/mlb-images/image/upload/mlb/atcjzj9j7wrgvsm8wnjq.pdf',
5
+ },
6
+ {
7
+ name: 'World Baseball Softball Confederation Rules',
8
+ url: 'https://www.wbsc.org/en/organisation/baseball/game-rules',
9
+ },
10
+ ];
@@ -0,0 +1,144 @@
1
+ ---
2
+ import type { KnownLocale } from '../../types';
3
+ import type { BaseballScoreKeeperUI } from './ui';
4
+
5
+ interface Props {
6
+ locale?: KnownLocale;
7
+ ui?: Record<string, unknown>;
8
+ }
9
+
10
+ const { ui } = Astro.props;
11
+ const t = (ui ?? {}) as BaseballScoreKeeperUI;
12
+ ---
13
+
14
+ <div class="bb-app" id="bb-app" data-bb-ui={JSON.stringify(t)}>
15
+
16
+ <div class="bb-main-card">
17
+
18
+ <div class="bb-strip">
19
+ <div class="bb-team">
20
+ <input type="text" class="bb-name" id="bb-name-away" value={t.away} />
21
+ <div class="bb-score" id="bb-score-away">0</div>
22
+ </div>
23
+ <div class="bb-divider">
24
+ <span class="bb-inning-badge" id="bb-inning-label">Top 1</span>
25
+ </div>
26
+ <div class="bb-team">
27
+ <input type="text" class="bb-name" id="bb-name-home" value={t.home} />
28
+ <div class="bb-score" id="bb-score-home">0</div>
29
+ </div>
30
+ </div>
31
+
32
+ <div class="bb-diamond-wrap">
33
+ <svg class="bb-diamond-svg" viewBox="0 0 240 240">
34
+ <polygon class="bb-diamond-bg" points="120,12 228,120 120,228 12,120" />
35
+ <circle class="bb-base" id="bb-base-first" cx="190" cy="155" r="24" />
36
+ <circle class="bb-base" id="bb-base-second" cx="120" cy="50" r="24" />
37
+ <circle class="bb-base" id="bb-base-third" cx="50" cy="155" r="24" />
38
+ <text class="bb-base-label" x="190" y="161">1B</text>
39
+ <text class="bb-base-label" x="120" y="56">2B</text>
40
+ <text class="bb-base-label" x="50" y="161">3B</text>
41
+ <path class="bb-home-plate" d="M 112 212 L 128 212 L 128 224 L 120 230 L 112 224 Z" />
42
+ </svg>
43
+ </div>
44
+
45
+ <div class="bb-count-row">
46
+ <div class="bb-count-item">
47
+ <span class="bb-count-label">{t.balls}</span>
48
+ <div class="bb-dots" id="bb-dots-balls">
49
+ <span class="bb-dot"></span><span class="bb-dot"></span><span class="bb-dot"></span><span class="bb-dot"></span>
50
+ </div>
51
+ </div>
52
+ <div class="bb-count-item">
53
+ <span class="bb-count-label">{t.strikes}</span>
54
+ <div class="bb-dots" id="bb-dots-strikes">
55
+ <span class="bb-dot"></span><span class="bb-dot"></span><span class="bb-dot"></span>
56
+ </div>
57
+ </div>
58
+ <div class="bb-count-item">
59
+ <span class="bb-count-label">{t.outs}</span>
60
+ <div class="bb-dots" id="bb-dots-outs">
61
+ <span class="bb-dot bb-dot-out"></span><span class="bb-dot bb-dot-out"></span><span class="bb-dot bb-dot-out"></span>
62
+ </div>
63
+ </div>
64
+ </div>
65
+
66
+ <div class="bb-rhe-wrap">
67
+ <table class="bb-rhe-table">
68
+ <thead>
69
+ <tr>
70
+ <th></th>
71
+ <th class="bb-th-runs">{t.runs}</th>
72
+ <th class="bb-th-hits">{t.hits}</th>
73
+ <th class="bb-th-errors">{t.errors}</th>
74
+ </tr>
75
+ </thead>
76
+ <tbody>
77
+ <tr>
78
+ <td class="bb-rhe-team" id="bb-rhe-away-label">{t.away}</td>
79
+ <td class="bb-rhe-val" id="bb-rhe-away-r">0</td>
80
+ <td class="bb-rhe-val" id="bb-rhe-away-h">0</td>
81
+ <td class="bb-rhe-val" id="bb-rhe-away-e">0</td>
82
+ </tr>
83
+ <tr>
84
+ <td class="bb-rhe-team" id="bb-rhe-home-label">{t.home}</td>
85
+ <td class="bb-rhe-val" id="bb-rhe-home-r">0</td>
86
+ <td class="bb-rhe-val" id="bb-rhe-home-h">0</td>
87
+ <td class="bb-rhe-val" id="bb-rhe-home-e">0</td>
88
+ </tr>
89
+ </tbody>
90
+ </table>
91
+ </div>
92
+
93
+ <div class="bb-inning-scroll" id="bb-inning-scroll">
94
+ <div class="bb-inning-header">
95
+ <span class="bb-ih-team"></span>
96
+ <span class="bb-ih-cell">1</span>
97
+ <span class="bb-ih-cell">2</span>
98
+ <span class="bb-ih-cell">3</span>
99
+ <span class="bb-ih-cell">4</span>
100
+ <span class="bb-ih-cell">5</span>
101
+ <span class="bb-ih-cell">6</span>
102
+ <span class="bb-ih-cell">7</span>
103
+ <span class="bb-ih-cell">8</span>
104
+ <span class="bb-ih-cell">9</span>
105
+ </div>
106
+ <div class="bb-inning-row" id="bb-row-away">
107
+ <span class="bb-ir-team" id="bb-ir-away-label">{t.away}</span>
108
+ </div>
109
+ <div class="bb-inning-row" id="bb-row-home">
110
+ <span class="bb-ir-team" id="bb-ir-home-label">{t.home}</span>
111
+ </div>
112
+ </div>
113
+
114
+ <div class="bb-btn-row">
115
+ <button class="bb-btn bb-btn-strike" id="bb-btn-strike">{t.strikeBtn}</button>
116
+ <button class="bb-btn bb-btn-ball" id="bb-btn-ball">{t.ballBtn}</button>
117
+ <button class="bb-btn bb-btn-foul" id="bb-btn-foul">{t.foulBtn}</button>
118
+ <button class="bb-btn bb-btn-hit" id="bb-btn-hit">{t.hitBtn}</button>
119
+ <button class="bb-btn bb-btn-out" id="bb-btn-out">{t.outBtn}</button>
120
+ </div>
121
+ <div class="bb-btn-row bb-btn-row-secondary">
122
+ <button class="bb-btn bb-btn-run" id="bb-btn-run">{t.runBtn}</button>
123
+ <button class="bb-btn bb-btn-error" id="bb-btn-error">{t.errorBtn}</button>
124
+ </div>
125
+
126
+ <button class="bb-btn bb-btn-reset" id="bb-btn-reset">{t.resetMatch}</button>
127
+
128
+ </div>
129
+
130
+ <div class="bb-reset-modal" id="bb-modal">
131
+ <div class="bb-modal-content">
132
+ <div class="bb-modal-text">{t.resetConfirm}</div>
133
+ <div class="bb-modal-btns">
134
+ <button class="bb-btn bb-btn-modal-cancel" id="bb-modal-cancel">{t.cancel}</button>
135
+ <button class="bb-btn bb-btn-modal-confirm" id="bb-modal-confirm">{t.confirm}</button>
136
+ </div>
137
+ </div>
138
+ </div>
139
+ </div>
140
+
141
+ <script>
142
+ import { initBaseballScorekeeper } from './ui-init';
143
+ initBaseballScorekeeper();
144
+ </script>
@@ -0,0 +1,30 @@
1
+ import type { SportsToolEntry, ToolLocaleContent } from '../../types';
2
+ import type { BaseballScoreKeeperUI } from './ui';
3
+
4
+ export type { BaseballScoreKeeperUI };
5
+ export type BaseballScoreKeeperLocaleContent = ToolLocaleContent<BaseballScoreKeeperUI>;
6
+
7
+ export const baseballScoreKeeper: SportsToolEntry<BaseballScoreKeeperUI> = {
8
+ id: 'baseball-scorekeeper',
9
+ icons: {
10
+ bg: 'mdi:baseball',
11
+ fg: 'mdi:scoreboard-outline',
12
+ },
13
+ i18n: {
14
+ en: () => import('./i18n/en').then((m) => m.content),
15
+ es: () => import('./i18n/es').then((m) => m.content),
16
+ fr: () => import('./i18n/fr').then((m) => m.content),
17
+ de: () => import('./i18n/de').then((m) => m.content),
18
+ it: () => import('./i18n/it').then((m) => m.content),
19
+ nl: () => import('./i18n/nl').then((m) => m.content),
20
+ pt: () => import('./i18n/pt').then((m) => m.content),
21
+ id: () => import('./i18n/id').then((m) => m.content),
22
+ pl: () => import('./i18n/pl').then((m) => m.content),
23
+ sv: () => import('./i18n/sv').then((m) => m.content),
24
+ tr: () => import('./i18n/tr').then((m) => m.content),
25
+ ja: () => import('./i18n/ja').then((m) => m.content),
26
+ ko: () => import('./i18n/ko').then((m) => m.content),
27
+ ru: () => import('./i18n/ru').then((m) => m.content),
28
+ zh: () => import('./i18n/zh').then((m) => m.content),
29
+ },
30
+ };