diff --git a/src/attribute-context.tsx b/src/attribute-context.tsx index 5f3ba19..b31cf9b 100644 --- a/src/attribute-context.tsx +++ b/src/attribute-context.tsx @@ -10,6 +10,10 @@ export type AttributeContextType = { * requests multiple options */ options: T[]; + /** + * A callback function that will remove an item from the options at the index + */ + remove?: (index: number) => void; }; /** diff --git a/src/list-group.tsx b/src/list-group.tsx index 4d9b806..75b72d6 100644 --- a/src/list-group.tsx +++ b/src/list-group.tsx @@ -37,14 +37,23 @@ const useArrayAttribute = createUseAttributeHook((value) => value); export function useListAttribute(attribute: string, newItem: () => T) { const { id, error, value, set } = useArrayAttribute(attribute, []); const add = () => set([...value, newItem()]); + const remove = (index: number) => { + // Only attempt to remove the item from the array if its a valid array + // index `splice` will throw errors for out of range. + if (index > -1 && index < value.length) { + const newValue = [...value]; + newValue.splice(index, 1); + set(newValue); + } + }; - return { id, error, value, set, add }; + return { id, error, value, set, add, remove }; } export const ListGroup: FC = ({ children, attribute, newItem }) => { - const { value: options, add } = useListAttribute(attribute, newItem || defaultNewItem); + const { value: options, add, remove } = useListAttribute(attribute, newItem || defaultNewItem); - return React.createElement(AttributeContextProvider, { attribute, options }, children({ add })); + return React.createElement(AttributeContextProvider, { attribute, options, remove }, children({ add })); }; ListGroup.defaultProps = { @@ -56,6 +65,10 @@ export interface ListOptionChildProps { * The index this option is at */ index: string; + /** + * Callback that will remove the current item from the list + */ + remove: () => void; } export interface ListOptionProps { @@ -66,13 +79,14 @@ export interface ListOptionProps { } export const ListOption: FC = ({ children }) => { - const { options } = useAttributeContext(); + const { options, remove } = useAttributeContext(); return ( <> {Object.keys(options).map((index) => children({ index, + remove: () => remove?.(parseInt(index)), }) )} diff --git a/tests/list-group.spec.tsx b/tests/list-group.spec.tsx index b1fb5c5..b95470b 100644 --- a/tests/list-group.spec.tsx +++ b/tests/list-group.spec.tsx @@ -13,17 +13,18 @@ it("will render and submit with a radio list", async () => { {({ add }) => (
- {({ index }) => ( -
- - {({ props }) => ( -
- - -
- )} -
-
+ {({ index, remove }) => ( + + {({ props }) => ( +
+ + + +
+ )} +
)}