diff --git a/bin/package.json b/bin/package.json index 0cd90b022bb..da119e09e60 100644 --- a/bin/package.json +++ b/bin/package.json @@ -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" diff --git a/package.json b/package.json index 35415a67b25..1df5e7df878 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c69a24023a5..f73ea1ba4c0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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: {} diff --git a/project/Dependencies.scala b/project/Dependencies.scala index bf27cf91dc8..e047e061488 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -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" diff --git a/ui/.build/package.json b/ui/.build/package.json index 798de8f6dc7..019513f1823 100644 --- a/ui/.build/package.json +++ b/ui/.build/package.json @@ -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", diff --git a/ui/.build/pnpm-lock.yaml b/ui/.build/pnpm-lock.yaml index cb10b573fc1..4df94798bc5 100644 --- a/ui/.build/pnpm-lock.yaml +++ b/ui/.build/pnpm-lock.yaml @@ -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: {} diff --git a/ui/@types/lichess/chessground.d.ts b/ui/@types/lichess/chessground.d.ts index 12dff3a22b7..20f4c0b8b36 100644 --- a/ui/@types/lichess/chessground.d.ts +++ b/ui/@types/lichess/chessground.d.ts @@ -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; diff --git a/ui/analyse/src/crazy/crazyView.ts b/ui/analyse/src/crazy/crazyView.ts index 45a0183b30a..191628b9d2a 100644 --- a/ui/analyse/src/crazy/crazyView.ts +++ b/ui/analyse/src/crazy/crazyView.ts @@ -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)); }); }), }, diff --git a/ui/analyse/src/explorer/explorerConfig.ts b/ui/analyse/src/explorer/explorerConfig.ts index a4f0e7df109..2e530ca1604 100644 --- a/ui/analyse/src/explorer/explorerConfig.ts +++ b/ui/analyse/src/explorer/explorerConfig.ts @@ -67,12 +67,7 @@ export class ExplorerConfigCtrl { const prevData = previous?.data; this.data = { open: prevData?.open || prop(false), - db: storedProp( - 'explorer.db2.' + variant, - this.allDbs[0], - str => str as ExplorerDb, - v => v, - ), + db: storedProp('explorer.db2.' + variant, this.allDbs[0], str => str as ExplorerDb), rating: storedJsonProp('analyse.explorer.rating', () => allRatings.slice(1)), speed: storedJsonProp('explorer.speed', () => allSpeeds.slice(1)), mode: storedJsonProp('explorer.mode', () => allModes), diff --git a/ui/analyse/src/study/chapterNewForm.ts b/ui/analyse/src/study/chapterNewForm.ts index 5776a14c704..52859ba2086 100644 --- a/ui/analyse/src/study/chapterNewForm.ts +++ b/ui/analyse/src/study/chapterNewForm.ts @@ -42,12 +42,7 @@ export class StudyChapterNewForm { if (!val) this.dialog?.close(); }); initial = toggle(false); - tab = storedProp( - 'analyse.study.form.tab', - 'init', - str => str as ChapterTab, - v => v, - ); + tab = storedProp('analyse.study.form.tab', 'init', str => str as ChapterTab); editor: LichessEditor | null = null; editorFen: Prop = prop(null); isDefaultName = toggle(true); diff --git a/ui/analyse/src/study/topics.ts b/ui/analyse/src/study/topics.ts index 927ae1d7862..fcf58ad162f 100644 --- a/ui/analyse/src/study/topics.ts +++ b/ui/analyse/src/study/topics.ts @@ -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('.tagify__input')?.focus(); }, }); diff --git a/ui/analyse/src/treeView/treeView.ts b/ui/analyse/src/treeView/treeView.ts index 1822d0928b4..ea324328c01 100644 --- a/ui/analyse/src/treeView/treeView.ts +++ b/ui/analyse/src/treeView/treeView.ts @@ -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('.analyse__moves')!; const moveEl = scrollView.querySelector('.active'); if (!moveEl) return scrollView.scrollTo({ top: 0, behavior }); diff --git a/ui/analyse/src/view/nvuiView.ts b/ui/analyse/src/view/nvuiView.ts index 7a526a100de..d2276e1290d 100644 --- a/ui/analyse/src/view/nvuiView.ts +++ b/ui/analyse/src/view/nvuiView.ts @@ -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('.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); diff --git a/ui/bits/src/bits.coachForm.ts b/ui/bits/src/bits.coachForm.ts index 6a37b16683b..b403477f321 100644 --- a/ui/bits/src/bits.coachForm.ts +++ b/ui/bits/src/bits.coachForm.ts @@ -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('form.async'); if (!form) return; xhr.formToXhr(form).then(() => { $editor.find('div.status').addClass('saved'); diff --git a/ui/bits/src/bits.confetti.ts b/ui/bits/src/bits.confetti.ts index 86356a1a01b..e10ea56e52a 100644 --- a/ui/bits/src/bits.confetti.ts +++ b/ui/bits/src/bits.confetti.ts @@ -15,7 +15,8 @@ export function initModule( fireworks: true, }, ): void { - const canvas = document.querySelector('canvas#confetti') as HTMLCanvasElement; + const canvas = document.querySelector('canvas#confetti'); + if (!canvas) return; const party = confetti.create(canvas, { disableForReducedMotion: true, diff --git a/ui/bits/src/bits.gameSearch.ts b/ui/bits/src/bits.gameSearch.ts index 69bc00bbf3d..e7e06420e3b 100644 --- a/ui/bits/src/bits.gameSearch.ts +++ b/ui/bits/src/bits.gameSearch.ts @@ -1,7 +1,7 @@ import { pubsub } from 'lib/pubsub'; site.load.then(() => { - const form = document.querySelector('.search__form') as HTMLFormElement, + const form = document.querySelector('.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(); } diff --git a/ui/bits/src/bits.ts b/ui/bits/src/bits.ts index 7be8dba16ea..a4e2c18849b 100644 --- a/ui/bits/src/bits.ts +++ b/ui/bits/src/bits.ts @@ -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(selector); const oplist = ops.split(' '); if (!el || oplist.length === 0) return; if (oplist.includes('focus')) el.focus(); diff --git a/ui/botPlay/src/play/view/autoScroll.ts b/ui/botPlay/src/play/view/autoScroll.ts index 76d04242261..a2150ffb0c8 100644 --- a/ui/botPlay/src/play/view/autoScroll.ts +++ b/ui/botPlay/src/play/view/autoScroll.ts @@ -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('.current'); if (plyEl) st = displayColumns() === 1 diff --git a/ui/coordinateTrainer/src/ctrl.ts b/ui/coordinateTrainer/src/ctrl.ts index 5d34708b446..6f85fa254b6 100644 --- a/ui/coordinateTrainer/src/ctrl.ts +++ b/ui/coordinateTrainer/src/ctrl.ts @@ -92,12 +92,7 @@ export default class CoordinateTrainerCtrl { } colorChoice: Prop = withEffect( - storedProp( - 'coordinateTrainer.colorChoice', - 'random', - str => str as ColorChoice, - v => v, - ), + storedProp('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, ); diff --git a/ui/lib/src/storage.ts b/ui/lib/src/storage.ts index 8432b0ea2d9..11bd4d8da7d 100644 --- a/ui/lib/src/storage.ts +++ b/ui/lib/src/storage.ts @@ -13,7 +13,12 @@ export function storedProp( 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 { const compatKey = 'analyse.' + key; let cached: V; @@ -35,20 +40,10 @@ export function storedProp( } export const storedStringProp = (k: string, defaultValue: string): StoredProp => - storedProp( - k, - defaultValue, - str => str, - v => v, - ); + storedProp(k, defaultValue, str => str); export const storedBooleanProp = (k: string, defaultValue: boolean): StoredProp => - storedProp( - k, - defaultValue, - str => str === 'true', - v => v.toString(), - ); + storedProp(k, defaultValue, str => str === 'true'); export const storedStringPropWithEffect = ( k: string, @@ -63,12 +58,7 @@ export const storedBooleanPropWithEffect = ( ): Prop => withEffect(storedBooleanProp(k, defaultValue), effect); export const storedIntProp = (k: string, defaultValue: number): StoredProp => - storedProp( - k, - defaultValue, - str => Number(str), - v => v + '', - ); + storedProp(k, defaultValue, str => Number(str)); export const storedIntPropWithEffect = ( k: string, diff --git a/ui/mod/src/checkBoxes.ts b/ui/mod/src/checkBoxes.ts index 51c97ba4ef1..caf66d5683d 100644 --- a/ui/mod/src/checkBoxes.ts +++ b/ui/mod/src/checkBoxes.ts @@ -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('input'); if (input && !input.disabled) { input.checked = !input.checked; onSelect(input, e.shiftKey); diff --git a/ui/puzzle/src/puzzle.opening.ts b/ui/puzzle/src/puzzle.opening.ts index 2d85795da57..40ff9e66209 100644 --- a/ui/puzzle/src/puzzle.opening.ts +++ b/ui/puzzle/src/puzzle.opening.ts @@ -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('.puzzle-openings'); if (rootEl && !('ontouchstart' in window)) loadBoardTips(rootEl); }); diff --git a/ui/recap/package.json b/ui/recap/package.json index 03a9a491eb6..00926bcf94c 100644 --- a/ui/recap/package.json +++ b/ui/recap/package.json @@ -4,7 +4,7 @@ "type": "module", "dependencies": { "lib": "workspace:*", - "swiper": "^12.0.3" + "swiper": "^12.1.2" }, "build": { "bundle": "src/recap.ts" diff --git a/ui/round/src/view/replay.ts b/ui/round/src/view/replay.ts index 29800d7ff0e..16a6c7ee6b3 100644 --- a/ui/round/src/view/replay.ts +++ b/ui/round/src/view/replay.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('.a1t'); if (plyEl) st = displayColumns() === 1