Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
httpRetry: 5

httpTimeout: 600000

nodeLinker: node-modules

npmRegistryServer: "https://registry.npmjs.org"
40 changes: 40 additions & 0 deletions cleanup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const fs = require('fs');
const path = require('path');

function deleteFolderRecursive(pathToDelete) {
if (fs.existsSync(pathToDelete)) {
fs.readdirSync(pathToDelete).forEach((file) => {
const curPath = path.join(pathToDelete, file);
if (fs.lstatSync(curPath).isDirectory()) {
deleteFolderRecursive(curPath);
} else {
try {
fs.unlinkSync(curPath);
} catch (err) {
// console.error(`Error deleting file ${curPath}:`, err);
}
}
});
try {
fs.rmdirSync(pathToDelete);
} catch (err) {
// console.error(`Error deleting directory ${pathToDelete}:`, err);
}
}
}

['node_modules', '.yarn'].forEach((dir) => {
// console.log(`Removing ${dir}...`);
deleteFolderRecursive(dir);
});

['.pnp.cjs', '.pnp.loader.mjs'].forEach((file) => {
if (fs.existsSync(file)) {
try {
fs.unlinkSync(file);
// console.log(`Removed ${file}`);
} catch (err) {
// console.error(`Error removing ${file}:`, err);
}
}
});
48 changes: 45 additions & 3 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,14 +1,45 @@
import { fixupPluginRules } from '@eslint/compat';
import js from '@eslint/js';
import patternflyReact from 'eslint-plugin-patternfly-react';
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
// Try to import the workspace plugin by package name first; if Node's ESM resolver
// can't find it in this environment (Yarn v4 workspace on Windows) fall back to
// the local package build. Using top-level await is valid in an ESM config.
let patternflyReact;
try {
const mod = await import('eslint-plugin-patternfly-react');
patternflyReact = mod && mod.default ? mod.default : mod;
} catch (e) {
// Fallback to the local lib build path. This keeps CI behavior unchanged while
// allowing local linting during development.
const local = await import('./packages/eslint-plugin-patternfly-react/lib/index.js');
patternflyReact = local && local.default ? local.default : local;
}
import prettier from 'eslint-plugin-prettier';
import reactCompiler from 'eslint-plugin-react-compiler';
import reactHooks from 'eslint-plugin-react-hooks';
import react from 'eslint-plugin-react';
import testingLibrary from 'eslint-plugin-testing-library';
import globals from 'globals';
import tseslint from 'typescript-eslint';

// The `recommended` export from some plugins (notably eslint-plugin-prettier)
// may include a legacy `extends` key which is invalid in flat config. To
// remain compatible we extract only the parts we can safely include here.
const prettierRecommended = (() => {
try {
const cfg = prettier && prettier.configs && prettier.configs.recommended;
if (cfg && typeof cfg === 'object') {
return {
rules: cfg.rules || {},
settings: cfg.settings || {},
languageOptions: cfg.languageOptions || {}
};
}
} catch (e) {
// swallow — we'll just not include it
}
return null;
})();

export default [
{
ignores: [
Expand All @@ -27,10 +58,20 @@ export default [
...tseslint.configs.recommended,
react.configs.flat.recommended,
react.configs.flat['jsx-runtime'],
eslintPluginPrettierRecommended,
// include only the safe parts of Prettier's recommended config (avoid legacy 'extends')
...(prettierRecommended
? [
{
languageOptions: prettierRecommended.languageOptions,
settings: prettierRecommended.settings,
rules: prettierRecommended.rules
}
]
: []),
{
plugins: {
'patternfly-react': fixupPluginRules(patternflyReact),
prettier: fixupPluginRules(prettier),
'react-hooks': fixupPluginRules(reactHooks),
'react-compiler': reactCompiler
},
Expand Down Expand Up @@ -68,6 +109,7 @@ export default [
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/no-misused-new': 'error',
'@typescript-eslint/no-namespace': 'error',
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"eslint": "^9.32.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-markdown": "^5.1.0",
"eslint-plugin-patternfly-react": "workspace:^",
"eslint-plugin-prettier": "^5.2.6",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-compiler": "19.0.0-beta-ebf51a3-20250411",
Expand Down
11 changes: 11 additions & 0 deletions packages/react-core/src/components/Toolbar/ToolbarGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,15 @@ export interface ToolbarGroupProps extends Omit<React.HTMLProps<HTMLDivElement>,
xl?: 'wrap' | 'nowrap';
'2xl'?: 'wrap' | 'nowrap';
};
/** Indicates whether a flex grow modifier of 1 is applied at various breakpoints */
flexGrow?: {
default?: 'flexGrow';
sm?: 'flexGrow';
md?: 'flexGrow';
lg?: 'flexGrow';
xl?: 'flexGrow';
'2xl'?: 'flexGrow';
};
/** Content to be rendered inside the data toolbar group */
children?: React.ReactNode;
/** Flag that modifies the toolbar group to hide overflow and respond to available space. Used for horizontal navigation. */
Expand All @@ -185,6 +194,7 @@ class ToolbarGroupWithRef extends Component<ToolbarGroupProps> {
columnGap,
rowGap,
rowWrap,
flexGrow,
className,
variant,
children,
Expand Down Expand Up @@ -221,6 +231,7 @@ class ToolbarGroupWithRef extends Component<ToolbarGroupProps> {
alignSelf === 'center' && styles.modifiers.alignSelfCenter,
alignSelf === 'baseline' && styles.modifiers.alignSelfBaseline,
isOverflowContainer && styles.modifiers.overflowContainer,
formatBreakpointMods(flexGrow, styles, '', getBreakpoint(width)),
className
)}
{...props}
Expand Down
Loading