UNPKG

@netdata/netdata-ui

Version:

netdata UI kit

182 lines (152 loc) 6.58 kB
## Input Currently only of type "text", as other types may need some special tweaks and implementations. ### How to use The `<TextInput>` implementation intended to be minimalistic, and mostly concentrated on applying props and props-dependent variablis to layout and styling. The `InputProps` type indicated props applied to the underlying `input` element, `ComponentProps` - those needed for layouting, state calculations and other means. Keep in mind, that the component is **uncontrolled** and requires hooks/wrappers to function. Additional event handlers and any other valid `HTMLInputElement` props could be applied to the underlying input by just passing them explicitly to the <TextInput />. ```typescript type CallBackRef = (input: any) => void export interface InputProps { onChange: (e: ChangeEvent<HTMLInputElement>) => void onFocus?: (e: FocusEvent) => void onBlur?: (e: FocusEvent) => void onKeyDown?: (e: KeyboardEvent<HTMLInputElement>) => void value: string inputRef?: MutableRefObject<HTMLInputElement | null> | CallBackRef disabled?: boolean iconLeft?: ReactNode iconRight?: ReactNode name?: string placeholder?: string autoFocus?: boolean } export interface MetaOptions { error?: boolean | string success?: boolean | string touched?: boolean isDirty?: boolean instantFeedback?: InstantFeedback prevValue: string | undefined value: string focused?: boolean } export interface ComponentProps { hint?: string error?: boolean | string success?: boolean | string touched?: boolean isDirty?: boolean instantFeedback?: "all" | "positiveFirst" className?: string fieldIndicator?: string | ReactNode metaShrinked?: boolean label?: string handleMetaDisplay?: (metaOptions: MetaOptions) => boolean } export type TextInputProps = InputProps & ComponentProps ``` Notable props: - `hint` - default message under the input field - `success` and `error` - status indicators, could be boolean or strings (in this case they render instead of `hint`) - `instantFeedback` - set this to true, if you want to provide validation status as user types, not onBlur/other. With `all` updates validation status on any value change, with `positiveFirst` - only when string is successfully validated (`success` prop), or user started to erase entered data and current string has errors according to `error` prop. - `isDirty` - boolean flag showing if something was ever entered into the input. Use together with instantFeedback. - `metaShrinked` - set this to true to not render any meta information and reserved space under the input field - `fieldIndicator` - additional information field, which could be used for displaying `maxChars` string or other meta info. - `handleMetaDisplay` - if instantFeedback / touched and default built-in logic is not suitable for some sophisticated usecases, this function could be used for full control over error/success display. ### Meta Display This API is provided to control the display of error/success (meta) feedback for the input. ```typescript export interface MetaOptions { error?: boolean | string success?: boolean | string touched?: boolean isDirty?: boolean instantFeedback?: InstantFeedback prevValue: string | undefined value: string focused?: boolean } ``` `handleMetaDisplay` function accepts the above arguments passed by the input internally. They include both props, and implementation-level values known only to the TextInput. Here is provided the default behaviour, which could be overriden using the same pattern: ```typescript const defaultHandleMetaDisplay = ({ isDirty, instantFeedback, value, prevValue, error, success, touched, }: MetaOptions) => touched || Boolean(instantFeedback === "all" && isDirty) || Boolean(instantFeedback === "positiveFirst" && isDirty && success) || Boolean( instantFeedback === "positiveFirst" && isDirty && error && prevValue && value.length < prevValue.length ) ``` ### Exposed hooks and application-level wrapping ```typescript type FocusHandler = FocusEventHandler type BlurHandler = FocusEventHandler type FocusedState = boolean type UseFocusedState = ({ onBlur, onFocus, defaultState, }: { onBlur?: FocusEventHandler onFocus?: FocusEventHandler defaultState?: boolean }) => [FocusedState, FocusHandler, BlurHandler] ``` `useFocusedState` hook is being used internally by the `<TextInput/>`, so normally you can just pass the custom blur/focus handlers to the component, and work with side effects as with default `<input />` tag. ```typescript type BlurHandler = FocusEventHandler type TouchedState = boolean type SetTouchedState = React.Dispatch<React.SetStateAction<boolean>> type UseTouchedState = ({ onBlur, defaultState, }: { onBlur?: BlurHandler defaultState?: boolean }) => [TouchedState, BlurHandler, SetTouchedState] ``` `useTouchedState` hook could be useful working with touched/untouched functionality in validated forms. It allows to manage the success and error feedback shown to the user. Apart from value and handler, it also exposes the programmatic method to set `touched` state for the input. TBD if we will use it, or procees with custom event-oriented form touch. ```typescript type InputValue = string type MaxCharsIndicator = string type IsDirty = boolean type UseInputValue = ({ value, onChange, maxChars, }: { value?: string onChange?: ChangeEventHandler maxChars?: number }) => [InputValue, ChangeEventHandler, MaxCharsIndicator, IsDirty] ``` `useInputValue` hook is a short way to add basic functionaluty to the `<TextInput />` - a controlled state for input value, and custom side-effects handling for onChange. If `maxChars` option is passed, it will also return a quantity of entered symbols in relation to maximum allowed `as string`. `isDirty` flag indicates if value was changed at least once, required for `instantFeedback` inputs to work properly. ### Further improvements TBD We may include existing convenience hooks/wrappers and write additional ones (for setting value directly to Redux, for instance). However, for now we need some data on how the control will be used in applications. For validation handling, there could be a hook, but we need to be very specific about the API. Right now it's possible to use the `<TextInput/>` together with any library, so when we will decide on our forms library or custom approach, we may start adding wrappers to the `netdata-ui`. For now it's better to leave convenience wrapping to the application-level code.