@johnmorrisdotca/kumimoji 1.0.1 → 1.1.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/dist/ui/style.js CHANGED
@@ -1,40 +1,48 @@
1
1
  /**
2
- * The table's own styles, scoped to `.km-root`, every colour a CSS variable
3
- * so a page can wear it in its own colours. Light and dark follow the
4
- * reader's system.
2
+ * The table's own styles, scoped to `.km-root`, every colour and size a CSS
3
+ * variable so a page can wear it in its own colours (set them on the element
4
+ * or any ancestor, or pass them as `theme`). Light and dark follow the
5
+ * reader's system. Everything to be tapped is at least 44px.
5
6
  */
6
7
  export const KUMIMOJI_STYLE = `
7
8
  .km-root {
8
- --km-square: 36px; --km-felt: #2f5d4a; --km-grid-line: rgba(255,255,255,.12); --km-tile: #f3e6c8; --km-tile-ink: #2a2118;
9
- --km-wild: #f6d27a; --km-wrong: #d9534f; --km-apart: #9aa3a0; --km-held: #ffcf3f; --km-ink: #1f2320; --km-panel: #f7f3ea;
9
+ --km-square: 44px; --km-felt: #2f5d4a; --km-grid-line: rgba(255,255,255,.12); --km-tile: #f3e6c8; --km-tile-ink: #2a2118;
10
+ --km-wild: #f6d27a; --km-wrong: #d9534f; --km-held: #ffcf3f; --km-ink: #1f2320; --km-panel: #f7f3ea;
10
11
  --km-line: rgba(20,20,20,.35); --km-accent: #2f5d4a; --km-accent-ink: #fff;
11
- display: grid; gap: 10px; color: var(--km-ink); font-family: system-ui, -apple-system, "Segoe UI", sans-serif; font-size: 15px;
12
+ --km-radius: 12px; --km-font: system-ui, -apple-system, "Segoe UI", sans-serif;
13
+ display: grid; gap: 10px; min-width: 0; color: var(--km-ink); font-family: var(--km-font); font-size: 15px;
12
14
  }
13
15
  @media (prefers-color-scheme: dark) {
14
16
  .km-root { --km-felt: #1e3a2f; --km-ink: #ece8dc; --km-panel: #1d201e; --km-line: rgba(255,255,255,.25); --km-accent: #6fb08f; --km-accent-ink: #10150f; }
15
17
  }
18
+ .km-root > * { min-width: 0; }
16
19
  .km-status { margin: 0; min-height: 1.4em; font-variant-numeric: tabular-nums; }
17
- .km-board { background: var(--km-felt); border-radius: 12px; padding: 10px; overflow: auto; max-height: 70vh; }
20
+ .km-board { background: var(--km-felt); border-radius: var(--km-radius); padding: 10px; overflow: auto; max-height: 70vh; }
18
21
  .km-grid { display: grid; gap: 2px; width: max-content; margin: 0 auto; }
19
- .km-square { width: var(--km-square); height: var(--km-square); border: 0; border-radius: 5px; background: var(--km-grid-line); padding: 0; cursor: pointer; }
22
+ .km-square { width: var(--km-square); height: var(--km-square); border: 0; border-radius: 5px; background: var(--km-grid-line); padding: 0; cursor: pointer; touch-action: manipulation; }
20
23
  .km-tile { display: grid; place-items: center; width: var(--km-square); height: var(--km-square); border-radius: 6px; border: 0; padding: 0;
21
- background: var(--km-tile); color: var(--km-tile-ink); font: 700 20px/1 system-ui, sans-serif; text-transform: uppercase;
22
- box-shadow: 0 2px 0 rgba(0,0,0,.35); cursor: pointer; }
23
- .km-japanese .km-tile { font-size: 19px; text-transform: none; }
24
+ background: var(--km-tile); color: var(--km-tile-ink); font: 700 calc(var(--km-square) * .55)/1 var(--km-font); text-transform: uppercase;
25
+ box-shadow: 0 2px 0 rgba(0,0,0,.35); cursor: pointer; touch-action: manipulation; }
26
+ .km-japanese .km-tile { font-size: calc(var(--km-square) * .52); text-transform: none; }
24
27
  .km-wild { background: var(--km-wild); }
25
28
  .km-misspelt { box-shadow: 0 0 0 3px var(--km-wrong) inset, 0 2px 0 rgba(0,0,0,.35); }
26
29
  .km-apart { opacity: .6; }
27
30
  .km-held { outline: 3px solid var(--km-held); outline-offset: 1px; }
28
- .km-notes { margin: 0; min-height: 1.4em; font-size: 14px; opacity: .8; }
29
- .km-hand { display: flex; flex-wrap: wrap; gap: 6px; min-height: 40px; align-items: center; padding: 8px; border-radius: 10px; background: var(--km-panel); }
31
+ .km-square:focus-visible, .km-button:focus-visible, .km-keep-title:focus-visible { outline: 3px solid var(--km-held); outline-offset: 2px; }
32
+ .km-notes { margin: 0; min-height: 1.4em; font-size: 14px; opacity: .8; overflow-wrap: anywhere; }
33
+ .km-hand { display: flex; flex-wrap: wrap; gap: 6px; min-height: calc(var(--km-square) + 16px); align-items: center; padding: 8px; border-radius: 10px; background: var(--km-panel); }
30
34
  .km-empty { opacity: .6; font-size: 14px; }
31
35
  .km-picker { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
32
36
  .km-picker:empty { display: none; }
33
37
  .km-picker-title { width: 100%; font-size: 14px; }
34
- .km-picker .km-button { padding: 4px 8px; min-width: 32px; text-transform: uppercase; }
38
+ .km-picker .km-button { padding: 0 8px; text-transform: uppercase; }
35
39
  .km-japanese .km-picker .km-button { text-transform: none; }
36
40
  .km-controls { display: flex; flex-wrap: wrap; gap: 8px; }
37
- .km-button { font: inherit; padding: 8px 14px; border-radius: 8px; border: 1px solid var(--km-line); background: var(--km-panel); color: var(--km-ink); cursor: pointer; }
41
+ .km-button { font: inherit; min-height: 44px; min-width: 44px; padding: 0 14px; border-radius: 8px; border: 1px solid var(--km-line); background: var(--km-panel); color: var(--km-ink); cursor: pointer; touch-action: manipulation; }
38
42
  .km-button:disabled { opacity: .45; cursor: default; }
39
43
  .km-primary { background: var(--km-accent); color: var(--km-accent-ink); border-color: transparent; }
44
+ .km-keep { border-radius: 10px; background: var(--km-panel); padding: 0 10px; }
45
+ .km-keep[open] { padding-bottom: 10px; }
46
+ .km-keep-title { min-height: 44px; display: flex; align-items: center; font-weight: 600; cursor: pointer; }
47
+ .km-note { margin: 8px 0 0; min-height: 1.4em; font-size: 13px; }
40
48
  `;
package/dist/ui.d.ts CHANGED
@@ -6,3 +6,4 @@
6
6
  export { mountKumimoji, type KumimojiTableHandle, type KumimojiTableOptions } from "./ui/mount.ts";
7
7
  export { BOARD_LEAST, BOARD_MARGIN, boardModel, type BoardModel, type BoardSquare, type TileMark } from "./ui/board.ts";
8
8
  export { KUMIMOJI_STYLE } from "./ui/style.ts";
9
+ export { KUMIMOJI_STRINGS, kumimojiSay, kumimojiStrings, type KumimojiLocale, type KumimojiStrings } from "./strings.ts";
package/dist/ui.js CHANGED
@@ -6,3 +6,4 @@
6
6
  export { mountKumimoji } from "./ui/mount.js";
7
7
  export { BOARD_LEAST, BOARD_MARGIN, boardModel } from "./ui/board.js";
8
8
  export { KUMIMOJI_STYLE } from "./ui/style.js";
9
+ export { KUMIMOJI_STRINGS, kumimojiSay, kumimojiStrings } from "./strings.js";
@@ -0,0 +1,2 @@
1
+ /** The version of this package, as `package.json` has it. A test holds the two together. */
2
+ export declare const KUMIMOJI_VERSION = "1.1.0";
@@ -0,0 +1,2 @@
1
+ /** The version of this package, as `package.json` has it. A test holds the two together. */
2
+ export const KUMIMOJI_VERSION = "1.1.0";
package/package.json CHANGED
@@ -1,36 +1,91 @@
1
1
  {
2
2
  "name": "@johnmorrisdotca/kumimoji",
3
- "version": "1.0.1",
4
- "description": "Kumimoji 組み文字: the race to build a crossword from a bag of letter tiles, in English or Japanese, alone or at a table of two to eight. Seeded deals, word checking, wild tiles, trades, a computer player, a plain-DOM table and React views.",
5
- "license": "MIT",
6
- "author": "John Morris <john@johnmorris.ca>",
7
- "homepage": "https://johnmorrisdotca.github.io/kumimoji/",
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/johnmorrisdotca/kumimoji.git"
11
- },
12
- "bugs": {
13
- "url": "https://github.com/johnmorrisdotca/kumimoji/issues"
14
- },
15
- "type": "module",
16
- "sideEffects": [
17
- "./dist/words.js",
18
- "./dist/tileWordsModule.js"
19
- ],
20
- "engines": {
21
- "node": ">=20"
22
- },
3
+ "version": "1.1.0",
4
+ "description": "Crossword tile race: a word game engine where each player builds a crossword from a bag of letter tiles, in English or Japanese kana, alone against the clock or at a table of two to eight. Seeded deals, word checking, wild tiles, a computer player, and a playable table for React, Vue, Svelte, Angular or plain HTML. Zero dependencies.",
23
5
  "keywords": [
24
6
  "word-game",
7
+ "word-puzzle",
25
8
  "crossword",
9
+ "crossword-game",
10
+ "crossword-builder",
11
+ "tile-game",
12
+ "letter-tiles",
26
13
  "tiles",
14
+ "word-tiles",
27
15
  "anagram",
16
+ "anagrams",
17
+ "word-race",
18
+ "spelling",
19
+ "vocabulary",
20
+ "dictionary",
21
+ "word-list",
22
+ "word-check",
23
+ "word-validation",
24
+ "english",
28
25
  "japanese",
29
26
  "kana",
27
+ "hiragana",
28
+ "nihongo",
29
+ "language-learning",
30
+ "scowl",
31
+ "jmdict",
32
+ "wild-tiles",
33
+ "blank-tiles",
34
+ "game",
30
35
  "game-engine",
36
+ "rules-engine",
37
+ "game-logic",
38
+ "puzzle",
39
+ "puzzle-generator",
31
40
  "seeded",
32
- "react"
41
+ "deterministic",
42
+ "prng",
43
+ "ai",
44
+ "computer-player",
45
+ "bot",
46
+ "multiplayer",
47
+ "pass-and-play",
48
+ "hotseat",
49
+ "party-game",
50
+ "save-game",
51
+ "json",
52
+ "export",
53
+ "import",
54
+ "browser-game",
55
+ "html5-game",
56
+ "typescript",
57
+ "javascript",
58
+ "esm",
59
+ "react",
60
+ "react-component",
61
+ "vue",
62
+ "svelte",
63
+ "angular",
64
+ "vanilla-js",
65
+ "dom",
66
+ "i18n",
67
+ "theming",
68
+ "dark-mode",
69
+ "zero-dependencies"
33
70
  ],
71
+ "homepage": "https://johnmorrisdotca.github.io/kumimoji/",
72
+ "bugs": {
73
+ "url": "https://github.com/johnmorrisdotca/kumimoji/issues"
74
+ },
75
+ "repository": {
76
+ "type": "git",
77
+ "url": "git+https://github.com/johnmorrisdotca/kumimoji.git"
78
+ },
79
+ "license": "MIT AND CC-BY-SA-4.0",
80
+ "author": {
81
+ "name": "John Morris",
82
+ "email": "john@johnmorris.ca",
83
+ "url": "https://johnmorris.ca"
84
+ },
85
+ "type": "module",
86
+ "main": "./dist/index.js",
87
+ "module": "./dist/index.js",
88
+ "types": "./dist/index.d.ts",
34
89
  "exports": {
35
90
  ".": {
36
91
  "types": "./dist/index.d.ts",
@@ -57,17 +112,37 @@
57
112
  "CHANGELOG.md",
58
113
  "CONTRIBUTING.md"
59
114
  ],
115
+ "sideEffects": [
116
+ "./dist/words.js",
117
+ "./dist/tileWordsModule.js"
118
+ ],
119
+ "engines": {
120
+ "node": ">=20"
121
+ },
60
122
  "scripts": {
61
123
  "build": "tsc -p tsconfig.json",
62
- "test": "vitest run",
63
124
  "lint": "eslint .",
64
125
  "typecheck": "tsc -p tsconfig.json --noEmit",
65
- "check": "pnpm run lint && pnpm run typecheck && pnpm test",
66
- "site": "pnpm run build && node scripts/site.mjs",
67
- "prepublishOnly": "pnpm run check && pnpm run build"
126
+ "test": "vitest run",
127
+ "test:table": "pnpm site && playwright test",
128
+ "test:package": "pnpm build && node scripts/check-package.mjs",
129
+ "test:frameworks": "pnpm build && node scripts/check-frameworks.mjs",
130
+ "check": "pnpm lint && pnpm typecheck && pnpm test",
131
+ "site": "pnpm build && node scripts/site.mjs",
132
+ "docs:make": "node scripts/docs.mjs",
133
+ "prepublishOnly": "pnpm check && pnpm build"
134
+ },
135
+ "peerDependencies": {
136
+ "react": ">=18"
137
+ },
138
+ "peerDependenciesMeta": {
139
+ "react": {
140
+ "optional": true
141
+ }
68
142
  },
69
143
  "devDependencies": {
70
144
  "@eslint/js": "^9.0.0",
145
+ "@playwright/test": "^1.63.0",
71
146
  "@types/node": "^24.0.0",
72
147
  "@types/react": "^19.0.0",
73
148
  "eslint": "^9.0.0",
@@ -78,13 +153,8 @@
78
153
  "typescript-eslint": "^8.0.0",
79
154
  "vitest": "^5.0.0"
80
155
  },
81
- "peerDependencies": {
82
- "react": ">=18"
83
- },
84
- "peerDependenciesMeta": {
85
- "react": {
86
- "optional": true
87
- }
156
+ "publishConfig": {
157
+ "access": "public"
88
158
  },
89
159
  "packageManager": "pnpm@10.11.0"
90
160
  }