@jjlmoya/utils-tabletop 1.10.0 → 1.12.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 (76) hide show
  1. package/package.json +1 -1
  2. package/src/entries.ts +8 -0
  3. package/src/tests/locale_completeness.test.ts +1 -1
  4. package/src/tests/tool_validation.test.ts +1 -1
  5. package/src/tool/decision-wheel/client.ts +2 -0
  6. package/src/tool/decision-wheel/components/SegmentEditor.astro +1 -1
  7. package/src/tool/decision-wheel/decision-wheel.css +23 -7
  8. package/src/tool/dice-roller-simulator/component.astro +116 -26
  9. package/src/tool/hidden-role-dealer/bibliography.astro +16 -0
  10. package/src/tool/hidden-role-dealer/bibliography.ts +12 -0
  11. package/src/tool/hidden-role-dealer/client.ts +265 -0
  12. package/src/tool/hidden-role-dealer/component.astro +184 -0
  13. package/src/tool/hidden-role-dealer/entry.ts +145 -0
  14. package/src/tool/hidden-role-dealer/hidden-role-dealer.css +604 -0
  15. package/src/tool/hidden-role-dealer/i18n/de.ts +195 -0
  16. package/src/tool/hidden-role-dealer/i18n/en.ts +279 -0
  17. package/src/tool/hidden-role-dealer/i18n/es.ts +279 -0
  18. package/src/tool/hidden-role-dealer/i18n/fr.ts +215 -0
  19. package/src/tool/hidden-role-dealer/i18n/id.ts +191 -0
  20. package/src/tool/hidden-role-dealer/i18n/it.ts +191 -0
  21. package/src/tool/hidden-role-dealer/i18n/ja.ts +191 -0
  22. package/src/tool/hidden-role-dealer/i18n/ko.ts +191 -0
  23. package/src/tool/hidden-role-dealer/i18n/nl.ts +191 -0
  24. package/src/tool/hidden-role-dealer/i18n/pl.ts +191 -0
  25. package/src/tool/hidden-role-dealer/i18n/pt.ts +191 -0
  26. package/src/tool/hidden-role-dealer/i18n/ru.ts +191 -0
  27. package/src/tool/hidden-role-dealer/i18n/sv.ts +191 -0
  28. package/src/tool/hidden-role-dealer/i18n/tr.ts +191 -0
  29. package/src/tool/hidden-role-dealer/i18n/zh.ts +191 -0
  30. package/src/tool/hidden-role-dealer/index.ts +10 -0
  31. package/src/tool/hidden-role-dealer/logic.test.ts +99 -0
  32. package/src/tool/hidden-role-dealer/logic.ts +134 -0
  33. package/src/tool/hidden-role-dealer/modules/custom-role-manager.ts +35 -0
  34. package/src/tool/hidden-role-dealer/modules/dealer-logic.ts +73 -0
  35. package/src/tool/hidden-role-dealer/modules/hold-controller.ts +38 -0
  36. package/src/tool/hidden-role-dealer/modules/particle-effects.ts +40 -0
  37. package/src/tool/hidden-role-dealer/modules/player-manager.ts +44 -0
  38. package/src/tool/hidden-role-dealer/modules/presets.ts +46 -0
  39. package/src/tool/hidden-role-dealer/modules/setup-handlers.ts +34 -0
  40. package/src/tool/hidden-role-dealer/modules/storage.ts +23 -0
  41. package/src/tool/hidden-role-dealer/modules/utils.ts +18 -0
  42. package/src/tool/hidden-role-dealer/modules/wizard-html.ts +161 -0
  43. package/src/tool/hidden-role-dealer/modules/wizard-renderer.ts +161 -0
  44. package/src/tool/hidden-role-dealer/modules/writer-handler.ts +70 -0
  45. package/src/tool/hidden-role-dealer/seo.astro +16 -0
  46. package/src/tool/hidden-role-dealer/types.ts +31 -0
  47. package/src/tool/scatter-direction-selector/animation.ts +278 -0
  48. package/src/tool/scatter-direction-selector/bibliography.astro +16 -0
  49. package/src/tool/scatter-direction-selector/bibliography.ts +12 -0
  50. package/src/tool/scatter-direction-selector/client.ts +296 -0
  51. package/src/tool/scatter-direction-selector/component.astro +184 -0
  52. package/src/tool/scatter-direction-selector/entry.ts +59 -0
  53. package/src/tool/scatter-direction-selector/history.ts +71 -0
  54. package/src/tool/scatter-direction-selector/i18n/de.ts +143 -0
  55. package/src/tool/scatter-direction-selector/i18n/en.ts +231 -0
  56. package/src/tool/scatter-direction-selector/i18n/es.ts +143 -0
  57. package/src/tool/scatter-direction-selector/i18n/fr.ts +143 -0
  58. package/src/tool/scatter-direction-selector/i18n/id.ts +143 -0
  59. package/src/tool/scatter-direction-selector/i18n/it.ts +143 -0
  60. package/src/tool/scatter-direction-selector/i18n/ja.ts +143 -0
  61. package/src/tool/scatter-direction-selector/i18n/ko.ts +143 -0
  62. package/src/tool/scatter-direction-selector/i18n/nl.ts +143 -0
  63. package/src/tool/scatter-direction-selector/i18n/pl.ts +143 -0
  64. package/src/tool/scatter-direction-selector/i18n/pt.ts +143 -0
  65. package/src/tool/scatter-direction-selector/i18n/ru.ts +143 -0
  66. package/src/tool/scatter-direction-selector/i18n/sv.ts +143 -0
  67. package/src/tool/scatter-direction-selector/i18n/tr.ts +143 -0
  68. package/src/tool/scatter-direction-selector/i18n/zh.ts +143 -0
  69. package/src/tool/scatter-direction-selector/index.ts +10 -0
  70. package/src/tool/scatter-direction-selector/logic.test.ts +62 -0
  71. package/src/tool/scatter-direction-selector/logic.ts +52 -0
  72. package/src/tool/scatter-direction-selector/scatter-direction-selector.css +794 -0
  73. package/src/tool/scatter-direction-selector/seo.astro +16 -0
  74. package/src/tool/scatter-direction-selector/settings.ts +81 -0
  75. package/src/tool/scatter-direction-selector/sound.ts +22 -0
  76. package/src/tools.ts +4 -0
@@ -0,0 +1,184 @@
1
+ ---
2
+ import './hidden-role-dealer.css';
3
+
4
+ interface Props {
5
+ ui: Record<string, string>;
6
+ }
7
+
8
+ const { ui } = Astro.props;
9
+ ---
10
+
11
+ <div class="hrd-card" data-tool="hidden-role-dealer" data-ui={JSON.stringify(ui)}>
12
+ <div id="view-setup">
13
+ <div class="hrd-setup-grid">
14
+ <div class="hrd-setup-section">
15
+ <div class="hrd-section-title">
16
+ <span>{ui.playerList}</span>
17
+ <button id="btn-clear-players" class="hrd-btn-secondary" type="button">
18
+ {ui.clearPlayers}
19
+ </button>
20
+ </div>
21
+ <div class="hrd-input-row">
22
+ <input
23
+ id="input-player-name"
24
+ class="hrd-input"
25
+ type="text"
26
+ placeholder={ui.addPlayerPlaceholder}
27
+ maxlength="20"
28
+ />
29
+ <button id="btn-add-player" class="hrd-btn-primary" type="button">
30
+ {ui.addPlayer}
31
+ </button>
32
+ </div>
33
+ <div id="players-list" class="hrd-players-container"></div>
34
+ </div>
35
+
36
+ <div class="hrd-setup-section">
37
+ <div class="hrd-section-title">
38
+ <span>{ui.presetsTitle}</span>
39
+ </div>
40
+ <div class="hrd-presets-list">
41
+ <button class="hrd-preset-card active" data-key="werewolf" type="button">
42
+ <div class="hrd-preset-name">{ui.werewolfName}</div>
43
+ <div class="hrd-preset-desc">{ui.werewolfDesc}</div>
44
+ </button>
45
+ <button class="hrd-preset-card" data-key="avalon" type="button">
46
+ <div class="hrd-preset-name">{ui.avalonName}</div>
47
+ <div class="hrd-preset-desc">{ui.avalonDesc}</div>
48
+ </button>
49
+ <button class="hrd-preset-card" data-key="hitler" type="button">
50
+ <div class="hrd-preset-name">{ui.hitlerName}</div>
51
+ <div class="hrd-preset-desc">{ui.hitlerDesc}</div>
52
+ </button>
53
+ <button class="hrd-preset-card" data-key="impostor" type="button">
54
+ <div class="hrd-preset-name">{ui.impostorPresetName}</div>
55
+ <div class="hrd-preset-desc">{ui.impostorPresetDesc}</div>
56
+ </button>
57
+ <button class="hrd-preset-card" data-key="custom" type="button">
58
+ <div class="hrd-preset-name">{ui.presetCustom}</div>
59
+ <div class="hrd-preset-desc">{ui.customDesc}</div>
60
+ </button>
61
+ </div>
62
+ <div id="impostor-settings" class="hrd-custom-section" style="display: none; margin-top: 1.5rem; border-top: 1px solid var(--dealer-border); padding-top: 1.5rem;">
63
+ <div class="hrd-section-title">
64
+ <span>{ui.impostorTitle}</span>
65
+ </div>
66
+ <div class="hrd-input-row" style="margin-bottom: 1rem;">
67
+ <label style="flex: 1; display: flex; flex-direction: column; gap: 0.5rem; font-size: 0.875rem;">
68
+ <span>{ui.impostorWriterLabel}</span>
69
+ <select id="select-impostor-writer" class="hrd-select" style="width: 100%;">
70
+ <option value="random">{ui.impostorWriterRandom}</option>
71
+ <option value="preround">{ui.impostorWriterPreround}</option>
72
+ </select>
73
+ <div id="impostor-writer-desc" style="font-size: 0.75rem; color: var(--dealer-text-muted); margin-top: 0.25rem; line-height: 1.4;"></div>
74
+ </label>
75
+ </div>
76
+ <div id="impostor-secret-wrapper" class="hrd-input-row" style="margin-bottom: 1rem;">
77
+ <label style="flex: 1; display: flex; flex-direction: column; gap: 0.5rem; font-size: 0.875rem;">
78
+ <span>{ui.impostorSharedSecretLabel}</span>
79
+ <input
80
+ id="input-impostor-secret"
81
+ class="hrd-input"
82
+ type="text"
83
+ placeholder={ui.impostorSharedSecretPlaceholder}
84
+ maxlength="50"
85
+ />
86
+ </label>
87
+ </div>
88
+ <div class="hrd-input-row" style="margin-bottom: 1rem;">
89
+ <label style="flex: 1; display: flex; flex-direction: column; gap: 0.5rem; font-size: 0.875rem;">
90
+ <span>{ui.impostorModeLabel}</span>
91
+ <select id="select-impostor-mode" class="hrd-select" style="width: 100%;">
92
+ <option value="fixed">{ui.impostorModeFixed}</option>
93
+ <option value="percentage">{ui.impostorModePercentage}</option>
94
+ <option value="range">{ui.impostorModeRange}</option>
95
+ </select>
96
+ </label>
97
+ </div>
98
+ <div id="impostor-fixed-wrapper" class="hrd-input-row" style="margin-bottom: 1rem;">
99
+ <label style="flex: 1; display: flex; flex-direction: column; gap: 0.5rem; font-size: 0.875rem;">
100
+ <span>{ui.impostorFixedLabel}</span>
101
+ <select id="select-impostor-fixed-count" class="hrd-select" style="width: 100%;">
102
+ <option value="1">1</option>
103
+ <option value="2">2</option>
104
+ <option value="3">3</option>
105
+ </select>
106
+ </label>
107
+ </div>
108
+ <div id="impostor-percent-wrapper" class="hrd-input-row" style="display: none; margin-bottom: 1rem;">
109
+ <label style="flex: 1; display: flex; flex-direction: column; gap: 0.5rem; font-size: 0.875rem;">
110
+ <span>{ui.impostorPercentageLabel}</span>
111
+ <input
112
+ id="input-impostor-percent"
113
+ class="hrd-input"
114
+ type="number"
115
+ value="25"
116
+ min="10"
117
+ max="90"
118
+ />
119
+ </label>
120
+ </div>
121
+ <div id="impostor-range-wrapper" class="hrd-input-row" style="display: none; margin-bottom: 1rem; gap: 1rem;">
122
+ <label style="flex: 1; display: flex; flex-direction: column; gap: 0.5rem; font-size: 0.875rem;">
123
+ <span>{ui.impostorRangeMinLabel}</span>
124
+ <input
125
+ id="input-impostor-min"
126
+ class="hrd-input"
127
+ type="number"
128
+ value="1"
129
+ min="1"
130
+ max="10"
131
+ />
132
+ </label>
133
+ <label style="flex: 1; display: flex; flex-direction: column; gap: 0.5rem; font-size: 0.875rem;">
134
+ <span>{ui.impostorRangeMaxLabel}</span>
135
+ <input
136
+ id="input-impostor-max"
137
+ class="hrd-input"
138
+ type="number"
139
+ value="2"
140
+ min="1"
141
+ max="10"
142
+ />
143
+ </label>
144
+ </div>
145
+ </div>
146
+ <div id="custom-roles-editor" class="hrd-custom-section" style="display: none; margin-top: 1.5rem; border-top: 1px solid var(--dealer-border); padding-top: 1.5rem;">
147
+ <div class="hrd-section-title">
148
+ <span>{ui.customRolesTitle}</span>
149
+ </div>
150
+ <div class="hrd-input-row" style="margin-bottom: 0.5rem;">
151
+ <input
152
+ id="input-role-name"
153
+ class="hrd-input"
154
+ type="text"
155
+ placeholder={ui.customRolePlaceholder}
156
+ maxlength="20"
157
+ style="flex: 2;"
158
+ />
159
+ <select id="select-role-alignment" class="hrd-select">
160
+ <option value="neutral">{ui.neutralLabel}</option>
161
+ <option value="good">{ui.goodLabel}</option>
162
+ <option value="evil">{ui.evilLabel}</option>
163
+ </select>
164
+ <button id="btn-add-role" class="hrd-btn-primary" type="button">
165
+ {ui.addPlayer}
166
+ </button>
167
+ </div>
168
+ <div id="custom-roles-list" class="hrd-players-container"></div>
169
+ </div>
170
+ </div>
171
+ </div>
172
+
173
+ <div class="hrd-deal-action-panel">
174
+ <div id="deal-warning" class="hrd-warning-box" style="display: none;"></div>
175
+ <button id="btn-deal-roles" class="hrd-btn-primary" type="button">
176
+ {ui.dealRoles}
177
+ </button>
178
+ </div>
179
+ </div>
180
+
181
+ <div id="view-wizard" class="hrd-wizard-container" style="display: none;"></div>
182
+ </div>
183
+
184
+ <script src="./client.ts"></script>
@@ -0,0 +1,145 @@
1
+ import type { TabletopToolEntry, ToolLocaleContent } from '../../types';
2
+
3
+ export interface HiddenRoleDealerUI {
4
+ title: string;
5
+ setupTitle: string;
6
+ playerList: string;
7
+ addPlayer: string;
8
+ addPlayerPlaceholder: string;
9
+ rolePool: string;
10
+ presetsTitle: string;
11
+ presetCustom: string;
12
+ dealRoles: string;
13
+ clearPlayers: string;
14
+ instructions: string;
15
+ passTo: string;
16
+ holdToReveal: string;
17
+ releasingResets: string;
18
+ hideRole: string;
19
+ nextPlayer: string;
20
+ finishedTitle: string;
21
+ finishedDesc: string;
22
+ restart: string;
23
+ rolesCount: string;
24
+ playersCount: string;
25
+ mismatchWarning: string;
26
+ werewolfName: string;
27
+ werewolfDesc: string;
28
+ avalonName: string;
29
+ avalonDesc: string;
30
+ hitlerName: string;
31
+ hitlerDesc: string;
32
+ customName: string;
33
+ customDesc: string;
34
+ roleWerewolfName: string;
35
+ roleWerewolfDesc: string;
36
+ roleWerewolfSecret: string;
37
+ roleSeerName: string;
38
+ roleSeerDesc: string;
39
+ roleSeerSecret: string;
40
+ roleDoctorName: string;
41
+ roleDoctorDesc: string;
42
+ roleDoctorSecret: string;
43
+ roleVillagerName: string;
44
+ roleVillagerDesc: string;
45
+ roleVillagerSecret: string;
46
+ roleMerlinName: string;
47
+ roleMerlinDesc: string;
48
+ roleMerlinSecret: string;
49
+ roleAssassinName: string;
50
+ roleAssassinDesc: string;
51
+ roleAssassinSecret: string;
52
+ roleMinionName: string;
53
+ roleMinionDesc: string;
54
+ roleMinionSecret: string;
55
+ roleServantName: string;
56
+ roleServantDesc: string;
57
+ roleServantSecret: string;
58
+ roleHitlerName: string;
59
+ roleHitlerDesc: string;
60
+ roleHitlerSecret: string;
61
+ roleFascistName: string;
62
+ roleFascistDesc: string;
63
+ roleFascistSecret: string;
64
+ roleLiberalName: string;
65
+ roleLiberalDesc: string;
66
+ roleLiberalSecret: string;
67
+ roleCustomName: string;
68
+ roleCustomDesc: string;
69
+ roleCustomSecret: string;
70
+ teamWerewolves: string;
71
+ teamVillagers: string;
72
+ teamGood: string;
73
+ teamEvil: string;
74
+ teamFascist: string;
75
+ teamLiberal: string;
76
+ teamCustom: string;
77
+ secretRoleIs: string;
78
+ customRolesTitle: string;
79
+ customRolePlaceholder: string;
80
+ neutralLabel: string;
81
+ goodLabel: string;
82
+ evilLabel: string;
83
+ customMismatchWarning: string;
84
+ impostorPresetName: string;
85
+ impostorPresetDesc: string;
86
+ impostorTitle: string;
87
+ impostorWarning: string;
88
+ roleImpostorName: string;
89
+ roleImpostorDesc: string;
90
+ roleImpostorSecret: string;
91
+ roleCrewmateName: string;
92
+ roleCrewmateDesc: string;
93
+ roleCrewmateSecret: string;
94
+ teamImpostor: string;
95
+ teamCrewmate: string;
96
+ impostorSharedSecretLabel: string;
97
+ impostorSharedSecretPlaceholder: string;
98
+ impostorModeLabel: string;
99
+ impostorModeFixed: string;
100
+ impostorModePercentage: string;
101
+ impostorModeRange: string;
102
+ impostorFixedLabel: string;
103
+ impostorPercentageLabel: string;
104
+ impostorRangeMinLabel: string;
105
+ impostorRangeMaxLabel: string;
106
+ impostorWriterLabel: string;
107
+ impostorWriterRandom: string;
108
+ roleWriterName: string;
109
+ roleWriterDesc: string;
110
+ writerInputPrompt: string;
111
+ writerInputPlaceholder: string;
112
+ btnSetWord: string;
113
+ impostorWriterPreround: string;
114
+ impostorWriterDescHost: string;
115
+ impostorWriterDescPreround: string;
116
+ impostorWriterDescPlayer: string;
117
+ preroundPassTitle: string;
118
+ preroundInputPrompt: string;
119
+ preroundPassHint: string;
120
+ btnSubmitWord: string;
121
+ }
122
+
123
+ export type HiddenRoleDealerLocaleContent = ToolLocaleContent<HiddenRoleDealerUI>;
124
+
125
+ export const hiddenRoleDealer: TabletopToolEntry<HiddenRoleDealerUI> = {
126
+ id: 'hidden-role-dealer',
127
+ icons: { bg: 'mdi:incognito', fg: 'mdi:incognito-circle' },
128
+ i18n: {
129
+ de: () => import('./i18n/de').then((m) => m.content),
130
+ en: () => import('./i18n/en').then((m) => m.content),
131
+ es: () => import('./i18n/es').then((m) => m.content),
132
+ fr: () => import('./i18n/fr').then((m) => m.content),
133
+ id: () => import('./i18n/id').then((m) => m.content),
134
+ it: () => import('./i18n/it').then((m) => m.content),
135
+ ja: () => import('./i18n/ja').then((m) => m.content),
136
+ ko: () => import('./i18n/ko').then((m) => m.content),
137
+ nl: () => import('./i18n/nl').then((m) => m.content),
138
+ pl: () => import('./i18n/pl').then((m) => m.content),
139
+ pt: () => import('./i18n/pt').then((m) => m.content),
140
+ ru: () => import('./i18n/ru').then((m) => m.content),
141
+ sv: () => import('./i18n/sv').then((m) => m.content),
142
+ tr: () => import('./i18n/tr').then((m) => m.content),
143
+ zh: () => import('./i18n/zh').then((m) => m.content),
144
+ },
145
+ };