hooks#useUuid TypeScript Examples
The following examples show how to use
hooks#useUuid.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: useIds.tsx From exevo-pan with The Unlicense | 6 votes |
useIds = (): UseIdsObject => {
const tabId = useUuid('tab')
const panelId = useUuid('panel')
const getTabId = useCallback((index: number) => `${index}-${tabId}`, [tabId])
const getPanelId = useCallback(
(index: number) => `${index}-${panelId}`,
[panelId],
)
return { getTabId, getPanelId }
}
Example #2
Source File: index.tsx From exevo-pan with The Unlicense | 5 votes |
Accordion = ({
title,
initialValue = false,
open: openProp,
onClick,
border = false,
children,
...props
}: AccordionProps) => {
const {
translations: { common },
} = useTranslations()
const buttonId = useUuid()
const contentId = useUuid()
const [innerOpen, setOpen] = useState(initialValue)
const open = openProp ?? innerOpen
const handleClick = useCallback(
(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
setOpen((prev) => !prev)
onClick?.(event)
},
[onClick],
)
return (
<div {...props}>
<button
id={buttonId}
type="button"
aria-expanded={open}
aria-controls={contentId}
aria-label={common.Accordion[open ? 'close' : 'open']}
onClick={handleClick}
suppressHydrationWarning
className={clsx(
'text-onSurface text-tsm flex w-full cursor-pointer items-center justify-between transition-all',
border && 'border-separator',
open ? 'py-2' : 'py-1',
)}
style={{
borderBottomStyle: 'solid',
borderBottomWidth: border ? '1px' : 0,
}}
>
{title}
<ArrowIcon
className="fill-onSurface ml-auto shrink-0 rounded transition-all"
style={{ transform: clsx(open && 'rotate(180deg)') }}
/>
</button>
<div id={contentId} aria-describedby={buttonId} suppressHydrationWarning>
{open && children}
</div>
</div>
)
}
Example #3
Source File: index.tsx From exevo-pan with The Unlicense | 5 votes |
LabeledTextBox = ({
className,
children,
labelText,
warning = false,
...props
}: LabeledTextBoxProps) => {
const {
translations: { common },
} = useTranslations()
const labelId = useUuid()
return (
<div
className={clsx(
'border-1 relative rounded-md border-solid px-3 pt-2.5 pb-2',
warning ? 'border-red' : 'border-separator',
className,
)}
aria-labelledby={labelText ? labelId : undefined}
suppressHydrationWarning
{...props}
>
{labelText && (
<span
id={labelId}
suppressHydrationWarning
className={clsx(
'bg-surface absolute top-0 left-2 flex select-none items-center px-1 text-[9px] font-light uppercase tracking-wider',
warning ? 'text-red' : 'text-onSurface',
)}
style={{ transform: 'translateY(-50%)' }}
>
{labelText}
{warning && (
<Image
src={warningSrc}
title={common.WarningLabel}
unoptimized
className={styles.warning}
/>
)}
</span>
)}
{children}
</div>
)
}
Example #4
Source File: index.tsx From exevo-pan with The Unlicense | 5 votes |
TagButton = ({ ...props }: React.HTMLAttributes<HTMLDivElement>) => {
const {
translations: { common },
} = useTranslations()
const [hoverState, setHoverState] = useState<HoveredState>('initial')
const handleHover = useCallback(() => {
setHoverState('hover')
}, [])
const handleUnhover = useCallback(() => {
setHoverState('off')
}, [])
const labelId = useUuid()
return (
<NextLink href={routes.ADVERTISE}>
<div
suppressHydrationWarning
tabIndex={0}
onMouseOver={handleHover}
onFocus={handleHover}
onMouseOut={handleUnhover}
onBlur={handleUnhover}
aria-describedby={labelId}
onClick={(event) => event.stopPropagation()}
className="relative h-11 w-7 shrink-0 cursor-pointer self-start"
{...props}
>
<div
className="z-2 absolute top-1/2 left-1/2 h-[72px] w-16"
style={{ transform: 'translate(-50%, -50%)' }}
/>
<div
className={clsx(
'animate-swing z-1 relative h-full w-full',
hoverState === 'hover' && 'animate-tilt',
hoverState === 'off' && 'animate-letGo',
hoverState === 'initial' && 'animate-swing',
)}
style={{
transformOrigin: '50% 0',
animationDelay: clsx(hoverState === 'initial' && '1s'),
}}
>
<TagIcon
className="h-full w-full"
style={{ filter: 'drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.3)' }}
/>
<AdvertiseIcon
className="z-1 fill-onPrimary absolute h-4 w-4"
style={{
top: 'calc(50% + 6px)',
left: 'calc(50% - 1px)',
transform: 'translate(-50%, -50%)',
}}
/>
</div>
<p
suppressHydrationWarning
id={labelId}
className={clsx(
'text-onSurface absolute bottom-0 left-1/2 text-center text-xs transition-opacity',
hoverState !== 'hover' && 'opacity-0',
)}
style={{ transform: 'translateX(-50%)' }}
>
{common.CharacterCard.highlightLabelText}
</p>
</div>
</NextLink>
)
}
Example #5
Source File: index.tsx From exevo-pan with The Unlicense | 5 votes |
PieChart = ({
title,
pieDataSet,
className,
...props
}: PieChartProps) => {
const titleId = useUuid()
const { colors } = useTheme()
const options = useMemo(
() => ({
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 400,
easing: 'easeOutCubic',
},
legend: {
display: true,
position: 'bottom',
labels: {
fontColor: colors.onSurface,
boxWidth: 12,
},
},
tooltips: {
displayColors: false,
callbacks: {
label: (
tooltipItem: Record<string, number>,
data: Record<string, Record<string, string>[]>,
) => {
const { index } = tooltipItem
return `${data.labels[index]}: ${data.datasets[0].data[index]}%`
},
},
},
}),
[colors],
)
const chartData = useMemo(
() => ({
labels: Object.keys(pieDataSet).map(capitalizeFirstLetter),
datasets: [
{
label: title,
data: Object.keys(pieDataSet).map((item) => pieDataSet[item]),
fill: false,
backgroundColor: chartColors,
borderColor: chartColors,
borderWidth: 0,
},
],
}),
[title, pieDataSet],
)
return (
<section
className={clsx('card p-5 transition-colors', className)}
{...props}
>
<h4
id={titleId}
className="text-onSurface mb-2 text-center text-base font-light"
>
{title}
</h4>
<div aria-describedby={titleId} className="w-full">
<Doughnut data={chartData} options={options} />
</div>
</section>
)
}
Example #6
Source File: index.tsx From exevo-pan with The Unlicense | 4 votes |
Input = ({
className,
style,
allowClear = false,
errorMessage,
value: valueProp,
onChange,
hasAlert = true,
...props
}: InputProps) => {
const {
translations: { common },
} = useTranslations()
const errorId = useUuid()
const [value, setValue] = useState<InputValue>(valueProp ?? '')
const derivedValue = valueProp ?? value
const isClearButtonActive = allowClear && !!derivedValue
const isInvalid = !!errorMessage
const inputRef = useRef<HTMLInputElement>(null)
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setValue(event.target.value)
}
const handleClearClick = () => {
if (inputRef.current) {
if (isClearButtonActive) {
const event = new Event('input', { bubbles: true })
setValue('')
inputRef.current.value = ''
inputRef.current.dispatchEvent(event)
}
inputRef.current.focus()
}
}
const handleInput = (event: React.ChangeEvent<HTMLInputElement>) => {
onChange?.(event)
}
return (
<div className={clsx('text-tsm', className)} style={style}>
<div
className={clsx(
'border-1 bg-surface flex w-full cursor-text rounded-md border-solid transition-colors',
isInvalid
? 'border-red'
: 'border-separator focus-within:border-primary',
)}
onClick={() => inputRef.current?.focus()}
>
<input
ref={inputRef}
value={derivedValue}
onChange={handleChange}
onInput={handleInput}
aria-invalid={isInvalid}
aria-errormessage={isInvalid ? errorId : undefined}
autoComplete="off"
className="text-tsm text-onSurface w-full border-none bg-transparent py-2.5 px-4 outline-none transition-all"
style={{ paddingRight: isClearButtonActive ? 0 : undefined }}
{...props}
/>
{allowClear && (
<button
type="button"
aria-label={common.ClearInputLabel}
disabled={!isClearButtonActive}
aria-hidden={!isClearButtonActive}
onClick={handleClearClick}
className={clsx(
'text-none w-[40px] shrink-0 transition-opacity',
isClearButtonActive
? 'cursor-pointer'
: 'pointer-events-none opacity-0',
)}
>
<ClearIcon className="fill-onSurface h-5 w-5" />
</button>
)}
</div>
{hasAlert && (
<span
id={errorId}
aria-hidden={!isInvalid}
role="alert"
className={clsx(
'text-red px-2.5 text-xs transition-opacity',
!isInvalid && 'opacity-0',
)}
suppressHydrationWarning
>
{errorMessage}
</span>
)}
</div>
)
}
Example #7
Source File: index.tsx From exevo-pan with The Unlicense | 4 votes |
AutocompleteInput = ({
className,
style,
itemList = [],
onItemSelect,
...props
}: AutocompleteInputProps) => {
const listboxId = useUuid()
const [currentList, setCurrentList] = useState<Option[]>(itemList)
const [{ listboxStatus, highlightedIndex, inputValue }, dispatch] =
useReducer(AutocompleteInputReducer, {
listboxStatus: false,
highlightedIndex: undefined,
inputValue: '',
})
const handleChange = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
dispatch({ type: 'USER_TYPING', value: event.target.value })
setCurrentList(filterByTerm(event.target.value, itemList))
},
[itemList],
)
const handleKeyboard: React.KeyboardEventHandler<HTMLInputElement> = (
event,
) => {
switch (event.code) {
case 'Tab':
case 'Escape':
dispatch({ type: 'SET_LISTBOX_STATUS', value: false })
break
case 'ArrowUp':
if (currentList.length)
dispatch({
type: 'ARROW_NAVIGATION',
value: -1,
list: currentList,
})
event.preventDefault()
break
case 'ArrowDown':
if (currentList.length)
dispatch({
type: 'ARROW_NAVIGATION',
value: 1,
list: currentList,
})
event.preventDefault()
break
case 'Enter':
case 'NumpadEnter':
if (currentList.length === 1) {
onItemSelect?.(currentList[0])
dispatch({ type: 'OPTION_SELECTED' })
} else if (highlightedIndex !== undefined) {
onItemSelect?.(currentList[highlightedIndex])
dispatch({ type: 'OPTION_SELECTED' })
}
break
default:
break
}
}
useEffect(() => {
if (highlightedIndex !== undefined) {
const item = document.getElementById(
indexToId(highlightedIndex, listboxId) as string,
)
item?.scrollIntoView({
block: 'nearest',
})
}
}, [highlightedIndex, listboxId])
useEffect(() => {
setCurrentList(itemList)
}, [itemList])
const onSelectOption = useCallback(
(option: Option) => {
onItemSelect?.(option)
dispatch({ type: 'OPTION_SELECTED' })
},
[onItemSelect],
)
return (
<div className={clsx('child:w-full relative', className)} style={style}>
<Popover
placement="bottom"
trigger="none"
visible={listboxStatus}
content={
<Listbox
id={listboxId}
highlightedIndex={highlightedIndex}
onSelectOption={onSelectOption}
className="max-h-[210px]"
>
{currentList.map((item) => (
<Option key={item.value} value={item.value}>
{item.name}
</Option>
))}
</Listbox>
}
>
<Input
aria-haspopup
role="combobox"
aria-autocomplete="list"
aria-expanded={listboxStatus}
aria-owns={listboxId}
allowClear
value={inputValue}
onChange={handleChange}
onFocus={() => dispatch({ type: 'SET_LISTBOX_STATUS', value: true })}
onClick={() => dispatch({ type: 'SET_LISTBOX_STATUS', value: true })}
onKeyDown={handleKeyboard}
hasAlert={false}
{...props}
/>
</Popover>
<button
type="button"
onMouseUp={() => dispatch({ type: 'SET_LISTBOX_STATUS', value: false })}
hidden={!listboxStatus}
className="fixed top-0 left-0 h-screen w-screen"
/>
</div>
)
}