mirror of
https://github.com/hanzoai/cd-ui.git
synced 2026-10-30 20:42:45 +00:00
* chore: fix Rules-of-React violations for React Compiler readiness Add eslint-plugin-react-hooks v7 (recommended-latest) and fix all error-level Rules-of-React findings so the React Compiler can optimize the component library. The healthcheck reports 100% of components compilable; these fixes clear the 34 ESLint errors across the src and v2 component trees: - refs: stop accessing ref.current during render (incl. the react-form compat shim, whose public ref-forwarding API is preserved) - set-state-in-effect: convert to derived state or restructure effects - immutability: clone-before-mutate; stop mutating props/state - rules-of-hooks: hoist conditional hook calls to top level All 47 unit tests pass; behavior is preserved. Signed-off-by: Jonathan Winters <[email protected]> * chore: resolve react-hooks deps from public npm registry The eslint-plugin-react-hooks@7 dependency subtree was locked to an internal mirror, which the public CI runner can't reach (ETIMEDOUT). Rewrite the 21 affected resolved URLs to registry.yarnpkg.com. Signed-off-by: Jonathan Winters <[email protected]> * useKeybinding -> registerKeybinding Signed-off-by: Jonathan Winters <[email protected]> * chore: fix Rules-of-React refs violations from registerKeybinding rename The useKeybinding->registerKeybinding rename turned hook calls into plain function calls in the render body; since registerKeybinding takes ref targets, the new react-hooks/refs lint flagged them. Move the calls into useEffect (registration is a side effect) in sliding-panel and the v2 autocomplete. In the v1 autocomplete, the flagged value is a forwarded callback ref, not a render-time read, so suppress that one with a comment. Also dedupe pnpm-lock.yaml. Signed-off-by: Jonathan Winters <[email protected]> --------- Signed-off-by: Jonathan Winters <[email protected]>
60 lines
2.0 KiB
TypeScript
60 lines
2.0 KiB
TypeScript
import * as React from 'react';
|
|
|
|
import './header.scss';
|
|
|
|
export const Logo = () => <img src='/argo-icon-color-square.png' style={{width: '35px', height: '35px', margin: '0 8px'}} alt='Argo Logo' />;
|
|
|
|
interface BrandProps {
|
|
path?: string;
|
|
welcomeText?: string;
|
|
brandName?: string;
|
|
logo?: React.ReactNode;
|
|
}
|
|
/**
|
|
* Brand Hero designed for display in a header. Includes the Argo Logo and a welcome message that fades after page load
|
|
*/
|
|
export const Brand = (props: BrandProps) => {
|
|
const [loading, setLoading] = React.useState(true);
|
|
const [prevWelcomeText, setPrevWelcomeText] = React.useState(props.welcomeText);
|
|
if (prevWelcomeText !== props.welcomeText) {
|
|
setPrevWelcomeText(props.welcomeText);
|
|
setLoading(true);
|
|
}
|
|
React.useEffect(() => {
|
|
const timeout = setTimeout(() => setLoading(false), 500);
|
|
return () => clearTimeout(timeout);
|
|
}, [props.welcomeText]);
|
|
|
|
const showWelcome = loading && !props.path;
|
|
const welcomeText = props.welcomeText || 'Welcome to';
|
|
return (
|
|
<div className='header__brand'>
|
|
{props.logo ? props.logo : <Logo />}
|
|
<h1>
|
|
<div className='header__welcome' style={{opacity: showWelcome ? 1 : 0, transform: showWelcome ? 'none' : 'scaleX(0.01)', width: `${welcomeText.length}ch`}}>
|
|
{welcomeText}
|
|
</div>
|
|
<div className='header__title' style={showWelcome ? {transform: `translateX(${welcomeText.length}ch)`} : {transform: 'translateX(0)'}}>
|
|
{props.brandName || 'Argo'} {props.path && <h2> / {props.path} </h2>}
|
|
</div>
|
|
</h1>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
interface HeaderProps {
|
|
children: React.ReactNode;
|
|
style?: React.CSSProperties;
|
|
}
|
|
|
|
/**
|
|
* Header banner in dark indigo color, designed for display at the top of a page. Wraps its children in indigo banner.
|
|
*/
|
|
export const Header = (props: HeaderProps) => {
|
|
return (
|
|
<header className='header' style={props.style as any}>
|
|
{props.children}
|
|
</header>
|
|
);
|
|
};
|