diff --git a/src/fields/Checkbox.tsx b/src/fields/Checkbox.tsx new file mode 100644 index 000000000..705350c55 --- /dev/null +++ b/src/fields/Checkbox.tsx @@ -0,0 +1,35 @@ +import { useCallback, useMemo } from 'react' +import { Checkbox as RsuiteCheckbox } from 'rsuite' + +import type { CheckboxProps as RsuiteCheckboxProps } from 'rsuite' +import type { ValueType } from 'rsuite/esm/Checkbox' +import type { Promisable } from 'type-fest' + +export type CheckboxProps = Omit & { + label: string + name: string + onChange?: (isCheched: boolean) => Promisable +} +export function Checkbox({ label, onChange, ...originalProps }: CheckboxProps) { + const key = useMemo( + () => `${originalProps.name}-${String(originalProps.defaultChecked)}`, + [originalProps.defaultChecked, originalProps.name] + ) + + const handleChange = useCallback( + (_: ValueType | undefined, isChecked: boolean) => { + if (!onChange) { + return + } + + onChange(isChecked) + }, + [onChange] + ) + + return ( + + {label} + + ) +} diff --git a/src/fields/DatePicker/index.tsx b/src/fields/DatePicker/index.tsx index b971f9f1f..0bb9ebce9 100644 --- a/src/fields/DatePicker/index.tsx +++ b/src/fields/DatePicker/index.tsx @@ -33,7 +33,7 @@ export type DatePickerProps = { * * @param nextUtcDateRange - A utcized date to be used as is to interact with the API. */ - onChange: (nextUtcDate: Date) => Promisable + onChange?: (nextUtcDate: Date) => Promisable withTime?: boolean } export function DatePicker({ @@ -66,7 +66,7 @@ export function DatePicker({ ) const submit = useCallback(() => { - if (!selectedDateRef.current) { + if (!onChange || !selectedDateRef.current) { return } diff --git a/src/fields/DateRangePicker/index.tsx b/src/fields/DateRangePicker/index.tsx index f756d3e8c..4fb4adb37 100644 --- a/src/fields/DateRangePicker/index.tsx +++ b/src/fields/DateRangePicker/index.tsx @@ -34,7 +34,7 @@ export type DateRangePickerProps = { * * @param nextUtcDateRange - A utcized date to be used as is to interact with the API. */ - onChange: (nextUtcDateRange: DateRange) => Promisable + onChange?: (nextUtcDateRange: DateRange) => Promisable withTime?: boolean } export function DateRangePicker({ @@ -79,7 +79,7 @@ export function DateRangePicker({ ) const submit = useCallback(() => { - if (!selectedStartDateRef.current || !selectedEndDateRef.current) { + if (!onChange || !selectedStartDateRef.current || !selectedEndDateRef.current) { return } diff --git a/src/fields/Select.tsx b/src/fields/Select.tsx index ce6daa03b..99a2774e7 100644 --- a/src/fields/Select.tsx +++ b/src/fields/Select.tsx @@ -1,28 +1,39 @@ -import { useCallback } from 'react' +import { useCallback, useMemo } from 'react' import { SelectPicker, TagPicker } from 'rsuite' import styled from 'styled-components' import type { Option } from '../types' -import type { TagPickerProps } from 'rsuite' +import type { SelectPickerProps as RsuiteSelectPickerProps, TagPickerProps } from 'rsuite' import type { Promisable } from 'type-fest' -export type SelectProps = Omit & { - isMulti?: boolean - label: string +type SelectCommonProps = { name: string - onChange: (valueOrValues: string | string[] | undefined) => Promisable options: Option[] } +export type MultiSelectProps = Omit & + SelectCommonProps & { + isMulti: true + onChange?: (values: string[] | undefined) => Promisable + } +export type SingleSelectProps = Omit, 'as' | 'data' | 'onChange' | 'value'> & + SelectCommonProps & { + isMulti?: false + onChange?: (value: string | undefined) => Promisable + } +export type SelectProps = MultiSelectProps | SingleSelectProps export function Select({ isMulti = false, - label, - name, onChange, options, // eslint-disable-next-line @typescript-eslint/naming-convention searchable = false, ...originalProps }: SelectProps) { + const key = useMemo( + () => `${originalProps.name}-${JSON.stringify(originalProps.defaultValue)}`, + [originalProps.defaultValue, originalProps.name] + ) + const handleChange = useCallback( (valueOrValues: string | string[] | null) => { if (!onChange) { @@ -32,30 +43,22 @@ export function Select({ const normalizedValueOrValues = !valueOrValues || (Array.isArray(valueOrValues) && !valueOrValues.length) ? undefined : valueOrValues - onChange(normalizedValueOrValues) + ;(onChange as (valueOrValues: string | string[] | undefined) => Promisable)(normalizedValueOrValues) }, [onChange] ) if (isMulti) { - return ( - - ) + return } return ( ) => void) | undefined` onChange={handleChange as any} - placeholder={label} searchable={searchable} {...originalProps} /> diff --git a/src/formiks/FormikSelect.tsx b/src/formiks/FormikSelect.tsx index a6068f073..e3aaa4099 100644 --- a/src/formiks/FormikSelect.tsx +++ b/src/formiks/FormikSelect.tsx @@ -5,7 +5,7 @@ import { Select } from '../fields/Select' import type { SelectProps } from '../fields/Select' -export type FormikSelectProps = Omit & { +export type FormikSelectProps = Omit & { name: string } export function FormikSelect({ name, ...originalProps }: FormikSelectProps) { diff --git a/src/index.ts b/src/index.ts index ff930bb43..73cddd815 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,12 @@ export * as MUI from './constants' export { THEME } from './theme' +export { Checkbox } from './fields/Checkbox' export { DateRangePicker } from './fields/DateRangePicker' export { DatePicker } from './fields/DatePicker' export { Select } from './fields/Select' +// export { FormikCheckbox } from './formiks/FormikCheckbox' export { FormikDatePicker } from './formiks/FormikDatePicker' export { FormikDateRangePicker } from './formiks/FormikDateRangePicker' export { FormikEffect } from './formiks/FormikEffect' @@ -14,10 +16,12 @@ export { ThemeProvider } from './ThemeProvider' export type { PartialTheme, Theme } from './theme' +export type { CheckboxProps } from './fields/Checkbox' export type { DateRangePickerProps } from './fields/DateRangePicker' export type { DatePickerProps } from './fields/DatePicker' export type { SelectProps } from './fields/Select' +// export type { FormikCheckboxProps } from './formiks/FormikCheckbox' export type { FormikDatePickerProps } from './formiks/FormikDatePicker' export type { FormikDateRangePickerProps } from './formiks/FormikDateRangePicker' export type { FormikEffectProps } from './formiks/FormikEffect' diff --git a/stories/fields/Checkbox.stories.tsx b/stories/fields/Checkbox.stories.tsx new file mode 100644 index 000000000..8a5bcf4b4 --- /dev/null +++ b/stories/fields/Checkbox.stories.tsx @@ -0,0 +1,31 @@ +import { useState } from 'react' + +import { Checkbox } from '../../src' +import { Output } from '../_components/Output' + +import type { CheckboxProps } from '../../src' + +export default { + title: 'Fields/Checkbox', + component: Checkbox, + + argTypes: {}, + + args: { + defaultChecked: false, + label: 'Check me', + name: 'myCheckbox' + } as CheckboxProps +} + +export const _Checkbox = (props: CheckboxProps) => { + const [outputValue, setOutputValue] = useState('∅') + + return ( + <> + + + {outputValue !== '∅' && } + + ) +} diff --git a/stories/fields/DatePicker.stories.tsx b/stories/fields/DatePicker.stories.tsx index 07f115637..269105c90 100644 --- a/stories/fields/DatePicker.stories.tsx +++ b/stories/fields/DatePicker.stories.tsx @@ -5,18 +5,20 @@ import { Output } from '../_components/Output' import type { DatePickerProps } from '../../src' +const args: DatePickerProps = { + isHistorical: false, + isLabelHidden: false, + label: 'A Date', + withTime: true +} + export default { title: 'Fields/DatePicker', component: DatePicker, argTypes: {}, - args: { - isHistorical: false, - isLabelHidden: false, - label: 'DatePicker Label', - withTime: true - } + args } export const _DatePicker = (props: DatePickerProps) => { diff --git a/stories/fields/DateRangePicker.stories.tsx b/stories/fields/DateRangePicker.stories.tsx index bb1d24e52..270ac3e79 100644 --- a/stories/fields/DateRangePicker.stories.tsx +++ b/stories/fields/DateRangePicker.stories.tsx @@ -6,18 +6,20 @@ import { Output } from '../_components/Output' import type { DateRangePickerProps } from '../../src' import type { DateRange } from '../../src/types' +const args: DateRangePickerProps = { + isHistorical: false, + isLabelHidden: false, + label: 'A Date Range', + withTime: true +} + export default { title: 'Fields/DateRangePicker', component: DateRangePicker, argTypes: {}, - args: { - isHistorical: false, - isLabelHidden: false, - label: 'DateRangePicker Label', - withTime: true - } + args } export const _DateRangePicker = (props: DateRangePickerProps) => { diff --git a/stories/fields/Select.stories.tsx b/stories/fields/Select.stories.tsx index d83cf44d3..019c1b4f7 100644 --- a/stories/fields/Select.stories.tsx +++ b/stories/fields/Select.stories.tsx @@ -5,20 +5,25 @@ import { Output } from '../_components/Output' import type { SelectProps } from '../../src' +const args: SelectProps = { + defaultValue: 'FIRST_OPTION', + isMulti: false, + placeholder: 'Pick an option', + name: 'mySelect', + options: [ + { label: 'First Option', value: 'FIRST_OPTION' }, + { label: 'Second Option', value: 'SECOND_OPTION' }, + { label: 'Third Option', value: 'THIRD_OPTION' } + ] +} + export default { title: 'Fields/Select', component: Select, argTypes: {}, - args: { - isMulti: false, - options: [ - { label: 'First Option', value: 'FIRST_OPTION' }, - { label: 'Second Option', value: 'SECOND_OPTION' }, - { label: 'Third Option', value: 'THIRD_OPTION' } - ] - } + args } export const _Select = (props: SelectProps) => { diff --git a/stories/formiks/FormikDatePicker.stories.tsx b/stories/formiks/FormikDatePicker.stories.tsx index 4a7ac0dd8..0991a54dc 100644 --- a/stories/formiks/FormikDatePicker.stories.tsx +++ b/stories/formiks/FormikDatePicker.stories.tsx @@ -7,19 +7,21 @@ import { noop } from '../_utils/noop' import type { FormikDatePickerProps } from '../../src' +const args: FormikDatePickerProps = { + isHistorical: false, + isLabelHidden: false, + label: 'A Date', + name: 'myDate', + withTime: false +} + export default { title: 'Formiks/FormikDatePicker', component: FormikDatePicker, argTypes: {}, - args: { - isHistorical: false, - isLabelHidden: false, - label: 'FormikDatePicker Label', - name: 'myDate', - withTime: false - } + args } export const _FormikDatePicker = (props: FormikDatePickerProps) => { diff --git a/stories/formiks/FormikDateRangePicker.stories.tsx b/stories/formiks/FormikDateRangePicker.stories.tsx index 69168f759..e302ca377 100644 --- a/stories/formiks/FormikDateRangePicker.stories.tsx +++ b/stories/formiks/FormikDateRangePicker.stories.tsx @@ -8,19 +8,21 @@ import { noop } from '../_utils/noop' import type { FormikDateRangePickerProps } from '../../src' import type { DateRange } from '../../src/types' +const args: FormikDateRangePickerProps = { + isHistorical: false, + isLabelHidden: false, + label: 'A Date Range', + name: 'myDateRange', + withTime: false +} + export default { title: 'Formiks/FormikDateRangePicker', component: FormikDateRangePicker, argTypes: {}, - args: { - isHistorical: false, - isLabelHidden: false, - label: 'FormikDateRangePicker Label', - name: 'myDateRange', - withTime: false - } + args } export const _FormikDateRangePicker = (props: FormikDateRangePickerProps) => { diff --git a/stories/formiks/FormikSelect.stories.tsx b/stories/formiks/FormikSelect.stories.tsx index 33a621e5d..566cfc012 100644 --- a/stories/formiks/FormikSelect.stories.tsx +++ b/stories/formiks/FormikSelect.stories.tsx @@ -7,21 +7,24 @@ import { noop } from '../_utils/noop' import type { FormikSelectProps } from '../../src' +const args: FormikSelectProps = { + isMulti: false, + placeholder: 'Pick an option', + name: 'mySelect', + options: [ + { label: 'First Option', value: 'FIRST_OPTION' }, + { label: 'Second Option', value: 'SECOND_OPTION' }, + { label: 'Third Option', value: 'THIRD_OPTION' } + ] +} + export default { title: 'Formiks/FormikSelect', component: FormikSelect, argTypes: {}, - args: { - isMulti: false, - name: 'mySelect', - options: [ - { label: 'First Option', value: 'FIRST_OPTION' }, - { label: 'Second Option', value: 'SECOND_OPTION' }, - { label: 'Third Option', value: 'THIRD_OPTION' } - ] - } + args } export const _FormikSelect = (props: FormikSelectProps) => {