@johnmorrisdotca/kumimoji 1.2.2 → 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.
Files changed (83) hide show
  1. package/CHANGELOG.md +33 -1
  2. package/CONTRIBUTING.md +11 -2
  3. package/README.md +80 -39
  4. package/dist/check.d.ts +26 -1
  5. package/dist/check.js +30 -3
  6. package/dist/computer.types.d.ts +24 -2
  7. package/dist/computerPlay.d.ts +45 -2
  8. package/dist/computerPlay.js +56 -6
  9. package/dist/computerTurn.d.ts +42 -3
  10. package/dist/computerTurn.js +47 -5
  11. package/dist/daily.d.ts +22 -2
  12. package/dist/daily.js +23 -3
  13. package/dist/element-define.d.ts +1 -1
  14. package/dist/element-define.js +3 -13
  15. package/dist/element.d.ts +85 -4
  16. package/dist/element.js +359 -77
  17. package/dist/embed-day.d.ts +4 -0
  18. package/dist/embed-day.js +23 -0
  19. package/dist/export.d.ts +123 -6
  20. package/dist/export.js +109 -9
  21. package/dist/generate.d.ts +14 -0
  22. package/dist/generate.js +32 -5
  23. package/dist/grid.d.ts +181 -10
  24. package/dist/grid.js +148 -11
  25. package/dist/help.d.ts +36 -3
  26. package/dist/help.js +36 -3
  27. package/dist/index.d.ts +22 -22
  28. package/dist/index.js +22 -22
  29. package/dist/judge.d.ts +14 -0
  30. package/dist/judge.js +14 -0
  31. package/dist/kana.d.ts +23 -1
  32. package/dist/kana.js +62 -7
  33. package/dist/kumimoji.types.d.ts +70 -5
  34. package/dist/party.d.ts +268 -14
  35. package/dist/party.js +296 -19
  36. package/dist/party.types.d.ts +50 -2
  37. package/dist/partyKept.d.ts +74 -4
  38. package/dist/partyKept.js +127 -12
  39. package/dist/partySeats.d.ts +92 -6
  40. package/dist/partySeats.js +83 -8
  41. package/dist/partyTurns.d.ts +171 -5
  42. package/dist/partyTurns.js +187 -8
  43. package/dist/placement.d.ts +50 -2
  44. package/dist/placement.js +35 -2
  45. package/dist/play.d.ts +247 -15
  46. package/dist/play.js +251 -18
  47. package/dist/random.d.ts +34 -3
  48. package/dist/random.js +23 -2
  49. package/dist/react.d.ts +42 -4
  50. package/dist/react.js +54 -7
  51. package/dist/showcase.d.ts +83 -7
  52. package/dist/showcase.js +61 -7
  53. package/dist/strings.d.ts +54 -5
  54. package/dist/strings.js +34 -3
  55. package/dist/tableView.d.ts +151 -8
  56. package/dist/tableView.js +129 -6
  57. package/dist/tileFace.d.ts +59 -5
  58. package/dist/tileFace.js +48 -4
  59. package/dist/tileFamily.d.ts +9 -0
  60. package/dist/tileFamily.js +9 -0
  61. package/dist/tileWords.d.ts +93 -6
  62. package/dist/tileWords.js +94 -12
  63. package/dist/tileWordsModule.d.ts +12 -2
  64. package/dist/tileWordsModule.js +14 -2
  65. package/dist/tiles.constants.d.ts +99 -5
  66. package/dist/tiles.constants.js +171 -13
  67. package/dist/turn.d.ts +82 -4
  68. package/dist/turn.js +88 -5
  69. package/dist/ui/board.d.ts +60 -5
  70. package/dist/ui/board.js +44 -4
  71. package/dist/ui/draw.d.ts +62 -0
  72. package/dist/ui/draw.js +229 -0
  73. package/dist/ui/mount.d.ts +41 -2
  74. package/dist/ui/mount.js +190 -265
  75. package/dist/ui/style.d.ts +6 -1
  76. package/dist/ui/style.js +6 -0
  77. package/dist/ui.d.ts +3 -3
  78. package/dist/ui.js +2 -2
  79. package/dist/version.d.ts +9 -2
  80. package/dist/version.js +9 -2
  81. package/dist/wilds.d.ts +22 -1
  82. package/dist/wilds.js +25 -3
  83. package/package.json +68 -61
@@ -24,9 +24,48 @@ import type { TileWords } from "./tileWords.ts";
24
24
  * - Resign only where the rules offer it (`mayResign`) and it can do nothing
25
25
  * at all: nothing to lay, nothing to trade for, and it is not its last turn.
26
26
  */
27
- /** The most things a computer does in one turn before pressing Done: at the page's pause, a turn of about three seconds. */
27
+ /** The most things a computer does in one turn before pressing Done: at the page's pause, a turn of about three seconds.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * import { COMPUTER_STEPS_MOST } from "@johnmorrisdotca/kumimoji";
32
+ * console.log(COMPUTER_STEPS_MOST);
33
+ * ```
34
+ */
28
35
  export declare const COMPUTER_STEPS_MOST = 8;
29
- /** A computer seat's whole turn as its steps, in order, for a page to show one at a time. None when it is not a computer's turn or the game is over. */
36
+ /** A computer seat's whole turn as its steps, in order, for a page to show one at a time. None when it is not a computer's turn or the game is over.
37
+ *
38
+ * @param game - The current immutable shared-bag party game.
39
+ * @param words - The loaded native language word list and tile mappings.
40
+ * @returns A computer seat's whole turn as its steps, in order, for a page to show one at a time. None when it is not a computer's turn or the game is over.
41
+ * @example
42
+ * ```ts no-run
43
+ * import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
44
+ * import { planComputerTurn, startParty } from "@johnmorrisdotca/kumimoji";
45
+ *
46
+ * const words = await loadTileWordsFromModule("english");
47
+ * const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
48
+ * const bag = "catdogsun";
49
+ * const game = startParty(settings,bag,["Seat 1","Seat 2"]);
50
+ * console.log(planComputerTurn(game,words).map(step=>step.said));
51
+ * ```
52
+ */
30
53
  export declare function planComputerTurn(game: PartyGame, words: TileWords): ComputerStep[];
31
- /** The game a computer's turn passes on: its plan's last step, or the game as it was where there is nothing to play. */
54
+ /** The game a computer's turn passes on: its plan's last step, or the game as it was where there is nothing to play.
55
+ *
56
+ * @param game - The current immutable shared-bag party game.
57
+ * @param words - The loaded native language word list and tile mappings.
58
+ * @returns The game a computer's turn passes on: its plan's last step, or the game as it was where there is nothing to play.
59
+ * @example
60
+ * ```ts no-run
61
+ * import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
62
+ * import { afterComputerTurn, startParty } from "@johnmorrisdotca/kumimoji";
63
+ *
64
+ * const words = await loadTileWordsFromModule("english");
65
+ * const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
66
+ * const bag = "catdogsun";
67
+ * const game = startParty(settings,bag,["Seat 1","Seat 2"]);
68
+ * console.log(afterComputerTurn(game,words).turn);
69
+ * ```
70
+ */
32
71
  export declare function afterComputerTurn(game: PartyGame, words: TileWords): PartyGame;
@@ -1,6 +1,6 @@
1
1
  import { bestLaying, judgeTiles, tradeChoice } from "./computerPlay.js";
2
2
  import { drawAll, isComputer, mayDrawAll, mayTradeThisTurn, seatPlay, withSeatPlay } from "./party.js";
3
- import { doneRefused, endTurn, goesOut, handCanSpell, isLastTurn, laidThisTurn, mayResign, resign } from "./partyTurns.js";
3
+ import { doneRefused, endTurn, goesOut, handCanSpell, isLastTurn, laidThisTurn, mayResign, resign, } from "./partyTurns.js";
4
4
  import { liftAll, mayTrade, trade } from "./play.js";
5
5
  /**
6
6
  * A COMPUTER'S TURN in a pass-and-play game (John, 2026-09-28: "Also you can
@@ -25,11 +25,34 @@ import { liftAll, mayTrade, trade } from "./play.js";
25
25
  * - Resign only where the rules offer it (`mayResign`) and it can do nothing
26
26
  * at all: nothing to lay, nothing to trade for, and it is not its last turn.
27
27
  */
28
- /** The most things a computer does in one turn before pressing Done: at the page's pause, a turn of about three seconds. */
28
+ /** The most things a computer does in one turn before pressing Done: at the page's pause, a turn of about three seconds.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * import { COMPUTER_STEPS_MOST } from "@johnmorrisdotca/kumimoji";
33
+ * console.log(COMPUTER_STEPS_MOST);
34
+ * ```
35
+ */
29
36
  export const COMPUTER_STEPS_MOST = 8;
30
37
  /** How many settling steps may be needed at the end to be allowed Done at all; one trade a turn and a hand of tiles, so it is bounded anyway. */
31
38
  const SETTLING_MOST = 200;
32
- /** A computer seat's whole turn as its steps, in order, for a page to show one at a time. None when it is not a computer's turn or the game is over. */
39
+ /** A computer seat's whole turn as its steps, in order, for a page to show one at a time. None when it is not a computer's turn or the game is over.
40
+ *
41
+ * @param game - The current immutable shared-bag party game.
42
+ * @param words - The loaded native language word list and tile mappings.
43
+ * @returns A computer seat's whole turn as its steps, in order, for a page to show one at a time. None when it is not a computer's turn or the game is over.
44
+ * @example
45
+ * ```ts no-run
46
+ * import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
47
+ * import { planComputerTurn, startParty } from "@johnmorrisdotca/kumimoji";
48
+ *
49
+ * const words = await loadTileWordsFromModule("english");
50
+ * const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
51
+ * const bag = "catdogsun";
52
+ * const game = startParty(settings,bag,["Seat 1","Seat 2"]);
53
+ * console.log(planComputerTurn(game,words).map(step=>step.said));
54
+ * ```
55
+ */
33
56
  export function planComputerTurn(game, words) {
34
57
  const steps = [];
35
58
  if (game.ending !== null || !isComputer(game, game.turn))
@@ -77,7 +100,10 @@ export function planComputerTurn(game, words) {
77
100
  break;
78
101
  }
79
102
  const hand = now.players[now.turn].hand;
80
- const stuck = hand.length > 0 && !laidThisTurn(now) && !mayTrade(seatPlay(now)) && bestLaying(seatPlay(now), words, rules) === null;
103
+ const stuck = hand.length > 0 &&
104
+ !laidThisTurn(now) &&
105
+ !mayTrade(seatPlay(now)) &&
106
+ bestLaying(seatPlay(now), words, rules) === null;
81
107
  const refused = doneRefused(now, verdict(), handSpells) !== null;
82
108
  if ((refused || (stuck && !isLastTurn(now))) && mayResign(now)) {
83
109
  take(resign(now), { kind: "resigned" });
@@ -89,7 +115,23 @@ export function planComputerTurn(game, words) {
89
115
  take(endTurn(now, verdict(), handSpells), { kind: "done", out: goesOut(now, verdict()) });
90
116
  return steps;
91
117
  }
92
- /** The game a computer's turn passes on: its plan's last step, or the game as it was where there is nothing to play. */
118
+ /** The game a computer's turn passes on: its plan's last step, or the game as it was where there is nothing to play.
119
+ *
120
+ * @param game - The current immutable shared-bag party game.
121
+ * @param words - The loaded native language word list and tile mappings.
122
+ * @returns The game a computer's turn passes on: its plan's last step, or the game as it was where there is nothing to play.
123
+ * @example
124
+ * ```ts no-run
125
+ * import { loadTileWordsFromModule } from "@johnmorrisdotca/kumimoji/words";
126
+ * import { afterComputerTurn, startParty } from "@johnmorrisdotca/kumimoji";
127
+ *
128
+ * const words = await loadTileWordsFromModule("english");
129
+ * const settings = {size:3,level:"hard",seed:44,gameLength:"short",language:"english",doubleSet:false,diagonals:false,hints:false} as const;
130
+ * const bag = "catdogsun";
131
+ * const game = startParty(settings,bag,["Seat 1","Seat 2"]);
132
+ * console.log(afterComputerTurn(game,words).turn);
133
+ * ```
134
+ */
93
135
  export function afterComputerTurn(game, words) {
94
136
  return planComputerTurn(game, words).at(-1)?.game ?? game;
95
137
  }
package/dist/daily.d.ts CHANGED
@@ -8,7 +8,27 @@
8
8
  * hand, level, length) gets the same bag, in the same order. The race against
9
9
  * the clock is then theirs.
10
10
  */
11
- /** The day a moment falls on, in UTC, written `YYYY-MM-DD`. Throws a `RangeError` for an invalid `Date`. */
11
+ /** The day a moment falls on, in UTC, written `YYYY-MM-DD`. Throws a `RangeError` for an invalid `Date`.
12
+ *
13
+ * @param at - The word offset, seat index or date specified by this signature.
14
+ * @returns The day a moment falls on, in UTC, written `YYYY-MM-DD`. Throws a `RangeError` for an invalid `Date`.
15
+ * @example
16
+ * ```ts
17
+ * import { kumimojiDay } from "@johnmorrisdotca/kumimoji";
18
+ *
19
+ * console.log(kumimojiDay(new Date("2026-10-12T12:00:00Z")));
20
+ * ```
21
+ */
12
22
  export declare function kumimojiDay(at: Date): string;
13
- /** Today's seed, the date as a number: 2026-10-01 is 20261001. The day is UTC, so it is one seed worldwide. */
23
+ /** Today's seed, the date as a number: 2026-10-01 is 20261001. The day is UTC, so it is one seed worldwide.
24
+ *
25
+ * @param at - The word offset, seat index or date specified by this signature.
26
+ * @returns Today's seed, the date as a number: 2026-10-01 is 20261001. The day is UTC, so it is one seed worldwide.
27
+ * @example
28
+ * ```ts
29
+ * import { kumimojiDailySeed } from "@johnmorrisdotca/kumimoji";
30
+ *
31
+ * console.log(kumimojiDailySeed(new Date("2026-10-12T12:00:00Z")));
32
+ * ```
33
+ */
14
34
  export declare function kumimojiDailySeed(at: Date): number;
package/dist/daily.js CHANGED
@@ -9,14 +9,34 @@
9
9
  * the clock is then theirs.
10
10
  */
11
11
  const pad = (value, width) => String(value).padStart(width, "0");
12
- /** The day a moment falls on, in UTC, written `YYYY-MM-DD`. Throws a `RangeError` for an invalid `Date`. */
12
+ /** The day a moment falls on, in UTC, written `YYYY-MM-DD`. Throws a `RangeError` for an invalid `Date`.
13
+ *
14
+ * @param at - The word offset, seat index or date specified by this signature.
15
+ * @returns The day a moment falls on, in UTC, written `YYYY-MM-DD`. Throws a `RangeError` for an invalid `Date`.
16
+ * @example
17
+ * ```ts
18
+ * import { kumimojiDay } from "@johnmorrisdotca/kumimoji";
19
+ *
20
+ * console.log(kumimojiDay(new Date("2026-10-12T12:00:00Z")));
21
+ * ```
22
+ */
13
23
  export function kumimojiDay(at) {
14
24
  if (Number.isNaN(at.getTime()))
15
25
  throw new RangeError("kumimoji: an invalid Date has no day");
16
26
  return `${pad(at.getUTCFullYear(), 4)}-${pad(at.getUTCMonth() + 1, 2)}-${pad(at.getUTCDate(), 2)}`;
17
27
  }
18
- /** Today's seed, the date as a number: 2026-10-01 is 20261001. The day is UTC, so it is one seed worldwide. */
28
+ /** Today's seed, the date as a number: 2026-10-01 is 20261001. The day is UTC, so it is one seed worldwide.
29
+ *
30
+ * @param at - The word offset, seat index or date specified by this signature.
31
+ * @returns Today's seed, the date as a number: 2026-10-01 is 20261001. The day is UTC, so it is one seed worldwide.
32
+ * @example
33
+ * ```ts
34
+ * import { kumimojiDailySeed } from "@johnmorrisdotca/kumimoji";
35
+ *
36
+ * console.log(kumimojiDailySeed(new Date("2026-10-12T12:00:00Z")));
37
+ * ```
38
+ */
19
39
  export function kumimojiDailySeed(at) {
20
40
  const [year, month, day] = kumimojiDay(at).split("-").map(Number);
21
- return year * 10000 + month * 100 + day;
41
+ return year * 10_000 + month * 100 + day;
22
42
  }
@@ -1 +1 @@
1
- export {};
1
+ export * from "./element.ts";
@@ -1,13 +1,3 @@
1
- /**
2
- * Defines the `<kumimoji-table>` element on the page. Import it for its effect:
3
- *
4
- * ```html
5
- * <script type="module" src="https://cdn.jsdelivr.net/npm/@johnmorrisdotca/kumimoji@1/dist/element-define.js"></script>
6
- * <kumimoji-table language="english" hand="7"></kumimoji-table>
7
- * ```
8
- *
9
- * A tag already defined is left as it is, and on a server, where there is no page, nothing happens.
10
- */
11
- import { KumimojiTable } from "./element.js";
12
- if (typeof customElements !== "undefined" && customElements.get("kumimoji-table") === undefined)
13
- customElements.define("kumimoji-table", KumimojiTable);
1
+ import { defineTable } from "./element.js";
2
+ defineTable();
3
+ export * from "./element.js";
package/dist/element.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { type KumimojiTableHandle } from "./ui/mount.ts";
2
1
  import type { KumimojiSaved } from "./export.ts";
2
+ import { type KumimojiTableHandle, type KumimojiTableOptions } from "./ui/mount.ts";
3
3
  declare const ElementBase: typeof HTMLElement;
4
4
  /**
5
5
  * THE `<kumimoji-table>` ELEMENT: a game of Kumimoji alone in a tag, with no
@@ -12,8 +12,7 @@ declare const ElementBase: typeof HTMLElement;
12
12
  * <kumimoji-table language="japanese" level="easy" seed="daily"></kumimoji-table>
13
13
  * ```
14
14
  *
15
- * Attributes (each is read again when it changes; a change to any but `lang`
16
- * deals a new game):
15
+ * Attributes configure the starting game; display, language and control changes preserve play:
17
16
  * - `language`: the tiles, `english` (default) or `japanese` kana.
18
17
  * - `hand`: the opening hand, 3, 7 (default) or 11.
19
18
  * - `level`: how many tiles are wild, `easy` (most), `medium` (default) or `hard` (none).
@@ -25,11 +24,41 @@ declare const ElementBase: typeof HTMLElement;
25
24
  * It fires `kumimoji-change` after every change to the game, with the game as it would
26
25
  * be saved as `event.detail.saved`, and `kumimoji-finish` when the last tile is laid and every run
27
26
  * is a word, with `event.detail` the deal, the play and the time it took. It has the methods
28
- * `newGame()` and `setGame()`. A table the rules do not offer (a hand of 5, say) draws nothing.
27
+ * `newGame()` and `setGame()`. Invalid input shows a status and a plain error event.
28
+ */
29
+ /**
30
+ * Native table options, checked alongside builder coverage.
31
+ * @example
32
+ * ```ts
33
+ * import { KUMIMOJI_EMBED_OPTION_KEYS } from "@johnmorrisdotca/kumimoji/element";
34
+ * console.log(KUMIMOJI_EMBED_OPTION_KEYS.includes("saved"));
35
+ * ```
36
+ */
37
+ export declare const KUMIMOJI_EMBED_OPTION_KEYS: string[];
38
+ /**
39
+ * Full native host options, including saved state, private words and callbacks.
40
+ * @example
41
+ * ```ts
42
+ * import type { KumimojiElementOptions } from "@johnmorrisdotca/kumimoji/element";
43
+ * const options: KumimojiElementOptions = { keep: false, locale: "ja" };
44
+ * console.log(options.locale);
45
+ * ```
46
+ */
47
+ export type KumimojiElementOptions = KumimojiTableOptions;
48
+ /**
49
+ * A reflected crossword table with the native table handle and saved-state getter.
50
+ * @example
51
+ * ```ts
52
+ * import { KumimojiTable } from "@johnmorrisdotca/kumimoji/element";
53
+ * console.log(KumimojiTable.observedAttributes.includes("daily"));
54
+ * ```
29
55
  */
30
56
  export declare class KumimojiTable extends ElementBase {
31
57
  #private;
32
58
  static observedAttributes: string[];
59
+ /** Native host options. Callback/presentation changes preserve the current game. */
60
+ get options(): KumimojiElementOptions;
61
+ set options(value: KumimojiElementOptions);
33
62
  connectedCallback(): void;
34
63
  disconnectedCallback(): void;
35
64
  attributeChangedCallback(): void;
@@ -41,5 +70,57 @@ export declare class KumimojiTable extends ElementBase {
41
70
  newGame(options?: Parameters<KumimojiTableHandle["newGame"]>[0]): Promise<void>;
42
71
  /** Put a game on the table: see `KumimojiTableHandle.setGame`. */
43
72
  setGame(saved: KumimojiSaved): Promise<void>;
73
+ /** The `language` attribute, reflected. */
74
+ get language(): string | null;
75
+ set language(value: string | number | boolean | null | undefined);
76
+ /** The `hand` attribute, reflected. */
77
+ get hand(): string | null;
78
+ set hand(value: string | number | boolean | null | undefined);
79
+ /** The `level` attribute, reflected. */
80
+ get level(): string | null;
81
+ set level(value: string | number | boolean | null | undefined);
82
+ /** The `length` attribute, reflected. */
83
+ get length(): string | null;
84
+ set length(value: string | number | boolean | null | undefined);
85
+ /** The `diagonals` attribute, reflected. */
86
+ get diagonals(): string | null;
87
+ set diagonals(value: string | number | boolean | null | undefined);
88
+ /** The `seed` attribute, reflected. */
89
+ get seed(): string | null;
90
+ set seed(value: string | number | boolean | null | undefined);
91
+ /** The `keep` attribute, reflected. */
92
+ get keep(): string | null;
93
+ set keep(value: string | number | boolean | null | undefined);
94
+ /** The `daily` attribute, reflected. */
95
+ get daily(): string | null;
96
+ set daily(value: string | number | boolean | null | undefined);
97
+ /** The `controls` attribute, reflected. */
98
+ get controls(): string | null;
99
+ set controls(value: string | number | boolean | null | undefined);
100
+ /** The `theme` attribute, reflected. */
101
+ get theme(): string | null;
102
+ set theme(value: string | number | boolean | null | undefined);
103
+ /** The `size` attribute, reflected. */
104
+ get size(): string | null;
105
+ set size(value: string | number | boolean | null | undefined);
106
+ /** The `width` attribute, reflected. */
107
+ get width(): string | null;
108
+ set width(value: string | number | boolean | null | undefined);
109
+ /** The `label` attribute, reflected. */
110
+ get label(): string | null;
111
+ set label(value: string | number | boolean | null | undefined);
44
112
  }
113
+ /**
114
+ * Defines the table or a subclass under a custom tag. Server-safe and idempotent.
115
+ * @param tagName - The tag name; kumimoji-table by default.
116
+ * @param registry - The page registry, or undefined on a server.
117
+ * @returns Nothing; existing definitions are left alone.
118
+ * @example
119
+ * ```ts
120
+ * import { defineTable } from "@johnmorrisdotca/kumimoji/element";
121
+ * defineTable();
122
+ * console.log(typeof defineTable);
123
+ * ```
124
+ */
125
+ export declare function defineTable(tagName?: string, registry?: CustomElementRegistry | undefined): void;
45
126
  export {};