react#useRef TypeScript Examples
The following examples show how to use
react#useRef.
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: useGetNamespaceList.tsx From one-platform with MIT License | 6 votes |
useGetNamespaceList = ({
limit = 10,
search,
}: Props): UseQueryReturn<UseGetNamespaceListQuery> => {
const searchCancelRef = useRef(new AbortController());
const query = useQuery<UseGetNamespaceListQuery, Props>({
gql: GET_NAMESPACE_LIST,
variables: {
limit,
search,
},
pause: !search,
context: useMemo(
() => ({
fetchOptions: () => {
const token = window.OpAuthHelper.jwtToken;
return {
signal: searchCancelRef.current.signal,
headers: { authorization: token ? `Bearer ${token}` : '' },
};
},
}),
[]
),
});
useEffect(() => {
searchCancelRef.current.abort();
}, [search]);
return query;
}
Example #2
Source File: index.tsx From Demae with MIT License | 6 votes |
useWidth = <T extends HTMLElement>(): [React.RefObject<T>, number] => {
const ref = useRef<T>(null)
const [width, setWidth] = useState(0)
useEffect(() => {
if (ref.current) {
const { width } = ref.current.getBoundingClientRect()
setWidth(width)
}
}, [ref.current])
return [ref, width]
}
Example #3
Source File: index.ts From react-useStateRef with MIT License | 6 votes |
useStateRef: UseStateRef = <S>(initialState?: S | (() => S)) => {
const [state, setState] = useState(initialState);
const ref = useRef(state);
const dispatch: typeof setState = useCallback((setStateAction:any) => {
ref.current = isFunction(setStateAction) ? setStateAction(ref.current) : setStateAction;
setState(ref.current);
}, []);
return [state, dispatch, ref];
}
Example #4
Source File: use-element-intersection.stories.tsx From anchor-web-app with Apache License 2.0 | 6 votes |
Basic = () => {
const elementRef = useRef<HTMLElement>(null);
const intersection = useElementIntersection({ elementRef, threshold: 0.2 });
return (
<div>
<div style={{ backgroundColor: 'red', height: 1500 }} />
<div
ref={elementRef as any}
style={{ backgroundColor: 'white', height: 500 }}
/>
<div style={{ backgroundColor: 'blue', height: 1500 }} />
<Intersecting>
{intersection?.isIntersecting
? 'White block is visible'
: 'White block is invisible'}
</Intersecting>
</div>
);
}
Example #5
Source File: StreamAvatar.tsx From binaural-meet with GNU General Public License v3.0 | 6 votes |
StreamAvatar: React.FC<StreamAvatarProps> = (props: StreamAvatarProps) => {
const classes = useStyles(props)
const videoRef = useRef<HTMLVideoElement>(null)
useEffect(
() => {
if (videoRef?.current !== null) {
setStream(videoRef.current, props.stream, props.blob,
classes.videoLargerWidth, classes.videoLargerHeight)
}
},
[videoRef, classes.videoLargerWidth, classes.videoLargerHeight, props.stream, props.blob],
)
return <div className={classes.root} style={props.style}>
<video ref={videoRef} style={props.style} />
</div>
}
Example #6
Source File: UseInterval.ts From bluebubbles-server with Apache License 2.0 | 6 votes |
useInterval = (callback: () => void, delay: number | null) => {
const savedCallback = useRef(callback);
// Remember the latest callback if it changes.
useIsomorphicLayoutEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
// Don't schedule if no delay is specified.
// Note: 0 is a valid value for delay.
if (!delay && delay !== 0) return;
const id = setInterval(() => savedCallback.current(), delay);
return () => clearInterval(id);
}, [delay]);
}
Example #7
Source File: click-outside.tsx From nextjs-shopify with MIT License | 6 votes |
ClickOutside = ({
active = true,
onClick,
children,
}: ClickOutsideProps) => {
const innerRef = useRef()
const handleClick = (event: any) => {
if (!hasParent(event.target, innerRef?.current)) {
if (typeof onClick === 'function') {
onClick(event)
}
}
}
useEffect(() => {
if (active) {
document.addEventListener('mousedown', handleClick)
document.addEventListener('touchstart', handleClick)
}
return () => {
if (active) {
document.removeEventListener('mousedown', handleClick)
document.removeEventListener('touchstart', handleClick)
}
}
})
return React.cloneElement(children, { ref: innerRef })
}
Example #8
Source File: useClearRestoreValue.tsx From firecms with MIT License | 6 votes |
/**
* Hook we use to restore a value after it has been cleared
* @param property
* @param value
* @param setValue
* @ignore
*/
export function useClearRestoreValue<T extends CMSType>({
property,
value,
setValue
}:
{
property: Property<T>,
value: T,
setValue: (value: T | null, shouldValidate?: boolean) => void
}) {
const clearedValueRef = useRef<T | null>(null);
useEffect(() => {
const shouldClearValueIfDisabled = typeof property.disabled === "object" && Boolean(property.disabled.clearOnDisabled);
if (shouldClearValueIfDisabled) {
if (value != null) {
clearedValueRef.current = value;
setValue(null);
}
} else if (clearedValueRef.current) {
setValue(clearedValueRef.current);
clearedValueRef.current = null;
}
}, [property]);
}
Example #9
Source File: hooks.ts From typed-react-form with MIT License | 6 votes |
/**
* Creates a new root form.
* This hook doesn't cause a rerender.
* @param defaultValues The default values for this form. When this value changes, nothing happens, use useEffect() with form.setValues to set form values on state change.
* @param validator The validator to use, optional.
* @param validateOnChange Validate on change? Optional, default is false.
* @param validateOnMount Validate on mount? Optional, default is false.
* @param defaultState The default state for this form. Form state contains custom global states, example: isSubmitting, isLoading ... Optional, default is `{ isSubmitting: false }`.
*/
export function useForm<T extends object, State = DefaultState, Error extends string = DefaultError>(
defaultValues: T,
validator?: Validator<T, Error>,
validateOnChange = false,
validateOnMount = false,
defaultState?: State
) {
let c = useRef<FormState<T, State, Error> | null>(null);
if (!c.current) {
c.current = new FormState(
defaultValues,
defaultValues,
defaultState ?? ({ isSubmitting: false } as any),
validator,
validateOnMount,
validateOnChange
);
}
return c.current;
}
Example #10
Source File: customFields.tsx From Cromwell with MIT License | 6 votes |
useInitialValue = (initialValue: string): [string, React.Dispatch<React.SetStateAction<string>>] => {
const [value, setValue] = useState(initialValue);
const initialValueRef = useRef(initialValue);
if (initialValue !== initialValueRef.current) {
initialValueRef.current = initialValue;
setValue(initialValue);
}
return [value, setValue];
}
Example #11
Source File: usePrevious.ts From dxvote with GNU Affero General Public License v3.0 | 6 votes |
export function usePrevious<T>(value: T) {
const ref = useRef<T>();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
Example #12
Source File: ContextMenu.tsx From wiregui with MIT License | 6 votes |
ContextMenu: React.FC<Props> = ({ children }) => {
const { isOpen, onClose: closeMenu, onOpen: openMenu } = useDisclosure();
const [position, setPosition] = useState<MousePosition>({ x: 0, y: 0 });
const menuRef = useRef<HTMLDivElement>(null);
return (
<ContextMenuContext.Provider
value={{
isOpen,
closeMenu,
openMenu,
menuRef,
position,
setPosition,
}}
>
{children}
</ContextMenuContext.Provider>
);
}
Example #13
Source File: useResizeObserver.ts From kliveide with MIT License | 6 votes |
useResizeObserver = (
element: React.MutableRefObject<Element | undefined>,
callback: ResizeObserverCallback
) => {
const current = element?.current;
const observer = useRef<ResizeObserver>();
useEffect(() => {
// --- We are already observing old element
if (observer?.current && current) {
observer.current.unobserve(current);
}
observer.current = new ResizeObserver(callback);
observe();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [current]);
const observe = () => {
if (element && element.current && observer.current) {
observer.current.observe(element.current);
}
};
}
Example #14
Source File: CommentForm.tsx From 3Speak-app with GNU General Public License v3.0 | 5 votes |
export function CommentForm(props) {
const [postingStatus, setPostingStatus] = useState(false)
const commentBodyRef = useRef() as any
const { parent_reflink } = props
const postComment = useCallback(async () => {
setPostingStatus(true)
const [networkId, parent_author, parent_permlink] = (RefLink.parse(parent_reflink) as any).link
const [reflink, finishOpt] = await AccountService.postComment({
accountType: 'hive',
body: commentBodyRef.current.value,
parent_author,
parent_permlink,
username: 'sisy',
permlink: `re-${parent_permlink}-${randomstring
.generate({
length: 8,
charset: 'alphabetic',
})
.toLowerCase()}`,
title: '',
json_metadata: {},
})
if (typeof props.onCommentPost === 'function') {
props.onCommentPost()
}
commentBodyRef.current.value = ''
setPostingStatus(false)
}, [parent_reflink])
return (
<>
<textarea
id="new-comment-body"
className="form-control w-100"
ref={commentBodyRef}
placeholder="Comment here..."
maxLength={25000}
></textarea>
<button
id="new-comment-btn"
className="btn mt-1 btn-primary float-right"
disabled={postingStatus}
onClick={postComment}
>
{postingStatus ? <FontAwesomeIcon icon={faSpinner as any} spin /> : <span>Comment</span>}
</button>
</>
)
}
Example #15
Source File: Tooltip.tsx From react-circular-menu with Apache License 2.0 | 5 votes |
Tooltip: FC<TooltipProps> = ({
title,
placement = TooltipPlacement.Top,
children,
}) => {
const [isOpen, setIsOpen] = useState(false);
const [tooltip, setTooltip] = useState<HTMLDivElement | null>(null);
const wrapperRef = useRef<HTMLDivElement>(null);
const tooltipStyles = useTooltipTransform(
wrapperRef.current,
tooltip,
placement
);
const openTooltip = () => !isOpen && setIsOpen(true);
const closeTooltip = () => isOpen && setIsOpen(false);
if (!title || !isValidElement(children)) {
return <>{children}</>;
}
return (
<div ref={wrapperRef}>
<>
{cloneElement(
Children.only(children),
getTooltipElementProps(children.props, openTooltip, closeTooltip)
)}
{isOpen &&
createPortal(
<StyledTooltip
style={tooltipStyles}
ref={(element: HTMLDivElement) => element && setTooltip(element)}
role="tooltip"
>
{title}
</StyledTooltip>,
document.getElementsByTagName("body")[0]
)}
</>
</div>
);
}
Example #16
Source File: HorizontalScrollTable.tsx From anchor-web-app with Apache License 2.0 | 5 votes |
function HorizontalScrollTableBase({
className,
headRulerWidth = defaultRulerWidth,
footRulerWidth = defaultRulerWidth,
minWidth,
startPadding,
endPadding,
...tableProps
}: HorizontalScrollTableProps) {
const container = useRef<HTMLDivElement>(null);
const table = useRef<HTMLTableElement>(null);
const headRuler = useRef<HTMLDivElement>(null);
const footRuler = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!container.current || !table.current) {
return;
}
const thead = table.current.querySelector('thead');
const tfoot = table.current.querySelector('tfoot');
const observer = new ResizeObserver((entries: ResizeObserverEntry[]) => {
for (const { target } of entries) {
if (target.tagName.toLowerCase() === 'thead' && headRuler.current) {
headRuler.current.style.top = `${
(target as HTMLElement).offsetTop +
(target as HTMLElement).offsetHeight -
headRulerWidth
}px`;
}
if (target.tagName.toLowerCase() === 'tfoot' && footRuler.current) {
footRuler.current.style.top = `${
(target as HTMLElement).offsetTop
}px`;
}
}
});
if (headRuler.current) {
if (thead) {
headRuler.current.style.visibility = 'visible';
headRuler.current.style.top = `${
thead.offsetTop + thead.offsetHeight - headRulerWidth
}px`;
observer.observe(thead);
} else {
headRuler.current.style.visibility = 'hidden';
}
}
if (footRuler.current) {
if (tfoot) {
footRuler.current.style.visibility = 'visible';
footRuler.current.style.top = `${tfoot.offsetTop}px`;
observer.observe(tfoot);
} else {
footRuler.current.style.visibility = 'hidden';
}
}
return () => {
observer.disconnect();
};
}, [footRulerWidth, headRulerWidth]);
return (
<div ref={container} className={className}>
<div className="scroll-container">
<table ref={table} cellSpacing="0" cellPadding="0" {...tableProps} />
</div>
<div ref={headRuler} className="headRuler" />
<div ref={footRuler} className="footRuler" />
</div>
);
}
Example #17
Source File: CodeEditor.tsx From firetable with Apache License 2.0 | 5 votes |
export default function CodeEditor({
onChange,
value,
height = 400,
wrapperProps,
disabled,
editorOptions,
}: ICodeEditorProps) {
const theme = useTheme();
const [initialEditorValue] = useState(value ?? "");
const { tableState } = useFiretableContext();
const classes = useStyles();
const monacoInstance = useMonaco();
const editorRef = useRef<any>();
function handleEditorDidMount(_, editor) {
editorRef.current = editor;
}
const themeTransformer = (theme: string) => {
switch (theme) {
case "dark":
return "vs-dark";
default:
return theme;
}
};
useMemo(async () => {
if (!monacoInstance) {
// useMonaco returns a monaco instance but initialisation is done asynchronously
// dont execute the logic until the instance is initialised
return;
}
try {
monacoInstance.languages.typescript.javascriptDefaults.setDiagnosticsOptions(
{
noSemanticValidation: true,
noSyntaxValidation: false,
}
);
// compiler options
monacoInstance.languages.typescript.javascriptDefaults.setCompilerOptions(
{
target: monacoInstance.languages.typescript.ScriptTarget.ES5,
allowNonTsExtensions: true,
}
);
} catch (error) {
console.error(
"An error occurred during initialization of Monaco: ",
error
);
}
}, [tableState?.columns]);
return (
<div
{...wrapperProps}
className={clsx(classes.editorWrapper, wrapperProps?.className)}
>
<Editor
theme={themeTransformer(theme.palette.type)}
height={height}
onMount={handleEditorDidMount}
language="javascript"
value={initialEditorValue}
options={{
readOnly: disabled,
fontFamily: theme.typography.fontFamilyMono,
...editorOptions,
}}
onChange={onChange as any}
/>
</div>
);
}
Example #18
Source File: data-loading.ts From abacus with GNU General Public License v2.0 | 5 votes |
/**
* Declarative data loader.
* Takes care of data, loading, and error state.
*
* @param createDataPromise A function that returns a promise to the data
* @param deps The hook dependencies for `createDataPromise`
* * @returns { data, isLoading, error, reloadRef } Where data, isLoading and error are data states and reloadRef is a Ref to a function that reloads the data.
*/
export function useDataSource<Data, Deps extends DependencyList | undefined, E extends Error>(
createDataPromise: () => Promise<Data>,
deps: Deps,
): DataSourceResult<Data, E> {
const [isLoading, setIsLoading] = useState<boolean>(false)
const [data, setData] = useState<Data | null>(null)
const [error, setError] = useState<E | null>(null)
const reloadRef = useRef<() => void>(noop)
useEffect(() => {
// The isSubscribed logic is necessary to prevent setStates after unmounts or dependency changes.
// For more information see: https://juliangaramendy.dev/use-promise-subscription/
let isSubscribed = true
// For isSubscribed to work with reloading we need to use reload as a Ref
reloadRef.current = async () => {
setIsLoading(true)
try {
const data = await createDataPromise()
if (isSubscribed) {
setData(data)
}
} catch (error) {
if (isSubscribed) {
setError(error)
}
} finally {
if (isSubscribed) {
setIsLoading(false)
}
}
}
reloadRef.current()
return () => {
isSubscribed = false
reloadRef.current = noop
}
// Dep checking here is not needed as we are using the additionalHooks option to check useDataSource
// eslint-disable-next-line react-hooks/exhaustive-deps
}, deps)
return {
data,
isLoading,
error,
reloadRef,
}
}
Example #19
Source File: Recaptcha.tsx From firebase-react-typescript-project-template with MIT License | 5 votes |
Recaptcha = () => {
const classes = useStyles();
const recaptchaVerified = useBooleanState(false);
const recaptchaError = useBooleanState(false);
const recaptcha = useRef<HTMLDivElement | null>(null);
useEffect(() => {
const setupRecaptcha = async () => {
(window as WindowWithRecaptcha).recaptchaVerifier = new firebase.auth.RecaptchaVerifier(
recaptcha.current,
{
size: "normal",
callback: () => {
recaptchaVerified.setTrue();
recaptchaError.setFalse();
},
"expired-callback": () => {
recaptchaVerified.setFalse();
recaptchaError.setTrue();
},
}
);
(window as WindowWithRecaptcha).recaptchaWidgetId = await (window as WindowWithRecaptcha).recaptchaVerifier?.render();
};
setupRecaptcha();
// eslint-disable-next-line
}, []);
return (
<FormControl
error={!recaptchaVerified.state && recaptchaError.state}
fullWidth
className={classes.recaptcha}
>
<div ref={recaptcha} />
{recaptchaError.state && (
<FormHelperText id="name-error-text">
Please verify you are a human
</FormHelperText>
)}
</FormControl>
);
}
Example #20
Source File: App.tsx From binaural-meet with GNU General Public License v3.0 | 5 votes |
App: React.FC<{}> = () => {
const clsSplit = styleForSplit()
const classes = styleCommon()
const DEBUG_VIDEO = false // To see all local and remote tracks or not.
const stores:Stores = {
map: mapStore,
participants: participantsStore,
contents: sharedContentsStore,
chat: chatStore,
roomInfo: roomInfo,
}
const refDiv = useRef<HTMLDivElement>(null)
// toucmove: prevent browser zoom by pinch
window.addEventListener('touchmove', (ev) => {
// if (ev.touches.length > 1) {
ev.preventDefault()
// }
}, {passive: false, capture: false})
// contextmenu: prevent to show context menu with right mouse click
window.addEventListener('contextmenu', (ev) => {
ev.preventDefault()
}, {passive: false, capture: false})
// Global error handler
window.onerror = (message, source, lineno, colno, error) => {
if ((error?.message === 'Ping timeout' || error?.message === 'Strophe: Websocket error [object Event]')
&& message === null && source === null && lineno === null && colno === null){
errorInfo.setType('connection')
if (urlParameters.testBot !== null){ // testBot
window.location.reload() // testBot will reload when connection is cutted off.
}
}else{
console.warn(`Global handler: ${message}`, source, lineno, colno, error)
}
return true
}
return <Observer>{()=>{
return <div ref={refDiv} className={classes.back} style={{backgroundColor: rgb2Color(roomInfo.backgroundFill)}}>
<SplitPane className={classes.fill} split="vertical" resizerClassName={clsSplit.resizerVertical}
minSize={0} defaultSize="7em">
<LeftBar stores={stores}/>
<Fragment>
<MainScreen showAllTracks = {DEBUG_VIDEO} stores={stores} />
<Observer>{() => <Map transparent={sharedContentsStore.tracks.mainStream !== undefined
|| DEBUG_VIDEO} stores={stores} />
}</Observer>
<Footer stores={stores} height={(isSmartphone() && isPortrait()) ? 100 : undefined} />
</Fragment>
</SplitPane>
</div>
}}</Observer>
}
Example #21
Source File: hooks.ts From react-qr-reader with MIT License | 5 votes |
useQrReader: UseQrReaderHook = ({
scanDelay: delayBetweenScanAttempts,
constraints: video,
onResult,
videoId,
}) => {
const controlsRef: MutableRefObject<IScannerControls> = useRef(null);
useEffect(() => {
const codeReader = new BrowserQRCodeReader(null, {
delayBetweenScanAttempts,
});
if (
!isMediaDevicesSupported() &&
isValidType(onResult, 'onResult', 'function')
) {
const message =
'MediaDevices API has no support for your browser. You can fix this by running "npm i webrtc-adapter"';
onResult(null, new Error(message), codeReader);
}
if (isValidType(video, 'constraints', 'object')) {
codeReader
.decodeFromConstraints({ video }, videoId, (result, error) => {
if (isValidType(onResult, 'onResult', 'function')) {
onResult(result, error, codeReader);
}
})
.then((controls: IScannerControls) => (controlsRef.current = controls))
.catch((error: Error) => {
if (isValidType(onResult, 'onResult', 'function')) {
onResult(null, error, codeReader);
}
});
}
return () => {
controlsRef.current?.stop();
};
}, []);
}
Example #22
Source File: Navbar.tsx From next-saas-starter with MIT License | 5 votes |
export default function Navbar({ items }: NavbarProps) {
const router = useRouter();
const { toggle } = Drawer.useDrawer();
const [scrollingDirection, setScrollingDirection] = useState<ScrollingDirections>('none');
let lastScrollY = useRef(0);
const lastRoute = useRef('');
const stepSize = useRef(50);
useScrollPosition(scrollPositionCallback, [router.asPath], undefined, undefined, 50);
function scrollPositionCallback({ currPos }: ScrollPositionEffectProps) {
const routerPath = router.asPath;
const hasRouteChanged = routerPath !== lastRoute.current;
if (hasRouteChanged) {
lastRoute.current = routerPath;
setScrollingDirection('none');
return;
}
const currentScrollY = currPos.y;
const isScrollingUp = currentScrollY > lastScrollY.current;
const scrollDifference = Math.abs(lastScrollY.current - currentScrollY);
const hasScrolledWholeStep = scrollDifference >= stepSize.current;
const isInNonCollapsibleArea = lastScrollY.current > -50;
if (isInNonCollapsibleArea) {
setScrollingDirection('none');
lastScrollY.current = currentScrollY;
return;
}
if (!hasScrolledWholeStep) {
lastScrollY.current = currentScrollY;
return;
}
setScrollingDirection(isScrollingUp ? 'up' : 'down');
lastScrollY.current = currentScrollY;
}
const isNavbarHidden = scrollingDirection === 'down';
const isTransparent = scrollingDirection === 'none';
return (
<NavbarContainer hidden={isNavbarHidden} transparent={isTransparent}>
<Content>
<NextLink href="/" passHref>
<LogoWrapper>
<Logo />
</LogoWrapper>
</NextLink>
<NavItemList>
{items.map((singleItem) => (
<NavItem key={singleItem.href} {...singleItem} />
))}
</NavItemList>
<ColorSwitcherContainer>
<ColorSwitcher />
</ColorSwitcherContainer>
<HamburgerMenuWrapper>
<HamburgerIcon aria-label="Toggle menu" onClick={toggle} />
</HamburgerMenuWrapper>
</Content>
</NavbarContainer>
);
}
Example #23
Source File: PrivateApiField.tsx From bluebubbles-server with Apache License 2.0 | 5 votes |
PrivateApiField = ({ helpText }: PrivateApiFieldProps): JSX.Element => {
const privateApi: boolean = (useAppSelector(state => state.config.enable_private_api) ?? false);
const alertRef = useRef(null);
const [requiresConfirmation, confirm] = useState((): string | null => {
return null;
});
return (
<Box mt={1}>
<PrivateApiRequirements />
<FormControl mt={5}>
<Stack direction='row'>
<Checkbox
id='enable_private_api'
isChecked={privateApi}
onChange={onCheckboxToggle}
>
Private API
</Checkbox>
<Button
size='xs'
onClick={() => confirm('reinstall')}
>
Re-install Helper
</Button>
</Stack>
<FormHelperText>
{helpText ?? (
<Text>
If you have set up the Private API features (via MacForge or MySIMBL),
enable this option to allow the server to communicate with the iMessage Private API.
</Text>
)}
</FormHelperText>
</FormControl>
<ConfirmationDialog
modalRef={alertRef}
onClose={() => confirm(null)}
body={confirmationActions[requiresConfirmation as string]?.message}
onAccept={() => {
confirmationActions[requiresConfirmation as string].func();
}}
isOpen={requiresConfirmation !== null}
/>
</Box>
);
}
Example #24
Source File: Searchbar.tsx From nextjs-shopify with MIT License | 5 votes |
Searchbar: FC<Props> = () => {
const router = useRouter()
const { q } = router.query
const [isOpen, setIsOpen] = useState(false)
const buttonRef = useRef<HTMLDivElement>(null)
useEffect(() => {
setIsOpen(false)
}, [router.asPath.split('?')[0]])
return (
<React.Fragment>
<ExpandModal
transitionConfig={{}}
contentTransition={{}}
overlayProps={{
style: {
maxWidth: 1920,
left: '50%',
transform: 'translateX(-50%)',
overflow: 'auto',
top: (buttonRef.current?.getBoundingClientRect().bottom || 0) + 15,
},
}}
isOpen={isOpen}
>
<SearchModalContent
initialSearch={q && String(q)}
onSearch={(term: string) => {
const op = q ? 'replace' : 'push'
router[op]({
pathname: router.asPath.split('?')[0],
query: {
q: term,
},
})
}}
/>
</ExpandModal>
<Themed.div
ref={buttonRef}
as={Button}
mx={2}
onClick={() => setIsOpen(!isOpen)}
aria-label="Search"
>
{isOpen ? (
<Cross />
) : (
<svg
width="20"
height="22"
viewBox="0 0 20 22"
fill="none"
stroke="currentColor"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
/>
</svg>
)}
</Themed.div>
</React.Fragment>
)
}
Example #25
Source File: TableInput.tsx From firecms with MIT License | 5 votes |
export function TableInput(props: {
error: Error | undefined;
value: string;
multiline: boolean;
focused: boolean;
disabled: boolean;
updateValue: (newValue: (string | null)) => void;
}) {
const { disabled, value, multiline, updateValue, focused } = props;
const [internalValue, setInternalValue] = useState<typeof value>(value);
const focusedState = useRef<boolean>(false);
useEffect(
() => {
const doUpdate = () => {
const emptyInitialValue = !value || value.length === 0;
if (emptyInitialValue && !internalValue)
return;
if (internalValue !== value)
updateValue(internalValue);
};
const handler = setTimeout(doUpdate, 300);
return () => {
clearTimeout(handler);
};
},
[internalValue]
);
useEffect(
() => {
if (!focused && value !== internalValue)
setInternalValue(value);
},
[value, focused]
);
const classes = useInputStyles();
const ref = React.createRef<HTMLTextAreaElement>();
useEffect(() => {
if (ref.current && focused && !focusedState.current) {
focusedState.current = true;
ref.current.focus({ preventScroll: true });
ref.current.selectionStart = ref.current.value.length;
ref.current.selectionEnd = ref.current.value.length;
} else {
focusedState.current = focused;
}
}, [focused, ref]);
return (
<div style={{ display: "flex" }}>
<TextareaAutosize
ref={ref}
disabled={disabled}
className={clsx(classes.input)}
value={internalValue ?? ""}
onChange={(evt) => {
const newValue = evt.target.value as string;
if (multiline || !newValue.endsWith("\n"))
setInternalValue(newValue);
}}
/>
</div>
);
}
Example #26
Source File: hooks.ts From typed-react-form with MIT License | 5 votes |
/**
* This is a wrapper around useObjectForm, with useful functions to manipulate arrays.
* This hook does cause a rerender, but only if the array size changes.
* @param parentForm The parent form.
* @param name The parent's field to create a child form for.
*/
export function useArrayField<
T extends FieldsOfType<any, any[]>,
K extends KeysOfType<T, any[] | object>,
State = DefaultState,
Error extends string = DefaultError
>(parentForm: FormState<T, State, Error>, name: K) {
const form = useObjectField(parentForm, name);
const oldLength = useRef(-1);
const [, setRender] = useState(0);
// Only rerender when array size changed
useEffect(() => {
let id = parentForm.listen(name, () => {
let val = parentForm.values[name] as any;
if (Array.isArray(val) && val.length !== oldLength.current) {
setRender((i) => i + 1);
oldLength.current = val.length;
}
});
return () => parentForm.ignore(name, id);
}, []);
const append = useCallback((value: NonNullable<T[K]>[any]) => {
form.setValues([...(form.values as any), value] as any, true, false);
}, []);
const remove = useCallback((index: number) => {
let newValues = [...(form.values as any)];
newValues.splice(index, 1);
form.setValues(newValues as any, true, false);
}, []);
const clear = useCallback(() => {
form.setValues([] as any, true, false);
}, []);
const move = useCallback((from: number, to: number) => {
if (to === from) return;
let newArr = [...(form.values as any)];
var target = newArr[from];
var increment = to < from ? -1 : 1;
for (var k = from; k !== to; k += increment) {
newArr[k] = newArr[k + increment];
}
newArr[to] = target;
form.setValues(newArr as any, true, false);
}, []);
const swap = useCallback((index: number, newIndex: number) => {
if (index === newIndex) {
return;
}
let values = [...(form.values as any)];
[values[index], values[newIndex]] = [values[newIndex], values[index]];
form.setValues(values as any, true, false);
}, []);
return {
remove: remove,
move: move,
swap: swap,
clear: clear,
append: append,
form: form,
values: form.values,
setValues: form.setValues.bind(form)
};
}
Example #27
Source File: Tabs.tsx From eth2stats-dashboard with MIT License | 5 votes |
Tabs: React.FC = observer(() => {
const {store} = useStores();
const {pathname} = useLocation();
const scrollRef = useRef(null);
const getElementOffset = (el: HTMLElement | null) => {
let rect = el!.getBoundingClientRect();
let scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
return {top: rect.top + scrollTop, left: rect.left + scrollLeft};
};
useEffect(() => {
const element = document.getElementById(`tab-link-/${pathname.split("/")[1]}`);
if (element !== null) {
let offset = getElementOffset(element);
if (scrollRef.current === null) {
return;
}
// @ts-ignore
scrollRef.current.scrollLeft(offset.left);
}
});
return (
<nav className="fixed top-0 w-full bg-darkblue-200 h-12 z-30 flex">
<Scrollbars autoHide autoHeight autoHeightMin={0} autoHeightMax={48}
ref={scrollRef}>
<div className="flex h-12 w-auto">
{store.networks.map((net) => (
<Link key={net.path} to={`${net.path}`}
className={`flex items-center ${pathname.startsWith(net.path) && "bg-darkblue-100"}`}
id={`tab-link-${net.path}`}
>
<p className={`text-sm px-6 py-2 rounded-lg whitespace-no-wrap ${pathname.startsWith(net.path) && "text-blue-500" || "text-grey-600"}`}>
{net.name}
</p>
</Link>
))}
<Link to="/add-node"
className={`flex items-center ${pathname.startsWith("/add-node") && "bg-darkblue-100"}`}
id={`tab-link-/add-node`}
>
<p className={`text-sm px-6 py-2 rounded-lg whitespace-no-wrap ${pathname.startsWith("/add-node") && "text-blue-500" || "text-grey-600"}`}>
<FontAwesomeIcon icon="plus-circle" className="mr-2"/>
<span className="font-semibold text-sm">Add your node</span>
</p>
</Link>
</div>
</Scrollbars>
</nav>
);
})
Example #28
Source File: CodeInput.tsx From mobile with Apache License 2.0 | 5 votes |
CodeInput = ({value, onChange, accessibilityLabel}: CodeInputProps) => {
const inputRef = useRef<TextInput>(null);
const onChangeTrimmed = useCallback(text => onChange(text.trim()), [onChange]);
const displayValue = useCallback(
() =>
Array(8)
.fill(null)
.map((_, x) => {
const characterToDisplay = value[x] || ' ';
return (
<Box
/* eslint-disable-next-line react/no-array-index-key */
key={`input-${x}`}
flex={1}
marginHorizontal="xs"
borderBottomWidth={1.5}
borderBottomColor={inputBorderColor(value, x)}
>
<Text variant="codeInput" color="overlayBodyText" textAlign="center" marginBottom="s">
{characterToDisplay}
</Text>
</Box>
);
}),
[value],
);
const giveFocus = useCallback(() => inputRef.current?.focus(), []);
return (
<>
<TextInput
value={value}
ref={inputRef}
onChangeText={onChangeTrimmed}
keyboardType="number-pad"
autoCorrect={false}
autoCompleteType="off"
returnKeyType="done"
accessibilityLabel={accessibilityLabel}
caretHidden
maxLength={8}
style={styles.input}
/>
<TouchableWithoutFeedback
onPress={giveFocus}
accessibilityElementsHidden
importantForAccessibility="no-hide-descendants"
>
<Box flexDirection="row" justifyContent="space-evenly" marginHorizontal="m" paddingVertical="l">
{displayValue()}
</Box>
</TouchableWithoutFeedback>
</>
);
}
Example #29
Source File: DesktopHeader.tsx From NewWorldMinimap with MIT License | 5 votes |
export default function DesktopHeader() {
const context = useContext(AppContext);
const { classes } = useStyles();
const { t } = useTranslation();
const [desktopWindow] = useState(() => {
return new OWWindow(windowNames.desktop);
});
const draggable = useRef<HTMLDivElement | null>(null);
const [maximized, setMaximized] = useState(false);
const useTransparency = context.settings.transparentHeader && context.gameRunning && !context.appSettingsVisible;
useEffect(() => {
if (draggable.current) {
desktopWindow.dragMove(draggable.current);
}
}, [draggable.current]);
useEffect(() => {
async function handleResize() {
const windowState = await desktopWindow.getWindowState();
setMaximized(windowState.window_state === overwolf.windows.WindowStateEx.MAXIMIZED);
}
handleResize(); // to set the initial maximized icon
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
function handleShowInGameWindow() {
backgroundController.openWindow('inGame');
}
function handleMinimize() {
desktopWindow.minimize();
}
function handleMaximizeRestore() {
if (maximized) {
desktopWindow.restore();
} else {
desktopWindow.maximize();
}
setMaximized(!maximized);
}
function handleClose() {
backgroundController.closeWindow('desktop');
}
return <header className={clsx(classes.root, useTransparency && classes.transparent, !context.settings.showHeader && classes.hidden)}>
<div ref={draggable} className={classes.draggable} onDoubleClick={handleMaximizeRestore}>
<span>{desktopAppTitle}</span>
</div>
<div className={classes.buttons}>
{context.gameRunning && <button className={clsx(classes.controlButton)} onClick={handleShowInGameWindow} title={t('header.openInGame')}>
<DesktopWindowIcon />
</button>}
<button className={clsx(classes.controlButton)} onClick={context.toggleFrameMenu} title={t('header.settings')}>
<SettingsIcon />
</button>
<button className={clsx(classes.controlButton)} onClick={handleMinimize}>
<Minimizeicon />
</button>
<button className={clsx(classes.controlButton)} onClick={handleMaximizeRestore}>
{maximized
? <RestoreIcon />
: <MaximizeIcon />
}
</button>
<button className={clsx(classes.controlButton, classes.close)} onClick={handleClose}>
<CloseIcon />
</button>
</div>
</header>;
}