react#ComponentPropsWithoutRef TypeScript Examples

The following examples show how to use react#ComponentPropsWithoutRef. 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: Button.tsx    From webapis-playground with MIT License 5 votes vote down vote up
Button = <Element extends ElementType = 'button'>({
  children,
  as,
  className,
  leftIcon,
  rightIcon,
  ...props
}: ButtonProps<Element> & ComponentPropsWithoutRef<Element>) => {
  let Component = as || 'button';

  return (
    <Component
      className={cx(
        `
          tw-inline-flex
          tw-items-center
          tw-justify-center
          tw-px-4
          tw-h-10
          tw-text-base
          tw-font-semibold 
          tw-text-white
          tw-whitespace-nowrap
          tw-rounded-md 
          tw-bg-blue-500
          tw-transition
          tw-duration-100
          tw-ease-in
          tw-appearance-none
          tw-select-none
          tw-align-middle
          focus:tw-ring-4
          focus:tw-ring-blue-300
          focus:tw-outline-none
          active:tw-bg-blue-800
          hover:tw-bg-blue-600
          disabled:tw-opacity-50
          disabled:tw-pointer-events-none
          disabled:tw-select-none
        `,
        className
      )}
      {...filterDOMProps(props)}
    >
      {leftIcon && (
        <span className="tw-inline-flex tw-self-center tw-flex-shrink-0 tw-mr-2">
          {leftIcon}
        </span>
      )}
      {children}
      {rightIcon && (
        <span className="tw-inline-flex tw-self-center tw-flex-shrink-0 tw-ml-2">
          {rightIcon}
        </span>
      )}
    </Component>
  );
}
Example #2
Source File: IconButton.tsx    From webapis-playground with MIT License 5 votes vote down vote up
IconButton = <Element extends ElementType = 'button'>({
  children,
  icon,
  as,
  className,
  ...props
}: IconButtonProps<Element> & ComponentPropsWithoutRef<Element>) => {
  let element = children || icon;

  const child = React.isValidElement(element)
    ? React.cloneElement(element as any, {
        'aria-hidden': true,
        focusable: false,
      })
    : null;

  let Component = as || 'button';

  return (
    <Component
      className={cx(
        `
          tw-inline-flex
          tw-items-center
          tw-justify-center
          tw-px-3
          tw-h-10
          tw-text-base
          tw-font-semibold 
          tw-text-gray-500
          tw-whitespace-nowrap
          tw-rounded-md 
          tw-bg-transparent
          tw-transition
          tw-duration-200
          tw-ease-in
          tw-appearance-none
          tw-select-none
          tw-align-middle
          focus:tw-ring-4
          focus:tw-ring-blue-200
          focus:tw-outline-none
          active:tw-bg-gray-200
          hover:tw-bg-gray-100
          disabled:tw-opacity-50
          disabled:tw-pointer-events-none
          disabled:tw-select-none
        `,
        className
      )}
      {...filterDOMProps(props)}
    >
      <span className="tw-inline-flex tw-self-center tw-flex-shrink-0">
        {child}
      </span>
    </Component>
  );
}
Example #3
Source File: Tag.tsx    From webapis-playground with MIT License 5 votes vote down vote up
Tag = <Element extends ElementType = 'span'>({
  children,
  as,
  className,
  leftIcon,
  rightIcon,
  ...props
}: TagProps<Element> & ComponentPropsWithoutRef<Element>) => {
  let Component = as || 'span';

  return (
    <Component
      className={cx(
        `
          tw-inline-flex
          tw-items-center
          tw-justify-center
          tw-py-1
          tw-px-2
          tw-text-xs
          tw-font-bold 
          tw-text-white
          tw-whitespace-nowrap
          tw-uppercase
          tw-rounded-md 
          tw-bg-gray-500
          tw-transition
          tw-duration-100
          tw-ease-in
          tw-appearance-none
          tw-select-none
          tw-align-middle
          active:tw-bg-gray-800
          hover:tw-bg-gray-600
        `,
        className
      )}
      {...filterDOMProps(props)}
    >
      {leftIcon && (
        <span className="tw-inline-flex tw-self-center tw-flex-shrink-0 tw-mr-1">
          {leftIcon}
        </span>
      )}
      {children}
      {rightIcon && (
        <span className="tw-inline-flex tw-self-center tw-flex-shrink-0 tw-ml-1">
          {rightIcon}
        </span>
      )}
    </Component>
  );
}
Example #4
Source File: optimize-heavy-screen.tsx    From react-navigation-heavy-screen with MIT License 5 votes vote down vote up
export function optimizeHeavyScreen<Props>(
	Component: ComponentType<Props>,
	Placeholder: ComponentType | null = null,
	options: {
		disableHoistStatics?: boolean
		transition?: ComponentPropsWithoutRef<
			typeof Transitioning.View
		>['transition']
	} = {}
) {
	const {
		disableHoistStatics = false,
		transition = (
			<Transition.Together>
				<Transition.Change interpolation="easeInOut" />
				<Transition.In type="fade" />
			</Transition.Together>
		),
	} = options
	const OptimizedHeavyScreen = (props: Props) => {
		const {
			transitionRef,
			areInteractionsComplete,
		} = useAfterInteractions()
		return (
			<Transitioning.View
				transition={transition}
				style={styles.container}
				ref={transitionRef}
			>
				{areInteractionsComplete ? (
					<Component {...props} />
				) : !!Placeholder ? (
					<Placeholder />
				) : null}
			</Transitioning.View>
		)
	}
	if (!disableHoistStatics) {
		// forward navigationOptions, and other statics
		hoistNonReactStatics(OptimizedHeavyScreen, Component)
	}
	return OptimizedHeavyScreen
}
Example #5
Source File: Carousel.tsx    From atlas with GNU General Public License v3.0 4 votes vote down vote up
Carousel = forwardRef<
  ReactNode,
  CarouselProps &
    ComponentPropsWithoutRef<'div'> & {
      prevArrowRef: RefObject<HTMLButtonElement>
      nextArrowRef: RefObject<HTMLButtonElement>
    }
>(
  (
    {
      children,
      className = '',
      arrowPosition,
      slidesToShow = 'auto',
      dotsVisible,
      prevArrowRef,
      nextArrowRef,
      ...gliderOptions
    },
    ref
  ) => {
    const dotsRef = useRef<HTMLDivElement>(null)
    const gliderInstanceRef = useRef<Glider<HTMLElement>>()
    const slidesToScrollRef = useRef<number>(0)

    const onAnimated = () => {
      if (gliderInstanceRef.current && gliderOptions.responsive) {
        const breakpointIndex = gliderOptions.responsive.findIndex(
          (item) => item.breakpoint === gliderInstanceRef.current?.breakpoint
        )
        const slidesToScroll = gliderOptions.responsive[breakpointIndex].settings.slidesToScroll as number
        const itemsRemainder = gliderInstanceRef.current.slides.length % slidesToScrollRef.current || slidesToScroll
        if (nextArrowRef.current && nextArrowRef.current?.classList.contains('disabled') && itemsRemainder) {
          gliderInstanceRef.current.setOption({ slidesToScroll: itemsRemainder }, false)
        } else {
          gliderInstanceRef.current.setOption({ slidesToScroll: slidesToScrollRef.current || slidesToScroll }, false)
          if (!slidesToScrollRef.current) {
            slidesToScrollRef.current = slidesToScroll
          }
        }
      }
    }

    const {
      ref: gliderRef,
      getContainerProps,
      getGliderProps,
      getTrackProps,
      getPrevArrowProps,
      getNextArrowProps,
      getDotsProps,
      glider,
    } = useGlider<HTMLDivElement>({
      slidesToShow,
      onAnimated,
      arrows: { prev: prevArrowRef.current, next: nextArrowRef.current },
      dots: dotsRef.current,
      ...gliderOptions,
    })

    const resetSlidesToScroll = () => {
      slidesToScrollRef.current = 0
    }

    useEffect(() => {
      window.addEventListener('resize', resetSlidesToScroll)

      return () => {
        window.removeEventListener('resize', resetSlidesToScroll)
      }
    }, [])

    useEffect(() => {
      if (!glider) return
      gliderInstanceRef.current = glider
    }, [glider])

    useImperativeHandle(ref, () => ({
      getPrevArrowProps,
      getNextArrowProps,
    }))
    return (
      <Container {...getContainerProps({ className })}>
        <GliderContainer {...getGliderProps()} ref={gliderRef}>
          <Track {...getTrackProps()}>{children}</Track>
        </GliderContainer>
        {dotsVisible && <Dots {...getDotsProps()} ref={dotsRef} />}
      </Container>
    )
  }
)
Example #6
Source File: MathJax.tsx    From better-react-mathjax with MIT License 4 votes vote down vote up
MathJax: FC<MathJaxProps & ComponentPropsWithoutRef<"span">> = ({
    inline = false,
    hideUntilTypeset,
    onInitTypeset,
    onTypeset,
    text,
    dynamic,
    typesettingOptions,
    renderMode,
    children,
    ...rest
}) => {
    // in render mode "pre", this keeps track of the last value on text to determine when we need to run typesetting
    const lastChildren = useRef<string>("")

    /* the parent of all MathJax content, in render mode "pre" the content generated by MathJax is added to this node
    after rendering whereas in render mode "post", the content of this node is processed by MathJax after rendering */
    const ref = useRef<HTMLElement>(null)

    const mjPromise = useContext(MathJaxBaseContext)

    // allow context values to steer this component for some props if they are undefined
    const usedHideUntilTypeset = hideUntilTypeset ?? mjPromise?.hideUntilTypeset
    const usedRenderMode = renderMode ?? mjPromise?.renderMode
    const usedConversionOptions = typesettingOptions ?? mjPromise?.typesettingOptions
    const usedDynamic = dynamic === false ? false : (dynamic || process.env.NODE_ENV !== "production")

    // whether initial typesetting of this element has been done or not
    const initLoad = useRef(false)

    // mutex to signal when typesetting is ongoing (without it we may have race conditions)
    const typesetting = useRef(false)

    // handler for initial loading
    const checkInitLoad = () => {
        if(!initLoad.current) {
            if(usedHideUntilTypeset === "first" && ref.current !== null) {
                ref.current.style.visibility = "visible"
            }
            if(onInitTypeset) onInitTypeset()
            initLoad.current = true
        }
    }

    // callback for when typesetting is done
    const onTypesetDone = () => {
        if(usedHideUntilTypeset === "every" && usedDynamic && usedRenderMode === "post" && ref.current !== null) {
            ref.current.style.visibility = rest.style?.visibility ?? "visible"
        }
        checkInitLoad()
        if(onTypeset) onTypeset()
        typesetting.current = false
    }

    // validator for text input with renderMode = "pre"
    const validText = (inputText?: string) => typeof inputText === "string" && inputText.length > 0

    // guard which resets the visibility to hidden when hiding the content between every typesetting
    if(
        !typesetting.current &&
        ref.current !== null &&
        usedDynamic &&
        usedHideUntilTypeset === "every" &&
        usedRenderMode === "post"
    ) {
        ref.current.style.visibility = "hidden"
    }

    /**
     * Effect for typesetting, important that this does not trigger a new render and runs as seldom as possible (only
     * when needed). It is good that it is in an effect because then we are sure that the DOM to be is ready and
     * thus, we don't have to use a custom timeout to accommodate for this. Layout effects runs on the DOM to be before
     * the browser has a chance to paint. Thereby, we reduce the chance of ugly flashes of non-typeset content.
     *
     * Note: useLayoutEffect causes an ugly warning in the server console with SSR so we make sure to use useEffect if
     * we are in the backend instead. Neither of them run in the backend so no extra care needs to be taken of the
     * Promise.reject() passed from context (which happens on SSR) on server.
     */
    const effectToUse = typeof window !== "undefined" ? useLayoutEffect : useEffect
    effectToUse(() => {
        if(usedDynamic || !initLoad.current) {
            if(ref.current !== null) {
                if(mjPromise) {
                    if(usedRenderMode === "pre") {
                        if(!validText(text))
                            throw Error(
                                `Render mode 'pre' requires text prop to be set and non-empty, which was currently "${text}"`
                            )
                        if(!typesettingOptions || !typesettingOptions.fn)
                            throw Error(
                                "Render mode 'pre' requires 'typesettingOptions' prop with 'fn' property to be set on MathJax element or in the MathJaxContext"
                            )
                        if(mjPromise.version === 2)
                            throw Error(
                                "Render mode 'pre' only available with MathJax 3, and version 2 is currently in use"
                            )
                    }
                    if(usedRenderMode === "post" || text !== lastChildren.current) {
                        if(!typesetting.current) {
                            typesetting.current = true
                            if(mjPromise.version === 3) {
                                mjPromise.promise
                                    .then((mathJax) => {
                                        if(usedRenderMode === "pre") {
                                            const updateFn = (output: HTMLElement) => {
                                                lastChildren.current = text!
                                                mathJax.startup.document.clear()
                                                mathJax.startup.document.updateDocument()
                                                if(ref.current !== null) ref.current.innerHTML = output.outerHTML
                                                onTypesetDone()
                                            }
                                            if(typesettingOptions!.fn.endsWith("Promise"))
                                                mathJax.startup.promise
                                                    .then(() =>
                                                        mathJax[usedConversionOptions!.fn](text, {
                                                            ...(usedConversionOptions?.options || {}),
                                                            display: !inline
                                                        })
                                                    )
                                                    .then(updateFn)
                                                    .catch((err) => {
                                                        onTypesetDone()
                                                        throw Error(typesettingFailed(err))
                                                    })
                                            else
                                                mathJax.startup.promise
                                                    .then(() => {
                                                        const output = mathJax[usedConversionOptions!.fn](text, {
                                                            ...(usedConversionOptions?.options || {}),
                                                            display: !inline
                                                        })
                                                        updateFn(output)
                                                    })
                                                    .catch((err) => {
                                                        onTypesetDone()
                                                        throw Error(typesettingFailed(err))
                                                    })
                                        } else {
                                            // renderMode "post"
                                            mathJax.startup.promise
                                                .then(() => {
                                                    mathJax.typesetClear([ref.current])
                                                    return mathJax.typesetPromise([ref.current])
                                                })
                                                .then(onTypesetDone)
                                                .catch((err) => {
                                                    onTypesetDone()
                                                    throw Error(typesettingFailed(err))
                                                })
                                        }
                                    })
                                    .catch((err) => {
                                        onTypesetDone()
                                        throw Error(typesettingFailed(err))
                                    })
                            } else {
                                // version 2
                                mjPromise.promise
                                    .then((mathJax) => {
                                        mathJax.Hub.Queue(["Typeset", mathJax.Hub, ref.current])
                                        mathJax.Hub.Queue(onTypesetDone)
                                    })
                                    .catch((err) => {
                                        onTypesetDone()
                                        throw Error(typesettingFailed(err))
                                    })
                            }
                        }
                    }
                } else
                    throw Error(
                        "MathJax was not loaded, did you use the MathJax component outside of a MathJaxContext?"
                    )
            }
        }
    })

    return (
        <span
            {...rest}
            style={{
                display: inline ? "inline" : "block",
                ...rest.style,
                visibility: usedHideUntilTypeset ? "hidden" : rest.style?.visibility
            }}
            ref={ref}
        >
            {children}
        </span>
    )
}