PR-227028: update dependencies, migrate to TypeScript 6 and ESLint flat config

- Bump all dependencies to latest (React 19.2.7, Storybook 10.4.3, Webpack
  5.107.2 + webpack-cli 7, Jest 30.4.2, Cypress 15.17.0, Babel 7.29.7,
  sass-loader 17, css-minimizer-webpack-plugin 8, eslint-webpack-plugin 6).
- Migrate TypeScript 5.9 -> 6.0.3: set tsconfig rootDir, add
  ignoreDeprecations "6.0", scope include to src/components + src/@types, and
  declare *.scss/*.sass/*.css modules for stricter side-effect imports.
- Switch @babel/preset-react to the automatic JSX runtime and drop redundant
  React imports in stories and tests.
- Migrate ESLint from the deprecated .eslintrc.js to flat config
  (eslint.config.mjs) using typescript-eslint, @eslint/js, globals and the
  React/Storybook plugins. Keep ESLint at v9 because eslint-plugin-react does
  not support v10 yet. This fixes the previously broken lint (missing
  @typescript-eslint parser/plugin) and normalizes formatting.
- Fix a latent bug in .storybook/main.js (comma instead of semicolon joining
  two assignments via the comma operator).
- npm audit fix: 0 vulnerabilities.
- Bump package version to 1.4.0.
This commit is contained in:
2026-06-09 17:33:58 +00:00
parent 6e54dac709
commit a8e3057f02
24 changed files with 3753 additions and 2534 deletions

View File

@@ -1,7 +1,7 @@
{
"presets": [
["@babel/preset-env", {"targets": {"node": "current"}}],
"@babel/preset-react",
["@babel/preset-react", {"runtime": "automatic"}],
"@babel/preset-typescript"
]
}

View File

@@ -1,30 +0,0 @@
module.exports = {
'env': {
'browser': true,
'node': true,
'es2021': true
},
'extends': ['eslint:recommended', 'plugin:react/recommended', 'plugin:@typescript-eslint/recommended', 'plugin:storybook/recommended', 'plugin:storybook/recommended'],
'parser': '@typescript-eslint/parser',
'parserOptions': {
'ecmaFeatures': {
'jsx': true
},
'ecmaVersion': 'latest',
'sourceType': 'module'
},
'plugins': ['react', '@typescript-eslint'],
'rules': {
'indent': ['error', 'tab'],
'linebreak-style': ['error', 'unix'],
'quotes': ['error', 'single'],
'semi': ['error', 'always'],
'eol-last': ['error', 'always'],
'@typescript-eslint/no-var-requires': 0
},
'settings': {
'react': {
'version': 'detect'
}
}
};

View File

@@ -2,13 +2,13 @@ const path = require('path');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const deFaultValues = {
PREFIX_URL: ''
}
};
const prefixUrl = process.env.PREFIX_URL ? process.env.PREFIX_URL : deFaultValues.PREFIX_URL;
module.exports = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: ["@storybook/addon-webpack5-compiler-babel", "@storybook/addon-links", {
addons: ['@storybook/addon-webpack5-compiler-babel', '@storybook/addon-links', {
name: '@storybook/addon-styling-webpack',
options: {
rules: [
@@ -31,33 +31,33 @@ module.exports = {
}
]
},
}, "@storybook/addon-docs"],
}, '@storybook/addon-docs'],
webpackFinal: async config => {
config.entry = config.entry.map(function(entry) {
if (entry.includes("webpack-hot-middleware")) {
if (entry.includes('webpack-hot-middleware')) {
return `${require.resolve('webpack-hot-middleware/client')}?path=${prefixUrl}__webpack_hmr&reload=true`;
}
return entry;
}),
});
config.resolve.alias = {
...config.resolve.alias,
'@components': path.resolve(__dirname, "../src/components/")
'@components': path.resolve(__dirname, '../src/components/')
};
config.resolve.plugins = [new TsconfigPathsPlugin()];
return config;
},
framework: {
name: "@storybook/react-webpack5",
name: '@storybook/react-webpack5',
options: {}
},
typescript: {
reactDocgenTypescriptOptions: {
compilerOptions: {
"paths": {
"@Components/*": ["Components/*"]
'paths': {
'@Components/*': ['Components/*']
}
},
propFilter: (prop) => {

View File

@@ -1,5 +1,5 @@
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
@@ -25,5 +25,5 @@ export const parameters = {
excludeDecorators: true,
},
},
}
export const tags = ["autodocs"];
};
export const tags = ['autodocs'];

View File

@@ -2,7 +2,7 @@
const { execSync } = require('child_process');
var fs = require('fs');
const isWin = process.platform === "win32";
const isWin = process.platform === 'win32';
const runCommand = command => {
try{
@@ -12,7 +12,7 @@ const runCommand = command => {
return false;
}
return true;
}
};
const runCommandWithOutput = command => {
try{
@@ -21,7 +21,7 @@ const runCommandWithOutput = command => {
console.error(`Failed to execute ${command}`, e);
return false;
}
}
};
const replaceTextOnFile = ({
file,
@@ -29,7 +29,7 @@ const replaceTextOnFile = ({
textReplace,
arrOfObjectsBeReplaced
}) => {
let data
let data;
try{
data = fs.readFileSync(file, 'utf8');
} catch (e) {
@@ -37,7 +37,7 @@ const replaceTextOnFile = ({
return false;
}
let result
let result;
if(arrOfObjectsBeReplaced){
arrOfObjectsBeReplaced.forEach( obj => {
if(result){
@@ -45,19 +45,19 @@ const replaceTextOnFile = ({
}else{
result = data.replace(obj.textToBeReplaced, obj.textReplace).replace(/^\s*[\r\n]/gm, ' ');
}
})
});
}else{
result = data.replace(textToBeReplaced, textReplace).replace(/^\s*[\r\n]/gm, ' ');
}
try{
console.log('text changed')
console.log('text changed');
fs.writeFileSync(file, result, 'utf8');
} catch (e) {
console.error(`Failed to read file ${file}`, e);
return false;
}
}
};
const repoName = process.argv[2];
const gitCheckoutCommand = `git clone --depth 1 https://github.com/aleleba/create-react-component-library ${repoName}`;
@@ -65,13 +65,13 @@ console.log(`Cloning the repository with name ${repoName}`);
const checkedOut = runCommand(gitCheckoutCommand);
if(!checkedOut) process.exit(-1);
const actualVersion = runCommandWithOutput(`cd ${repoName} && node -p "require('./package.json').version"`).toString().trim()
const actualVersion = runCommandWithOutput(`cd ${repoName} && node -p "require('./package.json').version"`).toString().trim();
const installDepsCommand = `cd ${repoName} && npm i`;
const cleanGitHistoryCommand = `cd ${repoName} && rm -rf .git && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`
const cleanGitHistoryCommandWindows = `cd ${repoName} && rmdir .git /s /q && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`
const deleteFoldersCommand = `cd ${repoName} && rm -rf .github && rm -rf bin`
const deleteFoldersCommandWindows = `cd ${repoName} && rmdir .github /s /q && rmdir bin /s /q`
const cleanGitHistoryCommand = `cd ${repoName} && rm -rf .git && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`;
const cleanGitHistoryCommandWindows = `cd ${repoName} && rmdir .git /s /q && git init && git add --all -- ":!.github" ":!bin" && git commit -m "Initial commit"`;
const deleteFoldersCommand = `cd ${repoName} && rm -rf .github && rm -rf bin`;
const deleteFoldersCommandWindows = `cd ${repoName} && rmdir .github /s /q && rmdir bin /s /q`;
console.log(`Installing dependencies for ${repoName}`);
const installedDeps = runCommand(installDepsCommand);
@@ -82,28 +82,28 @@ replaceTextOnFile({
file: `./${repoName}/package.json`,
arrOfObjectsBeReplaced: [
{
textToBeReplaced: `"bin": "./bin/cli.js",`,
textReplace: ``
textToBeReplaced: '"bin": "./bin/cli.js",',
textReplace: ''
},
{
textToBeReplaced: `"version": "${actualVersion}",`,
textReplace: `"version": "0.0.1",`
textReplace: '"version": "0.0.1",'
},
{
textToBeReplaced: `"name": "@aleleba/create-react-component-library",`,
textToBeReplaced: '"name": "@aleleba/create-react-component-library",',
textReplace: `"name": "${repoName}",`
}
]
})
});
console.log(`Cleaning History of Git for ${repoName}`);
const cleanGitHistory = isWin ? runCommand(cleanGitHistoryCommandWindows) : runCommand(cleanGitHistoryCommand);
if(!cleanGitHistory) process.exit(-1);
console.log("Congratulations! You are ready. Follow the following commands to start");
console.log('Congratulations! You are ready. Follow the following commands to start');
console.log(`cd ${repoName}`);
console.log('Create a .env file with LIBRARY_NAME=your_library_name(default: ui-library), External_CSS (optional)(Default: false), EXTERNAL_CSS_NAME=(optional)(Default: index.css)');
console.log(`Then you can run: npm start`);
console.log('Then you can run: npm start');
const deleteFolders = isWin ? runCommand(deleteFoldersCommandWindows) : runCommand(deleteFoldersCommand);
if(!deleteFolders) process.exit(-1);

View File

@@ -1,12 +1,12 @@
import { defineConfig } from "cypress";
import { defineConfig } from 'cypress';
import webpackConfig from './webpack.cy.config';
export default defineConfig({
component: {
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
devServer: {
framework: "react",
bundler: "webpack",
framework: 'react',
bundler: 'webpack',
webpackConfig: webpackConfig,
},
viewportWidth: 1280,

View File

@@ -15,16 +15,17 @@
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
import './commands';
// Alternatively you can use CommonJS syntax:
// require('./commands')
import { mount } from 'cypress/react'
import { mount } from 'cypress/react';
// Augment the Cypress namespace to include type definitions for
// your custom command.
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
interface Chainable {
mount: typeof mount
@@ -32,7 +33,7 @@ declare global {
}
}
Cypress.Commands.add('mount', mount)
Cypress.Commands.add('mount', mount);
// Example use:
// cy.mount(<MyComponent />)

50
eslint.config.mjs Normal file
View File

@@ -0,0 +1,50 @@
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import react from 'eslint-plugin-react';
import storybook from 'eslint-plugin-storybook';
import globals from 'globals';
export default tseslint.config(
{
ignores: ['node_modules/**', 'dist/**', 'build/**', 'storybook-static/**'],
},
js.configs.recommended,
...tseslint.configs.recommended,
react.configs.flat.recommended,
react.configs.flat['jsx-runtime'],
...storybook.configs['flat/recommended'],
{
settings: {
react: { version: 'detect' },
},
},
{
files: ['**/*.{js,jsx,ts,tsx}'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
parserOptions: {
ecmaFeatures: { jsx: true },
},
globals: {
...globals.browser,
...globals.node,
},
},
rules: {
indent: ['error', 'tab'],
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single'],
semi: ['error', 'always'],
'eol-last': ['error', 'always'],
'react/prop-types': 'off',
'@typescript-eslint/no-require-imports': 'off',
},
},
{
files: ['**/*.js'],
languageOptions: {
sourceType: 'commonjs',
},
},
);

5316
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@aleleba/create-react-component-library",
"version": "1.3.2",
"version": "1.4.0",
"description": "A starter kit for create a React component Library with storybook",
"bin": "./bin/cli.js",
"main": "dist/index.js",
@@ -16,8 +16,8 @@
"scripts": {
"start": "npm run storybook",
"build": "webpack",
"lint": "eslint ./ --ext .js --ext .ts --ext .jsx --ext .tsx",
"lint:fix": "eslint ./ --ext .js --ext .ts --ext .jsx --ext .tsx --fix",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"test": "jest",
"test:watch": "jest --watch",
"storybook": "storybook dev -p 3000",
@@ -44,59 +44,62 @@
},
"homepage": "https://github.com/aleleba/create-react-component-library#readme",
"devDependencies": {
"@babel/core": "^7.28.6",
"@babel/preset-env": "^7.28.6",
"@babel/preset-react": "^7.28.5",
"@babel/preset-typescript": "^7.28.5",
"@babel/register": "^7.28.6",
"@babel/core": "^7.29.7",
"@babel/preset-env": "^7.29.7",
"@babel/preset-react": "^7.29.7",
"@babel/preset-typescript": "^7.29.7",
"@babel/register": "^7.29.7",
"@eslint/js": "^9.39.4",
"@mdx-js/react": "^3.1.1",
"@storybook/addon-docs": "^10.2.1",
"@storybook/addon-links": "^10.2.1",
"@storybook/addon-styling-webpack": "^3.0.0",
"@storybook/addon-webpack5-compiler-babel": "^4.0.0",
"@storybook/cli": "^10.2.1",
"@storybook/addon-docs": "^10.4.3",
"@storybook/addon-links": "^10.4.3",
"@storybook/addon-styling-webpack": "^3.0.2",
"@storybook/addon-webpack5-compiler-babel": "^4.0.1",
"@storybook/cli": "^10.4.3",
"@storybook/preset-scss": "^1.0.3",
"@storybook/react-webpack5": "^10.2.1",
"@storybook/react-webpack5": "^10.4.3",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/jest": "^30.0.0",
"@types/node": "^25.0.10",
"@types/react": "^19.2.10",
"@types/node": "^25.9.2",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@types/webpack": "^5.28.5",
"babel-loader": "^10.0.0",
"babel-loader": "^10.1.1",
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^7.1.3",
"css-minimizer-webpack-plugin": "^7.0.4",
"cypress": "^15.9.0",
"dotenv": "^17.2.3",
"eslint": "^9.39.2",
"css-loader": "^7.1.4",
"css-minimizer-webpack-plugin": "^8.0.0",
"cypress": "^15.17.0",
"dotenv": "^17.4.2",
"eslint": "^9.39.4",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-storybook": "^10.2.1",
"eslint-webpack-plugin": "^5.0.2",
"html-webpack-plugin": "^5.6.6",
"eslint-plugin-storybook": "^10.4.3",
"eslint-webpack-plugin": "^6.0.0",
"globals": "^16.5.0",
"html-webpack-plugin": "^5.6.7",
"identity-obj-proxy": "^3.0.0",
"jest": "^30.2.0",
"jest-environment-jsdom": "^30.2.0",
"jest": "^30.4.2",
"jest-environment-jsdom": "^30.4.1",
"jest-fetch-mock": "^3.0.3",
"mini-css-extract-plugin": "^2.10.0",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"mini-css-extract-plugin": "^2.10.2",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"resolve-ts-aliases": "^1.0.1",
"sass": "^1.97.3",
"sass-loader": "^16.0.6",
"storybook": "^10.2.1",
"sass": "^1.100.0",
"sass-loader": "^17.0.0",
"storybook": "^10.4.3",
"style-loader": "^4.0.0",
"terser-webpack-plugin": "^5.3.16",
"ts-jest": "^29.4.6",
"ts-loader": "^9.5.4",
"terser-webpack-plugin": "^5.6.1",
"ts-jest": "^29.4.11",
"ts-loader": "^9.6.0",
"tsconfig-paths-webpack-plugin": "^4.2.0",
"typescript": "^5.9.3",
"typescript": "^6.0.3",
"typescript-eslint": "^8.61.0",
"url-loader": "^4.1.1",
"webpack": "^5.104.1",
"webpack-cli": "^6.0.1",
"webpack": "^5.107.2",
"webpack-cli": "^7.0.3",
"webpack-node-externals": "^3.0.0"
},
"peerDependencies": {

View File

@@ -5,7 +5,7 @@
import '@testing-library/jest-dom';
//import fetch Mock
import fetchMock from "jest-fetch-mock";
import fetchMock from 'jest-fetch-mock';
fetchMock.enableMocks();
//Fixing Pollyfill for react-slick

View File

@@ -1,8 +1,13 @@
declare module "*.svg" {
declare module '*.svg' {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const content: any;
export default content;
}
declare module "@storybook/react" {
export * from "@storybook/react/dist/index";
declare module '*.scss';
declare module '*.sass';
declare module '*.css';
declare module '@storybook/react' {
export * from '@storybook/react/dist/index';
}

View File

@@ -1,5 +1,4 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import type { Meta, StoryObj } from '@storybook/react-webpack5';
import { Card } from '@components';
// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export

View File

@@ -1,5 +1,5 @@
import React, { FC } from "react";
import "./style.scss";
import React, { FC } from 'react';
import './style.scss';
type TCardProps = {
/**
@@ -22,4 +22,4 @@ const Card: FC<TCardProps> = ({ title, children}) => {
);
};
export { Card, TCardProps }
export { Card, TCardProps };

View File

@@ -1,14 +1,13 @@
import React from 'react';
import { Card } from '@components';
describe('Testing Card Component', () => {
beforeEach(() => {
cy.mount(<Card title='Test Title'><p>Test Content</p></Card>);
})
});
it('Show Title', () => {
cy.get('div').contains('Test Title');
})
});
it('Show Child Component', () => {
cy.get('p').contains('Test Content');
})
})
});
});

View File

@@ -1,11 +1,10 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { Card } from '@components';
describe('<Card/> Component', () => {
beforeEach(() => {
// fetchMock.resetMocks();
render(<Card title='Test Title'><p>Test Content</p></Card>)
render(<Card title='Test Title'><p>Test Content</p></Card>);
});
it('Show Title', async () => {
/* fetchMock.mockResponseOnce(JSON.stringify({
@@ -13,12 +12,12 @@ describe('<Card/> Component', () => {
data: 'data'
})); */
expect(screen.getByText('Test Title')).toBeInTheDocument();
})
});
it('Show Child Component', async () => {
/* fetchMock.mockResponseOnce(JSON.stringify({
//First Data Fetch
data: 'data'
})); */
expect(screen.getByText('Test Content')).toBeInTheDocument();
})
})
});
});

View File

@@ -1,7 +1,9 @@
{
"compilerOptions": {
"ignoreDeprecations": "6.0",
"declaration": true,
"declarationDir": "./dist/types",
"rootDir": "./src/components",
"target": "es5",
"lib": [
"dom",
@@ -38,7 +40,8 @@
}
},
"include": [
"."
"src/components",
"src/@types"
],
"exclude": [
"node_modules",

View File

@@ -10,9 +10,9 @@ import ESLintPlugin from 'eslint-webpack-plugin';
import { resolveTsAliases } from 'resolve-ts-aliases';
const dotEnvToParse = dotenv.config();
const libraryName = process.env.LIBRARY_NAME ? process.env.LIBRARY_NAME : "ui-library"
const externalCss = process.env.EXTERNAL_CSS === 'true' ? true : false
const externalCssName = process.env.EXTERNAL_CSS_NAME ? process.env.EXTERNAL_CSS_NAME : 'index.css'
const libraryName = process.env.LIBRARY_NAME ? process.env.LIBRARY_NAME : 'ui-library';
const externalCss = process.env.EXTERNAL_CSS === 'true' ? true : false;
const externalCssName = process.env.EXTERNAL_CSS_NAME ? process.env.EXTERNAL_CSS_NAME : 'index.css';
const alias = resolveTsAliases(path.resolve('tsconfig.json'));
export default {
@@ -98,4 +98,4 @@ export default {
new TerserPlugin(),
],
},
}
};

View File

@@ -10,8 +10,8 @@ import ESLintPlugin from 'eslint-webpack-plugin';
import { resolveTsAliases } from 'resolve-ts-aliases';
const dotEnvToParse = dotenv.config();
const externalCss = process.env.EXTERNAL_CSS === 'true' ? true : false
const externalCssName = process.env.EXTERNAL_CSS_NAME ? process.env.EXTERNAL_CSS_NAME : 'index.css'
const externalCss = process.env.EXTERNAL_CSS === 'true' ? true : false;
const externalCssName = process.env.EXTERNAL_CSS_NAME ? process.env.EXTERNAL_CSS_NAME : 'index.css';
const alias = resolveTsAliases(path.resolve('tsconfig.json'));
export default {
@@ -89,4 +89,4 @@ export default {
new TerserPlugin(),
],
},
}
};