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