diff --git a/packages/components/src/formControls/InputText/InputText.tsx b/packages/components/src/formControls/InputText/InputText.tsx index 146c355f..df20647b 100644 --- a/packages/components/src/formControls/InputText/InputText.tsx +++ b/packages/components/src/formControls/InputText/InputText.tsx @@ -56,4 +56,4 @@ const FormControlInputText = ({ export default FormControlInputText; -export const FormControlInputTextStateful = withStateValue(FormControlInputText); +export const FormControlInputTextStateful = withStateValue(FormControlInputText); diff --git a/packages/components/src/formControls/RadioButtonsList/RadioButtonsList.stories.tsx b/packages/components/src/formControls/RadioButtonsList/RadioButtonsList.stories.tsx new file mode 100644 index 00000000..5b38ae7d --- /dev/null +++ b/packages/components/src/formControls/RadioButtonsList/RadioButtonsList.stories.tsx @@ -0,0 +1,70 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { action } from 'storybook/actions'; + +import { DIRECTION } from './RadioButtonsList.types'; +import { RadioButtonsListStateful } from './RadioButtonsList'; + +const meta: Meta = { + component: RadioButtonsListStateful, + parameters: { + layout: 'centered', + }, + tags: ['autodocs', 'foundation', 'base'], + argTypes: { + className: { control: 'text' }, + direction: { + control: 'select', + options: Object.values(DIRECTION), + }, + items: { control: false }, + }, + args: { + onChange: action('on-change'), + value: 'item1', + items: [ + { id: 'item1', label: 'Item 1', value: 'item1' }, + { id: 'item2', label: 'Item 2', value: 'item2' }, + { id: 'item3', label: 'Item 3', value: 'item3' }, + ], + }, +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + name: 'Default', + args: { + label: 'Choice Inputs List Label', + helperText: 'This is a helper text', + }, +}; + +export const Horizontal: Story = { + name: 'Horizontal', + args: { + label: 'Choice Inputs List Label', + helperText: 'This is a helper text', + direction: DIRECTION.HORIZONTAL, + }, +}; + +export const NoHelper: Story = { + name: 'No Helper', + args: { + label: 'Choice Inputs List Label', + }, +}; + +export const NoLabel: Story = { + name: 'No Label', + args: { + helperText: 'This is a helper text', + }, +}; + +export const OnlyItems: Story = { + name: 'Only Items', + args: {}, +}; diff --git a/packages/components/src/formControls/RadioButtonsList/RadioButtonsList.tsx b/packages/components/src/formControls/RadioButtonsList/RadioButtonsList.tsx new file mode 100644 index 00000000..9a46d75a --- /dev/null +++ b/packages/components/src/formControls/RadioButtonsList/RadioButtonsList.tsx @@ -0,0 +1,63 @@ +import React from 'react'; + +import BaseInputsList from '@ids-internal/partials/BaseInputsList'; +import RadioButtonField from '../RadioButtonField'; +import withStateValue from '@ids-internal/hoc/withStateValue'; + +import { DIRECTION, RadioButtonItem, RadioButtonsListProps } from './RadioButtonsList.types'; + +const RadioButtonsList = ({ + className = '', + direction = DIRECTION.VERTICAL, + helperText, + helperTextExtra = {}, + id, + items, + label, + labelExtra = {}, + name, + onChange = () => undefined, + required = false, + value = '', +}: RadioButtonsListProps) => { + const helperTextProps = { + children: helperText, + type: 'default' as const, + ...helperTextExtra, + }; + const labelProps = { + children: label, + error: false, + htmlFor: id, + required, + ...labelExtra, + }; + const renderItem = (item: RadioButtonItem) => { + return ( + { + onChange(item.value); + item.onChange?.(...args); + }} + /> + ); + }; + + return ( + + ); +}; + +export default RadioButtonsList; + +export const RadioButtonsListStateful = withStateValue(RadioButtonsList); diff --git a/packages/components/src/formControls/RadioButtonsList/RadioButtonsList.types.ts b/packages/components/src/formControls/RadioButtonsList/RadioButtonsList.types.ts new file mode 100644 index 00000000..4ffb8f09 --- /dev/null +++ b/packages/components/src/formControls/RadioButtonsList/RadioButtonsList.types.ts @@ -0,0 +1,24 @@ +import { BaseComponentAttributes } from '@ids-types/general'; + +import { DIRECTION } from '@ids-internal/partials/BaseInputsList/BaseInputsList.types'; +import { HelperTextProps } from '../../HelperText/HelperText.types'; +import { LabelProps } from '../../Label/Label.types'; +import { RadioButtonFieldProps } from '../RadioButtonField/RadioButtonField.types'; + +export { DIRECTION }; + +export type RadioButtonItem = Omit; + +export interface RadioButtonsListProps extends BaseComponentAttributes { + id: string; + name: string; + onChange?: (value: string) => void; + direction?: DIRECTION; + helperText?: HelperTextProps['children']; + helperTextExtra?: Omit; + items: RadioButtonItem[]; + label?: LabelProps['children']; + labelExtra?: Omit; + required?: boolean; + value?: string; +} diff --git a/packages/components/src/formControls/RadioButtonsList/index.ts b/packages/components/src/formControls/RadioButtonsList/index.ts new file mode 100644 index 00000000..05de8cc3 --- /dev/null +++ b/packages/components/src/formControls/RadioButtonsList/index.ts @@ -0,0 +1,5 @@ +import RadioButtonsList from './RadioButtonsList'; +import { RadioButtonsListProps } from './RadioButtonsList.types'; + +export default RadioButtonsList; +export type { RadioButtonsListProps }; diff --git a/packages/components/src/inputs/InputText/InputText.tsx b/packages/components/src/inputs/InputText/InputText.tsx index 867291f1..a80000f0 100644 --- a/packages/components/src/inputs/InputText/InputText.tsx +++ b/packages/components/src/inputs/InputText/InputText.tsx @@ -119,4 +119,4 @@ const InputText = ({ export default InputText; -export const InputTextStateful = withStateValue(InputText); +export const InputTextStateful = withStateValue(InputText); diff --git a/packages/components/src/inputs/RadioButton/RadioButton.stories.tsx b/packages/components/src/inputs/RadioButton/RadioButton.stories.tsx index 4fbe83fd..baf78462 100644 --- a/packages/components/src/inputs/RadioButton/RadioButton.stories.tsx +++ b/packages/components/src/inputs/RadioButton/RadioButton.stories.tsx @@ -23,6 +23,7 @@ const meta: Meta = { }, }, args: { + value: 'value1', onBlur: action('on-blur'), onChange: action('on-change'), onFocus: action('on-focus'), diff --git a/packages/components/src/inputs/RadioButton/RadioButton.types.ts b/packages/components/src/inputs/RadioButton/RadioButton.types.ts index f6c02a4c..17ea4779 100644 --- a/packages/components/src/inputs/RadioButton/RadioButton.types.ts +++ b/packages/components/src/inputs/RadioButton/RadioButton.types.ts @@ -1,3 +1,5 @@ import { BaseChoiceInputProps } from '@ids-internal/partials/BaseChoiceInput'; -export type RadioButtonProps = Omit; +export type RadioButtonProps = Omit & { + value: string; +}; diff --git a/packages/components/src/internal/hoc/withStateValue.tsx b/packages/components/src/internal/hoc/withStateValue.tsx index c9c45cac..7fb717d4 100644 --- a/packages/components/src/internal/hoc/withStateValue.tsx +++ b/packages/components/src/internal/hoc/withStateValue.tsx @@ -1,18 +1,20 @@ import React, { FC, useState } from 'react'; type OnChangeFn = (value: T, ...args: any[]) => any; // eslint-disable-line @typescript-eslint/no-explicit-any -interface WrappedComponentProps { + +interface BaseProps { onChange?: OnChangeFn; value: T; - [key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any } +export type WrappedComponentProps = BaseProps & Props; + // eslint-disable-next-line @typescript-eslint/no-explicit-any -export default (WrappedComponent: FC) => { - const WrapperComponent = ({ value, onChange, ...restProps }: WrappedComponentProps) => { +export default (WrappedComponent: FC) => { + const WrapperComponent = ({ value, onChange, ...restProps }: WrappedComponentProps) => { const [componentValue, setComponentValue] = useState(value); - const handleChange = (...args: Parameters>): ReturnType> => { + const handleChange = (...args: Parameters>): ReturnType> => { setComponentValue(args[0]); if (onChange) {