mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 19:07:17 +01:00
ts_core 0.1.1, web_ui 0.4.0: consume @kuhyx/ts-config
The two shared packages are the first repos on the preset (link:../ts_config inside the monorepo; consumers outside use the git tag). Each eslint.config.js is now the defineConfig() call plus one override with its reason: a public API name (`nextChance`, `fuzzyMatch`) the boolean-prefix rule would rename, which is a breaking change for the three repos importing it. Everything else the preset flagged is fixed in code, not disabled: key order (perfectionist), hex casing, sort compare functions in tests, Iterator#map().toArray(), explicit returns on multiline arrows. web_ui: react-refresh/only-export-components was a real finding -- range-slider.tsx exported `steppedValue` next to the component, which breaks Vite HMR for the module. The keyboard contract moves to stepped-value.ts as `steppedValue` + a new pure `keyTarget(key, values, current)`, which also resolves unicorn/no-late-event-control: the handler now decides the target first and calls preventDefault() only when it owns the key. Its tests move with it (the 250-line gate caught the combined file). Minor bump for the new export. dist/ rebuilt in both packages. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DnAYyNH1Sm4iJNidfYbrZJ
This commit is contained in:
parent
0f9699d4f3
commit
c5b3fceeae
2
ts_core/dist/clock.d.ts.map
vendored
2
ts_core/dist/clock.d.ts.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,KAAK;IACpB,4EAA4E;IAC5E,GAAG,EAAE,MAAM,MAAM,CAAA;CAClB;AAED,2EAA2E;AAC3E,eAAO,MAAM,eAAe,QAAO,KAEjC,CAAA;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,EAAE,KAAyB,CAAA;AAEjD,sEAAsE;AACtE,MAAM,WAAW,WAAY,SAAQ,KAAK;IACxC,mEAAmE;IACnE,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAElC,2DAA2D;IAC3D,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAC9B;AAED,uEAAuE;AACvE,eAAO,MAAM,iBAAiB,GAAI,gBAAW,KAAG,WAW/C,CAAA"}
|
{"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,KAAK;IACpB,4EAA4E;IAC5E,GAAG,EAAE,MAAM,MAAM,CAAA;CAClB;AAED,2EAA2E;AAC3E,eAAO,MAAM,eAAe,QAAO,KAAmD,CAAA;AAEtF;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,EAAE,KAAyB,CAAA;AAEjD,sEAAsE;AACtE,MAAM,WAAW,WAAY,SAAQ,KAAK;IACxC,mEAAmE;IACnE,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAElC,2DAA2D;IAC3D,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAC9B;AAED,uEAAuE;AACvE,eAAO,MAAM,iBAAiB,GAAI,gBAAW,KAAG,WAW/C,CAAA"}
|
||||||
6
ts_core/dist/clock.js
vendored
6
ts_core/dist/clock.js
vendored
@ -1,7 +1,5 @@
|
|||||||
/** A {@link Clock} backed by the browser's monotonic performance timer. */
|
/** A {@link Clock} backed by the browser's monotonic performance timer. */
|
||||||
export const createRealClock = () => ({
|
export const createRealClock = () => ({ now: () => performance.now() });
|
||||||
now: () => performance.now(),
|
|
||||||
});
|
|
||||||
/**
|
/**
|
||||||
* The one real clock instance UI code should pass around.
|
* The one real clock instance UI code should pass around.
|
||||||
*
|
*
|
||||||
@ -15,10 +13,10 @@ export const realClock = createRealClock();
|
|||||||
export const createManualClock = (startMs = 0) => {
|
export const createManualClock = (startMs = 0) => {
|
||||||
let current = startMs;
|
let current = startMs;
|
||||||
return {
|
return {
|
||||||
now: () => current,
|
|
||||||
advance: (deltaMs) => {
|
advance: (deltaMs) => {
|
||||||
current += deltaMs;
|
current += deltaMs;
|
||||||
},
|
},
|
||||||
|
now: () => current,
|
||||||
set: (timeMs) => {
|
set: (timeMs) => {
|
||||||
current = timeMs;
|
current = timeMs;
|
||||||
},
|
},
|
||||||
|
|||||||
2
ts_core/dist/clock.js.map
vendored
2
ts_core/dist/clock.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"clock.js","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":"AAaA,2EAA2E;AAC3E,MAAM,CAAC,MAAM,eAAe,GAAG,GAAU,EAAE,CAAC,CAAC;IAC3C,GAAG,EAAE,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;CACrC,CAAC,CAAA;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,SAAS,GAAU,eAAe,EAAE,CAAA;AAWjD,uEAAuE;AACvE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAO,GAAG,CAAC,EAAe,EAAE;IAC5D,IAAI,OAAO,GAAG,OAAO,CAAA;IACrB,OAAO;QACL,GAAG,EAAE,GAAW,EAAE,CAAC,OAAO;QAC1B,OAAO,EAAE,CAAC,OAAe,EAAQ,EAAE;YACjC,OAAO,IAAI,OAAO,CAAA;QACpB,CAAC;QACD,GAAG,EAAE,CAAC,MAAc,EAAQ,EAAE;YAC5B,OAAO,GAAG,MAAM,CAAA;QAClB,CAAC;KACF,CAAA;AACH,CAAC,CAAA"}
|
{"version":3,"file":"clock.js","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":"AAaA,2EAA2E;AAC3E,MAAM,CAAC,MAAM,eAAe,GAAG,GAAU,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAW,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;AAEtF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,SAAS,GAAU,eAAe,EAAE,CAAA;AAWjD,uEAAuE;AACvE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAO,GAAG,CAAC,EAAe,EAAE;IAC5D,IAAI,OAAO,GAAG,OAAO,CAAA;IACrB,OAAO;QACL,OAAO,EAAE,CAAC,OAAe,EAAQ,EAAE;YACjC,OAAO,IAAI,OAAO,CAAA;QACpB,CAAC;QACD,GAAG,EAAE,GAAW,EAAE,CAAC,OAAO;QAC1B,GAAG,EAAE,CAAC,MAAc,EAAQ,EAAE;YAC5B,OAAO,GAAG,MAAM,CAAA;QAClB,CAAC;KACF,CAAA;AACH,CAAC,CAAA"}
|
||||||
2
ts_core/dist/index.d.ts
vendored
2
ts_core/dist/index.d.ts
vendored
@ -6,6 +6,6 @@
|
|||||||
* -- that is the coupling that makes people vendor their own copy instead,
|
* -- that is the coupling that makes people vendor their own copy instead,
|
||||||
* which is how these ended up duplicated four ways to begin with.
|
* which is how these ended up duplicated four ways to begin with.
|
||||||
*/
|
*/
|
||||||
export { createManualClock, createRealClock, realClock, type Clock, type ManualClock, } from './clock.ts';
|
export { type Clock, createManualClock, createRealClock, type ManualClock, realClock, } from './clock.ts';
|
||||||
export { createRng, createSeededRng, nextChance, nextFloat, nextInt, pick, type Rng, type SeededRng, } from './rng.ts';
|
export { createRng, createSeededRng, nextChance, nextFloat, nextInt, pick, type Rng, type SeededRng, } from './rng.ts';
|
||||||
//# sourceMappingURL=index.d.ts.map
|
//# sourceMappingURL=index.d.ts.map
|
||||||
2
ts_core/dist/index.d.ts.map
vendored
2
ts_core/dist/index.d.ts.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,SAAS,EACT,KAAK,KAAK,EACV,KAAK,WAAW,GACjB,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,SAAS,EACT,eAAe,EACf,UAAU,EACV,SAAS,EACT,OAAO,EACP,IAAI,EACJ,KAAK,GAAG,EACR,KAAK,SAAS,GACf,MAAM,UAAU,CAAA"}
|
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,KAAK,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,KAAK,WAAW,EAChB,SAAS,GACV,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,SAAS,EACT,eAAe,EACf,UAAU,EACV,SAAS,EACT,OAAO,EACP,IAAI,EACJ,KAAK,GAAG,EACR,KAAK,SAAS,GACf,MAAM,UAAU,CAAA"}
|
||||||
2
ts_core/dist/index.js.map
vendored
2
ts_core/dist/index.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,SAAS,GAGV,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,SAAS,EACT,eAAe,EACf,UAAU,EACV,SAAS,EACT,OAAO,EACP,IAAI,GAGL,MAAM,UAAU,CAAA"}
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAEL,iBAAiB,EACjB,eAAe,EAEf,SAAS,GACV,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,SAAS,EACT,eAAe,EACf,UAAU,EACV,SAAS,EACT,OAAO,EACP,IAAI,GAGL,MAAM,UAAU,CAAA"}
|
||||||
4
ts_core/dist/rng.d.ts
vendored
4
ts_core/dist/rng.d.ts
vendored
@ -54,14 +54,14 @@ export declare const pick: <T>(rng: Rng, items: readonly [T, ...T[]]) => T;
|
|||||||
* around rather than threading mutable state through free functions.
|
* around rather than threading mutable state through free functions.
|
||||||
*/
|
*/
|
||||||
export interface SeededRng {
|
export interface SeededRng {
|
||||||
|
/** True with the given probability in [0, 1]. */
|
||||||
|
chance: (probability: number) => boolean;
|
||||||
/** Uniform float in [0, 1). */
|
/** Uniform float in [0, 1). */
|
||||||
float: () => number;
|
float: () => number;
|
||||||
/** Uniform integer in [minInclusive, maxInclusive]. */
|
/** Uniform integer in [minInclusive, maxInclusive]. */
|
||||||
int: (minInclusive: number, maxInclusive: number) => number;
|
int: (minInclusive: number, maxInclusive: number) => number;
|
||||||
/** Uniform element of a non-empty array. */
|
/** Uniform element of a non-empty array. */
|
||||||
pick: <T>(items: readonly T[]) => T;
|
pick: <T>(items: readonly T[]) => T;
|
||||||
/** True with the given probability in [0, 1]. */
|
|
||||||
chance: (probability: number) => boolean;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Creates a {@link SeededRng} over the same mulberry32 core.
|
* Creates a {@link SeededRng} over the same mulberry32 core.
|
||||||
|
|||||||
2
ts_core/dist/rng.d.ts.map
vendored
2
ts_core/dist/rng.d.ts.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"rng.d.ts","sourceRoot":"","sources":["../src/rng.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,gDAAgD;AAChD,MAAM,WAAW,GAAG;IAClB,qDAAqD;IACrD,CAAC,EAAE,MAAM,CAAA;CACV;AAED,mDAAmD;AACnD,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,GAA0B,CAAA;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,GAAG,KAAG,MAMpC,CAAA;AAED,uEAAuE;AACvE,eAAO,MAAM,OAAO,GAClB,KAAK,GAAG,EACR,cAAc,MAAM,EACpB,cAAc,MAAM,KACnB,MAC4E,CAAA;AAE/E,2DAA2D;AAC3D,eAAO,MAAM,UAAU,GAAI,KAAK,GAAG,EAAE,aAAa,MAAM,KAAG,OAC7B,CAAA;AAE9B;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,KAAK,GAAG,EAAE,OAAO,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,KAAG,CAW/D,CAAA;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,MAAM,CAAA;IACnB,uDAAuD;IACvD,GAAG,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IAC3D,4CAA4C;IAC5C,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC,CAAA;IACnC,iDAAiD;IACjD,MAAM,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAA;CACzC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,SAgB9C,CAAA"}
|
{"version":3,"file":"rng.d.ts","sourceRoot":"","sources":["../src/rng.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,gDAAgD;AAChD,MAAM,WAAW,GAAG;IAClB,qDAAqD;IACrD,CAAC,EAAE,MAAM,CAAA;CACV;AAED,mDAAmD;AACnD,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,KAAG,GAA0B,CAAA;AAEnE;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,GAAG,KAAG,MAMpC,CAAA;AAED,uEAAuE;AACvE,eAAO,MAAM,OAAO,GAClB,KAAK,GAAG,EACR,cAAc,MAAM,EACpB,cAAc,MAAM,KACnB,MAC4E,CAAA;AAE/E,2DAA2D;AAC3D,eAAO,MAAM,UAAU,GAAI,KAAK,GAAG,EAAE,aAAa,MAAM,KAAG,OAC7B,CAAA;AAE9B;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,EAAE,KAAK,GAAG,EAAE,OAAO,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,KAAG,CAW/D,CAAA;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,iDAAiD;IACjD,MAAM,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAA;IACxC,+BAA+B;IAC/B,KAAK,EAAE,MAAM,MAAM,CAAA;IACnB,uDAAuD;IACvD,GAAG,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IAC3D,4CAA4C;IAC5C,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,KAAK,CAAC,CAAA;CACpC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,SAgB9C,CAAA"}
|
||||||
4
ts_core/dist/rng.js
vendored
4
ts_core/dist/rng.js
vendored
@ -32,7 +32,7 @@ export const createRng = (seed) => ({ s: seed >>> 0 });
|
|||||||
* of it, so they all consume exactly one step per call.
|
* of it, so they all consume exactly one step per call.
|
||||||
*/
|
*/
|
||||||
export const nextFloat = (rng) => {
|
export const nextFloat = (rng) => {
|
||||||
rng.s = (rng.s + 0x6d_2b_79_f5) >>> 0;
|
rng.s = (rng.s + 0x6D_2B_79_F5) >>> 0;
|
||||||
let t = rng.s;
|
let t = rng.s;
|
||||||
t = Math.imul(t ^ (t >>> 15), t | 1);
|
t = Math.imul(t ^ (t >>> 15), t | 1);
|
||||||
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
||||||
@ -72,6 +72,7 @@ export const createSeededRng = (seed) => {
|
|||||||
const state = createRng(seed);
|
const state = createRng(seed);
|
||||||
const float = () => nextFloat(state);
|
const float = () => nextFloat(state);
|
||||||
return {
|
return {
|
||||||
|
chance: (probability) => float() < probability,
|
||||||
float,
|
float,
|
||||||
int: (minInclusive, maxInclusive) => nextInt(state, minInclusive, maxInclusive),
|
int: (minInclusive, maxInclusive) => nextInt(state, minInclusive, maxInclusive),
|
||||||
pick: (items) => {
|
pick: (items) => {
|
||||||
@ -81,7 +82,6 @@ export const createSeededRng = (seed) => {
|
|||||||
}
|
}
|
||||||
return chosen;
|
return chosen;
|
||||||
},
|
},
|
||||||
chance: (probability) => float() < probability,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
//# sourceMappingURL=rng.js.map
|
//# sourceMappingURL=rng.js.map
|
||||||
2
ts_core/dist/rng.js.map
vendored
2
ts_core/dist/rng.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"rng.js","sourceRoot":"","sources":["../src/rng.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAQH,mDAAmD;AACnD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAY,EAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC,CAAA;AAEnE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAQ,EAAU,EAAE;IAC5C,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAA;IACrC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;IACb,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;IACpC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAA;IACzC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,aAAa,CAAA;AACjD,CAAC,CAAA;AAED,uEAAuE;AACvE,MAAM,CAAC,MAAM,OAAO,GAAG,CACrB,GAAQ,EACR,YAAoB,EACpB,YAAoB,EACZ,EAAE,CACV,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAA;AAE/E,2DAA2D;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAQ,EAAE,WAAmB,EAAW,EAAE,CACnE,SAAS,CAAC,GAAG,CAAC,GAAG,WAAW,CAAA;AAE9B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAI,GAAQ,EAAE,KAA2B,EAAK,EAAE;IAClE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAChD,IAAI,GAAG,GAAM,KAAK,CAAC,CAAC,CAAC,CAAA;IACrB,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,GAAG,GAAG,IAAI,CAAA;QACZ,CAAC;QACD,IAAI,IAAI,CAAC,CAAA;IACX,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AAiBD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAY,EAAa,EAAE;IACzD,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAC7B,MAAM,KAAK,GAAG,GAAW,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC5C,OAAO;QACL,KAAK;QACL,GAAG,EAAE,CAAC,YAAoB,EAAE,YAAoB,EAAU,EAAE,CAC1D,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,YAAY,CAAC;QAC5C,IAAI,EAAE,CAAI,KAAmB,EAAK,EAAE;YAClC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;YACxD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;YAC7C,CAAC;YACD,OAAO,MAAM,CAAA;QACf,CAAC;QACD,MAAM,EAAE,CAAC,WAAmB,EAAW,EAAE,CAAC,KAAK,EAAE,GAAG,WAAW;KAChE,CAAA;AACH,CAAC,CAAA"}
|
{"version":3,"file":"rng.js","sourceRoot":"","sources":["../src/rng.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAQH,mDAAmD;AACnD,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,IAAY,EAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE,CAAC,CAAA;AAEnE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAQ,EAAU,EAAE;IAC5C,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAA;IACrC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;IACb,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;IACpC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAA;IACzC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,aAAa,CAAA;AACjD,CAAC,CAAA;AAED,uEAAuE;AACvE,MAAM,CAAC,MAAM,OAAO,GAAG,CACrB,GAAQ,EACR,YAAoB,EACpB,YAAoB,EACZ,EAAE,CACV,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAA;AAE/E,2DAA2D;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAQ,EAAE,WAAmB,EAAW,EAAE,CACnE,SAAS,CAAC,GAAG,CAAC,GAAG,WAAW,CAAA;AAE9B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAAI,GAAQ,EAAE,KAA2B,EAAK,EAAE;IAClE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAChD,IAAI,GAAG,GAAM,KAAK,CAAC,CAAC,CAAC,CAAA;IACrB,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,GAAG,GAAG,IAAI,CAAA;QACZ,CAAC;QACD,IAAI,IAAI,CAAC,CAAA;IACX,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AAiBD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,IAAY,EAAa,EAAE;IACzD,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAC7B,MAAM,KAAK,GAAG,GAAW,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC5C,OAAO;QACL,MAAM,EAAE,CAAC,WAAmB,EAAW,EAAE,CAAC,KAAK,EAAE,GAAG,WAAW;QAC/D,KAAK;QACL,GAAG,EAAE,CAAC,YAAoB,EAAE,YAAoB,EAAU,EAAE,CAC1D,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,YAAY,CAAC;QAC5C,IAAI,EAAE,CAAI,KAAmB,EAAK,EAAE;YAClC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;YACxD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;YAC7C,CAAC;YACD,OAAO,MAAM,CAAA;QACf,CAAC;KACF,CAAA;AACH,CAAC,CAAA"}
|
||||||
@ -1,28 +1,24 @@
|
|||||||
// Type-aware flat config, mirroring web_ui's so the two shared TS packages
|
// The shared preset, nothing else local except one frozen API name. This
|
||||||
// hold an identical bar.
|
// package is one of the repos the bar is defined for. Framework-free, so no
|
||||||
import js from "@eslint/js";
|
// React layer.
|
||||||
import tseslint from "typescript-eslint";
|
import { defineConfig } from "@kuhyx/ts-config";
|
||||||
|
|
||||||
export default tseslint.config(
|
export default defineConfig({
|
||||||
{ ignores: ["dist", "coverage", "eslint.config.js"] },
|
// Flat files under src/, no layers to fence and no alias configured.
|
||||||
{ linterOptions: { reportUnusedDisableDirectives: "error" } },
|
aliasOnly: false,
|
||||||
|
overrides: [
|
||||||
js.configs.recommended,
|
{
|
||||||
...tseslint.configs.strictTypeChecked,
|
files: ["src/rng.ts"],
|
||||||
...tseslint.configs.stylisticTypeChecked,
|
rules: {
|
||||||
|
// `nextChance` is public API consumed by three repos; the preset's
|
||||||
{
|
// boolean-name prefixes would rename it to `isNextChance`, which is
|
||||||
files: ["**/*.ts"],
|
// worse prose and a breaking change for no safety gain.
|
||||||
languageOptions: {
|
"unicorn/consistent-boolean-name": "off",
|
||||||
parserOptions: {
|
|
||||||
project: ["./tsconfig.lint.json"],
|
|
||||||
tsconfigRootDir: import.meta.dirname,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rules: {
|
],
|
||||||
// Every exported symbol crosses a package boundary, so an explicit
|
// tsconfig.json excludes the tests so they never land in dist/; the lint
|
||||||
// return type is documentation, not ceremony.
|
// project widens the include for type-aware rules (see tsconfig.lint.json).
|
||||||
"@typescript-eslint/explicit-function-return-type": "error",
|
project: ["./tsconfig.lint.json"],
|
||||||
},
|
tsconfigRootDir: import.meta.dirname,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@kuhyx/ts-core",
|
"name": "@kuhyx/ts-core",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": false,
|
"private": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Framework-free TypeScript utilities shared across kuhy's games and web apps: an injectable Clock and a seeded mulberry32 RNG. Deliberately no React and no CSS -- see @kuhyx/web-ui for the UI layer.",
|
"description": "Framework-free TypeScript utilities shared across kuhy's games and web apps: an injectable Clock and a seeded mulberry32 RNG. Deliberately no React and no CSS -- see @kuhyx/web-ui for the UI layer.",
|
||||||
@ -9,7 +9,7 @@
|
|||||||
"node": ">=24",
|
"node": ">=24",
|
||||||
"pnpm": ">=10"
|
"pnpm": ">=10"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
|
"packageManager": "pnpm@12.4.2",
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
@ -29,11 +29,12 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "10.0.1",
|
"@eslint/js": "10.0.1",
|
||||||
|
"@kuhyx/ts-config": "link:../ts_config",
|
||||||
"@types/node": "26.5.1",
|
"@types/node": "26.5.1",
|
||||||
"@vitest/coverage-v8": "5.0.0",
|
"@vitest/coverage-v8": "5.0.1",
|
||||||
"eslint": "10.10.0",
|
"eslint": "10.10.0",
|
||||||
"typescript": "6.0.3",
|
"typescript": "6.0.3",
|
||||||
"typescript-eslint": "8.70.0",
|
"typescript-eslint": "8.70.0",
|
||||||
"vitest": "5.0.0"
|
"vitest": "5.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -169,12 +169,15 @@ importers:
|
|||||||
'@eslint/js':
|
'@eslint/js':
|
||||||
specifier: 10.0.1
|
specifier: 10.0.1
|
||||||
version: 10.0.1(eslint@10.10.0(supports-color@7.2.0))
|
version: 10.0.1(eslint@10.10.0(supports-color@7.2.0))
|
||||||
|
'@kuhyx/ts-config':
|
||||||
|
specifier: link:../ts_config
|
||||||
|
version: link:../ts_config
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: 26.5.1
|
specifier: 26.5.1
|
||||||
version: 26.5.1
|
version: 26.5.1
|
||||||
'@vitest/coverage-v8':
|
'@vitest/coverage-v8':
|
||||||
specifier: 5.0.0
|
specifier: 5.0.1
|
||||||
version: 5.0.0(vitest@5.0.0)
|
version: 5.0.1(vitest@5.0.1)
|
||||||
eslint:
|
eslint:
|
||||||
specifier: 10.10.0
|
specifier: 10.10.0
|
||||||
version: 10.10.0(supports-color@7.2.0)
|
version: 10.10.0(supports-color@7.2.0)
|
||||||
@ -185,8 +188,8 @@ importers:
|
|||||||
specifier: 8.70.0
|
specifier: 8.70.0
|
||||||
version: 8.70.0(eslint@10.10.0(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)
|
version: 8.70.0(eslint@10.10.0(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: 5.0.0
|
specifier: 5.0.1
|
||||||
version: 5.0.0(@types/node@26.5.1)(@vitest/coverage-v8@5.0.0)(vite@8.2.1(@types/node@26.5.1))
|
version: 5.0.1(@types/node@26.5.1)(@vitest/coverage-v8@5.0.1)(vite@8.2.1(@types/node@26.5.1))
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@ -280,9 +283,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.5':
|
|
||||||
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.6.0':
|
'@jridgewell/sourcemap-codec@1.6.0':
|
||||||
resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==}
|
resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==}
|
||||||
|
|
||||||
@ -471,11 +471,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-BoC8PiO4Hkdo0TVJh9Ntxr5MxPDI7/oFsrygN5ADelFSeXG/qgNuucIGA+L5Z6JpPTE/uRfcTWtscjbUaufepQ==}
|
resolution: {integrity: sha512-BoC8PiO4Hkdo0TVJh9Ntxr5MxPDI7/oFsrygN5ADelFSeXG/qgNuucIGA+L5Z6JpPTE/uRfcTWtscjbUaufepQ==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@vitest/coverage-v8@5.0.0':
|
'@vitest/coverage-v8@5.0.1':
|
||||||
resolution: {integrity: sha512-toMg6PZGCIa/lQNCDoASrfb1ly4hsUKXFtFYC9kD4t78o5Y6LyNJU7AENt8eHPr3quYdxaxK7hj2mnbFfUk9NA==}
|
resolution: {integrity: sha512-FRC8ACiudC3dI6MTplzRSYWHDRnIv2IPfbzs4FdoJNsMal/35sWV8hwIfV8ZcqzSPy+uXHeMVONt9CEqtOU17w==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@vitest/browser': 5.0.0
|
'@vitest/browser': 5.0.1
|
||||||
vitest: 5.0.0
|
vitest: 5.0.1
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
'@vitest/browser':
|
'@vitest/browser':
|
||||||
optional: true
|
optional: true
|
||||||
@ -488,8 +488,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-1EOLRfsTMnyAr3+kEAsP4o9dhaDlGPpD7H5iLBBeq//YpNB1VIahkPhB+eRp9N2Dkfw8oySROjE3yf9XDeaIkQ==}
|
resolution: {integrity: sha512-1EOLRfsTMnyAr3+kEAsP4o9dhaDlGPpD7H5iLBBeq//YpNB1VIahkPhB+eRp9N2Dkfw8oySROjE3yf9XDeaIkQ==}
|
||||||
engines: {node: '>=22'}
|
engines: {node: '>=22'}
|
||||||
|
|
||||||
'@vitest/mocker@5.0.0':
|
'@vitest/mocker@5.0.1':
|
||||||
resolution: {integrity: sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA==}
|
resolution: {integrity: sha512-6K1DoBNAPGvuOcSsGA4D6x+5zEEff/KmOOP3uetT2TrGpVfI+HRHRnJJfKi5ib/g1vx8IYHQD8s0pbJz8WQI7Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
msw: ^2.4.9
|
msw: ^2.4.9
|
||||||
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||||
@ -499,8 +499,8 @@ packages:
|
|||||||
vite:
|
vite:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@vitest/spy@5.0.0':
|
'@vitest/spy@5.0.1':
|
||||||
resolution: {integrity: sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g==}
|
resolution: {integrity: sha512-rbto/mF/SGERxEgYOek7Xm6B9b+y+mVoo+f4b2LymYO8zM1b7uB5nHuhVMTP2hxdzgxvGiZYGxGIaMvL5y180Q==}
|
||||||
|
|
||||||
acorn-jsx@5.3.2:
|
acorn-jsx@5.3.2:
|
||||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||||
@ -978,20 +978,20 @@ packages:
|
|||||||
yaml:
|
yaml:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
vitest@5.0.0:
|
vitest@5.0.1:
|
||||||
resolution: {integrity: sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q==}
|
resolution: {integrity: sha512-iA95lQbKEkvrtTkdAgnWbXfbipWiiWe/hDl2P5tMi6WFwD76G0NxXAGp/M9EOcYupeGJRr6wppMc7CoA41TQjg==}
|
||||||
engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0}
|
engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@edge-runtime/vm': '*'
|
'@edge-runtime/vm': '*'
|
||||||
'@opentelemetry/api': ^1.9.0
|
'@opentelemetry/api': ^1.9.0
|
||||||
'@types/node': ^22.0.0 || >=24.0.0
|
'@types/node': ^22.0.0 || >=24.0.0
|
||||||
'@vitest/browser-playwright': 5.0.0
|
'@vitest/browser-playwright': 5.0.1
|
||||||
'@vitest/browser-preview': 5.0.0
|
'@vitest/browser-preview': 5.0.1
|
||||||
'@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0
|
'@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0
|
||||||
'@vitest/coverage-istanbul': 5.0.0
|
'@vitest/coverage-istanbul': 5.0.1
|
||||||
'@vitest/coverage-v8': 5.0.0
|
'@vitest/coverage-v8': 5.0.1
|
||||||
'@vitest/ui': 5.0.0
|
'@vitest/ui': 5.0.1
|
||||||
happy-dom: '*'
|
happy-dom: '*'
|
||||||
jsdom: '*'
|
jsdom: '*'
|
||||||
vite: ^6.4.0 || ^7.0.0 || ^8.0.0
|
vite: ^6.4.0 || ^7.0.0 || ^8.0.0
|
||||||
@ -1118,14 +1118,12 @@ snapshots:
|
|||||||
|
|
||||||
'@jridgewell/resolve-uri@3.1.2': {}
|
'@jridgewell/resolve-uri@3.1.2': {}
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.5': {}
|
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.6.0': {}
|
'@jridgewell/sourcemap-codec@1.6.0': {}
|
||||||
|
|
||||||
'@jridgewell/trace-mapping@0.3.31':
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.6.0
|
||||||
|
|
||||||
'@keyv/bigmap@1.3.1(keyv@5.6.0)':
|
'@keyv/bigmap@1.3.1(keyv@5.6.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1289,7 +1287,7 @@ snapshots:
|
|||||||
'@typescript-eslint/types': 8.70.0
|
'@typescript-eslint/types': 8.70.0
|
||||||
eslint-visitor-keys: 5.0.1
|
eslint-visitor-keys: 5.0.1
|
||||||
|
|
||||||
'@vitest/coverage-v8@5.0.0(vitest@5.0.0)':
|
'@vitest/coverage-v8@5.0.1(vitest@5.0.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@bcoe/v8-coverage': 1.0.2
|
'@bcoe/v8-coverage': 1.0.2
|
||||||
'@vitest/istanbul-lib-coverage': 1.0.1
|
'@vitest/istanbul-lib-coverage': 1.0.1
|
||||||
@ -1299,7 +1297,7 @@ snapshots:
|
|||||||
obug: 2.1.4
|
obug: 2.1.4
|
||||||
std-env: 4.2.0
|
std-env: 4.2.0
|
||||||
tinyrainbow: 3.1.1
|
tinyrainbow: 3.1.1
|
||||||
vitest: 5.0.0(@types/node@26.5.1)(@vitest/coverage-v8@5.0.0)(vite@8.2.1(@types/node@26.5.1))
|
vitest: 5.0.1(@types/node@26.5.1)(@vitest/coverage-v8@5.0.1)(vite@8.2.1(@types/node@26.5.1))
|
||||||
|
|
||||||
'@vitest/istanbul-lib-coverage@1.0.1': {}
|
'@vitest/istanbul-lib-coverage@1.0.1': {}
|
||||||
|
|
||||||
@ -1307,16 +1305,16 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/istanbul-lib-coverage': 1.0.1
|
'@vitest/istanbul-lib-coverage': 1.0.1
|
||||||
|
|
||||||
'@vitest/mocker@5.0.0(vite@8.2.1(@types/node@26.5.1))':
|
'@vitest/mocker@5.0.1(vite@8.2.1(@types/node@26.5.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/trace-mapping': 0.3.31
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
'@vitest/spy': 5.0.0
|
'@vitest/spy': 5.0.1
|
||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
magic-string: 1.3.1
|
magic-string: 1.3.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vite: 8.2.1(@types/node@26.5.1)
|
vite: 8.2.1(@types/node@26.5.1)
|
||||||
|
|
||||||
'@vitest/spy@5.0.0': {}
|
'@vitest/spy@5.0.1': {}
|
||||||
|
|
||||||
acorn-jsx@5.3.2(acorn@8.18.0):
|
acorn-jsx@5.3.2(acorn@8.18.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1725,10 +1723,10 @@ snapshots:
|
|||||||
'@types/node': 26.5.1
|
'@types/node': 26.5.1
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
||||||
vitest@5.0.0(@types/node@26.5.1)(@vitest/coverage-v8@5.0.0)(vite@8.2.1(@types/node@26.5.1)):
|
vitest@5.0.1(@types/node@26.5.1)(@vitest/coverage-v8@5.0.1)(vite@8.2.1(@types/node@26.5.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/chai': 5.2.3
|
'@types/chai': 5.2.3
|
||||||
'@vitest/mocker': 5.0.0(vite@8.2.1(@types/node@26.5.1))
|
'@vitest/mocker': 5.0.1(vite@8.2.1(@types/node@26.5.1))
|
||||||
chai: 6.2.2
|
chai: 6.2.2
|
||||||
es-module-lexer: 2.3.2
|
es-module-lexer: 2.3.2
|
||||||
expect-type: 1.4.0
|
expect-type: 1.4.0
|
||||||
@ -1743,7 +1741,7 @@ snapshots:
|
|||||||
why-is-node-running: 2.3.0
|
why-is-node-running: 2.3.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 26.5.1
|
'@types/node': 26.5.1
|
||||||
'@vitest/coverage-v8': 5.0.0(vitest@5.0.0)
|
'@vitest/coverage-v8': 5.0.1(vitest@5.0.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- msw
|
- msw
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
import { describe, expect, it, vi } from 'vitest'
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
type Clock,
|
||||||
createManualClock,
|
createManualClock,
|
||||||
createRealClock,
|
createRealClock,
|
||||||
realClock,
|
realClock,
|
||||||
type Clock,
|
|
||||||
} from './clock.ts'
|
} from './clock.ts'
|
||||||
|
|
||||||
describe('createRealClock', () => {
|
describe('createRealClock', () => {
|
||||||
|
|||||||
@ -12,9 +12,7 @@ export interface Clock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A {@link Clock} backed by the browser's monotonic performance timer. */
|
/** A {@link Clock} backed by the browser's monotonic performance timer. */
|
||||||
export const createRealClock = (): Clock => ({
|
export const createRealClock = (): Clock => ({ now: (): number => performance.now() })
|
||||||
now: (): number => performance.now(),
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The one real clock instance UI code should pass around.
|
* The one real clock instance UI code should pass around.
|
||||||
@ -39,10 +37,10 @@ export interface ManualClock extends Clock {
|
|||||||
export const createManualClock = (startMs = 0): ManualClock => {
|
export const createManualClock = (startMs = 0): ManualClock => {
|
||||||
let current = startMs
|
let current = startMs
|
||||||
return {
|
return {
|
||||||
now: (): number => current,
|
|
||||||
advance: (deltaMs: number): void => {
|
advance: (deltaMs: number): void => {
|
||||||
current += deltaMs
|
current += deltaMs
|
||||||
},
|
},
|
||||||
|
now: (): number => current,
|
||||||
set: (timeMs: number): void => {
|
set: (timeMs: number): void => {
|
||||||
current = timeMs
|
current = timeMs
|
||||||
},
|
},
|
||||||
|
|||||||
@ -7,11 +7,11 @@
|
|||||||
* which is how these ended up duplicated four ways to begin with.
|
* which is how these ended up duplicated four ways to begin with.
|
||||||
*/
|
*/
|
||||||
export {
|
export {
|
||||||
|
type Clock,
|
||||||
createManualClock,
|
createManualClock,
|
||||||
createRealClock,
|
createRealClock,
|
||||||
realClock,
|
|
||||||
type Clock,
|
|
||||||
type ManualClock,
|
type ManualClock,
|
||||||
|
realClock,
|
||||||
} from './clock.ts'
|
} from './clock.ts'
|
||||||
export {
|
export {
|
||||||
createRng,
|
createRng,
|
||||||
|
|||||||
@ -20,8 +20,8 @@ import {
|
|||||||
* would defeat the entire point of the test.
|
* would defeat the entire point of the test.
|
||||||
*/
|
*/
|
||||||
const GOLDEN_12345 = [
|
const GOLDEN_12345 = [
|
||||||
0.979_728_267_760_947_3, 0.306_752_264_499_664_3, 0.484_205_421_525_985,
|
0.9797282677609473, 0.3067522644996643, 0.484205421525985,
|
||||||
0.817_934_412_509_203, 0.509_428_369_347_006_1,
|
0.817934412509203, 0.5094283693470061,
|
||||||
]
|
]
|
||||||
|
|
||||||
describe('mulberry32 core', () => {
|
describe('mulberry32 core', () => {
|
||||||
@ -51,7 +51,7 @@ describe('mulberry32 core', () => {
|
|||||||
|
|
||||||
it('stays within [0, 1) across many draws', () => {
|
it('stays within [0, 1) across many draws', () => {
|
||||||
const rng = createRng(42)
|
const rng = createRng(42)
|
||||||
for (let i = 0; i < 1000; i += 1) {
|
for (let index = 0; index < 1000; index += 1) {
|
||||||
const value = nextFloat(rng)
|
const value = nextFloat(rng)
|
||||||
expect(value).toBeGreaterThanOrEqual(0)
|
expect(value).toBeGreaterThanOrEqual(0)
|
||||||
expect(value).toBeLessThan(1)
|
expect(value).toBeLessThan(1)
|
||||||
@ -68,10 +68,10 @@ describe('nextInt', () => {
|
|||||||
it('is inclusive of both bounds', () => {
|
it('is inclusive of both bounds', () => {
|
||||||
const rng = createRng(3)
|
const rng = createRng(3)
|
||||||
const seen = new Set<number>()
|
const seen = new Set<number>()
|
||||||
for (let i = 0; i < 500; i += 1) {
|
for (let index = 0; index < 500; index += 1) {
|
||||||
seen.add(nextInt(rng, 1, 3))
|
seen.add(nextInt(rng, 1, 3))
|
||||||
}
|
}
|
||||||
expect([...seen].sort()).toEqual([1, 2, 3])
|
expect([...seen].toSorted((a, b) => a - b)).toEqual([1, 2, 3])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns the only value when min equals max', () => {
|
it('returns the only value when min equals max', () => {
|
||||||
@ -97,7 +97,7 @@ describe('nextChance', () => {
|
|||||||
it('lands near the requested probability over many draws', () => {
|
it('lands near the requested probability over many draws', () => {
|
||||||
const rng = createRng(2024)
|
const rng = createRng(2024)
|
||||||
let hits = 0
|
let hits = 0
|
||||||
for (let i = 0; i < 4000; i += 1) {
|
for (let index = 0; index < 4000; index += 1) {
|
||||||
if (nextChance(rng, 0.25)) {
|
if (nextChance(rng, 0.25)) {
|
||||||
hits += 1
|
hits += 1
|
||||||
}
|
}
|
||||||
@ -115,10 +115,10 @@ describe('pick', () => {
|
|||||||
it('eventually returns every element', () => {
|
it('eventually returns every element', () => {
|
||||||
const rng = createRng(4)
|
const rng = createRng(4)
|
||||||
const seen = new Set<string>()
|
const seen = new Set<string>()
|
||||||
for (let i = 0; i < 500; i += 1) {
|
for (let index = 0; index < 500; index += 1) {
|
||||||
seen.add(pick(rng, ['a', 'b', 'c']))
|
seen.add(pick(rng, ['a', 'b', 'c']))
|
||||||
}
|
}
|
||||||
expect([...seen].sort()).toEqual(['a', 'b', 'c'])
|
expect([...seen].toSorted((a, b) => a.localeCompare(b))).toEqual(['a', 'b', 'c'])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('is deterministic for a given seed', () => {
|
it('is deterministic for a given seed', () => {
|
||||||
|
|||||||
@ -40,7 +40,7 @@ export const createRng = (seed: number): Rng => ({ s: seed >>> 0 })
|
|||||||
* of it, so they all consume exactly one step per call.
|
* of it, so they all consume exactly one step per call.
|
||||||
*/
|
*/
|
||||||
export const nextFloat = (rng: Rng): number => {
|
export const nextFloat = (rng: Rng): number => {
|
||||||
rng.s = (rng.s + 0x6d_2b_79_f5) >>> 0
|
rng.s = (rng.s + 0x6D_2B_79_F5) >>> 0
|
||||||
let t = rng.s
|
let t = rng.s
|
||||||
t = Math.imul(t ^ (t >>> 15), t | 1)
|
t = Math.imul(t ^ (t >>> 15), t | 1)
|
||||||
t ^= t + Math.imul(t ^ (t >>> 7), t | 61)
|
t ^= t + Math.imul(t ^ (t >>> 7), t | 61)
|
||||||
@ -84,14 +84,14 @@ export const pick = <T>(rng: Rng, items: readonly [T, ...T[]]): T => {
|
|||||||
* around rather than threading mutable state through free functions.
|
* around rather than threading mutable state through free functions.
|
||||||
*/
|
*/
|
||||||
export interface SeededRng {
|
export interface SeededRng {
|
||||||
|
/** True with the given probability in [0, 1]. */
|
||||||
|
chance: (probability: number) => boolean
|
||||||
/** Uniform float in [0, 1). */
|
/** Uniform float in [0, 1). */
|
||||||
float: () => number
|
float: () => number
|
||||||
/** Uniform integer in [minInclusive, maxInclusive]. */
|
/** Uniform integer in [minInclusive, maxInclusive]. */
|
||||||
int: (minInclusive: number, maxInclusive: number) => number
|
int: (minInclusive: number, maxInclusive: number) => number
|
||||||
/** Uniform element of a non-empty array. */
|
/** Uniform element of a non-empty array. */
|
||||||
pick: <T>(items: readonly T[]) => T
|
pick: <T>(items: readonly T[]) => T
|
||||||
/** True with the given probability in [0, 1]. */
|
|
||||||
chance: (probability: number) => boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,6 +105,7 @@ export const createSeededRng = (seed: number): SeededRng => {
|
|||||||
const state = createRng(seed)
|
const state = createRng(seed)
|
||||||
const float = (): number => nextFloat(state)
|
const float = (): number => nextFloat(state)
|
||||||
return {
|
return {
|
||||||
|
chance: (probability: number): boolean => float() < probability,
|
||||||
float,
|
float,
|
||||||
int: (minInclusive: number, maxInclusive: number): number =>
|
int: (minInclusive: number, maxInclusive: number): number =>
|
||||||
nextInt(state, minInclusive, maxInclusive),
|
nextInt(state, minInclusive, maxInclusive),
|
||||||
@ -115,6 +116,5 @@ export const createSeededRng = (seed: number): SeededRng => {
|
|||||||
}
|
}
|
||||||
return chosen
|
return chosen
|
||||||
},
|
},
|
||||||
chance: (probability: number): boolean => float() < probability,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
{
|
{
|
||||||
|
// Strictness comes from the shared base; only output/lib options live here.
|
||||||
|
"extends": "@kuhyx/ts-config/tsconfig",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2023",
|
"target": "ES2023",
|
||||||
// DOM is here only for `performance.now()` in clock.ts -- the package
|
// DOM is here only for `performance.now()` in clock.ts -- the package
|
||||||
@ -9,21 +11,6 @@
|
|||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
|
|
||||||
/* Strictness: everything on, matching the consumers so a file that
|
|
||||||
compiles here compiles there. */
|
|
||||||
"strict": true,
|
|
||||||
"noUncheckedIndexedAccess": true,
|
|
||||||
"noImplicitOverride": true,
|
|
||||||
"noImplicitReturns": true,
|
|
||||||
"noFallthroughCasesInSwitch": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"exactOptionalPropertyTypes": true,
|
|
||||||
"useUnknownInCatchVariables": true,
|
|
||||||
"verbatimModuleSyntax": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"erasableSyntaxOnly": true,
|
|
||||||
|
|
||||||
/* Ships a prebuilt dist/ (ESM + .d.ts) because consumers use Vite, which
|
/* Ships a prebuilt dist/ (ESM + .d.ts) because consumers use Vite, which
|
||||||
does not transpile dependencies. */
|
does not transpile dependencies. */
|
||||||
"rewriteRelativeImportExtensions": true,
|
"rewriteRelativeImportExtensions": true,
|
||||||
@ -32,10 +19,7 @@
|
|||||||
"declarationMap": true,
|
"declarationMap": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"rootDir": "src",
|
"rootDir": "src"
|
||||||
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"forceConsistentCasingInFileNames": true
|
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src"],
|
||||||
"exclude": ["src/**/*.test.ts"]
|
"exclude": ["src/**/*.test.ts"]
|
||||||
|
|||||||
3
web_ui/dist/index.d.ts
vendored
3
web_ui/dist/index.d.ts
vendored
@ -5,6 +5,7 @@
|
|||||||
* `import "@kuhyx/web-ui/tokens.css";`
|
* `import "@kuhyx/web-ui/tokens.css";`
|
||||||
*/
|
*/
|
||||||
export { clamp01, fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.ts";
|
export { clamp01, fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.ts";
|
||||||
export { RangeSlider, steppedValue, type RangeSliderProps } from "./range-slider.tsx";
|
export { RangeSlider, type RangeSliderProps } from "./range-slider.tsx";
|
||||||
|
export { keyTarget, steppedValue } from "./stepped-value.ts";
|
||||||
export { fuzzyMatch } from "./text.ts";
|
export { fuzzyMatch } from "./text.ts";
|
||||||
//# sourceMappingURL=index.d.ts.map
|
//# sourceMappingURL=index.d.ts.map
|
||||||
2
web_ui/dist/index.d.ts.map
vendored
2
web_ui/dist/index.d.ts.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtF,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
||||||
3
web_ui/dist/index.js
vendored
3
web_ui/dist/index.js
vendored
@ -5,6 +5,7 @@
|
|||||||
* `import "@kuhyx/web-ui/tokens.css";`
|
* `import "@kuhyx/web-ui/tokens.css";`
|
||||||
*/
|
*/
|
||||||
export { clamp01, fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.js";
|
export { clamp01, fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.js";
|
||||||
export { RangeSlider, steppedValue } from "./range-slider.js";
|
export { RangeSlider } from "./range-slider.js";
|
||||||
|
export { keyTarget, steppedValue } from "./stepped-value.js";
|
||||||
export { fuzzyMatch } from "./text.js";
|
export { fuzzyMatch } from "./text.js";
|
||||||
//# sourceMappingURL=index.js.map
|
//# sourceMappingURL=index.js.map
|
||||||
2
web_ui/dist/index.js.map
vendored
2
web_ui/dist/index.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,YAAY,EAAyB,MAAM,mBAAoB,CAAC;AACtF,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAChG,OAAO,EAAE,WAAW,EAAyB,MAAM,mBAAoB,CAAC;AACxE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
||||||
2
web_ui/dist/quantile.d.ts.map
vendored
2
web_ui/dist/quantile.d.ts.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"quantile.d.ts","sourceRoot":"","sources":["../src/quantile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;GAIG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMpE;AAED,kCAAkC;AAClC,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAS1E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAa9E;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1E"}
|
{"version":3,"file":"quantile.d.ts","sourceRoot":"","sources":["../src/quantile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;GAIG;AACH,wBAAgB,GAAG,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMpE;AAED,kCAAkC;AAClC,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzC;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAS1E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAY9E;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1E"}
|
||||||
4
web_ui/dist/quantile.js
vendored
4
web_ui/dist/quantile.js
vendored
@ -52,9 +52,7 @@ export function quantileValue(sorted, f) {
|
|||||||
*/
|
*/
|
||||||
export function valueQuantile(sorted, value) {
|
export function valueQuantile(sorted, value) {
|
||||||
const n = sorted.length;
|
const n = sorted.length;
|
||||||
if (n <= 1)
|
if ((n <= 1) || (value <= nth(sorted, 0)))
|
||||||
return 0;
|
|
||||||
if (value <= nth(sorted, 0))
|
|
||||||
return 0;
|
return 0;
|
||||||
if (value >= nth(sorted, n - 1))
|
if (value >= nth(sorted, n - 1))
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
2
web_ui/dist/quantile.js.map
vendored
2
web_ui/dist/quantile.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"quantile.js","sourceRoot":"","sources":["../src/quantile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;GAIG;AACH,MAAM,UAAU,GAAG,CAAC,MAAyB,EAAE,KAAa;IAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,UAAU,CAAC,SAAS,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,MAAyB,EAAE,CAAS;IAChE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACtB,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAyB,EAAE,KAAa;IACpE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACrB,IAAI,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IACtC,IAAI,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IAC1C,qEAAqE;IACrE,kDAAkD;IAClD,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAClB,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,yDAAyD;IACzD,OAAO,CAAC,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAa,EAAE,OAAe;IAChE,OAAO,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5E,CAAC"}
|
{"version":3,"file":"quantile.js","sourceRoot":"","sources":["../src/quantile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;GAIG;AACH,MAAM,UAAU,GAAG,CAAC,MAAyB,EAAE,KAAa;IAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,UAAU,CAAC,SAAS,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,OAAO,CAAC,CAAS;IAC/B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,MAAyB,EAAE,CAAS;IAChE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACtB,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAyB,EAAE,KAAa;IACpE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IACpD,IAAI,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IAC1C,qEAAqE;IACrE,kDAAkD;IAClD,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAClB,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC1B,yDAAyD;IACzD,OAAO,CAAC,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAa,EAAE,OAAe;IAChE,OAAO,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5E,CAAC"}
|
||||||
11
web_ui/dist/range-slider.d.ts
vendored
11
web_ui/dist/range-slider.d.ts
vendored
@ -16,16 +16,5 @@ export interface RangeSliderProps {
|
|||||||
/** The full ascending distribution — not just its endpoints. */
|
/** The full ascending distribution — not just its endpoints. */
|
||||||
readonly values: readonly number[];
|
readonly values: readonly number[];
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Steps one thumb by `delta` positions through the distribution. Pure, so the
|
|
||||||
* keyboard contract is testable without layout.
|
|
||||||
*
|
|
||||||
* Steps to the next *distinct* value rather than the next index. Real
|
|
||||||
* distributions are lumpy -- awesome-mcp-explorer's star counts hold ~1500
|
|
||||||
* duplicate zeros -- and an index step inside a run of equal values changes the
|
|
||||||
* index while leaving the value (and therefore the thumb, and the filter)
|
|
||||||
* exactly where it was. That reads as a dead arrow key.
|
|
||||||
*/
|
|
||||||
export declare function steppedValue(values: readonly number[], current: number, delta: number): number;
|
|
||||||
export declare function RangeSlider({ format, hi, label, lo, onChange, values, }: RangeSliderProps): null | React.JSX.Element;
|
export declare function RangeSlider({ format, hi, label, lo, onChange, values, }: RangeSliderProps): null | React.JSX.Element;
|
||||||
//# sourceMappingURL=range-slider.d.ts.map
|
//# sourceMappingURL=range-slider.d.ts.map
|
||||||
2
web_ui/dist/range-slider.d.ts.map
vendored
2
web_ui/dist/range-slider.d.ts.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"file":"range-slider.d.ts","sourceRoot":"","sources":["../src/range-slider.tsx"],"names":[],"mappings":"AAyBA,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAID;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,CAkBR;AAED,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,EAAE,EACF,KAAK,EACL,EAAE,EACF,QAAQ,EACR,MAAM,GACP,EAAE,gBAAgB,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAyG7C"}
|
{"version":3,"file":"range-slider.d.ts","sourceRoot":"","sources":["../src/range-slider.tsx"],"names":[],"mappings":"AA0BA,MAAM,WAAW,gBAAgB;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAID,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,EAAE,EACF,KAAK,EACL,EAAE,EACF,QAAQ,EACR,MAAM,GACP,EAAE,gBAAgB,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAkG7C"}
|
||||||
89
web_ui/dist/range-slider.js
vendored
89
web_ui/dist/range-slider.js
vendored
@ -22,36 +22,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|||||||
*/
|
*/
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import { fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.js";
|
import { fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.js";
|
||||||
/**
|
import { keyTarget } from "./stepped-value.js";
|
||||||
* Steps one thumb by `delta` positions through the distribution. Pure, so the
|
|
||||||
* keyboard contract is testable without layout.
|
|
||||||
*
|
|
||||||
* Steps to the next *distinct* value rather than the next index. Real
|
|
||||||
* distributions are lumpy -- awesome-mcp-explorer's star counts hold ~1500
|
|
||||||
* duplicate zeros -- and an index step inside a run of equal values changes the
|
|
||||||
* index while leaving the value (and therefore the thumb, and the filter)
|
|
||||||
* exactly where it was. That reads as a dead arrow key.
|
|
||||||
*/
|
|
||||||
export function steppedValue(values, current, delta) {
|
|
||||||
const last = values.length - 1;
|
|
||||||
// Round to a real sample index so a thumb sitting between two samples still
|
|
||||||
// advances rather than stalling on a fractional step.
|
|
||||||
const index = Math.round(valueQuantile(values, current) * last);
|
|
||||||
const direction = Math.sign(delta);
|
|
||||||
if (direction === 0)
|
|
||||||
return nth(values, index);
|
|
||||||
let cursor = index;
|
|
||||||
for (let taken = 0; taken < Math.abs(delta); taken++) {
|
|
||||||
let next = cursor + direction;
|
|
||||||
while (next >= 0 && next <= last && nth(values, next) === nth(values, cursor)) {
|
|
||||||
next += direction;
|
|
||||||
}
|
|
||||||
if (next < 0 || next > last)
|
|
||||||
break;
|
|
||||||
cursor = next;
|
|
||||||
}
|
|
||||||
return nth(values, cursor);
|
|
||||||
}
|
|
||||||
export function RangeSlider({ format, hi, label, lo, onChange, values, }) {
|
export function RangeSlider({ format, hi, label, lo, onChange, values, }) {
|
||||||
const [drag, setDrag] = useState(null);
|
const [drag, setDrag] = useState(null);
|
||||||
const apply = useCallback((thumb, value) => {
|
const apply = useCallback((thumb, value) => {
|
||||||
@ -63,29 +34,17 @@ export function RangeSlider({ format, hi, label, lo, onChange, values, }) {
|
|||||||
// Reads the rect off the event's own target rather than a ref: the pointer
|
// Reads the rect off the event's own target rather than a ref: the pointer
|
||||||
// handlers are bound to the track, so currentTarget *is* the track. A ref
|
// handlers are bound to the track, so currentTarget *is* the track. A ref
|
||||||
// would add a null branch that cannot happen once the element is mounted.
|
// would add a null branch that cannot happen once the element is mounted.
|
||||||
const valueAt = useCallback((track, clientX) => quantileValue(values, fractionFromPointer(track.getBoundingClientRect(), clientX)), [values]);
|
const valueAt = useCallback((track, clientX) => {
|
||||||
|
const fraction = fractionFromPointer(track.getBoundingClientRect(), clientX);
|
||||||
|
return quantileValue(values, fraction);
|
||||||
|
}, [values]);
|
||||||
const onKeyDown = useCallback((thumb, event) => {
|
const onKeyDown = useCallback((thumb, event) => {
|
||||||
const current = thumb === "lo" ? lo : hi;
|
const current = thumb === "lo" ? lo : hi;
|
||||||
const step = (delta) => {
|
const target = keyTarget(event.key, values, current);
|
||||||
event.preventDefault();
|
if (target === undefined)
|
||||||
apply(thumb, steppedValue(values, current, delta));
|
return;
|
||||||
};
|
event.preventDefault();
|
||||||
if (event.key === "ArrowLeft" || event.key === "ArrowDown")
|
apply(thumb, target);
|
||||||
step(-1);
|
|
||||||
else if (event.key === "ArrowRight" || event.key === "ArrowUp")
|
|
||||||
step(1);
|
|
||||||
else if (event.key === "PageDown")
|
|
||||||
step(-10);
|
|
||||||
else if (event.key === "PageUp")
|
|
||||||
step(10);
|
|
||||||
else if (event.key === "Home") {
|
|
||||||
event.preventDefault();
|
|
||||||
apply(thumb, nth(values, 0));
|
|
||||||
}
|
|
||||||
else if (event.key === "End") {
|
|
||||||
event.preventDefault();
|
|
||||||
apply(thumb, nth(values, values.length - 1));
|
|
||||||
}
|
|
||||||
}, [apply, hi, lo, values]);
|
}, [apply, hi, lo, values]);
|
||||||
// Fewer than two values means there is nothing to range over.
|
// Fewer than two values means there is nothing to range over.
|
||||||
if (values.length < 2)
|
if (values.length < 2)
|
||||||
@ -95,19 +54,21 @@ export function RangeSlider({ format, hi, label, lo, onChange, values, }) {
|
|||||||
const loFraction = valueQuantile(values, lo) * 100;
|
const loFraction = valueQuantile(values, lo) * 100;
|
||||||
const hiFraction = valueQuantile(values, hi) * 100;
|
const hiFraction = valueQuantile(values, hi) * 100;
|
||||||
const name = label ?? "Range";
|
const name = label ?? "Range";
|
||||||
const thumbProps = (thumb) => ({
|
const thumbProps = (thumb) => {
|
||||||
"aria-valuemax": highest,
|
return {
|
||||||
"aria-valuemin": lowest,
|
"aria-valuemax": highest,
|
||||||
"aria-valuenow": thumb === "lo" ? lo : hi,
|
"aria-valuemin": lowest,
|
||||||
className: `slider-thumb slider-${thumb}`,
|
"aria-valuenow": thumb === "lo" ? lo : hi,
|
||||||
onKeyDown: (event) => {
|
className: `slider-thumb slider-${thumb}`,
|
||||||
onKeyDown(thumb, event);
|
onKeyDown: (event) => {
|
||||||
},
|
onKeyDown(thumb, event);
|
||||||
role: "slider",
|
},
|
||||||
style: { left: `${String(thumb === "lo" ? loFraction : hiFraction)}%` },
|
role: "slider",
|
||||||
tabIndex: 0,
|
style: { left: `${String(thumb === "lo" ? loFraction : hiFraction)}%` },
|
||||||
type: "button",
|
tabIndex: 0,
|
||||||
});
|
type: "button",
|
||||||
|
};
|
||||||
|
};
|
||||||
return (_jsxs("div", { className: "slider", children: [label !== undefined && format !== undefined && (_jsxs("div", { className: "slider-head", children: [_jsx("span", { children: label }), _jsxs("span", { className: "slider-value", children: [format(lo), " \u2013 ", format(hi)] })] })), _jsxs("div", { className: "slider-track", onPointerDown: (event) => {
|
return (_jsxs("div", { className: "slider", children: [label !== undefined && format !== undefined && (_jsxs("div", { className: "slider-head", children: [_jsx("span", { children: label }), _jsxs("span", { className: "slider-value", children: [format(lo), " \u2013 ", format(hi)] })] })), _jsxs("div", { className: "slider-track", onPointerDown: (event) => {
|
||||||
const value = valueAt(event.currentTarget, event.clientX);
|
const value = valueAt(event.currentTarget, event.clientX);
|
||||||
// Grab whichever thumb is nearer, so a press anywhere on the track
|
// Grab whichever thumb is nearer, so a press anywhere on the track
|
||||||
|
|||||||
2
web_ui/dist/range-slider.js.map
vendored
2
web_ui/dist/range-slider.js.map
vendored
File diff suppressed because one or more lines are too long
19
web_ui/dist/stepped-value.d.ts
vendored
Normal file
19
web_ui/dist/stepped-value.d.ts
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Steps one thumb by `delta` positions through the distribution. Pure, so the
|
||||||
|
* keyboard contract is testable without layout.
|
||||||
|
*
|
||||||
|
* Steps to the next *distinct* value rather than the next index. Real
|
||||||
|
* distributions are lumpy -- awesome-mcp-explorer's star counts hold ~1500
|
||||||
|
* duplicate zeros -- and an index step inside a run of equal values changes the
|
||||||
|
* index while leaving the value (and therefore the thumb, and the filter)
|
||||||
|
* exactly where it was. That reads as a dead arrow key.
|
||||||
|
*/
|
||||||
|
export declare function steppedValue(values: readonly number[], current: number, delta: number): number;
|
||||||
|
/**
|
||||||
|
* The value a thumb at `current` moves to for a key, or `undefined` when the
|
||||||
|
* key is not one the slider handles (so the event is left to the browser).
|
||||||
|
* Arrow keys step one distinct value, Page keys ten, Home/End jump to the
|
||||||
|
* bounds.
|
||||||
|
*/
|
||||||
|
export declare function keyTarget(key: string, values: readonly number[], current: number): number | undefined;
|
||||||
|
//# sourceMappingURL=stepped-value.d.ts.map
|
||||||
1
web_ui/dist/stepped-value.d.ts.map
vendored
Normal file
1
web_ui/dist/stepped-value.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"stepped-value.d.ts","sourceRoot":"","sources":["../src/stepped-value.ts"],"names":[],"mappings":"AAOA;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,CAkBR;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CA0BpB"}
|
||||||
70
web_ui/dist/stepped-value.js
vendored
Normal file
70
web_ui/dist/stepped-value.js
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* The keyboard contract of the range slider, kept pure and in its own module
|
||||||
|
* so range-slider.tsx exports only the component (react-refresh needs that
|
||||||
|
* for HMR to keep working) and the contract is testable without layout.
|
||||||
|
*/
|
||||||
|
import { nth, valueQuantile } from "./quantile.js";
|
||||||
|
/**
|
||||||
|
* Steps one thumb by `delta` positions through the distribution. Pure, so the
|
||||||
|
* keyboard contract is testable without layout.
|
||||||
|
*
|
||||||
|
* Steps to the next *distinct* value rather than the next index. Real
|
||||||
|
* distributions are lumpy -- awesome-mcp-explorer's star counts hold ~1500
|
||||||
|
* duplicate zeros -- and an index step inside a run of equal values changes the
|
||||||
|
* index while leaving the value (and therefore the thumb, and the filter)
|
||||||
|
* exactly where it was. That reads as a dead arrow key.
|
||||||
|
*/
|
||||||
|
export function steppedValue(values, current, delta) {
|
||||||
|
const last = values.length - 1;
|
||||||
|
// Round to a real sample index so a thumb sitting between two samples still
|
||||||
|
// advances rather than stalling on a fractional step.
|
||||||
|
const index = Math.round(valueQuantile(values, current) * last);
|
||||||
|
const direction = Math.sign(delta);
|
||||||
|
if (direction === 0)
|
||||||
|
return nth(values, index);
|
||||||
|
let cursor = index;
|
||||||
|
for (let taken = 0; taken < Math.abs(delta); taken++) {
|
||||||
|
let next = cursor + direction;
|
||||||
|
while (next >= 0 && next <= last && nth(values, next) === nth(values, cursor)) {
|
||||||
|
next += direction;
|
||||||
|
}
|
||||||
|
if (next < 0 || next > last)
|
||||||
|
break;
|
||||||
|
cursor = next;
|
||||||
|
}
|
||||||
|
return nth(values, cursor);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The value a thumb at `current` moves to for a key, or `undefined` when the
|
||||||
|
* key is not one the slider handles (so the event is left to the browser).
|
||||||
|
* Arrow keys step one distinct value, Page keys ten, Home/End jump to the
|
||||||
|
* bounds.
|
||||||
|
*/
|
||||||
|
export function keyTarget(key, values, current) {
|
||||||
|
switch (key) {
|
||||||
|
case "ArrowDown":
|
||||||
|
case "ArrowLeft": {
|
||||||
|
return steppedValue(values, current, -1);
|
||||||
|
}
|
||||||
|
case "ArrowRight":
|
||||||
|
case "ArrowUp": {
|
||||||
|
return steppedValue(values, current, 1);
|
||||||
|
}
|
||||||
|
case "End": {
|
||||||
|
return nth(values, values.length - 1);
|
||||||
|
}
|
||||||
|
case "Home": {
|
||||||
|
return nth(values, 0);
|
||||||
|
}
|
||||||
|
case "PageDown": {
|
||||||
|
return steppedValue(values, current, -10);
|
||||||
|
}
|
||||||
|
case "PageUp": {
|
||||||
|
return steppedValue(values, current, 10);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=stepped-value.js.map
|
||||||
1
web_ui/dist/stepped-value.js.map
vendored
Normal file
1
web_ui/dist/stepped-value.js.map
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"stepped-value.js","sourceRoot":"","sources":["../src/stepped-value.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAyB,EACzB,OAAe,EACf,KAAa;IAEb,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,4EAA4E;IAC5E,sDAAsD;IACtD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,SAAS,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAE/C,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QACrD,IAAI,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;QAC9B,OAAO,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;YAC9E,IAAI,IAAI,SAAS,CAAC;QACpB,CAAC;QACD,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,IAAI;YAAE,MAAM;QACnC,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CACvB,GAAW,EACX,MAAyB,EACzB,OAAe;IAEf,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,WAAW,CAAC;QACjB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,OAAO,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3C,CAAC;QACD,KAAK,YAAY,CAAC;QAClB,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,OAAO,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QAC1C,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,OAAO,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACxC,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACxB,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,OAAO,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5C,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,OAAO,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACR,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;AACH,CAAC"}
|
||||||
@ -1,42 +1,25 @@
|
|||||||
// Type-aware flat config for the shared component layer.
|
// The shared preset with the React layer, plus one frozen API name. This
|
||||||
//
|
// package is one of the repos the bar is defined for.
|
||||||
// A trimmed version of awesome-mcp-explorer's: typescript-eslint's
|
import { defineConfig } from "@kuhyx/ts-config";
|
||||||
// *type-checked* strict + stylistic presets, so anything they flag is an error.
|
|
||||||
// The consumers layer unicorn/sonarjs/perfectionist on top; this package keeps
|
|
||||||
// to the presets its own devDependencies actually declare, because a config
|
|
||||||
// referencing plugins that are not installed is a lint script that cannot run.
|
|
||||||
import js from "@eslint/js";
|
|
||||||
import tseslint from "typescript-eslint";
|
|
||||||
|
|
||||||
export default tseslint.config(
|
export default defineConfig({
|
||||||
// eslint.config.js itself is not in tsconfig.lint.json, so type-aware
|
// Flat files under src/, no layers to fence and no alias configured.
|
||||||
// rules cannot run on it; linting the linter config buys nothing anyway.
|
aliasOnly: false,
|
||||||
{ ignores: ["dist", "coverage", "eslint.config.js"] },
|
overrides: [
|
||||||
{ linterOptions: { reportUnusedDisableDirectives: "error" } },
|
{
|
||||||
|
files: ["src/text.ts"],
|
||||||
js.configs.recommended,
|
rules: {
|
||||||
...tseslint.configs.strictTypeChecked,
|
// `fuzzyMatch` is public API at four call sites in dufs-cloud and
|
||||||
...tseslint.configs.stylisticTypeChecked,
|
// awesome-mcp-explorer; the preset's prefix list would rename it to
|
||||||
|
// `matchesFuzzy`, a breaking change for no safety gain. Revisit at
|
||||||
{
|
// the next major.
|
||||||
files: ["**/*.{ts,tsx}"],
|
"unicorn/consistent-boolean-name": "off",
|
||||||
languageOptions: {
|
|
||||||
parserOptions: {
|
|
||||||
project: ["./tsconfig.lint.json"],
|
|
||||||
tsconfigRootDir: import.meta.dirname,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rules: {
|
],
|
||||||
// Every exported symbol here is consumed across a package boundary, so
|
// tsconfig.json excludes the tests so they never land in dist/; the lint
|
||||||
// an explicit return type is documentation, not ceremony.
|
// project widens the include for type-aware rules (see tsconfig.lint.json).
|
||||||
"@typescript-eslint/explicit-function-return-type": "error",
|
project: ["./tsconfig.lint.json"],
|
||||||
},
|
react: true,
|
||||||
},
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
});
|
||||||
{
|
|
||||||
// Tests reach for non-null assertions on queries that cannot return null
|
|
||||||
// in a passing test; asserting them again would only add noise.
|
|
||||||
files: ["**/*.test.{ts,tsx}"],
|
|
||||||
rules: { "@typescript-eslint/no-non-null-assertion": "off" },
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@kuhyx/web-ui",
|
"name": "@kuhyx/web-ui",
|
||||||
"version": "0.3.2",
|
"version": "0.4.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "The shared token + component layer for kuhy's web apps: the frozen palette, spacing/radius/type scales as CSS custom properties, and the components that were each reimplemented in two or more repos.",
|
"description": "The shared token + component layer for kuhy's web apps: the frozen palette, spacing/radius/type scales as CSS custom properties, and the components that were each reimplemented in two or more repos.",
|
||||||
@ -9,7 +9,7 @@
|
|||||||
"node": ">=24",
|
"node": ">=24",
|
||||||
"pnpm": ">=10"
|
"pnpm": ">=10"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@12.4.1+sha512.2e81e399d73fe8390dab25e06aa788ab7a5908248d2f5a370f82b481147a6a7a367bf8048f9a6fdb6460f21a66f0542dedb8b94ca2c8723596741920b1656d4c",
|
"packageManager": "pnpm@12.4.2",
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
@ -34,19 +34,20 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "10.0.1",
|
"@eslint/js": "10.0.1",
|
||||||
|
"@kuhyx/ts-config": "link:../ts_config",
|
||||||
"@testing-library/jest-dom": "7.0.1",
|
"@testing-library/jest-dom": "7.0.1",
|
||||||
"@testing-library/react": "16.3.3",
|
"@testing-library/react": "16.3.3",
|
||||||
"@testing-library/user-event": "14.6.7",
|
"@testing-library/user-event": "14.6.7",
|
||||||
|
"@types/node": "26.5.1",
|
||||||
"@types/react": "19.3.0",
|
"@types/react": "19.3.0",
|
||||||
"@types/react-dom": "19.3.0",
|
"@types/react-dom": "19.3.0",
|
||||||
"@vitest/coverage-v8": "5.0.0",
|
"@vitest/coverage-v8": "5.0.1",
|
||||||
"eslint": "10.10.0",
|
"eslint": "10.10.0",
|
||||||
"jsdom": "30.0.1",
|
"jsdom": "30.0.1",
|
||||||
"react": "19.3.0",
|
"react": "19.3.0",
|
||||||
"react-dom": "19.3.0",
|
"react-dom": "19.3.0",
|
||||||
"typescript": "6.0.3",
|
"typescript": "6.0.3",
|
||||||
"typescript-eslint": "8.70.0",
|
"typescript-eslint": "8.70.0",
|
||||||
"vitest": "5.0.0",
|
"vitest": "5.0.1"
|
||||||
"@types/node": "26.5.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,153 +7,153 @@ importers:
|
|||||||
configDependencies: {}
|
configDependencies: {}
|
||||||
packageManagerDependencies:
|
packageManagerDependencies:
|
||||||
pnpm:
|
pnpm:
|
||||||
specifier: 12.4.1
|
specifier: 12.4.2
|
||||||
version: 12.4.1
|
version: 12.4.2
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
'@pnpm/exe.android-arm64@12.4.1':
|
'@pnpm/exe.android-arm64@12.4.2':
|
||||||
resolution: {integrity: sha512-/HwsqXMSmlOfgtV9+O0ratzjV6Vd/8n1hh4rGHpCGmDURvt52MwZxdbhyxP4K03ZfvgSDvotFPr8O+RzE5Eu8A==}
|
resolution: {integrity: sha512-E255MbcQ0V1577M2BV0ajWuP7KmTPYA0jqZnk3rK6Lq3kTvZWulMMb7iqRmnLsQbyWTkMEB2CfyM70loVDA8xg==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
'@pnpm/exe.android-x64@12.4.1':
|
'@pnpm/exe.android-x64@12.4.2':
|
||||||
resolution: {integrity: sha512-+l74Qb4c2YjOzNKHXJLg+1wr8xHM1ckkUhnU5KRUK9TJqiiczt6yeTZqqzHIlJ8i6pAoj5V0OJevDRwnQKLgrQ==}
|
resolution: {integrity: sha512-J1pSeCUwuKxMG70ZzpWn8JzElxiEa8NN/3N0SlZRtU2xbztChaJCKF3HaBNIj9yPfeofWzJo/lwNvDDjraQuZw==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [android]
|
os: [android]
|
||||||
|
|
||||||
'@pnpm/exe.darwin-arm64@12.4.1':
|
'@pnpm/exe.darwin-arm64@12.4.2':
|
||||||
resolution: {integrity: sha512-6rkZkT3iGfaxknUdGHraqSWFvTa6N0ajAHluv9Ax0GRWs0sIcGNiFhDopv6xSZCsJZmG483aNS/b6UEDy3blfw==}
|
resolution: {integrity: sha512-A0WDo8iErfZBXgrLseQxw8i8Y9ctUpOEl/Uu+cubnTzpD8tT9ykIB548L8YTM2WD4OS+ZOHSxy8aGZcvKq8PaQ==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@pnpm/exe.darwin-x64@12.4.1':
|
'@pnpm/exe.darwin-x64@12.4.2':
|
||||||
resolution: {integrity: sha512-Vb1CHlR88HghC1qUxjxjs82zQSXnXacPD+btG2CmG8Q/hBU7Q0/b2YWJKSQqZXicunV5khFtfTlAwJddV9RkYA==}
|
resolution: {integrity: sha512-MSgJdovBWHcb5DEOvfPH9yNi/T5O1Xa4ess+E1ESGo/5yuty7S4JoiIjami+fsNXfnoQMlwsMUqYU4zAvBcNCw==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@pnpm/exe.freebsd-x64@12.4.1':
|
'@pnpm/exe.freebsd-x64@12.4.2':
|
||||||
resolution: {integrity: sha512-iT3iHz3Nl0Sxxj7UPOtZ/aQ81AFsQhjoeWMAlPkSRO04gsgDGAXv3UYxOFaesMWsfNxaGn0A+CITbuCHFF66FA==}
|
resolution: {integrity: sha512-h2YumlQSNvgbRPv+RXwABohX65f9bOBZn+jMIt7bFDISZPCzQ+Nvpt6Awbp4ip5PwQgYxbu5iREJ1fHE39Fm8A==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [freebsd]
|
os: [freebsd]
|
||||||
|
|
||||||
'@pnpm/exe.linux-arm64-musl@12.4.1':
|
'@pnpm/exe.linux-arm64-musl@12.4.2':
|
||||||
resolution: {integrity: sha512-aBooZfNXM5f+OGUgCAMFWpE/kAhsWfvmqIyMtHy6zl3aNxyInWrcY/Saln/UElzo7lZWMC0Yktroxd/2J26lNQ==}
|
resolution: {integrity: sha512-LwSEtSEDTv6S51YLs3YvSkPyun/QmfMic1UGICUkPWFu6ByP43RdMlkKvmVkfGhAYCpnxO057vrmyJqtfZrPCA==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
libc: [musl]
|
||||||
|
|
||||||
'@pnpm/exe.linux-arm64@12.4.1':
|
'@pnpm/exe.linux-arm64@12.4.2':
|
||||||
resolution: {integrity: sha512-TlOdacTTP09BgcMvwWBFRsu8VAjfwqwnslBj+XSq1JFM3ck4f3k+1O/747EuctxZxs3/o785b6Q3s7Pd92Ptsg==}
|
resolution: {integrity: sha512-2dSiDXyhx+RTHsewxex8f/jVjqQXWJ2oow4kCVHEWdZKeBpgMxvZ6fHkTAUBJXgqhbKIDHvuNlZBP7gJfUWL5A==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@pnpm/exe.linux-ppc64@12.4.1':
|
'@pnpm/exe.linux-ppc64@12.4.2':
|
||||||
resolution: {integrity: sha512-r/ab/MlIBo75oizUP5ITiziCCrnXz4SJwfErLQ+603AshB+Yq7xTMCoMtzTSCAMu6aaymIKkAFtZvd2J75Wq0w==}
|
resolution: {integrity: sha512-8Itc+jQk+MTz04LS9D1RcH+VctAWmzM4l1cJQ+Sx7pAJNo7EKHdRMbC0Tok1jyQ7eEHNJZD5EleYneZqWfZM+g==}
|
||||||
cpu: [ppc64]
|
cpu: [ppc64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@pnpm/exe.linux-riscv64@12.4.1':
|
'@pnpm/exe.linux-riscv64@12.4.2':
|
||||||
resolution: {integrity: sha512-C/D1QWdKMiB8+wv/spl1rGITFUuqC+aI/fb6h8NB5sqxsOaGXeYc/g891oCuzggHn6SODk9p+I09hI76x/cMNw==}
|
resolution: {integrity: sha512-hleOeqhTVpH+z9RVMGnxvU4ZnrkBUClWjCbHD9u6kwyqhGSpevoU1wTGish+CBRhmIgMAy9pAfFpqhbAKOKNfw==}
|
||||||
cpu: [riscv64]
|
cpu: [riscv64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@pnpm/exe.linux-s390x@12.4.1':
|
'@pnpm/exe.linux-s390x@12.4.2':
|
||||||
resolution: {integrity: sha512-nxz5zD4yXt94uzbStDk0QTPKW+aE92hH1b5tFXK9ctB1HE9Xcq1vjTiA2LsZMFC6p4gdu5OwQeFqYNAVGa6QlA==}
|
resolution: {integrity: sha512-LAsQRRdP9aToENR6dtcIJ9l+e1zMYOX0tQcLGpRyLPVBQcYRLlvAPcmDshsiIHQjp05SDa9FI0czX1ZQ1a7a/A==}
|
||||||
cpu: [s390x]
|
cpu: [s390x]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@pnpm/exe.linux-x64-musl@12.4.1':
|
'@pnpm/exe.linux-x64-musl@12.4.2':
|
||||||
resolution: {integrity: sha512-5AwgFdGhVUg2kIweYGfxzSLEHiIG77PQhZAkXC3TwofQHsu1Wr+TrV5/rNX2PopFnHRzuE581zoB8F6Wle32yg==}
|
resolution: {integrity: sha512-kzfzH2/0BWdTABK14Yj5a1xsdkTEQUp2eXEPNakaD9jKL025lq3hyaKHIz/gIZaPDMe/1bFFK/En4ztFlbBJxw==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [musl]
|
libc: [musl]
|
||||||
|
|
||||||
'@pnpm/exe.linux-x64@12.4.1':
|
'@pnpm/exe.linux-x64@12.4.2':
|
||||||
resolution: {integrity: sha512-FJOZuuuQMhp0oLzBtcKkLXknBI92hfkmSnlKc47vfin4HrmfID5khY2lGekL9tCzk1cpR+HShEw/meFl+nHtzQ==}
|
resolution: {integrity: sha512-/pbt0UVTa8NMDhzOWLQRfZ6G9ROKXlJPZtx845BqyWfc7hCrWXhTLBd70yO2y8+E+IWN3oHM1s/JsIQNGk1yvg==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
libc: [glibc]
|
libc: [glibc]
|
||||||
|
|
||||||
'@pnpm/exe.win32-arm64@12.4.1':
|
'@pnpm/exe.win32-arm64@12.4.2':
|
||||||
resolution: {integrity: sha512-OO7eKBL9S+xk5hRy+JUUZSNJknGuGe3GEUffsrlC2LbqKF02g+VX1anGIzSbJDvkkdnpJhSlxF5AUz2JzJu2Jw==}
|
resolution: {integrity: sha512-PsW19e4dAUNpZ0cS9flaxFuAmpt2dKlH/Vvi8TZ4qyJjjQzue/CEsWm+6wKVP4CJ7IT8RdL4qh+soOPWIgF2Zw==}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@pnpm/exe.win32-x64@12.4.1':
|
'@pnpm/exe.win32-x64@12.4.2':
|
||||||
resolution: {integrity: sha512-x7gJHZgHo6hp354xCYA2NvoFzYJkHwovt2kVsUBK5EmXULLcP51JGMq09CX+5FRFJUZFKoXjLu3mZWmfP7o6PQ==}
|
resolution: {integrity: sha512-+xGoeE0g55ztWvl8i5QqdmNfW3nIrTVcoQrNshEOwxthm9Ag48oXton3uxOA3/SANyz5AXexEjj2KO20NnOrEw==}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
pnpm@12.4.1:
|
pnpm@12.4.2:
|
||||||
resolution: {integrity: sha512-LoHjmdc/6DkNqyXgaqeIq3pZCCSNL1o3D4K0gRR6ano2e/gEj5pv22Rg8hpm8FQt7bi5TKLIcjWWdBkgsWVtTA==}
|
resolution: {integrity: sha512-CK3GYTGAJ1x8ntraOdzwjJxhrU5+rzMKTzRh8QKw+QdCNFTRF/mOctR/7wYWBwZE17/8lzpqV/UJCm18NosHyQ==}
|
||||||
engines: {node: '>=18.*'}
|
engines: {node: '>=18.*'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
'@pnpm/exe.android-arm64@12.4.1':
|
'@pnpm/exe.android-arm64@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.android-x64@12.4.1':
|
'@pnpm/exe.android-x64@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.darwin-arm64@12.4.1':
|
'@pnpm/exe.darwin-arm64@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.darwin-x64@12.4.1':
|
'@pnpm/exe.darwin-x64@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.freebsd-x64@12.4.1':
|
'@pnpm/exe.freebsd-x64@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.linux-arm64-musl@12.4.1':
|
'@pnpm/exe.linux-arm64-musl@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.linux-arm64@12.4.1':
|
'@pnpm/exe.linux-arm64@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.linux-ppc64@12.4.1':
|
'@pnpm/exe.linux-ppc64@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.linux-riscv64@12.4.1':
|
'@pnpm/exe.linux-riscv64@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.linux-s390x@12.4.1':
|
'@pnpm/exe.linux-s390x@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.linux-x64-musl@12.4.1':
|
'@pnpm/exe.linux-x64-musl@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.linux-x64@12.4.1':
|
'@pnpm/exe.linux-x64@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.win32-arm64@12.4.1':
|
'@pnpm/exe.win32-arm64@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@pnpm/exe.win32-x64@12.4.1':
|
'@pnpm/exe.win32-x64@12.4.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
pnpm@12.4.1:
|
pnpm@12.4.2:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@pnpm/exe.android-arm64': 12.4.1
|
'@pnpm/exe.android-arm64': 12.4.2
|
||||||
'@pnpm/exe.android-x64': 12.4.1
|
'@pnpm/exe.android-x64': 12.4.2
|
||||||
'@pnpm/exe.darwin-arm64': 12.4.1
|
'@pnpm/exe.darwin-arm64': 12.4.2
|
||||||
'@pnpm/exe.darwin-x64': 12.4.1
|
'@pnpm/exe.darwin-x64': 12.4.2
|
||||||
'@pnpm/exe.freebsd-x64': 12.4.1
|
'@pnpm/exe.freebsd-x64': 12.4.2
|
||||||
'@pnpm/exe.linux-arm64': 12.4.1
|
'@pnpm/exe.linux-arm64': 12.4.2
|
||||||
'@pnpm/exe.linux-arm64-musl': 12.4.1
|
'@pnpm/exe.linux-arm64-musl': 12.4.2
|
||||||
'@pnpm/exe.linux-ppc64': 12.4.1
|
'@pnpm/exe.linux-ppc64': 12.4.2
|
||||||
'@pnpm/exe.linux-riscv64': 12.4.1
|
'@pnpm/exe.linux-riscv64': 12.4.2
|
||||||
'@pnpm/exe.linux-s390x': 12.4.1
|
'@pnpm/exe.linux-s390x': 12.4.2
|
||||||
'@pnpm/exe.linux-x64': 12.4.1
|
'@pnpm/exe.linux-x64': 12.4.2
|
||||||
'@pnpm/exe.linux-x64-musl': 12.4.1
|
'@pnpm/exe.linux-x64-musl': 12.4.2
|
||||||
'@pnpm/exe.win32-arm64': 12.4.1
|
'@pnpm/exe.win32-arm64': 12.4.2
|
||||||
'@pnpm/exe.win32-x64': 12.4.1
|
'@pnpm/exe.win32-x64': 12.4.2
|
||||||
|
|
||||||
---
|
---
|
||||||
lockfileVersion: '9.0'
|
lockfileVersion: '9.0'
|
||||||
@ -169,9 +169,12 @@ importers:
|
|||||||
'@eslint/js':
|
'@eslint/js':
|
||||||
specifier: 10.0.1
|
specifier: 10.0.1
|
||||||
version: 10.0.1(eslint@10.10.0(supports-color@7.2.0))
|
version: 10.0.1(eslint@10.10.0(supports-color@7.2.0))
|
||||||
|
'@kuhyx/ts-config':
|
||||||
|
specifier: link:../ts_config
|
||||||
|
version: link:../ts_config
|
||||||
'@testing-library/jest-dom':
|
'@testing-library/jest-dom':
|
||||||
specifier: 7.0.1
|
specifier: 7.0.1
|
||||||
version: 7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.0)
|
version: 7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.1)
|
||||||
'@testing-library/react':
|
'@testing-library/react':
|
||||||
specifier: 16.3.3
|
specifier: 16.3.3
|
||||||
version: 16.3.3(@testing-library/dom@10.4.1)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
|
version: 16.3.3(@testing-library/dom@10.4.1)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
|
||||||
@ -188,8 +191,8 @@ importers:
|
|||||||
specifier: 19.3.0
|
specifier: 19.3.0
|
||||||
version: 19.3.0(@types/react@19.3.0)
|
version: 19.3.0(@types/react@19.3.0)
|
||||||
'@vitest/coverage-v8':
|
'@vitest/coverage-v8':
|
||||||
specifier: 5.0.0
|
specifier: 5.0.1
|
||||||
version: 5.0.0(vitest@5.0.0)
|
version: 5.0.1(vitest@5.0.1)
|
||||||
eslint:
|
eslint:
|
||||||
specifier: 10.10.0
|
specifier: 10.10.0
|
||||||
version: 10.10.0(supports-color@7.2.0)
|
version: 10.10.0(supports-color@7.2.0)
|
||||||
@ -209,8 +212,8 @@ importers:
|
|||||||
specifier: 8.70.0
|
specifier: 8.70.0
|
||||||
version: 8.70.0(eslint@10.10.0(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)
|
version: 8.70.0(eslint@10.10.0(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)
|
||||||
vitest:
|
vitest:
|
||||||
specifier: 5.0.0
|
specifier: 5.0.1
|
||||||
version: 5.0.0(@types/node@26.5.1)(@vitest/coverage-v8@5.0.0)(jsdom@30.0.1)(vite@8.2.2(@types/node@26.5.1))
|
version: 5.0.1(@types/node@26.5.1)(@vitest/coverage-v8@5.0.1)(jsdom@30.0.1)(vite@8.2.2(@types/node@26.5.1))
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
@ -372,9 +375,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.5':
|
|
||||||
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.6.0':
|
'@jridgewell/sourcemap-codec@1.6.0':
|
||||||
resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==}
|
resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==}
|
||||||
|
|
||||||
@ -615,11 +615,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-BoC8PiO4Hkdo0TVJh9Ntxr5MxPDI7/oFsrygN5ADelFSeXG/qgNuucIGA+L5Z6JpPTE/uRfcTWtscjbUaufepQ==}
|
resolution: {integrity: sha512-BoC8PiO4Hkdo0TVJh9Ntxr5MxPDI7/oFsrygN5ADelFSeXG/qgNuucIGA+L5Z6JpPTE/uRfcTWtscjbUaufepQ==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@vitest/coverage-v8@5.0.0':
|
'@vitest/coverage-v8@5.0.1':
|
||||||
resolution: {integrity: sha512-toMg6PZGCIa/lQNCDoASrfb1ly4hsUKXFtFYC9kD4t78o5Y6LyNJU7AENt8eHPr3quYdxaxK7hj2mnbFfUk9NA==}
|
resolution: {integrity: sha512-FRC8ACiudC3dI6MTplzRSYWHDRnIv2IPfbzs4FdoJNsMal/35sWV8hwIfV8ZcqzSPy+uXHeMVONt9CEqtOU17w==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@vitest/browser': 5.0.0
|
'@vitest/browser': 5.0.1
|
||||||
vitest: 5.0.0
|
vitest: 5.0.1
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
'@vitest/browser':
|
'@vitest/browser':
|
||||||
optional: true
|
optional: true
|
||||||
@ -632,8 +632,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-1EOLRfsTMnyAr3+kEAsP4o9dhaDlGPpD7H5iLBBeq//YpNB1VIahkPhB+eRp9N2Dkfw8oySROjE3yf9XDeaIkQ==}
|
resolution: {integrity: sha512-1EOLRfsTMnyAr3+kEAsP4o9dhaDlGPpD7H5iLBBeq//YpNB1VIahkPhB+eRp9N2Dkfw8oySROjE3yf9XDeaIkQ==}
|
||||||
engines: {node: '>=22'}
|
engines: {node: '>=22'}
|
||||||
|
|
||||||
'@vitest/mocker@5.0.0':
|
'@vitest/mocker@5.0.1':
|
||||||
resolution: {integrity: sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA==}
|
resolution: {integrity: sha512-6K1DoBNAPGvuOcSsGA4D6x+5zEEff/KmOOP3uetT2TrGpVfI+HRHRnJJfKi5ib/g1vx8IYHQD8s0pbJz8WQI7Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
msw: ^2.4.9
|
msw: ^2.4.9
|
||||||
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||||
@ -643,8 +643,8 @@ packages:
|
|||||||
vite:
|
vite:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@vitest/spy@5.0.0':
|
'@vitest/spy@5.0.1':
|
||||||
resolution: {integrity: sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g==}
|
resolution: {integrity: sha512-rbto/mF/SGERxEgYOek7Xm6B9b+y+mVoo+f4b2LymYO8zM1b7uB5nHuhVMTP2hxdzgxvGiZYGxGIaMvL5y180Q==}
|
||||||
|
|
||||||
acorn-jsx@5.3.2:
|
acorn-jsx@5.3.2:
|
||||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||||
@ -1265,20 +1265,20 @@ packages:
|
|||||||
yaml:
|
yaml:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
vitest@5.0.0:
|
vitest@5.0.1:
|
||||||
resolution: {integrity: sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q==}
|
resolution: {integrity: sha512-iA95lQbKEkvrtTkdAgnWbXfbipWiiWe/hDl2P5tMi6WFwD76G0NxXAGp/M9EOcYupeGJRr6wppMc7CoA41TQjg==}
|
||||||
engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0}
|
engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@edge-runtime/vm': '*'
|
'@edge-runtime/vm': '*'
|
||||||
'@opentelemetry/api': ^1.9.0
|
'@opentelemetry/api': ^1.9.0
|
||||||
'@types/node': ^22.0.0 || >=24.0.0
|
'@types/node': ^22.0.0 || >=24.0.0
|
||||||
'@vitest/browser-playwright': 5.0.0
|
'@vitest/browser-playwright': 5.0.1
|
||||||
'@vitest/browser-preview': 5.0.0
|
'@vitest/browser-preview': 5.0.1
|
||||||
'@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0
|
'@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0
|
||||||
'@vitest/coverage-istanbul': 5.0.0
|
'@vitest/coverage-istanbul': 5.0.1
|
||||||
'@vitest/coverage-v8': 5.0.0
|
'@vitest/coverage-v8': 5.0.1
|
||||||
'@vitest/ui': 5.0.0
|
'@vitest/ui': 5.0.1
|
||||||
happy-dom: '*'
|
happy-dom: '*'
|
||||||
jsdom: '*'
|
jsdom: '*'
|
||||||
vite: ^6.4.0 || ^7.0.0 || ^8.0.0
|
vite: ^6.4.0 || ^7.0.0 || ^8.0.0
|
||||||
@ -1487,14 +1487,12 @@ snapshots:
|
|||||||
|
|
||||||
'@jridgewell/resolve-uri@3.1.2': {}
|
'@jridgewell/resolve-uri@3.1.2': {}
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.5': {}
|
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.6.0': {}
|
'@jridgewell/sourcemap-codec@1.6.0': {}
|
||||||
|
|
||||||
'@jridgewell/trace-mapping@0.3.31':
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.6.0
|
||||||
|
|
||||||
'@keyv/bigmap@1.3.1(keyv@5.6.0)':
|
'@keyv/bigmap@1.3.1(keyv@5.6.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1564,7 +1562,7 @@ snapshots:
|
|||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
pretty-format: 27.5.1
|
pretty-format: 27.5.1
|
||||||
|
|
||||||
'@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.0)':
|
'@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@adobe/css-tools': 4.5.0
|
'@adobe/css-tools': 4.5.0
|
||||||
'@testing-library/dom': 10.4.1
|
'@testing-library/dom': 10.4.1
|
||||||
@ -1574,7 +1572,7 @@ snapshots:
|
|||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
redent: 3.0.0
|
redent: 3.0.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vitest: 5.0.0(@types/node@26.5.1)(@vitest/coverage-v8@5.0.0)(jsdom@30.0.1)(vite@8.2.2(@types/node@26.5.1))
|
vitest: 5.0.1(@types/node@26.5.1)(@vitest/coverage-v8@5.0.1)(jsdom@30.0.1)(vite@8.2.2(@types/node@26.5.1))
|
||||||
|
|
||||||
'@testing-library/react@16.3.3(@testing-library/dom@10.4.1)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
|
'@testing-library/react@16.3.3(@testing-library/dom@10.4.1)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -1708,7 +1706,7 @@ snapshots:
|
|||||||
'@typescript-eslint/types': 8.70.0
|
'@typescript-eslint/types': 8.70.0
|
||||||
eslint-visitor-keys: 5.0.1
|
eslint-visitor-keys: 5.0.1
|
||||||
|
|
||||||
'@vitest/coverage-v8@5.0.0(vitest@5.0.0)':
|
'@vitest/coverage-v8@5.0.1(vitest@5.0.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@bcoe/v8-coverage': 1.0.2
|
'@bcoe/v8-coverage': 1.0.2
|
||||||
'@vitest/istanbul-lib-coverage': 1.0.1
|
'@vitest/istanbul-lib-coverage': 1.0.1
|
||||||
@ -1718,7 +1716,7 @@ snapshots:
|
|||||||
obug: 2.1.4
|
obug: 2.1.4
|
||||||
std-env: 4.2.0
|
std-env: 4.2.0
|
||||||
tinyrainbow: 3.1.1
|
tinyrainbow: 3.1.1
|
||||||
vitest: 5.0.0(@types/node@26.5.1)(@vitest/coverage-v8@5.0.0)(jsdom@30.0.1)(vite@8.2.2(@types/node@26.5.1))
|
vitest: 5.0.1(@types/node@26.5.1)(@vitest/coverage-v8@5.0.1)(jsdom@30.0.1)(vite@8.2.2(@types/node@26.5.1))
|
||||||
|
|
||||||
'@vitest/istanbul-lib-coverage@1.0.1': {}
|
'@vitest/istanbul-lib-coverage@1.0.1': {}
|
||||||
|
|
||||||
@ -1726,16 +1724,16 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/istanbul-lib-coverage': 1.0.1
|
'@vitest/istanbul-lib-coverage': 1.0.1
|
||||||
|
|
||||||
'@vitest/mocker@5.0.0(vite@8.2.2(@types/node@26.5.1))':
|
'@vitest/mocker@5.0.1(vite@8.2.2(@types/node@26.5.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/trace-mapping': 0.3.31
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
'@vitest/spy': 5.0.0
|
'@vitest/spy': 5.0.1
|
||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
magic-string: 1.3.1
|
magic-string: 1.3.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vite: 8.2.2(@types/node@26.5.1)
|
vite: 8.2.2(@types/node@26.5.1)
|
||||||
|
|
||||||
'@vitest/spy@5.0.0': {}
|
'@vitest/spy@5.0.1': {}
|
||||||
|
|
||||||
acorn-jsx@5.3.2(acorn@8.18.0):
|
acorn-jsx@5.3.2(acorn@8.18.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -2283,10 +2281,10 @@ snapshots:
|
|||||||
'@types/node': 26.5.1
|
'@types/node': 26.5.1
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
|
||||||
vitest@5.0.0(@types/node@26.5.1)(@vitest/coverage-v8@5.0.0)(jsdom@30.0.1)(vite@8.2.2(@types/node@26.5.1)):
|
vitest@5.0.1(@types/node@26.5.1)(@vitest/coverage-v8@5.0.1)(jsdom@30.0.1)(vite@8.2.2(@types/node@26.5.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/chai': 5.2.3
|
'@types/chai': 5.2.3
|
||||||
'@vitest/mocker': 5.0.0(vite@8.2.2(@types/node@26.5.1))
|
'@vitest/mocker': 5.0.1(vite@8.2.2(@types/node@26.5.1))
|
||||||
chai: 6.2.2
|
chai: 6.2.2
|
||||||
es-module-lexer: 2.3.2
|
es-module-lexer: 2.3.2
|
||||||
expect-type: 1.4.0
|
expect-type: 1.4.0
|
||||||
@ -2301,7 +2299,7 @@ snapshots:
|
|||||||
why-is-node-running: 2.3.0
|
why-is-node-running: 2.3.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 26.5.1
|
'@types/node': 26.5.1
|
||||||
'@vitest/coverage-v8': 5.0.0(vitest@5.0.0)
|
'@vitest/coverage-v8': 5.0.1(vitest@5.0.1)
|
||||||
jsdom: 30.0.1
|
jsdom: 30.0.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- msw
|
- msw
|
||||||
|
|||||||
@ -5,5 +5,6 @@
|
|||||||
* `import "@kuhyx/web-ui/tokens.css";`
|
* `import "@kuhyx/web-ui/tokens.css";`
|
||||||
*/
|
*/
|
||||||
export { clamp01, fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.ts";
|
export { clamp01, fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.ts";
|
||||||
export { RangeSlider, steppedValue, type RangeSliderProps } from "./range-slider.tsx";
|
export { RangeSlider, type RangeSliderProps } from "./range-slider.tsx";
|
||||||
|
export { keyTarget, steppedValue } from "./stepped-value.ts";
|
||||||
export { fuzzyMatch } from "./text.ts";
|
export { fuzzyMatch } from "./text.ts";
|
||||||
|
|||||||
@ -55,8 +55,7 @@ export function quantileValue(sorted: readonly number[], f: number): number {
|
|||||||
*/
|
*/
|
||||||
export function valueQuantile(sorted: readonly number[], value: number): number {
|
export function valueQuantile(sorted: readonly number[], value: number): number {
|
||||||
const n = sorted.length;
|
const n = sorted.length;
|
||||||
if (n <= 1) return 0;
|
if ((n <= 1) || (value <= nth(sorted, 0))) return 0;
|
||||||
if (value <= nth(sorted, 0)) return 0;
|
|
||||||
if (value >= nth(sorted, n - 1)) return 1;
|
if (value >= nth(sorted, n - 1)) return 1;
|
||||||
// value strictly inside the range, so there is an index hi >= 1 with
|
// value strictly inside the range, so there is an index hi >= 1 with
|
||||||
// sorted[hi] >= value and sorted[hi - 1] < value.
|
// sorted[hi] >= value and sorted[hi - 1] < value.
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { fireEvent, render, screen } from "@testing-library/react";
|
import { fireEvent, render, screen } from "@testing-library/react";
|
||||||
import { describe, expect, it, vi } from "vitest";
|
import { describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
import { RangeSlider, steppedValue } from "./range-slider.tsx";
|
import { RangeSlider } from "./range-slider.tsx";
|
||||||
|
|
||||||
/** Ten evenly spaced values, so a quantile fraction maps to a predictable value. */
|
/** Ten evenly spaced values, so a quantile fraction maps to a predictable value. */
|
||||||
const VALUES = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90];
|
const VALUES = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90];
|
||||||
@ -29,63 +29,6 @@ function thumbs(): HTMLElement[] {
|
|||||||
return screen.getAllByRole("slider");
|
return screen.getAllByRole("slider");
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("steppedValue", () => {
|
|
||||||
it("advances one sample at a time", () => {
|
|
||||||
expect(steppedValue(VALUES, 30, 1)).toBe(40);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("moves backwards for a negative delta", () => {
|
|
||||||
expect(steppedValue(VALUES, 30, -1)).toBe(20);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("clamps at the top", () => {
|
|
||||||
expect(steppedValue(VALUES, 90, 5)).toBe(90);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("clamps at the bottom", () => {
|
|
||||||
expect(steppedValue(VALUES, 0, -5)).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("rounds a between-samples value to a real sample", () => {
|
|
||||||
expect(steppedValue(VALUES, 34, 1)).toBe(40);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns the current sample for a zero delta", () => {
|
|
||||||
expect(steppedValue(VALUES, 30, 0)).toBe(30);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("on a lumpy distribution", () => {
|
|
||||||
// The shape that actually broke in the browser: awesome-mcp-explorer's
|
|
||||||
// star counts hold ~1500 duplicate zeros, so an index step inside the run
|
|
||||||
// moved the index but not the value, and the arrow key looked dead.
|
|
||||||
const LUMPY = [...Array.from({ length: 50 }, () => 0), 5, 5, 5, 100, 5000];
|
|
||||||
|
|
||||||
it("escapes a run of duplicates instead of stalling", () => {
|
|
||||||
expect(steppedValue(LUMPY, 0, 1)).toBe(5);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("keeps stepping past the second run", () => {
|
|
||||||
expect(steppedValue(LUMPY, 5, 1)).toBe(100);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("steps back out of a run", () => {
|
|
||||||
expect(steppedValue(LUMPY, 5, -1)).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("counts distinct values for a multi-step jump", () => {
|
|
||||||
expect(steppedValue(LUMPY, 0, 2)).toBe(100);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("clamps at the top rather than running off the end", () => {
|
|
||||||
expect(steppedValue(LUMPY, 5000, 1)).toBe(5000);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("clamps at the bottom", () => {
|
|
||||||
expect(steppedValue(LUMPY, 0, -1)).toBe(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("RangeSlider", () => {
|
describe("RangeSlider", () => {
|
||||||
it("renders nothing when there is nothing to range over", () => {
|
it("renders nothing when there is nothing to range over", () => {
|
||||||
const { container } = render(<RangeSlider hi={1} lo={1} onChange={vi.fn()} values={[1]} />);
|
const { container } = render(<RangeSlider hi={1} lo={1} onChange={vi.fn()} values={[1]} />);
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
import { fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.ts";
|
import { fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.ts";
|
||||||
|
import { keyTarget } from "./stepped-value.ts";
|
||||||
|
|
||||||
export interface RangeSliderProps {
|
export interface RangeSliderProps {
|
||||||
/**
|
/**
|
||||||
@ -44,40 +45,6 @@ export interface RangeSliderProps {
|
|||||||
|
|
||||||
type Thumb = "hi" | "lo";
|
type Thumb = "hi" | "lo";
|
||||||
|
|
||||||
/**
|
|
||||||
* Steps one thumb by `delta` positions through the distribution. Pure, so the
|
|
||||||
* keyboard contract is testable without layout.
|
|
||||||
*
|
|
||||||
* Steps to the next *distinct* value rather than the next index. Real
|
|
||||||
* distributions are lumpy -- awesome-mcp-explorer's star counts hold ~1500
|
|
||||||
* duplicate zeros -- and an index step inside a run of equal values changes the
|
|
||||||
* index while leaving the value (and therefore the thumb, and the filter)
|
|
||||||
* exactly where it was. That reads as a dead arrow key.
|
|
||||||
*/
|
|
||||||
export function steppedValue(
|
|
||||||
values: readonly number[],
|
|
||||||
current: number,
|
|
||||||
delta: number,
|
|
||||||
): number {
|
|
||||||
const last = values.length - 1;
|
|
||||||
// Round to a real sample index so a thumb sitting between two samples still
|
|
||||||
// advances rather than stalling on a fractional step.
|
|
||||||
const index = Math.round(valueQuantile(values, current) * last);
|
|
||||||
const direction = Math.sign(delta);
|
|
||||||
if (direction === 0) return nth(values, index);
|
|
||||||
|
|
||||||
let cursor = index;
|
|
||||||
for (let taken = 0; taken < Math.abs(delta); taken++) {
|
|
||||||
let next = cursor + direction;
|
|
||||||
while (next >= 0 && next <= last && nth(values, next) === nth(values, cursor)) {
|
|
||||||
next += direction;
|
|
||||||
}
|
|
||||||
if (next < 0 || next > last) break;
|
|
||||||
cursor = next;
|
|
||||||
}
|
|
||||||
return nth(values, cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function RangeSlider({
|
export function RangeSlider({
|
||||||
format,
|
format,
|
||||||
hi,
|
hi,
|
||||||
@ -86,7 +53,7 @@ export function RangeSlider({
|
|||||||
onChange,
|
onChange,
|
||||||
values,
|
values,
|
||||||
}: RangeSliderProps): null | React.JSX.Element {
|
}: RangeSliderProps): null | React.JSX.Element {
|
||||||
const [drag, setDrag] = useState<Thumb | null>(null);
|
const [drag, setDrag] = useState<null | Thumb>(null);
|
||||||
|
|
||||||
const apply = useCallback(
|
const apply = useCallback(
|
||||||
(thumb: Thumb, value: number): void => {
|
(thumb: Thumb, value: number): void => {
|
||||||
@ -100,29 +67,20 @@ export function RangeSlider({
|
|||||||
// handlers are bound to the track, so currentTarget *is* the track. A ref
|
// handlers are bound to the track, so currentTarget *is* the track. A ref
|
||||||
// would add a null branch that cannot happen once the element is mounted.
|
// would add a null branch that cannot happen once the element is mounted.
|
||||||
const valueAt = useCallback(
|
const valueAt = useCallback(
|
||||||
(track: HTMLElement, clientX: number): number =>
|
(track: HTMLElement, clientX: number): number => {
|
||||||
quantileValue(values, fractionFromPointer(track.getBoundingClientRect(), clientX)),
|
const fraction = fractionFromPointer(track.getBoundingClientRect(), clientX);
|
||||||
|
return quantileValue(values, fraction);
|
||||||
|
},
|
||||||
[values],
|
[values],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onKeyDown = useCallback(
|
const onKeyDown = useCallback(
|
||||||
(thumb: Thumb, event: React.KeyboardEvent): void => {
|
(thumb: Thumb, event: React.KeyboardEvent): void => {
|
||||||
const current = thumb === "lo" ? lo : hi;
|
const current = thumb === "lo" ? lo : hi;
|
||||||
const step = (delta: number): void => {
|
const target = keyTarget(event.key, values, current);
|
||||||
event.preventDefault();
|
if (target === undefined) return;
|
||||||
apply(thumb, steppedValue(values, current, delta));
|
event.preventDefault();
|
||||||
};
|
apply(thumb, target);
|
||||||
if (event.key === "ArrowLeft" || event.key === "ArrowDown") step(-1);
|
|
||||||
else if (event.key === "ArrowRight" || event.key === "ArrowUp") step(1);
|
|
||||||
else if (event.key === "PageDown") step(-10);
|
|
||||||
else if (event.key === "PageUp") step(10);
|
|
||||||
else if (event.key === "Home") {
|
|
||||||
event.preventDefault();
|
|
||||||
apply(thumb, nth(values, 0));
|
|
||||||
} else if (event.key === "End") {
|
|
||||||
event.preventDefault();
|
|
||||||
apply(thumb, nth(values, values.length - 1));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[apply, hi, lo, values],
|
[apply, hi, lo, values],
|
||||||
);
|
);
|
||||||
@ -136,19 +94,21 @@ export function RangeSlider({
|
|||||||
const hiFraction = valueQuantile(values, hi) * 100;
|
const hiFraction = valueQuantile(values, hi) * 100;
|
||||||
const name = label ?? "Range";
|
const name = label ?? "Range";
|
||||||
|
|
||||||
const thumbProps = (thumb: Thumb): React.ComponentProps<"button"> => ({
|
const thumbProps = (thumb: Thumb): React.ComponentProps<"button"> => {
|
||||||
"aria-valuemax": highest,
|
return {
|
||||||
"aria-valuemin": lowest,
|
"aria-valuemax": highest,
|
||||||
"aria-valuenow": thumb === "lo" ? lo : hi,
|
"aria-valuemin": lowest,
|
||||||
className: `slider-thumb slider-${thumb}`,
|
"aria-valuenow": thumb === "lo" ? lo : hi,
|
||||||
onKeyDown: (event): void => {
|
className: `slider-thumb slider-${thumb}`,
|
||||||
onKeyDown(thumb, event);
|
onKeyDown: (event): void => {
|
||||||
},
|
onKeyDown(thumb, event);
|
||||||
role: "slider",
|
},
|
||||||
style: { left: `${String(thumb === "lo" ? loFraction : hiFraction)}%` },
|
role: "slider",
|
||||||
tabIndex: 0,
|
style: { left: `${String(thumb === "lo" ? loFraction : hiFraction)}%` },
|
||||||
type: "button",
|
tabIndex: 0,
|
||||||
});
|
type: "button",
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="slider">
|
<div className="slider">
|
||||||
|
|||||||
79
web_ui/src/stepped-value.test.ts
Normal file
79
web_ui/src/stepped-value.test.ts
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { keyTarget, steppedValue } from "./stepped-value.ts";
|
||||||
|
|
||||||
|
/** Ten evenly spaced values, so a quantile fraction maps to a predictable value. */
|
||||||
|
const VALUES = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90];
|
||||||
|
|
||||||
|
describe("keyTarget", () => {
|
||||||
|
it("leaves keys the slider does not own to the browser", () => {
|
||||||
|
expect(keyTarget("Tab", VALUES, 30)).toBeUndefined();
|
||||||
|
expect(keyTarget("a", VALUES, 30)).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("maps every owned key onto the distribution", () => {
|
||||||
|
expect(keyTarget("ArrowLeft", VALUES, 30)).toBe(20);
|
||||||
|
expect(keyTarget("ArrowDown", VALUES, 30)).toBe(20);
|
||||||
|
expect(keyTarget("ArrowRight", VALUES, 30)).toBe(40);
|
||||||
|
expect(keyTarget("ArrowUp", VALUES, 30)).toBe(40);
|
||||||
|
expect(keyTarget("Home", VALUES, 30)).toBe(0);
|
||||||
|
expect(keyTarget("End", VALUES, 30)).toBe(90);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("steppedValue", () => {
|
||||||
|
it("advances one sample at a time", () => {
|
||||||
|
expect(steppedValue(VALUES, 30, 1)).toBe(40);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("moves backwards for a negative delta", () => {
|
||||||
|
expect(steppedValue(VALUES, 30, -1)).toBe(20);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("clamps at the top", () => {
|
||||||
|
expect(steppedValue(VALUES, 90, 5)).toBe(90);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("clamps at the bottom", () => {
|
||||||
|
expect(steppedValue(VALUES, 0, -5)).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rounds a between-samples value to a real sample", () => {
|
||||||
|
expect(steppedValue(VALUES, 34, 1)).toBe(40);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns the current sample for a zero delta", () => {
|
||||||
|
expect(steppedValue(VALUES, 30, 0)).toBe(30);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("on a lumpy distribution", () => {
|
||||||
|
// The shape that actually broke in the browser: awesome-mcp-explorer's
|
||||||
|
// star counts hold ~1500 duplicate zeros, so an index step inside the run
|
||||||
|
// moved the index but not the value, and the arrow key looked dead.
|
||||||
|
const LUMPY = [...Array.from({ length: 50 }, () => 0), 5, 5, 5, 100, 5000];
|
||||||
|
|
||||||
|
it("escapes a run of duplicates instead of stalling", () => {
|
||||||
|
expect(steppedValue(LUMPY, 0, 1)).toBe(5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps stepping past the second run", () => {
|
||||||
|
expect(steppedValue(LUMPY, 5, 1)).toBe(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("steps back out of a run", () => {
|
||||||
|
expect(steppedValue(LUMPY, 5, -1)).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("counts distinct values for a multi-step jump", () => {
|
||||||
|
expect(steppedValue(LUMPY, 0, 2)).toBe(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("clamps at the top rather than running off the end", () => {
|
||||||
|
expect(steppedValue(LUMPY, 5000, 1)).toBe(5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("clamps at the bottom", () => {
|
||||||
|
expect(steppedValue(LUMPY, 0, -1)).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
78
web_ui/src/stepped-value.ts
Normal file
78
web_ui/src/stepped-value.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* The keyboard contract of the range slider, kept pure and in its own module
|
||||||
|
* so range-slider.tsx exports only the component (react-refresh needs that
|
||||||
|
* for HMR to keep working) and the contract is testable without layout.
|
||||||
|
*/
|
||||||
|
import { nth, valueQuantile } from "./quantile.ts";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Steps one thumb by `delta` positions through the distribution. Pure, so the
|
||||||
|
* keyboard contract is testable without layout.
|
||||||
|
*
|
||||||
|
* Steps to the next *distinct* value rather than the next index. Real
|
||||||
|
* distributions are lumpy -- awesome-mcp-explorer's star counts hold ~1500
|
||||||
|
* duplicate zeros -- and an index step inside a run of equal values changes the
|
||||||
|
* index while leaving the value (and therefore the thumb, and the filter)
|
||||||
|
* exactly where it was. That reads as a dead arrow key.
|
||||||
|
*/
|
||||||
|
export function steppedValue(
|
||||||
|
values: readonly number[],
|
||||||
|
current: number,
|
||||||
|
delta: number,
|
||||||
|
): number {
|
||||||
|
const last = values.length - 1;
|
||||||
|
// Round to a real sample index so a thumb sitting between two samples still
|
||||||
|
// advances rather than stalling on a fractional step.
|
||||||
|
const index = Math.round(valueQuantile(values, current) * last);
|
||||||
|
const direction = Math.sign(delta);
|
||||||
|
if (direction === 0) return nth(values, index);
|
||||||
|
|
||||||
|
let cursor = index;
|
||||||
|
for (let taken = 0; taken < Math.abs(delta); taken++) {
|
||||||
|
let next = cursor + direction;
|
||||||
|
while (next >= 0 && next <= last && nth(values, next) === nth(values, cursor)) {
|
||||||
|
next += direction;
|
||||||
|
}
|
||||||
|
if (next < 0 || next > last) break;
|
||||||
|
cursor = next;
|
||||||
|
}
|
||||||
|
return nth(values, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value a thumb at `current` moves to for a key, or `undefined` when the
|
||||||
|
* key is not one the slider handles (so the event is left to the browser).
|
||||||
|
* Arrow keys step one distinct value, Page keys ten, Home/End jump to the
|
||||||
|
* bounds.
|
||||||
|
*/
|
||||||
|
export function keyTarget(
|
||||||
|
key: string,
|
||||||
|
values: readonly number[],
|
||||||
|
current: number,
|
||||||
|
): number | undefined {
|
||||||
|
switch (key) {
|
||||||
|
case "ArrowDown":
|
||||||
|
case "ArrowLeft": {
|
||||||
|
return steppedValue(values, current, -1);
|
||||||
|
}
|
||||||
|
case "ArrowRight":
|
||||||
|
case "ArrowUp": {
|
||||||
|
return steppedValue(values, current, 1);
|
||||||
|
}
|
||||||
|
case "End": {
|
||||||
|
return nth(values, values.length - 1);
|
||||||
|
}
|
||||||
|
case "Home": {
|
||||||
|
return nth(values, 0);
|
||||||
|
}
|
||||||
|
case "PageDown": {
|
||||||
|
return steppedValue(values, current, -10);
|
||||||
|
}
|
||||||
|
case "PageUp": {
|
||||||
|
return steppedValue(values, current, 10);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,7 +13,7 @@ const TRACK_WIDTH = 1000;
|
|||||||
if (hasDom) {
|
if (hasDom) {
|
||||||
Object.defineProperty(Element.prototype, "getBoundingClientRect", {
|
Object.defineProperty(Element.prototype, "getBoundingClientRect", {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
value(): DOMRect {
|
value: (): DOMRect => {
|
||||||
return {
|
return {
|
||||||
bottom: 20,
|
bottom: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
// @vitest-environment node
|
// @vitest-environment node
|
||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
|
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
const css = readFileSync(new URL("tokens.css", import.meta.url), "utf8");
|
const css = readFileSync(new URL("tokens.css", import.meta.url), "utf8");
|
||||||
@ -13,9 +12,10 @@ const css = readFileSync(new URL("tokens.css", import.meta.url), "utf8");
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function declared(name: string): string[] {
|
function declared(name: string): string[] {
|
||||||
return [...css.matchAll(new RegExp(`--${name}:\\s*([^;]+);`, "g"))].map((m) =>
|
return css
|
||||||
(m[1] ?? "").trim(),
|
.matchAll(new RegExp(String.raw`--${name}:\s*([^;]+);`, "g"))
|
||||||
);
|
.map((m) => (m[1] ?? "").trim())
|
||||||
|
.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("tokens.css", () => {
|
describe("tokens.css", () => {
|
||||||
@ -124,7 +124,7 @@ describe("tokens.css", () => {
|
|||||||
const block = /@media \(prefers-reduced-motion: reduce\)\s*\{([\s\S]*?)\n\}/.exec(css)?.[1];
|
const block = /@media \(prefers-reduced-motion: reduce\)\s*\{([\s\S]*?)\n\}/.exec(css)?.[1];
|
||||||
expect(block).toBeDefined();
|
expect(block).toBeDefined();
|
||||||
for (const step of ["fast", "base", "slow"]) {
|
for (const step of ["fast", "base", "slow"]) {
|
||||||
expect(block).toMatch(new RegExp(`--duration-${step}:\\s*0ms;`));
|
expect(block).toMatch(new RegExp(String.raw`--duration-${step}:\s*0ms;`));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
{
|
{
|
||||||
|
// Strictness comes from the shared base; only output/lib options live here.
|
||||||
|
"extends": "@kuhyx/ts-config/tsconfig",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2023",
|
"target": "ES2023",
|
||||||
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||||
@ -7,20 +9,6 @@
|
|||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"types": ["vitest/globals"],
|
"types": ["vitest/globals"],
|
||||||
|
|
||||||
/* Strictness: everything on, matching both consumers so a file that
|
|
||||||
compiles here compiles there. */
|
|
||||||
"strict": true,
|
|
||||||
"noUncheckedIndexedAccess": true,
|
|
||||||
"noImplicitOverride": true,
|
|
||||||
"noImplicitReturns": true,
|
|
||||||
"noFallthroughCasesInSwitch": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"exactOptionalPropertyTypes": true,
|
|
||||||
"useUnknownInCatchVariables": true,
|
|
||||||
"verbatimModuleSyntax": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"erasableSyntaxOnly": true,
|
|
||||||
|
|
||||||
/* This package ships a prebuilt dist/ (ESM + .d.ts) because consumers use
|
/* This package ships a prebuilt dist/ (ESM + .d.ts) because consumers use
|
||||||
Vite, which does not transpile dependencies. So unlike the consumers,
|
Vite, which does not transpile dependencies. So unlike the consumers,
|
||||||
@ -31,10 +19,7 @@
|
|||||||
"declarationMap": true,
|
"declarationMap": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"rootDir": "src",
|
"rootDir": "src"
|
||||||
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"forceConsistentCasingInFileNames": true
|
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src"],
|
||||||
"exclude": ["src/**/*.test.ts", "src/**/*.test.tsx", "src/test"]
|
"exclude": ["src/**/*.test.ts", "src/**/*.test.tsx", "src/test"]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user