This repository has been archived by the owner on Oct 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add useCharacterCount to create controlled components (#369)
* Skip themekit and pronouns story for lostpixel
- Loading branch information
1 parent
c2333cd
commit 1921d41
Showing
5 changed files
with
136 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
src/utils/hooks/useCharacterCount/useCharacterCount.state.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
export interface CharacterCountState { | ||
error?: boolean; | ||
warning?: boolean; | ||
remainingCharacters?: number; | ||
} | ||
|
||
export type UserAction = | ||
| { type: 'SET_ERROR'; payload?: undefined } | ||
| { type: 'SET_WARNING'; payload?: undefined } | ||
| { type: 'RESET_STATUS'; payload?: undefined } | ||
| { type: 'SET_REMAINING_CHARACTERS'; payload: number }; | ||
|
||
export function reducer( | ||
state: CharacterCountState, | ||
{ type, payload }: UserAction | ||
): CharacterCountState { | ||
switch (type) { | ||
case 'SET_ERROR': | ||
return { | ||
...state, | ||
error: true, | ||
warning: false, | ||
}; | ||
case 'SET_WARNING': | ||
return { | ||
...state, | ||
warning: true, | ||
error: false, | ||
}; | ||
case 'RESET_STATUS': | ||
return { | ||
...state, | ||
warning: false, | ||
error: false, | ||
}; | ||
case 'SET_REMAINING_CHARACTERS': | ||
return { | ||
...state, | ||
remainingCharacters: payload, | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { useReducer, useCallback } from 'react'; | ||
|
||
import { | ||
reducer, | ||
CharacterCountState, | ||
UserAction, | ||
} from './useCharacterCount.state'; | ||
|
||
export interface UseCharacterCountInit { | ||
value?: string; | ||
/** Max number of characters allowed */ | ||
maxCharacters?: number; | ||
/** Shows warning color when threshold is met */ | ||
warningThreshold?: number; | ||
} | ||
|
||
export interface UseCharacterCount { | ||
state: CharacterCountState; | ||
dispatch: React.Dispatch<UserAction>; | ||
handleChange: (value: string) => void; | ||
clean: () => void; | ||
} | ||
|
||
/** | ||
* Based on withCharacterCount, this provides handlers for a character count message to create a controlled component. | ||
* Helpful to use in conjuction with custom inputs that need more control of input messages | ||
*/ | ||
|
||
export function useCharacterCount({ | ||
maxCharacters = 10, | ||
warningThreshold = 5, | ||
}: UseCharacterCountInit): UseCharacterCount { | ||
const [state, dispatch] = useReducer(reducer, { | ||
remainingCharacters: maxCharacters, | ||
}); | ||
|
||
function handleError() { | ||
dispatch({ | ||
type: 'SET_ERROR', | ||
}); | ||
} | ||
|
||
function handleWarn() { | ||
dispatch({ | ||
type: 'SET_WARNING', | ||
}); | ||
} | ||
|
||
const clean = useCallback(() => { | ||
dispatch({ | ||
type: 'RESET_STATUS', | ||
}); | ||
}, []); | ||
|
||
const handleChange = useCallback( | ||
(value: string) => { | ||
const remaining = maxCharacters - value.length; | ||
if (remaining <= warningThreshold && remaining > 0) | ||
handleWarn(); | ||
else if (remaining <= 0) handleError(); | ||
else clean(); | ||
|
||
dispatch({ | ||
type: 'SET_REMAINING_CHARACTERS', | ||
payload: remaining, | ||
}); | ||
}, | ||
[clean, maxCharacters, warningThreshold] | ||
); | ||
|
||
return { | ||
state, | ||
dispatch, | ||
handleChange, | ||
clean, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters