Skip to content

Commit d61b908

Browse files
committed
feat(project-evaluations): migrate to React 19
Replace vanilla TypeScript (HTML string templates + manual DOM events) with a React 19 component tree. Components: App (state), Sidebar, ProtocolDetail, PropertyRow (local notes/url state with onBlur sync), AddModal (uncontrolled refs). Vite config updated with @vitejs/plugin-react; ESLint config restored to two-config setup covering gas-benchmarks and project-evaluations with React + react-hooks plugins for the eval package. https://claude.ai/code/session_01WSPUjmH7CpmkYDJgy5zeKQ
1 parent 268e725 commit d61b908

13 files changed

Lines changed: 1135 additions & 655 deletions

File tree

eslint.config.js

Lines changed: 192 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import { defineConfig, globalIgnores } from "eslint/config";
77
import _import from "eslint-plugin-import";
88
import json from "eslint-plugin-json";
99
import prettier from "eslint-plugin-prettier";
10+
import reactPlugin from "eslint-plugin-react";
11+
import reactHooksPlugin from "eslint-plugin-react-hooks";
1012
import unusedImports from "eslint-plugin-unused-imports";
13+
import globals from "globals";
1114

1215
import { readFileSync } from "fs";
1316
import { dirname } from "node:path";
@@ -29,169 +32,201 @@ const prettierConfig = readFileSync(resolve(__dirname, "./.prettierrc.json"), "u
2932
const prettierOptions = JSON.parse(prettierConfig);
3033
const isProduction = process.env.NODE_ENV === "production";
3134

32-
export default defineConfig([
33-
{
34-
extends: fixupConfigRules(
35-
compat.extends(
36-
"airbnb",
37-
"prettier",
38-
"plugin:import/recommended",
39-
"plugin:@typescript-eslint/eslint-recommended",
40-
"plugin:@typescript-eslint/recommended",
41-
"plugin:@typescript-eslint/recommended-type-checked",
42-
"plugin:@typescript-eslint/strict",
43-
"plugin:@typescript-eslint/strict-type-checked",
44-
"plugin:@typescript-eslint/stylistic",
45-
"plugin:@typescript-eslint/stylistic-type-checked",
46-
"plugin:import/typescript",
47-
),
48-
),
49-
50-
plugins: {
51-
json,
52-
prettier,
53-
"unused-imports": unusedImports,
54-
import: fixupPluginRules(_import),
55-
"@typescript-eslint": fixupPluginRules(typescriptEslint),
35+
// ── Shared plugins ────────────────────────────────────────────────────────────
36+
37+
const sharedPlugins = {
38+
json,
39+
prettier,
40+
"unused-imports": unusedImports,
41+
import: fixupPluginRules(_import),
42+
"@typescript-eslint": fixupPluginRules(typescriptEslint),
43+
};
44+
45+
const sharedParserOptions = {
46+
typescript: true,
47+
experimentalDecorators: true,
48+
requireConfigFile: false,
49+
ecmaFeatures: { classes: true, impliedStrict: true },
50+
warnOnUnsupportedTypeScriptVersion: true,
51+
};
52+
53+
// ── Shared rules applied to both packages ────────────────────────────────────
54+
55+
const sharedRules = {
56+
"no-console": "error",
57+
"unused-imports/no-unused-imports": "error",
58+
"prettier/prettier": ["error", prettierOptions],
59+
"@typescript-eslint/no-non-null-assertion": "off",
60+
"@typescript-eslint/prefer-nullish-coalescing": "off",
61+
"@typescript-eslint/use-unknown-in-catch-callback-variable": "off",
62+
"@typescript-eslint/no-explicit-any": "error",
63+
"@typescript-eslint/consistent-type-imports": ["error", { fixStyle: "inline-type-imports" }],
64+
"@typescript-eslint/no-misused-promises": ["error", { checksVoidReturn: false }],
65+
"@typescript-eslint/restrict-template-expressions": ["error", { allowNumber: true }],
66+
"@typescript-eslint/no-shadow": [
67+
"error",
68+
{
69+
builtinGlobals: true,
70+
allow: ["location", "event", "history", "name", "status", "Option", "test", "expect", "jest"],
5671
},
57-
58-
languageOptions: {
59-
parser: tsParser,
60-
sourceType: "module",
61-
ecmaVersion: 2022,
62-
parserOptions: {
63-
project: resolve(__dirname, "./tsconfig.json"),
64-
typescript: true,
65-
experimentalDecorators: true,
66-
requireConfigFile: false,
67-
ecmaFeatures: {
68-
classes: true,
69-
impliedStrict: true,
70-
},
71-
warnOnUnsupportedTypeScriptVersion: true,
72-
},
72+
],
73+
};
74+
75+
// ── gas-benchmarks: Node.js, full airbnb + typescript ruleset ────────────────
76+
77+
const gasExtends = fixupConfigRules(
78+
compat.extends(
79+
"airbnb",
80+
"prettier",
81+
"plugin:import/recommended",
82+
"plugin:@typescript-eslint/eslint-recommended",
83+
"plugin:@typescript-eslint/recommended",
84+
"plugin:@typescript-eslint/recommended-type-checked",
85+
"plugin:@typescript-eslint/strict",
86+
"plugin:@typescript-eslint/strict-type-checked",
87+
"plugin:@typescript-eslint/stylistic",
88+
"plugin:@typescript-eslint/stylistic-type-checked",
89+
"plugin:import/typescript",
90+
),
91+
);
92+
93+
const gasConfig = {
94+
files: ["gas-benchmarks/src/**/*.ts"],
95+
extends: gasExtends,
96+
plugins: sharedPlugins,
97+
languageOptions: {
98+
parser: tsParser,
99+
sourceType: "module",
100+
ecmaVersion: 2022,
101+
globals: globals.node,
102+
parserOptions: {
103+
...sharedParserOptions,
104+
project: resolve(__dirname, "./gas-benchmarks/tsconfig.json"),
73105
},
74-
75-
settings: {
76-
react: {
77-
version: "999.999.999",
106+
},
107+
settings: {
108+
react: { version: "999.999.999" },
109+
"import/resolver": {
110+
typescript: { project: resolve(__dirname, "./gas-benchmarks/tsconfig.json") },
111+
node: { extensions: [".ts", ".js"], moduleDirectory: ["node_modules", "ts", "src"] },
112+
},
113+
},
114+
linterOptions: { reportUnusedDisableDirectives: isProduction },
115+
rules: {
116+
...sharedRules,
117+
"import/no-cycle": ["error"],
118+
"import/no-extraneous-dependencies": [
119+
"error",
120+
{
121+
devDependencies: [
122+
"**/*.test.ts",
123+
"**/__benchmarks__/**",
124+
"**/tests/**",
125+
"**/__tests__/**",
126+
"**/vitest.config.ts",
127+
],
78128
},
79-
80-
"import/resolver": {
81-
typescript: {
82-
project: resolve(__dirname, "./tsconfig.json"),
83-
},
84-
85-
node: {
86-
extensions: [".ts", ".js"],
87-
moduleDirectory: ["node_modules", "ts", "src"],
88-
},
129+
],
130+
"no-debugger": isProduction ? "error" : "off",
131+
"no-underscore-dangle": "error",
132+
"no-redeclare": ["error", { builtinGlobals: true }],
133+
"import/order": [
134+
"error",
135+
{
136+
groups: ["external", "builtin", "internal", "type", "parent", "sibling", "index", "object"],
137+
alphabetize: { order: "asc", caseInsensitive: true },
138+
warnOnUnassignedImports: true,
139+
"newlines-between": "always",
89140
},
141+
],
142+
"import/prefer-default-export": "off",
143+
"import/extensions": ["error", { json: "always" }],
144+
"class-methods-use-this": "off",
145+
"prefer-promise-reject-errors": "off",
146+
"max-classes-per-file": "off",
147+
"no-use-before-define": ["off"],
148+
"no-shadow": "off",
149+
curly: ["error", "all"],
150+
"no-return-await": "off",
151+
"@typescript-eslint/explicit-member-accessibility": ["error", { accessibility: "no-public" }],
152+
"@typescript-eslint/explicit-module-boundary-types": "error",
153+
"@typescript-eslint/no-use-before-define": ["error", { functions: false, classes: false }],
154+
},
155+
};
156+
157+
// ── project-evaluations: React + Browser, leaner typescript + prettier ruleset ──
158+
159+
const evalExtends = fixupConfigRules(
160+
compat.extends(
161+
"prettier",
162+
"plugin:react/recommended",
163+
"plugin:react-hooks/recommended",
164+
"plugin:@typescript-eslint/eslint-recommended",
165+
"plugin:@typescript-eslint/recommended",
166+
"plugin:@typescript-eslint/recommended-type-checked",
167+
"plugin:@typescript-eslint/strict",
168+
"plugin:@typescript-eslint/strict-type-checked",
169+
"plugin:@typescript-eslint/stylistic",
170+
"plugin:@typescript-eslint/stylistic-type-checked",
171+
),
172+
);
173+
174+
const evalConfig = {
175+
files: ["project-evaluations/src/**/*.ts", "project-evaluations/src/**/*.tsx"],
176+
extends: evalExtends,
177+
plugins: {
178+
prettier,
179+
"unused-imports": unusedImports,
180+
"@typescript-eslint": fixupPluginRules(typescriptEslint),
181+
react: fixupPluginRules(reactPlugin),
182+
"react-hooks": fixupPluginRules(reactHooksPlugin),
183+
},
184+
languageOptions: {
185+
parser: tsParser,
186+
sourceType: "module",
187+
ecmaVersion: 2022,
188+
globals: globals.browser,
189+
parserOptions: {
190+
...sharedParserOptions,
191+
project: resolve(__dirname, "./project-evaluations/tsconfig.json"),
90192
},
193+
},
194+
settings: {
195+
react: { version: "detect" },
196+
},
197+
linterOptions: { reportUnusedDisableDirectives: isProduction },
198+
rules: {
199+
...sharedRules,
200+
// Not needed with the new JSX transform (react-jsx).
201+
"react/react-in-jsx-scope": "off",
202+
// TypeScript enforces prop types; PropTypes are redundant.
203+
"react/prop-types": "off",
204+
// PropertyDefinition clashes with the DOM global of the same name.
205+
"@typescript-eslint/no-shadow": [
206+
"error",
207+
{
208+
builtinGlobals: true,
209+
allow: [
210+
"location",
211+
"event",
212+
"history",
213+
"name",
214+
"status",
215+
"Option",
216+
"test",
217+
"expect",
218+
"jest",
219+
"PropertyDefinition",
220+
],
221+
},
222+
],
223+
},
224+
};
91225

92-
linterOptions: {
93-
reportUnusedDisableDirectives: isProduction,
94-
},
226+
// ── Export ────────────────────────────────────────────────────────────────────
95227

96-
rules: {
97-
"import/no-cycle": ["error"],
98-
"unused-imports/no-unused-imports": "error",
99-
"import/no-extraneous-dependencies": [
100-
"error",
101-
{
102-
devDependencies: [
103-
"**/*.test.ts",
104-
"**/__benchmarks__/**",
105-
"**/tests/**",
106-
"**/__tests__/**",
107-
"**/vitest.config.ts",
108-
],
109-
},
110-
],
111-
"no-debugger": isProduction ? "error" : "off",
112-
"no-console": "error",
113-
"no-underscore-dangle": "error",
114-
"no-redeclare": [
115-
"error",
116-
{
117-
builtinGlobals: true,
118-
},
119-
],
120-
"import/order": [
121-
"error",
122-
{
123-
groups: ["external", "builtin", "internal", "type", "parent", "sibling", "index", "object"],
124-
125-
alphabetize: {
126-
order: "asc",
127-
caseInsensitive: true,
128-
},
129-
130-
warnOnUnassignedImports: true,
131-
"newlines-between": "always",
132-
},
133-
],
134-
"prettier/prettier": ["error", prettierOptions],
135-
"import/prefer-default-export": "off",
136-
"import/extensions": [
137-
"error",
138-
{
139-
json: "always",
140-
},
141-
],
142-
"class-methods-use-this": "off",
143-
"prefer-promise-reject-errors": "off",
144-
"max-classes-per-file": "off",
145-
"no-use-before-define": ["off"],
146-
"no-shadow": "off",
147-
curly: ["error", "all"],
148-
"no-return-await": "off",
149-
"@typescript-eslint/explicit-member-accessibility": [
150-
"error",
151-
{
152-
accessibility: "no-public",
153-
},
154-
],
155-
"@typescript-eslint/no-non-null-assertion": "off",
156-
"@typescript-eslint/prefer-nullish-coalescing": "off",
157-
"@typescript-eslint/no-floating-promises": "off",
158-
"@typescript-eslint/use-unknown-in-catch-callback-variable": "off",
159-
"@typescript-eslint/no-explicit-any": "error",
160-
"@typescript-eslint/explicit-module-boundary-types": "error",
161-
"@typescript-eslint/consistent-type-imports": [
162-
"error",
163-
{
164-
fixStyle: "inline-type-imports",
165-
},
166-
],
167-
"@typescript-eslint/no-use-before-define": [
168-
"error",
169-
{
170-
functions: false,
171-
classes: false,
172-
},
173-
],
174-
"@typescript-eslint/no-misused-promises": [
175-
"error",
176-
{
177-
checksVoidReturn: false,
178-
},
179-
],
180-
"@typescript-eslint/no-shadow": [
181-
"error",
182-
{
183-
builtinGlobals: true,
184-
185-
allow: ["location", "event", "history", "name", "status", "Option", "test", "expect", "jest"],
186-
},
187-
],
188-
"@typescript-eslint/restrict-template-expressions": [
189-
"error",
190-
{
191-
allowNumber: true,
192-
},
193-
],
194-
},
195-
},
228+
export default defineConfig([
229+
gasConfig,
230+
evalConfig,
196231
globalIgnores(["**/node_modules", "**/dist", "**/coverage", "**/build", "eslint.config.js"]),
197232
]);

0 commit comments

Comments
 (0)