ink-form
Version:
Complex user-friendly form component for React Ink
59 lines (58 loc) • 3.01 kB
JavaScript
import { Box, useFocusManager, useInput } from 'ink';
import { useEffect, useMemo, useState } from 'react';
import * as React from 'react';
import { FormHeader } from './FormHeader.js';
import { FormFieldRenderer } from './FormFieldRenderer.js';
import { DescriptionRenderer } from './DescriptionRenderer.js';
import { canSubmit } from './canSubmit.js';
import { SubmitButton } from './SubmitButton.js';
export const Form = props => {
const isControlled = props.value !== undefined;
const [currentTab, setCurrentTab] = useState(0);
const [value, setValue] = useState(props.value ?? {});
const [editingField, setEditingField] = useState();
const canSubmitForm = useMemo(() => canSubmit(props.form, value), [value, props.form]);
const focusManager = useFocusManager();
useEffect(() => {
focusManager.enableFocus();
}, []);
useEffect(() => {
if (props.value) {
setValue(props.value);
}
}, [props.value]);
useEffect(() => {
// Set initial values
if (!isControlled) {
setValueAndPropagate({
...value,
...props.form.sections
.map(section => section.fields
.map(field => (field.initialValue !== undefined ? { [field.name]: field.initialValue } : {}))
.reduce((obj1, obj2) => ({ ...obj1, ...obj2 }), {}))
.reduce((obj1, obj2) => ({ ...obj1, ...obj2 }), {}),
});
}
}, []);
const setValueAndPropagate = (value) => {
setValue(value);
props.onChange?.(value);
};
useInput((input, key) => {
if (key.upArrow) {
focusManager.focusPrevious();
}
else if (key.downArrow) {
focusManager.focusNext();
}
}, { isActive: !editingField });
return (React.createElement(Box, { width: "100%", height: "100%", flexDirection: "column" },
React.createElement(FormHeader, { ...props, currentTab: currentTab, onChangeTab: setCurrentTab, editingField: editingField }),
!editingField && props.form.sections[currentTab].description && (React.createElement(Box, { marginX: 4 },
React.createElement(DescriptionRenderer, { description: props.form.sections[currentTab].description }))),
React.createElement(Box, { flexDirection: "column" }, currentTab > props.form.sections.length - 1
? null
: props.form.sections[currentTab].fields.map(field => (React.createElement(FormFieldRenderer, { field: field, key: field.name, form: props.form, value: value[field.name], onChange: v => setValueAndPropagate({ ...value, [field.name]: v }), onSetEditingField: setEditingField, editingField: editingField, customManagers: props.customManagers })))),
!editingField && (React.createElement(Box, { flexDirection: "row-reverse" },
React.createElement(SubmitButton, { canSubmit: canSubmitForm, onSubmit: () => props.onSubmit?.(value) })))));
};