chore(deps): drop four dependencies nothing imports

react-hook-form, @hookform/resolvers, next-themes and @vitejs/plugin-react
have no import anywhere in src/, scripts/, tests/, e2e/ or the build and
test configs; knip only stayed quiet because each sat on its ignore list.
Forms keep a controlled draft and validate with the shared Zod schemas,
and the theme bootstrap is hand-written. The ignore entries, the comments
that still named the form library, and the guideline text go with them.
This commit is contained in:
Marc-André Bombeck committed 2026-10-20 08:39:06 +02:00
1 parent 9b93247ae0
commit b50b5fcd21
8 files changed
+9 -168

No files matched your search

+3 -3
View File
@@ -132,7 +132,8 @@ helper text explaining why. Silent disabled buttons frustrate users.
### 2.2 Inputs and forms
We use `react-hook-form` + Zod schemas from `src/lib/validations/`.
Forms keep a controlled draft in component state and validate it with the
Zod schemas from `src/lib/validations/`; the server's schema is the authority.
Wrap inputs in `<label>` (visible) plus `aria-describedby` for helper text.
- **Text / number / email**: `<Input>`. Always set `autocomplete`. See §4.4.
@@ -425,8 +426,7 @@ control. Behavior:
### 4.6 Server actions and mutations
We use `react-hook-form` + TanStack Query mutations, never raw fetch
calls in components. Every mutation:
Mutations go through TanStack Query, never raw fetch calls in components. Every mutation:
1. Optimistically updates the cache with a rollback handler.
2. Toast on success ("Saved" — translated) and on error (with retry).
-4
View File
@@ -134,11 +134,7 @@
"@types/node",
"@types/react",
"@types/react-dom",
"@hookform/resolvers",
"react-hook-form",
"@prisma/client",
"next-themes",
"@vitejs/plugin-react",
"shadcn",
"tailwindcss",
"testcontainers",
-4
View File
@@ -58,7 +58,6 @@
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@hookform/resolvers": "^5.9.1",
"@modelcontextprotocol/sdk": "^1.32.1",
"@napi-rs/canvas": "1.0.11",
"@node-rs/argon2": "^2.2.2",
@@ -81,7 +80,6 @@
"lucide-react": "^1.56.0",
"mmdb-lib": "^3.0.3",
"next": "16.3.8",
"next-themes": "^0.4.6",
"nodemailer": "10.1.0",
"otpauth": "^9.5.2",
"p-limit": "^7.3.3",
@@ -93,7 +91,6 @@
"react": "19.3.0",
"react-day-picker": "^10.0.2",
"react-dom": "19.3.0",
"react-hook-form": "7.90.0",
"recharts": "^3.10.1",
"rrule": "^2.8.1",
"sax": "^1.6.1",
@@ -121,7 +118,6 @@
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"@types/web-push": "^3.6.4",
"@vitejs/plugin-react": "^6.1.2",
"@vitest/coverage-v8": "^5.0.4",
"ajv": "^8.20.0",
"eslint": "^9",
-150
View File
@@ -56,9 +56,6 @@ importers:
'@dnd-kit/utilities':
specifier: ^3.2.2
version: 3.2.2(react@19.3.0)
'@hookform/resolvers':
specifier: ^5.9.1
version: 5.9.1(@standard-schema/spec@1.1.0)(ajv-formats@2.1.1(ajv@8.20.0))(ajv@8.20.0)(effect@3.20.0)(react-hook-form@7.90.0(@types/react@19.3.0)(react@19.3.0))(valibot@1.4.2(typescript@6.0.3))(zod@4.6.7)
'@modelcontextprotocol/sdk':
specifier: ^1.32.1
version: 1.32.1(@cfworker/json-schema@4.1.1)(supports-color@7.2.0)(zod@4.6.7)
@@ -125,9 +122,6 @@ importers:
next:
specifier: 16.3.8
version: 16.3.8(@babel/core@7.29.7(supports-color@7.2.0))(@opentelemetry/api@1.9.1)(@playwright/test@1.64.0)(@types/node@26.6.5)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
next-themes:
specifier: ^0.4.6
version: 0.4.6(react-dom@19.3.0(react@19.3.0))(react@19.3.0)
nodemailer:
specifier: 10.1.0
version: 10.1.0
@@ -161,9 +155,6 @@ importers:
react-dom:
specifier: 19.3.0
version: 19.3.0(react@19.3.0)
react-hook-form:
specifier: 7.90.0
version: 7.90.0(@types/react@19.3.0)(react@19.3.0)
recharts:
specifier: ^3.10.1
version: 3.10.1(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react-is@16.13.1)(react@19.3.0)(redux@5.0.1)
@@ -240,9 +231,6 @@ importers:
'@types/web-push':
specifier: ^3.6.4
version: 3.6.4
'@vitejs/plugin-react':
specifier: ^6.1.2
version: 6.1.2(vite@8.1.5(@types/node@26.6.5)(jiti@2.7.0)(yaml@2.9.1))
'@vitest/coverage-v8':
specifier: ^5.0.4
version: 5.0.4(vitest@5.0.4)
@@ -683,84 +671,6 @@ packages:
peerDependencies:
hono: ^4.13.5
'@hookform/resolvers@5.9.1':
resolution: {integrity: sha512-7b7vsbraJxKgjVSA1Nur9tLwj539WGJUBLA7QNvXnFoT2pM5Z7G+6rlukk4B2/QrTZy6huRtH6wKeESPKuIr6w==}
peerDependencies:
'@sinclair/typebox': '>=0.25.24'
'@standard-schema/spec': ^1.0.0
'@typeschema/main': '>=0.13.7'
'@vinejs/vine': ^2.0.0 || ^3.0.0 || ^4.0.0
ajv: ^8.12.0
ajv-errors: ^3.0.0
ajv-formats: ^2.1.1
arktype: ^2.0.0
ata-validator: ^1.2.0
class-transformer: '>=0.4.0'
class-validator: '>=0.12.0'
computed-types: ^1.0.0
effect: ^3.10.3
fluentvalidation-ts: ^3.0.0
fp-ts: ^2.7.0
io-ts: ^2.0.0
joi: ^17.0.0 || ^18.0.0
nope-validator: '>=0.12.0'
react-hook-form: ^7.55.0
superstruct: '>=0.12.0'
typanion: ^3.3.2
valibot: ^1.4.2
vest: '>=6.0.0'
yup: ^1.0.0
zod: ^3.25.0 || ^4.0.0
peerDependenciesMeta:
'@sinclair/typebox':
optional: true
'@standard-schema/spec':
optional: true
'@typeschema/main':
optional: true
'@vinejs/vine':
optional: true
ajv:
optional: true
ajv-errors:
optional: true
ajv-formats:
optional: true
arktype:
optional: true
ata-validator:
optional: true
class-transformer:
optional: true
class-validator:
optional: true
computed-types:
optional: true
effect:
optional: true
fluentvalidation-ts:
optional: true
fp-ts:
optional: true
io-ts:
optional: true
joi:
optional: true
nope-validator:
optional: true
superstruct:
optional: true
typanion:
optional: true
valibot:
optional: true
vest:
optional: true
yup:
optional: true
zod:
optional: true
'@humanfs/core@0.19.2':
resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==}
engines: {node: '>=18.18.0'}
@@ -3166,22 +3076,6 @@ packages:
'@visx/vendor@4.0.0-alpha.0':
resolution: {integrity: sha512-6I+MuqXBcv9jnlcVowHoHKSdk9gXTWkHLKyqBwRWg7LY6A3Ei8SHfubpqGV5rBUSppxMq2RszPJUS6w+H0YgmQ==}
'@vitejs/plugin-react@6.1.2':
resolution: {integrity: sha512-fhJNGUdscQa4HkI0xFxwonWyhnVReCPDbXI7FH7jmzpnVCrFQI7PRrhWecO263610vOrs9tr2Y4xcf8uAdFxbw==}
engines: {node: ^20.19.0 || >=22.12.0}
peerDependencies:
'@rolldown/plugin-babel': ^0.1.7 || ^0.2.0
babel-plugin-react-compiler: ^1.0.0
oxc-transform-react: ^0.152.0
vite: ^8.0.0
peerDependenciesMeta:
'@rolldown/plugin-babel':
optional: true
babel-plugin-react-compiler:
optional: true
oxc-transform-react:
optional: true
'@vitest/coverage-v8@5.0.4':
resolution: {integrity: sha512-P5YcQY8Y6RmoE9xRXI38rT8pssbcubEzqtYTM2XQoxOXMDn04nRaTI1SM8qCl9/NfW3ag9GlzdSXu7IwO5Ft8A==}
peerDependencies:
@@ -5305,12 +5199,6 @@ packages:
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
engines: {node: '>= 0.6'}
next-themes@0.4.6:
resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
peerDependencies:
react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
next@16.3.8:
resolution: {integrity: sha512-U7QEZaTini6wKrb8A8hqLLqYQyCetegKjCpJOyxk642vWoMoU1x5PyZCJFvgYgiptA8xc5j/9xYlZFO7w9Sjmw==}
engines: {node: '>=20.9.0'}
@@ -5880,16 +5768,6 @@ packages:
peerDependencies:
react: ^19.3.0
react-hook-form@7.90.0:
resolution: {integrity: sha512-+NdG0FLzCPhFOp2NNxaUYLF9fyZhNjx9FTBBSYWF71/l6BBlmIc/j6xlp3DbaHWLJbIG7Zd8oznA19xJClU97w==}
engines: {node: '>=18.0.0'}
peerDependencies:
'@types/react': '*'
react: ^16.8.0 || ^17 || ^18 || ^19
peerDependenciesMeta:
'@types/react':
optional: true
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
@@ -7508,18 +7386,6 @@ snapshots:
dependencies:
hono: 4.13.7
'@hookform/resolvers@5.9.1(@standard-schema/spec@1.1.0)(ajv-formats@2.1.1(ajv@8.20.0))(ajv@8.20.0)(effect@3.20.0)(react-hook-form@7.90.0(@types/react@19.3.0)(react@19.3.0))(valibot@1.4.2(typescript@6.0.3))(zod@4.6.7)':
dependencies:
'@standard-schema/utils': 0.3.0
react-hook-form: 7.90.0(@types/react@19.3.0)(react@19.3.0)
optionalDependencies:
'@standard-schema/spec': 1.1.0
ajv: 8.20.0
ajv-formats: 2.1.1(ajv@8.20.0)
effect: 3.20.0
valibot: 1.4.2(typescript@6.0.3)
zod: 4.6.7
'@humanfs/core@0.19.2':
dependencies:
'@humanfs/types': 0.15.0
@@ -9848,11 +9714,6 @@ snapshots:
d3-time-format: 4.1.0
internmap: 2.0.3
'@vitejs/plugin-react@6.1.2(vite@8.1.5(@types/node@26.6.5)(jiti@2.7.0)(yaml@2.9.1))':
dependencies:
'@rolldown/pluginutils': 1.0.1
vite: 8.1.5(@types/node@26.6.5)(jiti@2.7.0)(yaml@2.9.1)
'@vitest/coverage-v8@5.0.4(vitest@5.0.4)':
dependencies:
'@bcoe/v8-coverage': 1.0.2
@@ -12056,11 +11917,6 @@ snapshots:
negotiator@1.0.0: {}
next-themes@0.4.6(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
dependencies:
react: 19.3.0
react-dom: 19.3.0(react@19.3.0)
next@16.3.8(@babel/core@7.29.7(supports-color@7.2.0))(@opentelemetry/api@1.9.1)(@playwright/test@1.64.0)(@types/node@26.6.5)(react-dom@19.3.0(react@19.3.0))(react@19.3.0):
dependencies:
'@next/env': 16.3.8
@@ -12676,12 +12532,6 @@ snapshots:
react: 19.3.0
scheduler: 0.28.0
react-hook-form@7.90.0(@types/react@19.3.0)(react@19.3.0):
dependencies:
react: 19.3.0
optionalDependencies:
'@types/react': 19.3.0
react-is@16.13.1: {}
react-redux@9.2.0(@types/react@19.3.0)(react@19.3.0)(redux@5.0.1):
+2 -3
View File
@@ -78,9 +78,8 @@ overrides:
# override is the only way through. It runs on the config-loading and CLI
# path, not under a request, but a red audit blocks the whole release train.
"deepmerge-ts@<8.0.0": "^8.0.0"
# CVE-2026-59952. Two copies arrive, neither of them ours to call: an
# optional peer of `@hookform/resolvers` (this app validates with zod) and
# prisma's local dev server. Mirrored for /opt/prisma-cli in the Dockerfile,
# CVE-2026-59952. The copy arrives through prisma's local dev server, not
# ours to call. Mirrored for /opt/prisma-cli in the Dockerfile,
# where the flagged 1.2.0 landed. 1.4.2 is the same major, so no consumer is
# dragged onto a new one.
"valibot@<1.4.2": "^1.4.2"
@@ -4,7 +4,7 @@
* The quick-entry forms, loaded when a sheet first opens rather than with the
* page. The dashboard and the bottom bar's capture picker are on nearly every
* authenticated paint, and both used to import all five forms eagerly (each
* with react-hook-form, zod, its pickers and its own queries) for sheets most
* with zod, its pickers and its own queries) for sheets most
* visits never open.
*
* Client-only (`ssr: false`): every sheet is closed on the server render. The
+2 -2
View File
@@ -38,7 +38,7 @@ const DateFieldCalendar = dynamic(
*
* The committed VALUE is always ISO `yyyy-MM-dd` — identical to the native
* `<input type="date">` contract `<DateInput>` ships — so this is a drop-in
* for `<DateInput>` and existing react-hook-form wiring is unchanged.
* for `<DateInput>` and existing form wiring is unchanged.
*
* How it works:
* - A text overlay paints the formatted display string (or the placeholder)
@@ -52,7 +52,7 @@ const DateFieldCalendar = dynamic(
* quirks) is gone.
* - A hidden mirror input carries `name` + the ISO value so any caller that
* relies on native form submission still sees a normal field; the forwarded
* ref points at it for react-hook-form `register()` parity.
* ref points at it, so a caller reads it like any native input.
*
* Height / a11y / target-size parity with `<DateInput>`: the same
* `min-h-11 h-11 sm:min-h-10 sm:h-10` floor (WCAG 2.5.5 — 44 px on mobile,
@@ -17,7 +17,7 @@
* new definition can be added from it without leaving the form.
*
* Follows the encounter form's controlled-draft shape rather than a
* react-hook-form instance — the sibling surface this plan cites as its
* form-library instance — the sibling surface this plan cites as its
* precedent uses a draft, and the server's Zod schema is the validation
* authority either way. The client guard is for the two properties a person
* feels immediately: a date is present, and the vaccine is named somehow.