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]>
86 lines
2.9 KiB
TypeScript
86 lines
2.9 KiB
TypeScript
import * as React from 'react';
|
|
import Text from '../text/text';
|
|
|
|
import {ActionButton} from './action-button';
|
|
|
|
const IconOptions = ['fa-hand-point-up', 'fa-exclamation-circle'];
|
|
|
|
export default {
|
|
title: 'Components/ActionButton',
|
|
component: ActionButton,
|
|
argTypes: {
|
|
sampleAction: {
|
|
name: 'Sample Action',
|
|
description: 'A set of sample actions to demo the Action Button. Not available for real component',
|
|
control: {
|
|
type: 'radio',
|
|
options: ['Say hello', 'Surprise'],
|
|
},
|
|
},
|
|
action: {control: {disable: true}, description: 'Function that is called when button is clicked', action: 'clicked'},
|
|
style: {control: {disable: true}},
|
|
icon: {
|
|
name: 'Sample Icon',
|
|
description: 'A set of sample icons to choose from. For real component, use any FontAwesome class name.',
|
|
options: IconOptions,
|
|
mapping: IconOptions,
|
|
control: {
|
|
type: 'select',
|
|
labels: {
|
|
faHandPointUp: 'Pointer',
|
|
faExclamationCircle: 'Error',
|
|
},
|
|
},
|
|
},
|
|
theme: {description: 'Takes precidence over dark boolean switch'},
|
|
dark: {description: 'Convenience flag to make button appear dark without special Theme logic'},
|
|
tooltip: {control: {type: 'text'}},
|
|
short: {description: 'Displays only the icon (hides the label). Does nothing if icon is not specified'},
|
|
indicateLoading: {description: 'Displays a spinner for a brief period on click, but only if the icon prop is set'},
|
|
indicateSuccess: {description: 'Displays a checkmark after the specified action is complete, but only if the icon prop is set'},
|
|
},
|
|
};
|
|
|
|
const Template = (args: any) => {
|
|
const [message, setMessage] = React.useState('');
|
|
const clickAction = args.action;
|
|
|
|
const tempSetMessage = (text: string) => {
|
|
clickAction();
|
|
setMessage(text);
|
|
setTimeout(() => {
|
|
setMessage('');
|
|
}, 1000);
|
|
};
|
|
|
|
const SampleActions: {[key: string]: () => void} = {
|
|
'Say hello': () => tempSetMessage('Hello!'),
|
|
'Surprise': () => tempSetMessage('Boo!'),
|
|
};
|
|
const buttonArgs = {
|
|
...args,
|
|
action: SampleActions[args.sampleAction],
|
|
tooltip: args.tooltip && args.tooltip !== '' ? <Text>{args.tooltip}</Text> : args.tooltip,
|
|
};
|
|
|
|
return (
|
|
<React.Fragment>
|
|
<div style={{display: 'flex'}}>
|
|
<ActionButton {...buttonArgs} />
|
|
</div>
|
|
{message !== '' && (
|
|
<div style={{marginTop: '1em'}}>
|
|
<Text dark={args.dark}>{message}</Text>
|
|
</div>
|
|
)}
|
|
</React.Fragment>
|
|
);
|
|
};
|
|
|
|
export const Primary = Template.bind({});
|
|
|
|
Primary.args = {
|
|
label: 'Click me!',
|
|
sampleAction: 'Say hello',
|
|
};
|