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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
/**
 * 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 vote down vote up
/**
 * 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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
/**
 * 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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
/**
 * 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 vote down vote up
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 vote down vote up
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 vote down vote up
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>;
}