@johnmorrisdotca/kumimoji 1.3.0 → 1.3.1
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.
- package/CHANGELOG.md +12 -0
- package/CONTRIBUTING.md +11 -2
- package/README.md +2 -2
- package/dist/check.js +4 -2
- package/dist/computerPlay.js +11 -4
- package/dist/computerTurn.js +5 -2
- package/dist/daily.js +1 -1
- package/dist/element.d.ts +1 -1
- package/dist/element.js +313 -162
- package/dist/export.js +18 -5
- package/dist/generate.js +18 -5
- package/dist/grid.js +26 -4
- package/dist/index.d.ts +22 -22
- package/dist/index.js +22 -22
- package/dist/kana.js +39 -6
- package/dist/party.js +28 -5
- package/dist/partyKept.js +53 -8
- package/dist/partySeats.js +11 -4
- package/dist/partyTurns.js +16 -3
- package/dist/placement.js +5 -2
- package/dist/play.js +14 -3
- package/dist/react.js +33 -3
- package/dist/showcase.js +12 -3
- package/dist/tileWords.js +11 -6
- package/dist/tileWordsModule.d.ts +1 -1
- package/dist/tileWordsModule.js +3 -1
- package/dist/tiles.constants.js +72 -8
- package/dist/turn.js +6 -1
- package/dist/ui/board.js +16 -2
- package/dist/ui/draw.d.ts +62 -0
- package/dist/ui/draw.js +229 -0
- package/dist/ui/mount.js +163 -275
- package/dist/ui/style.d.ts +1 -1
- package/dist/ui/style.js +1 -1
- package/dist/ui.d.ts +3 -3
- package/dist/ui.js +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/wilds.js +3 -2
- package/package.json +12 -13
package/dist/element.js
CHANGED
|
@@ -1,23 +1,11 @@
|
|
|
1
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
-
};
|
|
6
|
-
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
7
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
8
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
9
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
10
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
11
|
-
};
|
|
12
|
-
var _KumimojiTable_instances, _KumimojiTable_table, _KumimojiTable_key, _KumimojiTable_queued, _KumimojiTable_seed, _KumimojiTable_options, _KumimojiTable_revision, _KumimojiTable_widthBefore, _KumimojiTable_widthOwned, _KumimojiTable_labelBefore, _KumimojiTable_write, _KumimojiTable_frame, _KumimojiTable_refresh;
|
|
13
|
-
import { embedDay } from "./embed-day.js";
|
|
14
|
-
import { KUMIMOJI_STYLE } from "./ui/style.js";
|
|
15
1
|
import { kumimojiDailySeed } from "./daily.js";
|
|
2
|
+
import { embedDay } from "./embed-day.js";
|
|
16
3
|
import { KUMIMOJI_HANDS } from "./tiles.constants.js";
|
|
17
4
|
import { mountKumimoji } from "./ui/mount.js";
|
|
5
|
+
import { KUMIMOJI_STYLE } from "./ui/style.js";
|
|
18
6
|
const ElementBase = typeof HTMLElement === "undefined" ? class {
|
|
19
7
|
} : HTMLElement;
|
|
20
|
-
const oneOf = (value, allowed) =>
|
|
8
|
+
const oneOf = (value, allowed) => allowed.includes(value) ? value : undefined;
|
|
21
9
|
const isOn = (value, fallback = false) => value === null ? fallback : !["false", "off", "no", "0"].includes(value.trim().toLowerCase());
|
|
22
10
|
const HANDS = Object.values(KUMIMOJI_HANDS);
|
|
23
11
|
/**
|
|
@@ -53,7 +41,23 @@ const HANDS = Object.values(KUMIMOJI_HANDS);
|
|
|
53
41
|
* console.log(KUMIMOJI_EMBED_OPTION_KEYS.includes("saved"));
|
|
54
42
|
* ```
|
|
55
43
|
*/
|
|
56
|
-
export const KUMIMOJI_EMBED_OPTION_KEYS = Object.keys({
|
|
44
|
+
export const KUMIMOJI_EMBED_OPTION_KEYS = Object.keys({
|
|
45
|
+
language: true,
|
|
46
|
+
hand: true,
|
|
47
|
+
level: true,
|
|
48
|
+
gameLength: true,
|
|
49
|
+
diagonals: true,
|
|
50
|
+
seed: true,
|
|
51
|
+
onFinish: true,
|
|
52
|
+
onChange: true,
|
|
53
|
+
locale: true,
|
|
54
|
+
strings: true,
|
|
55
|
+
theme: true,
|
|
56
|
+
keep: true,
|
|
57
|
+
controls: true,
|
|
58
|
+
saved: true,
|
|
59
|
+
onError: true,
|
|
60
|
+
});
|
|
57
61
|
/**
|
|
58
62
|
* A reflected crossword table with the native table handle and saved-state getter.
|
|
59
63
|
* @example
|
|
@@ -63,187 +67,332 @@ export const KUMIMOJI_EMBED_OPTION_KEYS = Object.keys({ language: true, hand: tr
|
|
|
63
67
|
* ```
|
|
64
68
|
*/
|
|
65
69
|
export class KumimojiTable extends ElementBase {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
static observedAttributes = [
|
|
71
|
+
"language",
|
|
72
|
+
"hand",
|
|
73
|
+
"level",
|
|
74
|
+
"length",
|
|
75
|
+
"diagonals",
|
|
76
|
+
"seed",
|
|
77
|
+
"lang",
|
|
78
|
+
"keep",
|
|
79
|
+
"daily",
|
|
80
|
+
"controls",
|
|
81
|
+
"theme",
|
|
82
|
+
"size",
|
|
83
|
+
"width",
|
|
84
|
+
"label",
|
|
85
|
+
];
|
|
86
|
+
#table = null;
|
|
87
|
+
#key = "";
|
|
88
|
+
#queued = false;
|
|
89
|
+
#seed = null;
|
|
90
|
+
#options = {};
|
|
91
|
+
#revision = 0;
|
|
92
|
+
#widthBefore = null;
|
|
93
|
+
#widthOwned = false;
|
|
94
|
+
#labelBefore = null;
|
|
79
95
|
/** Native host options. Callback/presentation changes preserve the current game. */
|
|
80
|
-
get options() {
|
|
81
|
-
|
|
82
|
-
|
|
96
|
+
get options() {
|
|
97
|
+
return this.#options;
|
|
98
|
+
}
|
|
99
|
+
set options(value) {
|
|
100
|
+
this.#options = value ?? {};
|
|
101
|
+
if (this.isConnected)
|
|
102
|
+
this.#refresh();
|
|
103
|
+
}
|
|
104
|
+
#write(name, value) {
|
|
105
|
+
if (value === null || value === undefined)
|
|
106
|
+
this.removeAttribute(name);
|
|
107
|
+
else
|
|
108
|
+
this.setAttribute(name, String(value));
|
|
109
|
+
}
|
|
83
110
|
connectedCallback() {
|
|
84
|
-
|
|
111
|
+
this.#refresh();
|
|
85
112
|
}
|
|
86
113
|
disconnectedCallback() {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
__classPrivateFieldSet(this, _KumimojiTable_key, "", "f");
|
|
114
|
+
++this.#revision;
|
|
115
|
+
this.#table?.destroy();
|
|
116
|
+
this.#table = null;
|
|
117
|
+
this.#key = "";
|
|
92
118
|
}
|
|
93
119
|
attributeChangedCallback() {
|
|
94
|
-
if (!this.isConnected ||
|
|
120
|
+
if (!this.isConnected || this.#queued)
|
|
95
121
|
return;
|
|
96
|
-
|
|
122
|
+
this.#queued = true;
|
|
97
123
|
queueMicrotask(() => {
|
|
98
|
-
|
|
124
|
+
this.#queued = false;
|
|
99
125
|
if (this.isConnected)
|
|
100
|
-
|
|
126
|
+
this.#refresh();
|
|
101
127
|
});
|
|
102
128
|
}
|
|
103
129
|
/** The mounted table's handle (`mountKumimoji`), or null while the attributes name no table the rules offer. */
|
|
104
130
|
get table() {
|
|
105
|
-
return
|
|
131
|
+
return this.#table;
|
|
106
132
|
}
|
|
107
133
|
/** The game as it would be saved, or null while there is none (or it is still being dealt). */
|
|
108
134
|
get saved() {
|
|
109
|
-
return
|
|
135
|
+
return this.#table?.saved() ?? null;
|
|
110
136
|
}
|
|
111
137
|
/** A new game at the same table: see `KumimojiTableHandle.newGame`. */
|
|
112
138
|
newGame(options) {
|
|
113
|
-
return
|
|
139
|
+
return this.#table?.newGame(options) ?? Promise.resolve();
|
|
114
140
|
}
|
|
115
141
|
/** Put a game on the table: see `KumimojiTableHandle.setGame`. */
|
|
116
142
|
setGame(saved) {
|
|
117
|
-
return
|
|
143
|
+
return this.#table?.setGame(saved) ?? Promise.resolve();
|
|
118
144
|
}
|
|
119
145
|
/** The `language` attribute, reflected. */
|
|
120
|
-
get language() {
|
|
121
|
-
|
|
146
|
+
get language() {
|
|
147
|
+
return this.getAttribute("language");
|
|
148
|
+
}
|
|
149
|
+
set language(value) {
|
|
150
|
+
this.#write("language", value);
|
|
151
|
+
}
|
|
122
152
|
/** The `hand` attribute, reflected. */
|
|
123
|
-
get hand() {
|
|
124
|
-
|
|
153
|
+
get hand() {
|
|
154
|
+
return this.getAttribute("hand");
|
|
155
|
+
}
|
|
156
|
+
set hand(value) {
|
|
157
|
+
this.#write("hand", value);
|
|
158
|
+
}
|
|
125
159
|
/** The `level` attribute, reflected. */
|
|
126
|
-
get level() {
|
|
127
|
-
|
|
160
|
+
get level() {
|
|
161
|
+
return this.getAttribute("level");
|
|
162
|
+
}
|
|
163
|
+
set level(value) {
|
|
164
|
+
this.#write("level", value);
|
|
165
|
+
}
|
|
128
166
|
/** The `length` attribute, reflected. */
|
|
129
|
-
get length() {
|
|
130
|
-
|
|
167
|
+
get length() {
|
|
168
|
+
return this.getAttribute("length");
|
|
169
|
+
}
|
|
170
|
+
set length(value) {
|
|
171
|
+
this.#write("length", value);
|
|
172
|
+
}
|
|
131
173
|
/** The `diagonals` attribute, reflected. */
|
|
132
|
-
get diagonals() {
|
|
133
|
-
|
|
174
|
+
get diagonals() {
|
|
175
|
+
return this.getAttribute("diagonals");
|
|
176
|
+
}
|
|
177
|
+
set diagonals(value) {
|
|
178
|
+
this.#write("diagonals", value);
|
|
179
|
+
}
|
|
134
180
|
/** The `seed` attribute, reflected. */
|
|
135
|
-
get seed() {
|
|
136
|
-
|
|
181
|
+
get seed() {
|
|
182
|
+
return this.getAttribute("seed");
|
|
183
|
+
}
|
|
184
|
+
set seed(value) {
|
|
185
|
+
this.#write("seed", value);
|
|
186
|
+
}
|
|
137
187
|
/** The `keep` attribute, reflected. */
|
|
138
|
-
get keep() {
|
|
139
|
-
|
|
188
|
+
get keep() {
|
|
189
|
+
return this.getAttribute("keep");
|
|
190
|
+
}
|
|
191
|
+
set keep(value) {
|
|
192
|
+
this.#write("keep", value);
|
|
193
|
+
}
|
|
140
194
|
/** The `daily` attribute, reflected. */
|
|
141
|
-
get daily() {
|
|
142
|
-
|
|
195
|
+
get daily() {
|
|
196
|
+
return this.getAttribute("daily");
|
|
197
|
+
}
|
|
198
|
+
set daily(value) {
|
|
199
|
+
this.#write("daily", value);
|
|
200
|
+
}
|
|
143
201
|
/** The `controls` attribute, reflected. */
|
|
144
|
-
get controls() {
|
|
145
|
-
|
|
202
|
+
get controls() {
|
|
203
|
+
return this.getAttribute("controls");
|
|
204
|
+
}
|
|
205
|
+
set controls(value) {
|
|
206
|
+
this.#write("controls", value);
|
|
207
|
+
}
|
|
146
208
|
/** The `theme` attribute, reflected. */
|
|
147
|
-
get theme() {
|
|
148
|
-
|
|
209
|
+
get theme() {
|
|
210
|
+
return this.getAttribute("theme");
|
|
211
|
+
}
|
|
212
|
+
set theme(value) {
|
|
213
|
+
this.#write("theme", value);
|
|
214
|
+
}
|
|
149
215
|
/** The `size` attribute, reflected. */
|
|
150
|
-
get size() {
|
|
151
|
-
|
|
216
|
+
get size() {
|
|
217
|
+
return this.getAttribute("size");
|
|
218
|
+
}
|
|
219
|
+
set size(value) {
|
|
220
|
+
this.#write("size", value);
|
|
221
|
+
}
|
|
152
222
|
/** The `width` attribute, reflected. */
|
|
153
|
-
get width() {
|
|
154
|
-
|
|
223
|
+
get width() {
|
|
224
|
+
return this.getAttribute("width");
|
|
225
|
+
}
|
|
226
|
+
set width(value) {
|
|
227
|
+
this.#write("width", value);
|
|
228
|
+
}
|
|
155
229
|
/** The `label` attribute, reflected. */
|
|
156
|
-
get label() {
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (target.querySelector("style[data-kumimoji-embed-style]") === null) {
|
|
182
|
-
const style = this.ownerDocument.createElement("style");
|
|
183
|
-
style.setAttribute("data-kumimoji-embed-style", "");
|
|
184
|
-
const light = KUMIMOJI_STYLE.match(/\.km-root \{([^}]+)\}/)?.[1] ?? "";
|
|
185
|
-
const dark = KUMIMOJI_STYLE.match(/@media \(prefers-color-scheme: dark\) \{\s*\.km-root \{([^}]+)\}/)?.[1] ?? "";
|
|
186
|
-
style.textContent = `[data-kumimoji-embed][theme="light"] .km-root{${light}}[data-kumimoji-embed][theme="dark"] .km-root{${dark}}[data-kumimoji-embed]>.km-root{background:var(--km-panel);padding:12px;border-radius:12px}[data-kumimoji-embed] .km-controls[hidden]{display:none}`;
|
|
187
|
-
target.append(style);
|
|
188
|
-
}
|
|
189
|
-
if (this.hasAttribute("label")) {
|
|
190
|
-
__classPrivateFieldSet(this, _KumimojiTable_labelBefore, __classPrivateFieldGet(this, _KumimojiTable_labelBefore, "f") ?? { role: this.getAttribute("role"), label: this.getAttribute("aria-label") }, "f");
|
|
191
|
-
this.setAttribute("role", "group");
|
|
192
|
-
this.setAttribute("aria-label", this.getAttribute("label"));
|
|
193
|
-
}
|
|
194
|
-
else if (__classPrivateFieldGet(this, _KumimojiTable_labelBefore, "f") !== null) {
|
|
195
|
-
for (const [name, value] of [["role", __classPrivateFieldGet(this, _KumimojiTable_labelBefore, "f").role], ["aria-label", __classPrivateFieldGet(this, _KumimojiTable_labelBefore, "f").label]]) {
|
|
196
|
-
if (value === null)
|
|
197
|
-
this.removeAttribute(name);
|
|
198
|
-
else
|
|
199
|
-
this.setAttribute(name, value);
|
|
230
|
+
get label() {
|
|
231
|
+
return this.getAttribute("label");
|
|
232
|
+
}
|
|
233
|
+
set label(value) {
|
|
234
|
+
this.#write("label", value);
|
|
235
|
+
}
|
|
236
|
+
#frame() {
|
|
237
|
+
this.style.display = "block";
|
|
238
|
+
this.style.maxWidth = "100%";
|
|
239
|
+
const width = Number(this.getAttribute("width"));
|
|
240
|
+
const size = this.getAttribute("size");
|
|
241
|
+
const pixels = this.hasAttribute("width") && width > 0 && Number.isFinite(width)
|
|
242
|
+
? Math.min(width, 2000)
|
|
243
|
+
: size === "small"
|
|
244
|
+
? 320
|
|
245
|
+
: size === "medium"
|
|
246
|
+
? 480
|
|
247
|
+
: size === "large"
|
|
248
|
+
? 640
|
|
249
|
+
: null;
|
|
250
|
+
if (pixels !== null) {
|
|
251
|
+
if (!this.#widthOwned)
|
|
252
|
+
this.#widthBefore = this.style.width;
|
|
253
|
+
this.#widthOwned = true;
|
|
254
|
+
this.style.width = `${pixels}px`;
|
|
200
255
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
const
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
if (
|
|
219
|
-
|
|
220
|
-
|
|
256
|
+
else if (this.#widthOwned) {
|
|
257
|
+
this.style.width = this.#widthBefore ?? "";
|
|
258
|
+
this.#widthOwned = false;
|
|
259
|
+
}
|
|
260
|
+
const theme = this.getAttribute("theme");
|
|
261
|
+
this.style.colorScheme = theme === "light" || theme === "dark" ? theme : "light dark";
|
|
262
|
+
this.setAttribute("data-kumimoji-embed", "");
|
|
263
|
+
const root = this.getRootNode();
|
|
264
|
+
const target = typeof ShadowRoot !== "undefined" && root instanceof ShadowRoot ? root : this.ownerDocument.head;
|
|
265
|
+
if (target.querySelector("style[data-kumimoji-embed-style]") === null) {
|
|
266
|
+
const style = this.ownerDocument.createElement("style");
|
|
267
|
+
style.setAttribute("data-kumimoji-embed-style", "");
|
|
268
|
+
const light = KUMIMOJI_STYLE.match(/\.km-root \{([^}]+)\}/)?.[1] ?? "";
|
|
269
|
+
const dark = KUMIMOJI_STYLE.match(/@media \(prefers-color-scheme: dark\) \{\s*\.km-root \{([^}]+)\}/)?.[1] ?? "";
|
|
270
|
+
style.textContent = `[data-kumimoji-embed][theme="light"] .km-root{${light}}[data-kumimoji-embed][theme="dark"] .km-root{${dark}}[data-kumimoji-embed]>.km-root{background:var(--km-panel);padding:12px;border-radius:12px}[data-kumimoji-embed] .km-controls[hidden]{display:none}`;
|
|
271
|
+
target.append(style);
|
|
272
|
+
}
|
|
273
|
+
if (this.hasAttribute("label")) {
|
|
274
|
+
this.#labelBefore ??= { role: this.getAttribute("role"), label: this.getAttribute("aria-label") };
|
|
275
|
+
this.setAttribute("role", "group");
|
|
276
|
+
this.setAttribute("aria-label", this.getAttribute("label"));
|
|
277
|
+
}
|
|
278
|
+
else if (this.#labelBefore !== null) {
|
|
279
|
+
for (const [name, value] of [
|
|
280
|
+
["role", this.#labelBefore.role],
|
|
281
|
+
["aria-label", this.#labelBefore.label],
|
|
282
|
+
]) {
|
|
283
|
+
if (value === null)
|
|
284
|
+
this.removeAttribute(name);
|
|
285
|
+
else
|
|
286
|
+
this.setAttribute(name, value);
|
|
287
|
+
}
|
|
288
|
+
this.#labelBefore = null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
#refresh() {
|
|
292
|
+
this.#frame();
|
|
293
|
+
try {
|
|
294
|
+
const language = oneOf(this.getAttribute("language"), ["english", "japanese"]) ?? this.#options.language;
|
|
295
|
+
const hand = this.hasAttribute("hand") ? Number(this.getAttribute("hand")) : this.#options.hand;
|
|
296
|
+
const level = oneOf(this.getAttribute("level"), ["easy", "medium", "hard"]) ?? this.#options.level;
|
|
297
|
+
const gameLength = oneOf(this.getAttribute("length"), ["short", "medium", "full"]) ?? this.#options.gameLength;
|
|
298
|
+
const diagonals = isOn(this.getAttribute("diagonals"), this.#options.diagonals ?? false);
|
|
299
|
+
const seedAttribute = this.getAttribute("seed");
|
|
300
|
+
const asked = Number(seedAttribute);
|
|
301
|
+
const day = embedDay(this.hasAttribute("daily") ? this.getAttribute("daily") : seedAttribute === "daily" ? "today" : null);
|
|
302
|
+
let seed;
|
|
303
|
+
if (day !== null)
|
|
304
|
+
seed = kumimojiDailySeed(new Date(`${day}T00:00:00Z`));
|
|
305
|
+
else if (seedAttribute !== null && Number.isInteger(asked) && asked >= 0 && asked <= 0xffffffff)
|
|
306
|
+
seed = asked;
|
|
307
|
+
else if (this.#options.seed !== undefined && this.#options.seed !== null)
|
|
308
|
+
seed = this.#options.seed;
|
|
309
|
+
else {
|
|
310
|
+
let held = this.#seed;
|
|
311
|
+
if (held === null) {
|
|
312
|
+
held = Math.floor(Math.random() * 2 ** 31);
|
|
313
|
+
this.#seed = held;
|
|
314
|
+
}
|
|
315
|
+
seed = held;
|
|
316
|
+
}
|
|
317
|
+
const lang = this.getAttribute("lang");
|
|
318
|
+
const locale = lang === "en" || lang === "ja"
|
|
319
|
+
? lang
|
|
320
|
+
: (this.#options.locale ??
|
|
321
|
+
(this.ownerDocument.documentElement.lang.toLowerCase().startsWith("ja") ? "ja" : "en"));
|
|
322
|
+
const keep = isOn(this.getAttribute("keep"), this.#options.keep ?? true);
|
|
323
|
+
const controls = isOn(this.getAttribute("controls"), this.#options.controls ?? true);
|
|
324
|
+
const key = JSON.stringify([language, hand, level, gameLength, diagonals, seed, day, this.#options.saved]);
|
|
325
|
+
if (key === this.#key && this.#table !== null) {
|
|
326
|
+
this.#table.set({ locale, strings: this.#options.strings, theme: this.#options.theme ?? {}, keep, controls });
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
if (hand !== undefined && !HANDS.includes(hand))
|
|
330
|
+
throw new RangeError("Choose a hand of 3, 7 or 11 tiles.");
|
|
331
|
+
this.#table?.destroy();
|
|
332
|
+
this.#table = null;
|
|
333
|
+
this.#key = "";
|
|
334
|
+
this.replaceChildren();
|
|
335
|
+
const revision = ++this.#revision;
|
|
336
|
+
const table = mountKumimoji(this, {
|
|
337
|
+
...this.#options,
|
|
338
|
+
language,
|
|
339
|
+
hand,
|
|
340
|
+
level,
|
|
341
|
+
gameLength,
|
|
342
|
+
diagonals,
|
|
343
|
+
seed,
|
|
344
|
+
locale,
|
|
345
|
+
keep,
|
|
346
|
+
controls,
|
|
347
|
+
onChange: (saved) => {
|
|
348
|
+
this.dispatchEvent(new CustomEvent("kumimoji-change", {
|
|
349
|
+
detail: JSON.parse(JSON.stringify({ saved })),
|
|
350
|
+
bubbles: true,
|
|
351
|
+
composed: true,
|
|
352
|
+
}));
|
|
353
|
+
this.#options.onChange?.(saved);
|
|
354
|
+
},
|
|
355
|
+
onFinish: (result) => {
|
|
356
|
+
this.dispatchEvent(new CustomEvent("kumimoji-finish", {
|
|
357
|
+
detail: JSON.parse(JSON.stringify(result)),
|
|
358
|
+
bubbles: true,
|
|
359
|
+
composed: true,
|
|
360
|
+
}));
|
|
361
|
+
this.#options.onFinish?.(result);
|
|
362
|
+
},
|
|
363
|
+
onError: (error) => {
|
|
364
|
+
this.dispatchEvent(new CustomEvent("kumimoji-error", { detail: { message: error.message }, bubbles: true, composed: true }));
|
|
365
|
+
this.#options.onError?.(error);
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
this.#table = table;
|
|
369
|
+
this.#key = key;
|
|
370
|
+
void table.ready
|
|
371
|
+
.then(() => {
|
|
372
|
+
if (this.isConnected && revision === this.#revision && table.saved() !== null)
|
|
373
|
+
this.dispatchEvent(new CustomEvent("kumimoji-load", {
|
|
374
|
+
bubbles: true,
|
|
375
|
+
composed: true,
|
|
376
|
+
detail: { seed: table.saved().deal.seed, day },
|
|
377
|
+
}));
|
|
378
|
+
})
|
|
379
|
+
.catch(() => {
|
|
380
|
+
/* The native ready error handler reports the load failure. */
|
|
381
|
+
});
|
|
221
382
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
catch (error) {
|
|
236
|
-
__classPrivateFieldGet(this, _KumimojiTable_table, "f")?.destroy();
|
|
237
|
-
__classPrivateFieldSet(this, _KumimojiTable_table, null, "f");
|
|
238
|
-
__classPrivateFieldSet(this, _KumimojiTable_key, "", "f");
|
|
239
|
-
const message = error instanceof Error ? error.message : String(error), status = this.ownerDocument.createElement("p");
|
|
240
|
-
status.setAttribute("role", "status");
|
|
241
|
-
status.textContent = message;
|
|
242
|
-
this.replaceChildren(status);
|
|
243
|
-
this.dispatchEvent(new CustomEvent("kumimoji-error", { detail: { message }, bubbles: true, composed: true }));
|
|
244
|
-
}
|
|
245
|
-
};
|
|
246
|
-
KumimojiTable.observedAttributes = ["language", "hand", "level", "length", "diagonals", "seed", "lang", "keep", "daily", "controls", "theme", "size", "width", "label"];
|
|
383
|
+
catch (error) {
|
|
384
|
+
this.#table?.destroy();
|
|
385
|
+
this.#table = null;
|
|
386
|
+
this.#key = "";
|
|
387
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
388
|
+
const status = this.ownerDocument.createElement("p");
|
|
389
|
+
status.setAttribute("role", "status");
|
|
390
|
+
status.textContent = message;
|
|
391
|
+
this.replaceChildren(status);
|
|
392
|
+
this.dispatchEvent(new CustomEvent("kumimoji-error", { detail: { message }, bubbles: true, composed: true }));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
247
396
|
/**
|
|
248
397
|
* Defines the table or a subclass under a custom tag. Server-safe and idempotent.
|
|
249
398
|
* @param tagName - The tag name; kumimoji-table by default.
|
|
@@ -256,6 +405,8 @@ KumimojiTable.observedAttributes = ["language", "hand", "level", "length", "diag
|
|
|
256
405
|
* console.log(typeof defineTable);
|
|
257
406
|
* ```
|
|
258
407
|
*/
|
|
259
|
-
export function defineTable(tagName = "kumimoji-table", registry = typeof customElements === "undefined" ? undefined : customElements) {
|
|
260
|
-
registry.
|
|
261
|
-
|
|
408
|
+
export function defineTable(tagName = "kumimoji-table", registry = typeof customElements === "undefined" ? undefined : customElements) {
|
|
409
|
+
if (registry !== undefined && registry.get(tagName) === undefined)
|
|
410
|
+
registry.define(tagName, tagName === "kumimoji-table" ? KumimojiTable : class extends KumimojiTable {
|
|
411
|
+
});
|
|
412
|
+
}
|
package/dist/export.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { boundsOf, squareAt } from "./grid.js";
|
|
2
1
|
import { generateKumimoji } from "./generate.js";
|
|
2
|
+
import { boundsOf, squareAt } from "./grid.js";
|
|
3
3
|
import { judgeWithWords } from "./judge.js";
|
|
4
4
|
import { decodeTileProgress, encodeTileProgress, isFinished, tilesLeft } from "./play.js";
|
|
5
5
|
import { KUMIMOJI_STRINGS, kumimojiSay } from "./strings.js";
|
|
@@ -145,7 +145,12 @@ export async function kumimojiFromJSON(text) {
|
|
|
145
145
|
await loadTileWords(language);
|
|
146
146
|
let deal;
|
|
147
147
|
try {
|
|
148
|
-
deal = generateKumimoji(size, level, seed, {
|
|
148
|
+
deal = generateKumimoji(size, level, seed, {
|
|
149
|
+
language,
|
|
150
|
+
gameLength: gameLength,
|
|
151
|
+
doubleSet,
|
|
152
|
+
diagonals,
|
|
153
|
+
});
|
|
149
154
|
}
|
|
150
155
|
catch {
|
|
151
156
|
return null;
|
|
@@ -231,13 +236,21 @@ export function gridToText(tiles, language = "english") {
|
|
|
231
236
|
export function kumimojiToText(saved, strings = KUMIMOJI_STRINGS.en) {
|
|
232
237
|
const { deal, play } = saved;
|
|
233
238
|
const words = tileWords(deal.language);
|
|
234
|
-
const face = (tile) =>
|
|
235
|
-
const lines = [
|
|
239
|
+
const face = (tile) => tileFace(tile).blank ? "*" : deal.language === "japanese" ? words.glyphOf(tile) : words.glyphOf(tile).toUpperCase();
|
|
240
|
+
const lines = [
|
|
241
|
+
kumimojiSay(strings.textTitle, {
|
|
242
|
+
language: deal.language === "japanese" ? strings.japanese : strings.english,
|
|
243
|
+
hand: deal.size,
|
|
244
|
+
seed: deal.seed,
|
|
245
|
+
}),
|
|
246
|
+
];
|
|
236
247
|
lines.push(play.tiles.size === 0 ? strings.textEmpty : gridToText(play.tiles, deal.language));
|
|
237
248
|
if (isFinished(play, judgeWithWords(play.tiles, words, { diagonals: deal.diagonals === true })))
|
|
238
249
|
lines.push(strings.textFinished);
|
|
239
250
|
else {
|
|
240
|
-
lines.push(play.hand.length === 0
|
|
251
|
+
lines.push(play.hand.length === 0
|
|
252
|
+
? strings.textHandEmpty
|
|
253
|
+
: kumimojiSay(strings.textHand, { tiles: play.hand.map(face).join(" ") }));
|
|
241
254
|
lines.push(kumimojiSay(strings.textLeft, { n: tilesLeft(play) }));
|
|
242
255
|
}
|
|
243
256
|
lines.push(kumimojiSay(strings.textTime, { time: kumimojiClock(saved.elapsedMs) }));
|