diff --git a/.github/workflows/web-ui-tests.yml b/.github/workflows/web-ui-tests.yml new file mode 100644 index 0000000..a22a5d4 --- /dev/null +++ b/.github/workflows/web-ui-tests.yml @@ -0,0 +1,52 @@ +name: web_ui tests + +on: + push: + branches: [main] + paths: ['web_ui/**'] + pull_request: + branches: [main] + paths: ['web_ui/**'] + +jobs: + test: + runs-on: ubuntu-latest + defaults: + run: + working-directory: web_ui + + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 10 + + - uses: actions/setup-node@v4 + with: + node-version: '24' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Lint + run: pnpm lint + + - name: Run tests with the 100% coverage gate + run: pnpm coverage + + # The tag ships a prebuilt dist/ because Vite does not transpile + # dependencies. A committed dist/ that does not match src/ would ship + # stale code to every consumer with no error anywhere, so rebuild and + # fail if the result differs from what is checked in. + - name: dist/ is in sync with src/ + run: | + pnpm build + if ! git diff --exit-code -- dist; then + echo "::error::dist/ is stale — run 'pnpm build' in web_ui and commit the result." + exit 1 + fi + + - name: Categorical ramp still passes its constraints + working-directory: . + run: python3 unified-design-system/scripts/ramp_check.py diff --git a/web_ui/.pre-commit-config.yaml b/web_ui/.pre-commit-config.yaml new file mode 100644 index 0000000..4197518 --- /dev/null +++ b/web_ui/.pre-commit-config.yaml @@ -0,0 +1,67 @@ +# Pre-commit Configuration for web_ui +# Install: pre-commit install && pre-commit install --hook-type pre-push +# Run: pre-commit run --config web_ui/.pre-commit-config.yaml --all-files + +# NOTE: this subproject lives inside the ~/utils monorepo, whose git root is +# one level up. pre-commit always runs hooks from the git root, so every path +# below is written relative to THAT, not to this directory, and the top-level +# `files` key keeps these hooks off the sibling subprojects. CI invokes this +# config exactly the same way. Mirrors design_system/.pre-commit-config.yaml. +files: ^web_ui/ +# dist/ is generated by tsc and committed for consumers. The whitespace hooks +# would "fix" it, the next build would revert them, and the dist-fresh hook +# would fail forever -- so formatting hooks must not see it. +exclude: ^web_ui/dist/ + +default_stages: [pre-commit] +fail_fast: false + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] + - id: end-of-file-fixer + - id: check-yaml + - id: check-json + - id: check-merge-conflict + - id: mixed-line-ending + args: [--fix=lf] + + - repo: local + hooks: + - id: subproject-scope + name: subproject scope regex still matches + entry: scripts/check_subproject_scope.sh web_ui + language: script + # always_run so the top-level `files` filter cannot skip the one hook + # whose job is to notice that filter has stopped matching anything. + always_run: true + pass_filenames: false + + - id: web-ui-lint + name: tsc --noEmit && eslint + entry: bash -c 'cd web_ui && pnpm lint' + language: system + pass_filenames: false + + - id: web-ui-dist-fresh + name: committed dist/ matches src/ + # The tag ships a prebuilt dist/ (Vite does not transpile deps), so a + # stale dist/ ships old code to every consumer with no error anywhere. + entry: >- + bash -c 'cd web_ui && pnpm build && + git diff --exit-code -- dist || + { echo "dist/ is stale -- pnpm build in web_ui and commit it"; exit 1; }' + language: system + pass_filenames: false + require_serial: true + + - id: web-ui-test-coverage + name: vitest with the 100% coverage gate + entry: bash -c 'cd web_ui && pnpm coverage' + language: system + pass_filenames: false + require_serial: true + stages: [pre-push] diff --git a/web_ui/dist/index.d.ts b/web_ui/dist/index.d.ts index 698bcea..e846cfb 100644 --- a/web_ui/dist/index.d.ts +++ b/web_ui/dist/index.d.ts @@ -7,4 +7,4 @@ export { clamp01, fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.ts"; export { RangeSlider, steppedValue, type RangeSliderProps } from "./range-slider.tsx"; export { fuzzyMatch } from "./text.ts"; -//# sourceMappingURL=index.d.ts.map \ No newline at end of file +//# sourceMappingURL=index.d.ts.map diff --git a/web_ui/dist/index.d.ts.map b/web_ui/dist/index.d.ts.map index 6f893b9..ee006c2 100644 --- a/web_ui/dist/index.d.ts.map +++ b/web_ui/dist/index.d.ts.map @@ -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"} \ No newline at end of file +{"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"} diff --git a/web_ui/dist/index.js b/web_ui/dist/index.js index 8afe078..a1ba36a 100644 --- a/web_ui/dist/index.js +++ b/web_ui/dist/index.js @@ -7,4 +7,4 @@ export { clamp01, fractionFromPointer, nth, quantileValue, valueQuantile } from "./quantile.js"; export { RangeSlider, steppedValue } from "./range-slider.js"; export { fuzzyMatch } from "./text.js"; -//# sourceMappingURL=index.js.map \ No newline at end of file +//# sourceMappingURL=index.js.map diff --git a/web_ui/dist/index.js.map b/web_ui/dist/index.js.map index 9eac3c7..05cae80 100644 --- a/web_ui/dist/index.js.map +++ b/web_ui/dist/index.js.map @@ -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"} \ No newline at end of file +{"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"} diff --git a/web_ui/dist/quantile.d.ts b/web_ui/dist/quantile.d.ts index 88e517f..0c6e512 100644 --- a/web_ui/dist/quantile.d.ts +++ b/web_ui/dist/quantile.d.ts @@ -40,4 +40,4 @@ export declare function valueQuantile(sorted: readonly number[], value: number): * which jsdom does not implement. */ export declare function fractionFromPointer(rect: DOMRect, clientX: number): number; -//# sourceMappingURL=quantile.d.ts.map \ No newline at end of file +//# sourceMappingURL=quantile.d.ts.map diff --git a/web_ui/dist/quantile.d.ts.map b/web_ui/dist/quantile.d.ts.map index a9122bd..580786b 100644 --- a/web_ui/dist/quantile.d.ts.map +++ b/web_ui/dist/quantile.d.ts.map @@ -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"} \ No newline at end of file +{"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"} diff --git a/web_ui/dist/quantile.js b/web_ui/dist/quantile.js index b41f2ac..7ff274a 100644 --- a/web_ui/dist/quantile.js +++ b/web_ui/dist/quantile.js @@ -19,7 +19,7 @@ export function nth(values, index) { const value = values[index]; if (value === undefined) { - throw new RangeError(`index ${index} out of range`); + throw new RangeError(`index ${String(index)} out of range`); } return value; } @@ -76,4 +76,4 @@ export function valueQuantile(sorted, value) { export function fractionFromPointer(rect, clientX) { return rect.width === 0 ? 0 : clamp01((clientX - rect.left) / rect.width); } -//# sourceMappingURL=quantile.js.map \ No newline at end of file +//# sourceMappingURL=quantile.js.map diff --git a/web_ui/dist/quantile.js.map b/web_ui/dist/quantile.js.map index 51c4e24..ce278d5 100644 --- a/web_ui/dist/quantile.js.map +++ b/web_ui/dist/quantile.js.map @@ -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,KAAK,eAAe,CAAC,CAAC;IACtD,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"} \ No newline at end of file +{"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"} diff --git a/web_ui/dist/range-slider.d.ts b/web_ui/dist/range-slider.d.ts index 0bf8b57..78554bc 100644 --- a/web_ui/dist/range-slider.d.ts +++ b/web_ui/dist/range-slider.d.ts @@ -28,4 +28,4 @@ export interface RangeSliderProps { */ 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; -//# sourceMappingURL=range-slider.d.ts.map \ No newline at end of file +//# sourceMappingURL=range-slider.d.ts.map diff --git a/web_ui/dist/range-slider.d.ts.map b/web_ui/dist/range-slider.d.ts.map index af3fcb5..3afb388 100644 --- a/web_ui/dist/range-slider.d.ts.map +++ b/web_ui/dist/range-slider.d.ts.map @@ -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"} \ No newline at end of file +{"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"} diff --git a/web_ui/dist/range-slider.js b/web_ui/dist/range-slider.js index 9e238d7..6fa7947 100644 --- a/web_ui/dist/range-slider.js +++ b/web_ui/dist/range-slider.js @@ -127,4 +127,4 @@ export function RangeSlider({ format, hi, label, lo, onChange, values, }) { event.currentTarget.releasePointerCapture(event.pointerId); }, children: [_jsx("div", { className: "slider-fill", style: { left: `${String(loFraction)}%`, width: `${String(hiFraction - loFraction)}%` } }), _jsx("button", { "aria-label": `${name} minimum`, ...thumbProps("lo") }), _jsx("button", { "aria-label": `${name} maximum`, ...thumbProps("hi") })] })] })); } -//# sourceMappingURL=range-slider.js.map \ No newline at end of file +//# sourceMappingURL=range-slider.js.map diff --git a/web_ui/dist/range-slider.js.map b/web_ui/dist/range-slider.js.map index 537c126..94ac921 100644 --- a/web_ui/dist/range-slider.js.map +++ b/web_ui/dist/range-slider.js.map @@ -1 +1 @@ -{"version":3,"file":"range-slider.js","sourceRoot":"","sources":["../src/range-slider.tsx"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"range-slider.js","sourceRoot":"","sources":["../src/range-slider.tsx"],"names":[],"mappings":"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"} diff --git a/web_ui/dist/text.d.ts b/web_ui/dist/text.d.ts index 8c5ee3e..81d1ff5 100644 --- a/web_ui/dist/text.d.ts +++ b/web_ui/dist/text.d.ts @@ -13,4 +13,4 @@ * the implementations were identical apart from identifier names. */ export declare function fuzzyMatch(query: string, target: string): boolean; -//# sourceMappingURL=text.d.ts.map \ No newline at end of file +//# sourceMappingURL=text.d.ts.map diff --git a/web_ui/dist/text.d.ts.map b/web_ui/dist/text.d.ts.map index 61b157b..0121649 100644 --- a/web_ui/dist/text.d.ts.map +++ b/web_ui/dist/text.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CASjE"} \ No newline at end of file +{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CASjE"} diff --git a/web_ui/dist/text.js b/web_ui/dist/text.js index 91f9794..bc2727d 100644 --- a/web_ui/dist/text.js +++ b/web_ui/dist/text.js @@ -24,4 +24,4 @@ export function fuzzyMatch(query, target) { } return index === q.length; } -//# sourceMappingURL=text.js.map \ No newline at end of file +//# sourceMappingURL=text.js.map diff --git a/web_ui/dist/text.js.map b/web_ui/dist/text.js.map index 9efdd79..e1fba52 100644 --- a/web_ui/dist/text.js.map +++ b/web_ui/dist/text.js.map @@ -1 +1 @@ -{"version":3,"file":"text.js","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,MAAc;IACtD,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC9B,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAC/B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,IAAI,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QAC/D,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC;YAAE,KAAK,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC;AAC5B,CAAC"} \ No newline at end of file +{"version":3,"file":"text.js","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,MAAc;IACtD,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC9B,MAAM,CAAC,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAC/B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,MAAM,IAAI,KAAK,GAAG,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QAC/D,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC;YAAE,KAAK,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC;AAC5B,CAAC"} diff --git a/web_ui/eslint.config.js b/web_ui/eslint.config.js new file mode 100644 index 0000000..2654444 --- /dev/null +++ b/web_ui/eslint.config.js @@ -0,0 +1,42 @@ +// Type-aware flat config for the shared component layer. +// +// A trimmed version of awesome-mcp-explorer's: typescript-eslint's +// *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( + // eslint.config.js itself is not in tsconfig.lint.json, so type-aware + // rules cannot run on it; linting the linter config buys nothing anyway. + { ignores: ["dist", "coverage", "eslint.config.js"] }, + { linterOptions: { reportUnusedDisableDirectives: "error" } }, + + js.configs.recommended, + ...tseslint.configs.strictTypeChecked, + ...tseslint.configs.stylisticTypeChecked, + + { + files: ["**/*.{ts,tsx}"], + languageOptions: { + parserOptions: { + project: ["./tsconfig.lint.json"], + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + // Every exported symbol here is consumed across a package boundary, so + // an explicit return type is documentation, not ceremony. + "@typescript-eslint/explicit-function-return-type": "error", + }, + }, + + { + // 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" }, + }, +); diff --git a/web_ui/package.json b/web_ui/package.json index f57e80b..fb5d060 100644 --- a/web_ui/package.json +++ b/web_ui/package.json @@ -25,7 +25,7 @@ }, "scripts": { "build": "tsc -b && cp src/tokens.css src/range-slider.css dist/", - "lint": "tsc --noEmit && eslint src", + "lint": "tsc --noEmit -p tsconfig.lint.json && eslint .", "test": "vitest run", "coverage": "vitest run --coverage" }, @@ -46,6 +46,7 @@ "react-dom": "^19.2.7", "typescript": "^6.0.3", "typescript-eslint": "^8.64.0", - "vitest": "^4.1.10" + "vitest": "^4.1.10", + "@types/node": "^26.1.1" } } diff --git a/web_ui/pnpm-lock.yaml b/web_ui/pnpm-lock.yaml index cd49620..5442a81 100644 --- a/web_ui/pnpm-lock.yaml +++ b/web_ui/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: '@testing-library/user-event': specifier: ^14.6.1 version: 14.6.4(@testing-library/dom@10.4.1) + '@types/node': + specifier: ^26.1.1 + version: 26.2.0 '@types/react': specifier: ^19.2.17 version: 19.2.18 @@ -49,7 +52,7 @@ importers: version: 8.67.0(eslint@10.8.1)(typescript@6.0.3) vitest: specifier: ^4.1.10 - version: 4.1.10(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.1) + version: 4.1.10(@types/node@26.2.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.1(@types/node@26.2.0)) packages: @@ -361,6 +364,9 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/node@26.2.0': + resolution: {integrity: sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==} + '@types/react-dom@19.2.4': resolution: {integrity: sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==} peerDependencies: @@ -1040,6 +1046,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + undici-types@8.3.0: + resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==} + undici@7.29.0: resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} engines: {node: '>=20.18.1'} @@ -1406,6 +1415,10 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/node@26.2.0': + dependencies: + undici-types: 8.3.0 + '@types/react-dom@19.2.4(@types/react@19.2.18)': dependencies: '@types/react': 19.2.18 @@ -1517,7 +1530,7 @@ snapshots: obug: 2.1.4 std-env: 4.2.0 tinyrainbow: 3.1.1 - vitest: 4.1.10(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.1) + vitest: 4.1.10(@types/node@26.2.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.1(@types/node@26.2.0)) '@vitest/expect@4.1.10': dependencies: @@ -1528,13 +1541,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.1 - '@vitest/mocker@4.1.10(vite@8.2.1)': + '@vitest/mocker@4.1.10(vite@8.2.1(@types/node@26.2.0))': dependencies: '@vitest/spy': 4.1.10 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.2.1 + vite: 8.2.1(@types/node@26.2.0) '@vitest/pretty-format@4.1.10': dependencies: @@ -2086,13 +2099,15 @@ snapshots: typescript@6.0.3: {} + undici-types@8.3.0: {} + undici@7.29.0: {} uri-js@4.4.1: dependencies: punycode: 2.3.1 - vite@8.2.1: + vite@8.2.1(@types/node@26.2.0): dependencies: lightningcss: 1.33.0 picomatch: 4.0.5 @@ -2100,12 +2115,13 @@ snapshots: rolldown: 1.2.4 tinyglobby: 0.2.17 optionalDependencies: + '@types/node': 26.2.0 fsevents: 2.3.3 - vitest@4.1.10(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.1): + vitest@4.1.10(@types/node@26.2.0)(@vitest/coverage-v8@4.1.10)(jsdom@29.1.1)(vite@8.2.1(@types/node@26.2.0)): dependencies: '@vitest/expect': 4.1.10 - '@vitest/mocker': 4.1.10(vite@8.2.1) + '@vitest/mocker': 4.1.10(vite@8.2.1(@types/node@26.2.0)) '@vitest/pretty-format': 4.1.10 '@vitest/runner': 4.1.10 '@vitest/snapshot': 4.1.10 @@ -2122,9 +2138,10 @@ snapshots: tinyexec: 1.3.0 tinyglobby: 0.2.17 tinyrainbow: 3.1.1 - vite: 8.2.1 + vite: 8.2.1(@types/node@26.2.0) why-is-node-running: 2.3.0 optionalDependencies: + '@types/node': 26.2.0 '@vitest/coverage-v8': 4.1.10(vitest@4.1.10) jsdom: 29.1.1 transitivePeerDependencies: diff --git a/web_ui/src/quantile.ts b/web_ui/src/quantile.ts index 72882ed..e23e371 100644 --- a/web_ui/src/quantile.ts +++ b/web_ui/src/quantile.ts @@ -20,7 +20,7 @@ export function nth(values: readonly number[], index: number): number { const value = values[index]; if (value === undefined) { - throw new RangeError(`index ${index} out of range`); + throw new RangeError(`index ${String(index)} out of range`); } return value; } diff --git a/web_ui/src/range-slider.test.tsx b/web_ui/src/range-slider.test.tsx index 57a770e..b1b5f69 100644 --- a/web_ui/src/range-slider.test.tsx +++ b/web_ui/src/range-slider.test.tsx @@ -136,7 +136,7 @@ describe("RangeSlider", () => { ["ArrowUp", 10], ])("%s steps the low thumb up", (key, expected) => { const { onChange } = renderSlider(); - fireEvent.keyDown(thumbs()[0] as HTMLElement, { key }); + fireEvent.keyDown(thumbs()[0]!, { key }); expect(onChange).toHaveBeenCalledWith(expected, 90); }); @@ -145,58 +145,61 @@ describe("RangeSlider", () => { ["ArrowDown", 80], ])("%s steps the high thumb down", (key, expected) => { const { onChange } = renderSlider(); - fireEvent.keyDown(thumbs()[1] as HTMLElement, { key }); + fireEvent.keyDown(thumbs()[1]!, { key }); expect(onChange).toHaveBeenCalledWith(0, expected); }); it("PageUp jumps ten samples", () => { const { onChange } = renderSlider({ lo: 0 }); - fireEvent.keyDown(thumbs()[0] as HTMLElement, { key: "PageUp" }); + fireEvent.keyDown(thumbs()[0]!, { key: "PageUp" }); expect(onChange).toHaveBeenCalledWith(90, 90); }); it("PageDown jumps ten samples down", () => { const { onChange } = renderSlider({ hi: 90 }); - fireEvent.keyDown(thumbs()[1] as HTMLElement, { key: "PageDown" }); + fireEvent.keyDown(thumbs()[1]!, { key: "PageDown" }); expect(onChange).toHaveBeenCalledWith(0, 0); }); it("Home sends a thumb to the floor", () => { const { onChange } = renderSlider({ lo: 50 }); - fireEvent.keyDown(thumbs()[0] as HTMLElement, { key: "Home" }); + fireEvent.keyDown(thumbs()[0]!, { key: "Home" }); expect(onChange).toHaveBeenCalledWith(0, 90); }); it("End sends a thumb to the ceiling", () => { const { onChange } = renderSlider({ hi: 50 }); - fireEvent.keyDown(thumbs()[1] as HTMLElement, { key: "End" }); + fireEvent.keyDown(thumbs()[1]!, { key: "End" }); expect(onChange).toHaveBeenCalledWith(0, 90); }); it("ignores keys it does not handle", () => { const { onChange } = renderSlider(); - fireEvent.keyDown(thumbs()[0] as HTMLElement, { key: "a" }); + fireEvent.keyDown(thumbs()[0]!, { key: "a" }); expect(onChange).not.toHaveBeenCalled(); }); it("does not let the low thumb cross the high one", () => { const { onChange } = renderSlider({ hi: 10, lo: 10 }); - fireEvent.keyDown(thumbs()[0] as HTMLElement, { key: "ArrowRight" }); + fireEvent.keyDown(thumbs()[0]!, { key: "ArrowRight" }); expect(onChange).toHaveBeenCalledWith(10, 10); }); it("does not let the high thumb cross the low one", () => { const { onChange } = renderSlider({ hi: 10, lo: 10 }); - fireEvent.keyDown(thumbs()[1] as HTMLElement, { key: "ArrowLeft" }); + fireEvent.keyDown(thumbs()[1]!, { key: "ArrowLeft" }); expect(onChange).toHaveBeenCalledWith(10, 10); }); }); describe("pointer", () => { function track(): HTMLElement { - // eslint-disable-next-line testing-library/no-node-access -- the track is - // presentational; there is no role or text to query it by. - return document.querySelector(".slider-track") as HTMLElement; + // Queried by class rather than by role: the track is presentational, so + // it has neither a role nor text to find it by. (The consumers run + // eslint-plugin-testing-library, which flags this; this package does not + // install that plugin, so a disable comment here would itself be an + // unknown-rule error.) + return document.querySelector(".slider-track")!; } it("grabs the nearer thumb when pressed anywhere on the track", () => { diff --git a/web_ui/tsconfig.lint.json b/web_ui/tsconfig.lint.json new file mode 100644 index 0000000..f131dba --- /dev/null +++ b/web_ui/tsconfig.lint.json @@ -0,0 +1,14 @@ +{ + // tsconfig.json deliberately excludes tests -- they must not land in the + // published dist/. Type-aware linting still needs them in a project, so this + // config widens the include for eslint (and `tsc --noEmit`) only. It emits + // nothing and clears rootDir, so it cannot affect the shipped build. + "extends": "./tsconfig.json", + "compilerOptions": { + "noEmit": true, + "rootDir": ".", + "types": ["vitest/globals", "node"] + }, + "include": ["src", "*.config.ts"], + "exclude": [] +}