Skip to content

Commit 086ee77

Browse files
committed
fix: Fixed add and remove logic. Added comments.
1 parent b95db3b commit 086ee77

3 files changed

Lines changed: 18 additions & 11 deletions

File tree

src/Button.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import React from 'react';
44
export function Button(props: {
55
label: string;
66
onClicked?: () => void;
7+
id?: string;
78
}) {
8-
const { isFocused } = useFocus({});
9+
const { isFocused } = useFocus(props.id ? { id: props.id } : {});
910
useInput((input, key) => {
1011
if (key.return && isFocused) {
1112
props.onClicked?.();

src/Form.tsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ export const Form: React.FC<FormProps> = props => {
1616
const [currentTab, setCurrentTab] = useState(0);
1717
const [isSubmitted, setIsSubmitted] = useState(false);
1818
const [sections, setSections] = useState(props.form.sections);
19+
const form = { ...props.form, sections }
1920
const [value, setValue] = useState<Array<Record<string, unknown>>>(props.value ?? Array.from({ length: sections.length }, () => ({})));
2021
const [editingField, setEditingField] = useState<string>();
21-
const canSubmitForm = useMemo(() => canSubmit(props.form, value), [value, props.form]);
22+
const canSubmitForm = useMemo(() => canSubmit(form, value), [value, form]);
2223
const focusManager = useFocusManager();
2324
const [focusedElement, setFocusedElement] = useState(0);
2425
const headerRef = useRef();
2526
const headerHeight = headerRef.current ? measureElement(headerRef.current).height : 5
27+
const [, fullHeight] = useStdoutDimensions()
2628

2729
useEffect(() => {
2830
focusManager.enableFocus();
@@ -45,7 +47,7 @@ export const Form: React.FC<FormProps> = props => {
4547
}
4648
}, []);
4749

48-
const onChangeTab = (tab) => {
50+
const onChangeTab = (tab: number) => {
4951
setCurrentTab(tab);
5052
focusManager.focus('0');
5153
setFocusedElement(0)
@@ -67,6 +69,8 @@ export const Form: React.FC<FormProps> = props => {
6769
setFocusedElement((focusedElement) => focusedElement - 1);
6870
focusManager.focusPrevious();
6971
} else if (key.downArrow) {
72+
// This calculates the maximum amount of children there is. We don't want to scroll past the last item
73+
// Fields.length is number of json fields. 2 is the add and remove buttons. Submit button is sometimes focusable
7074
if (focusedElement + 1 > sections[currentTab].fields.length + 2 + (canSubmitForm ? 1 : 0)) {
7175
return;
7276
}
@@ -96,18 +100,17 @@ export const Form: React.FC<FormProps> = props => {
96100

97101
setSections(newTabs);
98102
setValue([...value]);
103+
onChangeTab(currentTab - 1)
99104
}
100105

101-
const [, fullHeight] = useStdoutDimensions()
102-
103106
return (
104107
<FullScreen>
105108
<Box width="100%" height="90%" flexDirection="column" overflowY="hidden">
106-
<FormHeader {...props} headerRef={headerRef} form={{ ...props.form, sections }} currentTab={currentTab} onChangeTab={onChangeTab} editingField={editingField} />
109+
<FormHeader {...props} headerRef={headerRef} form={form} currentTab={currentTab} onChangeTab={onChangeTab} editingField={editingField} />
107110
<ScrollArea height={fullHeight - headerHeight} key={currentTab} isStart={focusedElement === 0}>
108111
{!editingField && sections[currentTab].description && (
109112
<Box marginX={4}>
110-
<DescriptionRenderer description={props.form.sections[currentTab]?.description} />
113+
<DescriptionRenderer description={sections[currentTab]?.description} />
111114
</Box>
112115
)}
113116
{!editingField && (
@@ -119,14 +122,14 @@ export const Form: React.FC<FormProps> = props => {
119122
</Box>
120123
)}
121124
<Box flexDirection="column">
122-
{currentTab > props.form.sections.length - 1
125+
{currentTab > sections.length - 1
123126
? null
124127
: sections[currentTab].fields.map((field, index) => (
125128
<FormFieldRenderer
126129
id={index + ''}
127130
field={field}
128131
key={field.name + currentTab}
129-
form={props.form}
132+
form={form}
130133
value={value[currentTab][field.name]}
131134
onChange={v => setValueAndPropagate(currentTab, { ...value[currentTab], [field.name]: v })}
132135
onSetEditingField={setEditingField}
@@ -138,10 +141,10 @@ export const Form: React.FC<FormProps> = props => {
138141
<Text>{' }'}</Text>
139142
)}
140143
<Box flexDirection="row-reverse">
141-
<Button label="Add Item (duplicate)" onClicked={() => duplicateCurrentItem()}/>
144+
<Button label="Add (duplicate)" id={'addButton'} onClicked={() => duplicateCurrentItem()}/>
142145
</Box>
143146
<Box flexDirection="row-reverse">
144-
<Button label="Remove" onClicked={() => removeCurrentItem()}/>
147+
<Button label="Remove" id={'removeButton'} onClicked={() => removeCurrentItem()}/>
145148
</Box>
146149
</Box>
147150
{!editingField && (

src/ScrollArea.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ export function ScrollArea({height, isStart, children}) {
4747
const innerRef = React.useRef();
4848

4949
useLayoutEffect(() => {
50+
// Couple of custom logic baked into here to improve the user experience
51+
// isStart ensures that the first down event will not scroll. This is because initially nothing has focus so the first down gives focus to the first element
52+
// The children.length calculation calculates a rough estimate of the total height. The 3 is the height of the buttons at the bottom.
5053
if (isStart || (children.length) * 1 + 3 * 3 < (height - 6)) {
5154
setCanScroll(false);
5255
dispatch({

0 commit comments

Comments
 (0)