fix: resolve ESLint configuration and TypeScript errors across monorepo
- Add "type": "module" to @tpmjs/eslint-config package.json for ES module support - Rename eslint.config.js to eslint.config.mjs in apps/web and packages/ui - Update ESLint configs to ignore build directories (.next, dist, .turbo) - Extend import/no-internal-modules allowlist for Next.js, testing libs, and React - Fix unescaped quotes in playground page code elements - Convert CardDescriptionProps from empty interface to type alias - Disable jsx-a11y/no-autofocus rule in test files - Change web app lint script from 'next lint' to 'eslint .' - Fix TypeScript ref type inference errors in UI package tests by using non-null assertions - Disable Biome noNonNullAssertion rule for test files 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
27f867ff24
commit
54f2c1a2d1
23 changed files with 161 additions and 100 deletions
|
|
@ -1,3 +0,0 @@
|
|||
import reactConfig from '@tpmjs/eslint-config/react.js';
|
||||
|
||||
export default reactConfig;
|
||||
16
apps/web/eslint.config.mjs
Normal file
16
apps/web/eslint.config.mjs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import reactConfig from '@tpmjs/eslint-config/react.js';
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: [
|
||||
'.next/**',
|
||||
'.turbo/**',
|
||||
'node_modules/**',
|
||||
'*.config.js',
|
||||
'*.config.ts',
|
||||
'next-env.d.ts',
|
||||
'eslint.config.mjs'
|
||||
]
|
||||
},
|
||||
...reactConfig,
|
||||
];
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"lint": "eslint .",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rm -rf .next .turbo"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -167,7 +167,8 @@ export default function PlaygroundPage() {
|
|||
<div className="space-y-4">
|
||||
<h3 className="text-xl font-medium">Available Icons</h3>
|
||||
<div className="grid grid-cols-4 md:grid-cols-6 lg:grid-cols-8 gap-6">
|
||||
{([
|
||||
{(
|
||||
[
|
||||
"check",
|
||||
"x",
|
||||
"chevronDown",
|
||||
|
|
@ -176,7 +177,8 @@ export default function PlaygroundPage() {
|
|||
"github",
|
||||
"sun",
|
||||
"moon",
|
||||
] as const).map((icon) => (
|
||||
] as const
|
||||
).map((icon) => (
|
||||
<div
|
||||
key={icon}
|
||||
className="flex flex-col items-center gap-2 p-3 rounded-lg hover:bg-surface transition-colors"
|
||||
|
|
@ -463,28 +465,28 @@ export default function Example() {
|
|||
<Container size="sm" padding="md">
|
||||
<Card>
|
||||
<CardContent className="p-4 text-center">
|
||||
<code className="text-sm">size="sm"</code>
|
||||
<code className="text-sm">size="sm"</code>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Container>
|
||||
<Container size="md" padding="md">
|
||||
<Card>
|
||||
<CardContent className="p-4 text-center">
|
||||
<code className="text-sm">size="md"</code>
|
||||
<code className="text-sm">size="md"</code>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Container>
|
||||
<Container size="lg" padding="md">
|
||||
<Card>
|
||||
<CardContent className="p-4 text-center">
|
||||
<code className="text-sm">size="lg"</code>
|
||||
<code className="text-sm">size="lg"</code>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Container>
|
||||
<Container size="xl" padding="md">
|
||||
<Card>
|
||||
<CardContent className="p-4 text-center">
|
||||
<code className="text-sm">size="xl"</code>
|
||||
<code className="text-sm">size="xl"</code>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Container>
|
||||
|
|
|
|||
|
|
@ -37,5 +37,17 @@
|
|||
"trailingCommas": "es5",
|
||||
"semicolons": "always"
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"include": ["**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/*.spec.tsx"],
|
||||
"linter": {
|
||||
"rules": {
|
||||
"style": {
|
||||
"noNonNullAssertion": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import js from '@eslint/js';
|
||||
import tseslint from 'typescript-eslint';
|
||||
import importPlugin from 'eslint-plugin-import';
|
||||
import js from "@eslint/js";
|
||||
import importPlugin from "eslint-plugin-import";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
export default tseslint.config(
|
||||
js.configs.recommended,
|
||||
|
|
@ -11,22 +11,34 @@ export default tseslint.config(
|
|||
},
|
||||
rules: {
|
||||
// Module boundaries
|
||||
'import/no-internal-modules': ['error', {
|
||||
"import/no-internal-modules": [
|
||||
"error",
|
||||
{
|
||||
allow: [
|
||||
'@tpmjs/ui/*/[!index]*',
|
||||
'@tpmjs/utils/*',
|
||||
'@tpmjs/types/*',
|
||||
]
|
||||
}],
|
||||
'import/no-restricted-paths': ['error', {
|
||||
zones: [
|
||||
{ target: './packages', from: './apps' },
|
||||
{ target: './packages/ui', from: './packages/utils' },
|
||||
]
|
||||
}],
|
||||
'import/no-anonymous-default-export': 'error',
|
||||
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/no-explicit-any': 'warn',
|
||||
"@tpmjs/ui/*/[!index]*",
|
||||
"@tpmjs/utils/*",
|
||||
"@tpmjs/types/*",
|
||||
"@tpmjs/eslint-config/*",
|
||||
"next/**",
|
||||
"./.next/*",
|
||||
],
|
||||
},
|
||||
],
|
||||
"import/no-restricted-paths": [
|
||||
"error",
|
||||
{
|
||||
zones: [
|
||||
{ target: "./packages", from: "./apps" },
|
||||
{ target: "./packages/ui", from: "./packages/utils" },
|
||||
],
|
||||
},
|
||||
],
|
||||
"import/no-anonymous-default-export": "error",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{ argsIgnorePattern: "^_" },
|
||||
],
|
||||
"@typescript-eslint/no-explicit-any": "warn",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,11 +2,9 @@
|
|||
"name": "@tpmjs/eslint-config",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "./base.js",
|
||||
"files": [
|
||||
"base.js",
|
||||
"react.js"
|
||||
],
|
||||
"files": ["base.js", "react.js"],
|
||||
"dependencies": {
|
||||
"@eslint/js": "^9.18.0",
|
||||
"eslint": "^9.18.0",
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
import reactConfig from '@tpmjs/eslint-config/react.js';
|
||||
|
||||
export default reactConfig;
|
||||
28
packages/ui/eslint.config.mjs
Normal file
28
packages/ui/eslint.config.mjs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import reactConfig from '@tpmjs/eslint-config/react.js';
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: ['dist/**', 'node_modules/**', 'eslint.config.mjs']
|
||||
},
|
||||
...reactConfig,
|
||||
{
|
||||
rules: {
|
||||
'import/no-internal-modules': ['error', {
|
||||
allow: [
|
||||
'@tpmjs/ui/*/[!index]*',
|
||||
'@tpmjs/utils/*',
|
||||
'@tpmjs/types/*',
|
||||
'@tpmjs/eslint-config/*',
|
||||
'@testing-library/**',
|
||||
'react/*',
|
||||
]
|
||||
}],
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.test.ts', '**/*.test.tsx', '**/*.spec.ts', '**/*.spec.tsx'],
|
||||
rules: {
|
||||
'jsx-a11y/no-autofocus': 'off',
|
||||
}
|
||||
}
|
||||
];
|
||||
|
|
@ -242,7 +242,7 @@ describe("Badge", () => {
|
|||
let ref: HTMLDivElement | null = null;
|
||||
render(
|
||||
<Badge
|
||||
ref={(el: HTMLDivElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
>
|
||||
|
|
@ -250,7 +250,7 @@ describe("Badge", () => {
|
|||
</Badge>,
|
||||
);
|
||||
expect(ref).toBeInstanceOf(HTMLDivElement);
|
||||
expect(ref?.tagName).toBe("DIV");
|
||||
expect(ref!.tagName).toBe("DIV");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ describe("Button", () => {
|
|||
let ref: HTMLButtonElement | null = null;
|
||||
render(
|
||||
<Button
|
||||
ref={(el: HTMLButtonElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
>
|
||||
|
|
@ -241,7 +241,7 @@ describe("Button", () => {
|
|||
</Button>,
|
||||
);
|
||||
expect(ref).toBeInstanceOf(HTMLButtonElement);
|
||||
expect(ref?.tagName).toBe("BUTTON");
|
||||
expect(ref!.tagName).toBe("BUTTON");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -409,7 +409,7 @@ describe("Card", () => {
|
|||
let ref: HTMLDivElement | null = null;
|
||||
render(
|
||||
<Card
|
||||
ref={(el: HTMLDivElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
>
|
||||
|
|
@ -417,7 +417,7 @@ describe("Card", () => {
|
|||
</Card>,
|
||||
);
|
||||
expect(ref).toBeInstanceOf(HTMLDivElement);
|
||||
expect(ref?.tagName).toBe("DIV");
|
||||
expect(ref!.tagName).toBe("DIV");
|
||||
});
|
||||
|
||||
it("forwards ref to CardHeader element", () => {
|
||||
|
|
@ -425,7 +425,7 @@ describe("Card", () => {
|
|||
render(
|
||||
<Card>
|
||||
<CardHeader
|
||||
ref={(el: HTMLDivElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
>
|
||||
|
|
@ -442,7 +442,7 @@ describe("Card", () => {
|
|||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle
|
||||
ref={(el: HTMLHeadingElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
>
|
||||
|
|
@ -452,7 +452,7 @@ describe("Card", () => {
|
|||
</Card>,
|
||||
);
|
||||
expect(ref).toBeInstanceOf(HTMLHeadingElement);
|
||||
expect(ref?.tagName).toBe("H3");
|
||||
expect(ref!.tagName).toBe("H3");
|
||||
});
|
||||
|
||||
it("forwards ref to CardDescription element", () => {
|
||||
|
|
@ -461,7 +461,7 @@ describe("Card", () => {
|
|||
<Card>
|
||||
<CardHeader>
|
||||
<CardDescription
|
||||
ref={(el: HTMLParagraphElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
>
|
||||
|
|
@ -478,7 +478,7 @@ describe("Card", () => {
|
|||
render(
|
||||
<Card>
|
||||
<CardContent
|
||||
ref={(el: HTMLDivElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
>
|
||||
|
|
@ -494,7 +494,7 @@ describe("Card", () => {
|
|||
render(
|
||||
<Card>
|
||||
<CardFooter
|
||||
ref={(el: HTMLDivElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -42,8 +42,7 @@ export interface CardTitleProps extends HTMLAttributes<HTMLHeadingElement> {
|
|||
/**
|
||||
* CardDescription component props
|
||||
*/
|
||||
export interface CardDescriptionProps
|
||||
extends HTMLAttributes<HTMLParagraphElement> {}
|
||||
export type CardDescriptionProps = HTMLAttributes<HTMLParagraphElement>;
|
||||
|
||||
/**
|
||||
* CardContent component props
|
||||
|
|
|
|||
|
|
@ -287,13 +287,13 @@ describe("CodeBlock", () => {
|
|||
render(
|
||||
<CodeBlock
|
||||
code="code"
|
||||
ref={(el: HTMLDivElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
expect(ref).toBeInstanceOf(HTMLDivElement);
|
||||
expect(ref?.querySelector("code")).toBeInTheDocument();
|
||||
expect(ref!.querySelector("code")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@ describe("Container", () => {
|
|||
let ref: HTMLDivElement | null = null;
|
||||
render(
|
||||
<Container
|
||||
ref={(el: HTMLDivElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
>
|
||||
|
|
@ -223,7 +223,7 @@ describe("Container", () => {
|
|||
</Container>,
|
||||
);
|
||||
expect(ref).toBeInstanceOf(HTMLDivElement);
|
||||
expect(ref?.tagName).toBe("DIV");
|
||||
expect(ref!.tagName).toBe("DIV");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ describe("GridContainer", () => {
|
|||
let ref: HTMLDivElement | null = null;
|
||||
render(
|
||||
<GridContainer
|
||||
ref={(el: HTMLDivElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -249,13 +249,13 @@ describe("Header", () => {
|
|||
let ref: HTMLElement | null = null;
|
||||
render(
|
||||
<Header
|
||||
ref={(el: HTMLElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
expect(ref).toBeInstanceOf(HTMLElement);
|
||||
expect(ref?.tagName).toBe("HEADER");
|
||||
expect(ref!.tagName).toBe("HEADER");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ describe("Icon", () => {
|
|||
/>,
|
||||
);
|
||||
expect(ref).toBeInstanceOf(SVGSVGElement);
|
||||
expect(ref?.tagName).toBe("svg");
|
||||
expect(ref!.tagName).toBe("svg");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -311,26 +311,26 @@ describe("Input", () => {
|
|||
let ref: HTMLInputElement | null = null;
|
||||
render(
|
||||
<Input
|
||||
ref={(el: HTMLInputElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
expect(ref).toBeInstanceOf(HTMLInputElement);
|
||||
expect(ref?.tagName).toBe("INPUT");
|
||||
expect(ref!.tagName).toBe("INPUT");
|
||||
});
|
||||
|
||||
it("can focus input through ref", () => {
|
||||
let ref: HTMLInputElement | null = null;
|
||||
render(
|
||||
<Input
|
||||
ref={(el: HTMLInputElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
data-testid="input"
|
||||
/>,
|
||||
);
|
||||
ref?.focus();
|
||||
ref!.focus();
|
||||
expect(screen.getByTestId("input")).toHaveFocus();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ describe("Label", () => {
|
|||
</Label>,
|
||||
);
|
||||
expect(ref).toBeInstanceOf(HTMLLabelElement);
|
||||
expect(ref?.tagName).toBe("LABEL");
|
||||
expect(ref!.tagName).toBe("LABEL");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ describe("ProgressBar", () => {
|
|||
render(
|
||||
<ProgressBar
|
||||
value={50}
|
||||
ref={(el: HTMLDivElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
/>,
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ describe("Section", () => {
|
|||
let ref: HTMLElement | null = null;
|
||||
render(
|
||||
<Section
|
||||
ref={(el: HTMLElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
>
|
||||
|
|
@ -292,7 +292,7 @@ describe("Section", () => {
|
|||
</Section>,
|
||||
);
|
||||
expect(ref).toBeInstanceOf(HTMLElement);
|
||||
expect(ref?.tagName).toBe("SECTION");
|
||||
expect(ref!.tagName).toBe("SECTION");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -370,7 +370,7 @@ describe("Tabs", () => {
|
|||
tabs={mockTabs}
|
||||
activeTab="all"
|
||||
onTabChange={handleChange}
|
||||
ref={(el: HTMLDivElement | null) => {
|
||||
ref={(el) => {
|
||||
ref = el;
|
||||
}}
|
||||
/>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue