mirror of
https://github.com/lichess-org/lila.git
synced 2026-05-26 13:51:00 +00:00
Merge branch 'master' into lint-bin-files
This commit is contained in:
+2
-2
@@ -2,9 +2,9 @@
|
||||
"name": "bin",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@types/node": "24.0.1",
|
||||
"@types/node": "24.10.13",
|
||||
"cheerio": "^1.1.2",
|
||||
"fast-xml-parser": "^5.3.4",
|
||||
"fast-xml-parser": "^5.3.6",
|
||||
"mongodb": "6.16.0"
|
||||
},
|
||||
"license": "ISC"
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
"@lichess-org/chessground": "^10.0.2",
|
||||
"@lichess-org/pgn-viewer": "^2.5.9",
|
||||
"@types/lichess": "workspace:*",
|
||||
"@types/node": "^24.10.0",
|
||||
"@types/node": "^24.10.13",
|
||||
"ab": "github:lichess-org/ab-stub",
|
||||
"chessops": "^0.15",
|
||||
"jsdom": "^27.1.0",
|
||||
|
||||
Generated
+18
-30
@@ -23,8 +23,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:ui/@types/lichess
|
||||
'@types/node':
|
||||
specifier: ^24.10.0
|
||||
version: 24.10.0
|
||||
specifier: ^24.10.13
|
||||
version: 24.10.13
|
||||
ab:
|
||||
specifier: github:lichess-org/ab-stub
|
||||
version: https://codeload.github.com/lichess-org/ab-stub/tar.gz/94236bf34dbc9c05daf50f4c9842d859b9142be0
|
||||
@@ -68,14 +68,14 @@ importers:
|
||||
bin:
|
||||
dependencies:
|
||||
'@types/node':
|
||||
specifier: 24.0.1
|
||||
version: 24.0.1
|
||||
specifier: 24.10.13
|
||||
version: 24.10.13
|
||||
cheerio:
|
||||
specifier: ^1.1.2
|
||||
version: 1.1.2
|
||||
fast-xml-parser:
|
||||
specifier: ^5.3.4
|
||||
version: 5.3.4
|
||||
specifier: ^5.3.6
|
||||
version: 5.3.6
|
||||
mongodb:
|
||||
specifier: 6.16.0
|
||||
version: 6.16.0
|
||||
@@ -501,8 +501,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../lib
|
||||
swiper:
|
||||
specifier: ^12.0.3
|
||||
version: 12.0.3
|
||||
specifier: ^12.1.2
|
||||
version: 12.1.2
|
||||
|
||||
ui/round:
|
||||
dependencies:
|
||||
@@ -1085,11 +1085,8 @@ packages:
|
||||
'@types/node@22.17.0':
|
||||
resolution: {integrity: sha512-bbAKTCqX5aNVryi7qXVMi+OkB3w/OyblodicMbvE38blyAz7GxXf6XYhklokijuPwwVg9sDLKRxt0ZHXQwZVfQ==}
|
||||
|
||||
'@types/node@24.0.1':
|
||||
resolution: {integrity: sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==}
|
||||
|
||||
'@types/node@24.10.0':
|
||||
resolution: {integrity: sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==}
|
||||
'@types/node@24.10.13':
|
||||
resolution: {integrity: sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==}
|
||||
|
||||
'@types/qrcode@1.5.6':
|
||||
resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==}
|
||||
@@ -1409,8 +1406,8 @@ packages:
|
||||
fast-uri@3.1.0:
|
||||
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
|
||||
|
||||
fast-xml-parser@5.3.4:
|
||||
resolution: {integrity: sha512-EFd6afGmXlCx8H8WTZHhAoDaWaGyuIBoZJ2mknrNxug+aZKjkp0a0dlars9Izl+jF+7Gu1/5f/2h68cQpe0IiA==}
|
||||
fast-xml-parser@5.3.6:
|
||||
resolution: {integrity: sha512-QNI3sAvSvaOiaMl8FYU4trnEzCwiRr8XMWgAHzlrWpTSj+QaCSvOf1h82OEP1s4hiAXhnbXSyFWCf4ldZzZRVA==}
|
||||
hasBin: true
|
||||
|
||||
fastest-levenshtein@1.0.16:
|
||||
@@ -2102,8 +2099,8 @@ packages:
|
||||
resolution: {integrity: sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
swiper@12.0.3:
|
||||
resolution: {integrity: sha512-BHd6U1VPEIksrXlyXjMmRWO0onmdNPaTAFduzqR3pgjvi7KfmUCAm/0cj49u2D7B0zNjMw02TSeXfinC1hDCXg==}
|
||||
swiper@12.1.2:
|
||||
resolution: {integrity: sha512-4gILrI3vXZqoZh71I1PALqukCFgk+gpOwe1tOvz5uE9kHtl2gTDzmYflYCwWvR4LOvCrJi6UEEU+gnuW5BtkgQ==}
|
||||
engines: {node: '>= 4.7.0'}
|
||||
|
||||
symbol-tree@3.2.4:
|
||||
@@ -2166,9 +2163,6 @@ packages:
|
||||
undici-types@7.16.0:
|
||||
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
|
||||
|
||||
undici-types@7.8.0:
|
||||
resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==}
|
||||
|
||||
undici@7.16.0:
|
||||
resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==}
|
||||
engines: {node: '>=20.18.1'}
|
||||
@@ -2638,17 +2632,13 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
|
||||
'@types/node@24.0.1':
|
||||
dependencies:
|
||||
undici-types: 7.8.0
|
||||
|
||||
'@types/node@24.10.0':
|
||||
'@types/node@24.10.13':
|
||||
dependencies:
|
||||
undici-types: 7.16.0
|
||||
|
||||
'@types/qrcode@1.5.6':
|
||||
dependencies:
|
||||
'@types/node': 24.10.0
|
||||
'@types/node': 24.10.13
|
||||
|
||||
'@types/react@19.1.9':
|
||||
dependencies:
|
||||
@@ -2973,7 +2963,7 @@ snapshots:
|
||||
|
||||
fast-uri@3.1.0: {}
|
||||
|
||||
fast-xml-parser@5.3.4:
|
||||
fast-xml-parser@5.3.6:
|
||||
dependencies:
|
||||
strnum: 2.1.2
|
||||
|
||||
@@ -3677,7 +3667,7 @@ snapshots:
|
||||
dependencies:
|
||||
svg.js: 2.7.1
|
||||
|
||||
swiper@12.0.3: {}
|
||||
swiper@12.1.2: {}
|
||||
|
||||
symbol-tree@3.2.4: {}
|
||||
|
||||
@@ -3732,8 +3722,6 @@ snapshots:
|
||||
|
||||
undici-types@7.16.0: {}
|
||||
|
||||
undici-types@7.8.0: {}
|
||||
|
||||
undici@7.16.0: {}
|
||||
|
||||
unicorn-magic@0.4.0: {}
|
||||
|
||||
@@ -22,7 +22,7 @@ object Dependencies {
|
||||
val maxmind = "com.maxmind.geoip2" % "geoip2" % "4.0.1"
|
||||
val caffeine = "com.github.ben-manes.caffeine" % "caffeine" % "3.2.3" % "compile"
|
||||
val scaffeine = "com.github.blemale" %% "scaffeine" % "5.3.0" % "compile"
|
||||
val googleOAuth = "com.google.auth" % "google-auth-library-oauth2-http" % "1.42.1"
|
||||
val googleOAuth = "com.google.auth" % "google-auth-library-oauth2-http" % "1.43.0"
|
||||
val galimatias = "io.mola.galimatias" % "galimatias" % "0.2.2-NF"
|
||||
val scalatags = "com.lihaoyi" %% "scalatags" % "0.13.1"
|
||||
val lettuce = "io.lettuce" % "lettuce-core" % "7.4.0.RELEASE"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/micromatch": "4.0.10",
|
||||
"@types/node": "24.8.1",
|
||||
"@types/node": "24.10.13",
|
||||
"@types/tinycolor2": "1.4.6",
|
||||
"esbuild": "0.27.3",
|
||||
"fast-glob": "3.3.3",
|
||||
|
||||
Generated
+9
-9
@@ -12,8 +12,8 @@ importers:
|
||||
specifier: 4.0.10
|
||||
version: 4.0.10
|
||||
'@types/node':
|
||||
specifier: 24.8.1
|
||||
version: 24.8.1
|
||||
specifier: 24.10.13
|
||||
version: 24.10.13
|
||||
'@types/tinycolor2':
|
||||
specifier: 1.4.6
|
||||
version: 1.4.6
|
||||
@@ -114,8 +114,8 @@ packages:
|
||||
'@types/micromatch@4.0.10':
|
||||
resolution: {integrity: sha512-5jOhFDElqr4DKTrTEbnW8DZ4Hz5LRUEmyrGpCMrD/NphYv3nUnaF08xmSLx1rGGnyEs/kFnhiw6dCgcDqMr5PQ==}
|
||||
|
||||
'@types/node@24.8.1':
|
||||
resolution: {integrity: sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==}
|
||||
'@types/node@24.10.13':
|
||||
resolution: {integrity: sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==}
|
||||
|
||||
'@types/tinycolor2@1.4.6':
|
||||
resolution: {integrity: sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==}
|
||||
@@ -236,8 +236,8 @@ packages:
|
||||
engines: {node: '>=14.17'}
|
||||
hasBin: true
|
||||
|
||||
undici-types@7.14.0:
|
||||
resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==}
|
||||
undici-types@7.16.0:
|
||||
resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
|
||||
|
||||
ignoredOptionalDependencies:
|
||||
- '@esbuild/*-arm'
|
||||
@@ -293,9 +293,9 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/braces': 3.0.5
|
||||
|
||||
'@types/node@24.8.1':
|
||||
'@types/node@24.10.13':
|
||||
dependencies:
|
||||
undici-types: 7.14.0
|
||||
undici-types: 7.16.0
|
||||
|
||||
'@types/tinycolor2@1.4.6': {}
|
||||
|
||||
@@ -391,4 +391,4 @@ snapshots:
|
||||
|
||||
typescript@5.9.3: {}
|
||||
|
||||
undici-types@7.14.0: {}
|
||||
undici-types@7.16.0: {}
|
||||
|
||||
Vendored
+3
-3
@@ -1,6 +1,6 @@
|
||||
import { Api } from '../../../node_modules/@lichess-org/chessground/dist/api';
|
||||
import { Config } from '../../../node_modules/@lichess-org/chessground/dist/config';
|
||||
import * as cg from '../../../node_modules/@lichess-org/chessground/dist/types';
|
||||
import { Api } from '@lichess-org/chessground/api';
|
||||
import { Config } from '@lichess-org/chessground/config';
|
||||
import * as cg from '@lichess-org/chessground/types';
|
||||
|
||||
declare global {
|
||||
type CgApi = Api;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { drag } from './crazyCtrl';
|
||||
import { h } from 'snabbdom';
|
||||
import type { MouchEvent } from '@lichess-org/chessground/types';
|
||||
import { onInsert } from 'lib/view';
|
||||
import type AnalyseCtrl from '../ctrl';
|
||||
|
||||
const eventNames = ['mousedown', 'touchstart'];
|
||||
const eventNames = ['mousedown', 'touchstart'] as const;
|
||||
const oKeys = ['pawn', 'knight', 'bishop', 'rook', 'queen'] as const;
|
||||
|
||||
type Position = 'top' | 'bottom';
|
||||
@@ -23,7 +22,7 @@ export default function (ctrl: AnalyseCtrl, color: Color, position: Position) {
|
||||
class: { usable },
|
||||
hook: onInsert(el => {
|
||||
eventNames.forEach(name => {
|
||||
el.addEventListener(name, e => drag(ctrl, color, e as MouchEvent));
|
||||
el.addEventListener(name, e => drag(ctrl, color, e));
|
||||
});
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -67,12 +67,7 @@ export class ExplorerConfigCtrl {
|
||||
const prevData = previous?.data;
|
||||
this.data = {
|
||||
open: prevData?.open || prop(false),
|
||||
db: storedProp<ExplorerDb>(
|
||||
'explorer.db2.' + variant,
|
||||
this.allDbs[0],
|
||||
str => str as ExplorerDb,
|
||||
v => v,
|
||||
),
|
||||
db: storedProp<ExplorerDb>('explorer.db2.' + variant, this.allDbs[0], str => str as ExplorerDb),
|
||||
rating: storedJsonProp('analyse.explorer.rating', () => allRatings.slice(1)),
|
||||
speed: storedJsonProp<ExplorerSpeed[]>('explorer.speed', () => allSpeeds.slice(1)),
|
||||
mode: storedJsonProp<ExplorerMode[]>('explorer.mode', () => allModes),
|
||||
|
||||
@@ -42,12 +42,7 @@ export class StudyChapterNewForm {
|
||||
if (!val) this.dialog?.close();
|
||||
});
|
||||
initial = toggle(false);
|
||||
tab = storedProp<ChapterTab>(
|
||||
'analyse.study.form.tab',
|
||||
'init',
|
||||
str => str as ChapterTab,
|
||||
v => v,
|
||||
);
|
||||
tab = storedProp<ChapterTab>('analyse.study.form.tab', 'init', str => str as ChapterTab);
|
||||
editor: LichessEditor | null = null;
|
||||
editorFen: Prop<FEN | null> = prop(null);
|
||||
isDefaultName = toggle(true);
|
||||
|
||||
@@ -66,7 +66,7 @@ export const formView = (ctrl: TopicsCtrl, userId?: string): VNode =>
|
||||
],
|
||||
onInsert: dlg => {
|
||||
dlg.show();
|
||||
(dlg.view.querySelector('.tagify__input') as HTMLElement)?.focus();
|
||||
dlg.view.querySelector<HTMLElement>('.tagify__input')?.focus();
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -13,14 +13,11 @@ import type { TreePath } from 'lib/tree/types';
|
||||
|
||||
export class TreeView {
|
||||
constructor(readonly ctrl: AnalyseCtrl) {}
|
||||
private autoScrollRequest: 'instant' | 'smooth' | false = false;
|
||||
private autoScrollRequest: ScrollBehavior | false = false;
|
||||
|
||||
hidden = true;
|
||||
modePreference = storedProp<'column' | 'inline'>(
|
||||
'treeView',
|
||||
'column',
|
||||
str => (str === 'column' ? 'column' : 'inline'),
|
||||
v => v,
|
||||
modePreference = storedProp<'column' | 'inline'>('treeView', 'column', str =>
|
||||
str === 'column' ? 'column' : 'inline',
|
||||
);
|
||||
mode: 'column' | 'inline';
|
||||
|
||||
@@ -33,7 +30,7 @@ export class TreeView {
|
||||
return this.mode === 'column' ? renderColumnView(this.ctrl, concealOf) : renderInlineView(this.ctrl);
|
||||
}
|
||||
|
||||
requestAutoScroll(request: 'instant' | 'smooth' | false) {
|
||||
requestAutoScroll(request: ScrollBehavior | false) {
|
||||
this.autoScrollRequest = request;
|
||||
}
|
||||
|
||||
@@ -82,7 +79,7 @@ function eventPath(e: MouseEvent): TreePath | null {
|
||||
);
|
||||
}
|
||||
|
||||
const autoScroll = throttle(200, (behavior: 'instant' | 'smooth' = 'instant') => {
|
||||
const autoScroll = throttle(200, (behavior: ScrollBehavior = 'instant') => {
|
||||
const scrollView = document.querySelector<HTMLElement>('.analyse__moves')!;
|
||||
const moveEl = scrollView.querySelector<HTMLElement>('.active');
|
||||
if (!moveEl) return scrollView.scrollTo({ top: 0, behavior });
|
||||
|
||||
@@ -166,11 +166,12 @@ export function renderNvui(ctx: AnalyseNvuiContext): VNode {
|
||||
});
|
||||
});
|
||||
root.find('.copy-fen').on('click', function (this: HTMLElement) {
|
||||
const inputFen = document.querySelector('.analyse__underboard__fen input') as HTMLInputElement;
|
||||
const fen = inputFen.value;
|
||||
navigator.clipboard.writeText(fen).then(() => {
|
||||
notify.set(i18n.nvui.copiedToClipboard('FEN'));
|
||||
});
|
||||
const fen = document.querySelector<HTMLInputElement>('.analyse__underboard__fen input')?.value;
|
||||
if (fen) {
|
||||
navigator.clipboard.writeText(fen).then(() => {
|
||||
notify.set(i18n.nvui.copiedToClipboard('FEN'));
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
@@ -346,7 +347,7 @@ function onSubmit(ctx: AnalyseNvuiContext, $input: Cash) {
|
||||
if (command && !command.invalid?.(ctrl)) command.cb(ctx, input);
|
||||
else {
|
||||
const move = inputToMove(input, ctrl.node.fen, ctrl.chessground);
|
||||
const isDrop = (u: undefined | string | DropMove) => !!(u && typeof u !== 'string');
|
||||
const isDrop = (u?: string | DropMove) => !!(u && typeof u !== 'string');
|
||||
const isInvalidDrop = (d: DropMove) =>
|
||||
!ctrl.crazyValid(d.role, d.key) || ctrl.chessground.state.pieces.has(d.key);
|
||||
const isInvalidCrazy = isDrop(move) && isInvalidDrop(move);
|
||||
|
||||
@@ -91,7 +91,7 @@ site.load.then(() => {
|
||||
$editor.find('div.status').removeClass('saved');
|
||||
});
|
||||
const submit = debounce(() => {
|
||||
const form = document.querySelector('form.async') as HTMLFormElement;
|
||||
const form = document.querySelector<HTMLFormElement>('form.async');
|
||||
if (!form) return;
|
||||
xhr.formToXhr(form).then(() => {
|
||||
$editor.find('div.status').addClass('saved');
|
||||
|
||||
@@ -15,7 +15,8 @@ export function initModule(
|
||||
fireworks: true,
|
||||
},
|
||||
): void {
|
||||
const canvas = document.querySelector('canvas#confetti') as HTMLCanvasElement;
|
||||
const canvas = document.querySelector<HTMLCanvasElement>('canvas#confetti');
|
||||
if (!canvas) return;
|
||||
|
||||
const party = confetti.create(canvas, {
|
||||
disableForReducedMotion: true,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { pubsub } from 'lib/pubsub';
|
||||
|
||||
site.load.then(() => {
|
||||
const form = document.querySelector('.search__form') as HTMLFormElement,
|
||||
const form = document.querySelector<HTMLFormElement>('.search__form'),
|
||||
$form = $(form),
|
||||
$usernames = $form.find('.usernames input'),
|
||||
$userRows = $form.find('.user-row'),
|
||||
@@ -65,8 +65,8 @@ site.load.then(() => {
|
||||
|
||||
function serialize() {
|
||||
const params = new URLSearchParams();
|
||||
for (const [k, v] of new FormData(form).entries()) {
|
||||
if (v != '') params.set(k, v as string);
|
||||
for (const [k, v] of new FormData(form ?? undefined).entries()) {
|
||||
if (v != '') params.set(k, v.toString());
|
||||
}
|
||||
return params.toString();
|
||||
}
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ function appeal() {
|
||||
}
|
||||
|
||||
function autoForm({ selector, ops }: { selector: string; ops: string }) {
|
||||
const el = document.querySelector(selector) as HTMLElement;
|
||||
const el = document.querySelector<HTMLElement>(selector);
|
||||
const oplist = ops.split(' ');
|
||||
if (!el || oplist.length === 0) return;
|
||||
if (oplist.includes('focus')) el.focus();
|
||||
|
||||
@@ -10,7 +10,7 @@ export const autoScroll = throttle(100, (movesEl: HTMLElement, ctrl: PlayCtrl) =
|
||||
if (ctrl.board.onPly < 3) st = 0;
|
||||
else if (ctrl.isOnLastPly()) st = scrollMax;
|
||||
else {
|
||||
const plyEl = movesEl.querySelector('.current') as HTMLElement | undefined;
|
||||
const plyEl = movesEl.querySelector<HTMLElement>('.current');
|
||||
if (plyEl)
|
||||
st =
|
||||
displayColumns() === 1
|
||||
|
||||
@@ -92,12 +92,7 @@ export default class CoordinateTrainerCtrl {
|
||||
}
|
||||
|
||||
colorChoice: Prop<ColorChoice> = withEffect<ColorChoice>(
|
||||
storedProp<ColorChoice>(
|
||||
'coordinateTrainer.colorChoice',
|
||||
'random',
|
||||
str => str as ColorChoice,
|
||||
v => v,
|
||||
),
|
||||
storedProp<ColorChoice>('coordinateTrainer.colorChoice', 'random', str => str as ColorChoice),
|
||||
() => this.setOrientationFromColorChoice(),
|
||||
);
|
||||
|
||||
@@ -114,7 +109,6 @@ export default class CoordinateTrainerCtrl {
|
||||
'coordinateTrainer.mode',
|
||||
window.location.hash === '#name' ? 'nameSquare' : 'findSquare',
|
||||
str => str as Mode,
|
||||
v => v,
|
||||
),
|
||||
() => this.onModeChange(),
|
||||
);
|
||||
@@ -148,7 +142,6 @@ export default class CoordinateTrainerCtrl {
|
||||
'coordinateTrainer.timeControl',
|
||||
document.body.classList.contains('kid') ? 'untimed' : 'thirtySeconds',
|
||||
str => str as TimeControl,
|
||||
v => v,
|
||||
),
|
||||
this.redraw,
|
||||
);
|
||||
@@ -192,7 +185,6 @@ export default class CoordinateTrainerCtrl {
|
||||
'coordinateTrainer.coordinateInputMethod',
|
||||
window.innerWidth >= 980 ? 'text' : 'buttons',
|
||||
str => str as InputMethod,
|
||||
v => v,
|
||||
),
|
||||
this.redraw,
|
||||
);
|
||||
|
||||
+9
-19
@@ -13,7 +13,12 @@ export function storedProp<V>(
|
||||
key: string,
|
||||
defaultValue: V,
|
||||
fromStr: (str: string) => V,
|
||||
toStr: (v: V) => string,
|
||||
toStr: (v: V) => string = (v: V) => {
|
||||
if (v && typeof v.toString === 'function') {
|
||||
return v.toString();
|
||||
}
|
||||
throw new Error(`storedProp: value ${typeof v} has no toString method, provide a custom stringifier`);
|
||||
},
|
||||
): StoredProp<V> {
|
||||
const compatKey = 'analyse.' + key;
|
||||
let cached: V;
|
||||
@@ -35,20 +40,10 @@ export function storedProp<V>(
|
||||
}
|
||||
|
||||
export const storedStringProp = (k: string, defaultValue: string): StoredProp<string> =>
|
||||
storedProp<string>(
|
||||
k,
|
||||
defaultValue,
|
||||
str => str,
|
||||
v => v,
|
||||
);
|
||||
storedProp<string>(k, defaultValue, str => str);
|
||||
|
||||
export const storedBooleanProp = (k: string, defaultValue: boolean): StoredProp<boolean> =>
|
||||
storedProp<boolean>(
|
||||
k,
|
||||
defaultValue,
|
||||
str => str === 'true',
|
||||
v => v.toString(),
|
||||
);
|
||||
storedProp<boolean>(k, defaultValue, str => str === 'true');
|
||||
|
||||
export const storedStringPropWithEffect = (
|
||||
k: string,
|
||||
@@ -63,12 +58,7 @@ export const storedBooleanPropWithEffect = (
|
||||
): Prop<boolean> => withEffect(storedBooleanProp(k, defaultValue), effect);
|
||||
|
||||
export const storedIntProp = (k: string, defaultValue: number): StoredProp<number> =>
|
||||
storedProp<number>(
|
||||
k,
|
||||
defaultValue,
|
||||
str => Number(str),
|
||||
v => v + '',
|
||||
);
|
||||
storedProp<number>(k, defaultValue, str => Number(str));
|
||||
|
||||
export const storedIntPropWithEffect = (
|
||||
k: string,
|
||||
|
||||
@@ -23,7 +23,7 @@ export const expandCheckboxZone = (table: HTMLTableElement, tdSelector: string,
|
||||
$(table).on('click', tdSelector, (e: MouseEvent) => {
|
||||
if ((e.target as HTMLElement).tagName === 'INPUT') onSelect(e.target as HTMLInputElement, e.shiftKey);
|
||||
else {
|
||||
const input = (e.target as HTMLTableElement).querySelector('input') as HTMLInputElement | undefined;
|
||||
const input = (e.target as HTMLTableElement).querySelector<HTMLInputElement>('input');
|
||||
if (input && !input.disabled) {
|
||||
input.checked = !input.checked;
|
||||
onSelect(input, e.shiftKey);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { initMiniBoardWith } from 'lib/view';
|
||||
|
||||
site.load.then(() => {
|
||||
const rootEl = document.querySelector('.puzzle-openings') as HTMLElement | undefined;
|
||||
const rootEl = document.querySelector<HTMLElement>('.puzzle-openings');
|
||||
if (rootEl && !('ontouchstart' in window)) loadBoardTips(rootEl);
|
||||
});
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"lib": "workspace:*",
|
||||
"swiper": "^12.0.3"
|
||||
"swiper": "^12.1.2"
|
||||
},
|
||||
"build": {
|
||||
"bundle": "src/recap.ts"
|
||||
|
||||
@@ -34,7 +34,7 @@ const autoScroll = throttle(100, (movesEl: HTMLElement, ctrl: RoundController) =
|
||||
if (ctrl.ply < 3) st = 0;
|
||||
else if (ctrl.ply === util.lastPly(ctrl.data)) st = scrollMax;
|
||||
else {
|
||||
const plyEl = movesEl.querySelector('.a1t') as HTMLElement | undefined;
|
||||
const plyEl = movesEl.querySelector<HTMLElement>('.a1t');
|
||||
if (plyEl)
|
||||
st =
|
||||
displayColumns() === 1
|
||||
|
||||
Reference in New Issue
Block a user