react#cloneElement TypeScript Examples

The following examples show how to use react#cloneElement. 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: LoadingMask.tsx    From datart with Apache License 2.0 6 votes vote down vote up
export function LoadingMask({ loading, children }: LoadingMaskProps) {
  return (
    <>
      {loading && (
        <SpinWrapper>
          <LoadingOutlined />
        </SpinWrapper>
      )}
      {cloneElement(children, loading ? { className: 'blur' } : void 0)}
      <LoadingMaskStyle />
    </>
  );
}
Example #2
Source File: flattenChildren.ts    From splitter with MIT License 6 votes vote down vote up
export default function flattenChildren(
  children: ReactNode,
  depth: number = 0,
  keys: (string | number)[] = []
): ReactChild[] {
  return Children.toArray(children).reduce(
    (acc: ReactChild[], node, nodeIndex) => {
      if (isFragment(node)) {
        acc.push.apply(
          acc,
          flattenChildren(
            node.props.children,
            depth + 1,
            keys.concat(node.key || nodeIndex)
          )
        );
      } else {
        if (isValidElement(node)) {
          acc.push(
            cloneElement(node, {
              key: keys.concat(String(node.key)).join('.')
            })
          );
        } else if (typeof node === 'string' || typeof node === 'number') {
          acc.push(node);
        }
      }
      return acc;
    },
    []
  );
}
Example #3
Source File: createClientRender.tsx    From use-platform with MIT License 6 votes vote down vote up
function clientRender<T>(element: ReactElement<T>, options: RenderOptions = {}) {
  const { container, hydrate } = options
  const render = testingLibraryRender(element, { container, hydrate })

  function setProps(props: any) {
    render.rerender(cloneElement(element, props))
  }

  Object.assign(render, { setProps })

  return render as Render<T>
}
Example #4
Source File: index.tsx    From react-amap with MIT License 6 votes vote down vote up
Polygon = forwardRef<PolygonProps, PolygonProps>((props, ref) => {
  const { children } = props;
  const { polygon } = usePolygon(props);
  useImperativeHandle(ref, () => ({ ...props, polygon }));
  if (children && isValidElement(children)) {
    return cloneElement(children, { ...props, polygon });
  }
  return null;
})
Example #5
Source File: DotDotDot.tsx    From app-stormkit-io with GNU General Public License v3.0 6 votes vote down vote up
DotDotDot: React.FC<React.HTMLAttributes<HTMLButtonElement>> & {
  Item: React.FC<ItemProps>;
} = ({ children, className, ...rest }): React.ReactElement => {
  const [isOpen, toggleVisibility] = useState(false);
  const childArray = React.Children.toArray(children);

  return (
    <OutsideClick handler={() => toggleVisibility(false)}>
      <div className={cn("relative", className)}>
        <Button
          styled={false}
          onClick={() => toggleVisibility(!isOpen)}
          {...rest}
        >
          <i className="fas fa-ellipsis-h" />
        </Button>
        {isOpen && (
          <div className="flex flex-col min-w-56 absolute right-0 rounded shadow bg-white z-50 items-start mt-4 text-left">
            {childArray.map((child: React.ReactNode, index: number) => {
              if (!React.isValidElement(child)) {
                throw new Error(
                  "[DotDotDot]: Invalid element provided as a child"
                );
              }

              return cloneElement(child, {
                toggleVisibility,
                isLast: childArray.length - 1 === index,
              });
            })}
          </div>
        )}
      </div>
    </OutsideClick>
  );
}
Example #6
Source File: index.tsx    From frontegg-react with MIT License 6 votes vote down vote up
MenuItem: FC<MenuItemProps> = (props) => {
  const { withIcons, loading, icon, iconClassName } = props;

  const renderIcon = useCallback(() => {
    if (loading) return <Loader size={24} className={iconClassName} />;
    if (icon) return cloneElement(icon, { className: iconClassName });
    return null;
  }, [loading, icon, iconClassName]);

  if (withIcons) {
    return (
      <MaterialMenuItem
        selected={props.selected}
        className={props.className}
        onClick={(e) => props.onClick?.(e, props)}
      >
        <ListItemIcon>{renderIcon()}</ListItemIcon>
        <ListItemText>{props.text}</ListItemText>
      </MaterialMenuItem>
    );
  } else {
    return (
      <MaterialMenuItem
        selected={props.selected}
        className={props.className}
        onClick={(e) => props.onClick?.(e, props)}
      >
        {props.text}
      </MaterialMenuItem>
    );
  }
}
Example #7
Source File: ButtonContent.tsx    From react-native-base-ui with MIT License 6 votes vote down vote up
ButtonContent = ({ style, children: Children }: ButtonContentProps) => {
  if (Children === null || Children === undefined) {
    return null;
  }

  if (typeof Children === 'function') {
    return Children({ style });
  }

  if (typeof Children === 'object') {
    //@ts-ignore
    return cloneElement(Children, {
      //@ts-ignore
      ...Children.props,
      //@ts-ignore
      style: [style, Children.props.style],
    });
  }

  if (typeof Children === 'string') {
    return <Text style={style}>{Children}</Text>;
  }

  return null;
}
Example #8
Source File: FlexCollapse.tsx    From datart with Apache License 2.0 6 votes vote down vote up
Collapse = memo(
  ({ defaultActiveKeys, activeKeys, children }: FlexCollapseProps) => {
    const panels = useMemo(() => {
      let panels: ReactElement[] = [];
      Children.forEach(children, c => {
        if (c.type === Panel) {
          panels.push(cloneElement(c, { defaultActiveKeys, activeKeys }));
        }
      });
      return panels;
    }, [defaultActiveKeys, activeKeys, children]);

    return <Container>{panels}</Container>;
  },
)
Example #9
Source File: SortableItem.tsx    From gio-design with Apache License 2.0 6 votes vote down vote up
public render() {
    const { isOver, template, sortData, index, className, isDragging, prefixCls = 'gio-sortable' } = this.props;
    const { hovered } = this.state;
    return cloneElement(template, {
      sortData,
      index,
      isOver,
      isDragging,
      ref: this._createRef(),
      onMouseEnter: this._onMouseEnter,
      onMouseLeave: this._onMouseLeave,
      onDragStart: this._onDragStart,
      className: classnames(className, `${prefixCls}-item`, {
        'is-over': isOver,
        'is-dragging': isDragging,
        'is-hovered': hovered,
      }),
    });
  }
Example #10
Source File: index.tsx    From datart with Apache License 2.0 6 votes vote down vote up
export function Popup({
  content,
  overlayClassName,
  onVisibleChange,
  ...rest
}: PopoverProps) {
  const [visible, setVisible] = useState(false);

  const visibleChange = useCallback(
    v => {
      setVisible(v);
      onVisibleChange && onVisibleChange(v);
    },
    [onVisibleChange],
  );

  const onClose = useCallback(() => {
    setVisible(false);
  }, []);

  const injectedContent = useMemo(
    () =>
      isValidElement(content) ? cloneElement(content, { onClose }) : content,
    [content, onClose],
  );

  const className = mergeClassNames(overlayClassName, 'datart-popup');
  return (
    <Popover
      {...rest}
      overlayClassName={className}
      content={injectedContent}
      visible={visible}
      onVisibleChange={visibleChange}
    />
  );
}
Example #11
Source File: DOMView.tsx    From react-ecs with MIT License 6 votes vote down vote up
render() {
        if (Children.count(this.props.children) !== 1) {
            throw new Error('<DOMView /> must have a single child.')
        }

        return <>
            {cloneElement(this.props.children, {
                ref: this.ref,
            })}
        </>
    }
Example #12
Source File: ListSwitch.tsx    From datart with Apache License 2.0 6 votes vote down vote up
ListSwitch = memo(
  ({ titles, selectedKey: selectedKeyProp, onSelect }: ListSwitchProps) => {
    const [selectedKey, setSelectedKey] = useState(
      selectedKeyProp || (titles.length ? titles[0].key : ''),
    );

    useEffect(() => {
      if (selectedKeyProp) {
        setSelectedKey(selectedKeyProp);
      }
    }, [selectedKeyProp]);

    const itemSelect = useCallback(
      key => () => {
        if (key !== selectedKey) {
          setSelectedKey(key);
          onSelect && onSelect(key);
        }
      },
      [onSelect, selectedKey],
    );

    return (
      <Container>
        {titles.map(({ key, icon, text }) => (
          <li
            key={key}
            className={classnames({ selected: key === selectedKey })}
            onClick={itemSelect(key)}
          >
            {icon && cloneElement(icon, { className: 'icon' })}
            {text}
          </li>
        ))}
      </Container>
    );
  },
)
Example #13
Source File: Card.tsx    From mantine with MIT License 6 votes vote down vote up
Card: CardComponent = forwardRef(
  (props: CardProps<'div'>, ref: PolymorphicRef<'div'>) => {
    const { component, className, p, radius, children, classNames, styles, ...others } =
      useMantineDefaultProps('Card', defaultProps, props);
    const { classes, cx } = useStyles(null, { name: 'Card', classNames, styles });
    const _children = Children.toArray(children);

    const content = _children.map((child, index) => {
      if (typeof child === 'object' && child && 'type' in child && child.type === CardSection) {
        return cloneElement(child, {
          padding: p,
          first: index === 0,
          last: index === _children.length - 1,
        });
      }

      return child;
    });

    return (
      <Paper
        className={cx(classes.root, className)}
        radius={radius}
        p={p}
        component={component || 'div'}
        ref={ref}
        {...others}
      >
        {content}
      </Paper>
    );
  }
) as any
Example #14
Source File: Confirm.tsx    From datart with Apache License 2.0 6 votes vote down vote up
export function Confirm({
  title,
  content,
  icon,
  footer,
  ...modalProps
}: ConfirmProps) {
  return (
    <Modal width={400} footer={false} closable={false} {...modalProps}>
      <ConfirmBody>
        {icon &&
          cloneElement(icon, {
            className: mergeClassNames(icon.props.className, 'icon'),
          })}
        <ConfirmContent>
          {title && typeof title === 'string' ? <h2>{title}</h2> : title}
          {content && typeof content === 'string' ? <p>{content}</p> : content}
          <Actions>{footer}</Actions>
        </ConfirmContent>
      </ConfirmBody>
    </Modal>
  );
}
Example #15
Source File: repeatedElement.ts    From plasmic with MIT License 6 votes vote down vote up
repeatedElementFn = <T>(isPrimary: boolean, elt: T): T => {
  if (isPrimary) {
    return elt;
  }
  if (Array.isArray(elt)) {
    return (elt.map((v) => repeatedElement(isPrimary, v)) as any) as T;
  }
  if (elt && isValidElement(elt) && typeof elt !== "string") {
    return (cloneElement(elt) as any) as T;
  }
  return elt;
}
Example #16
Source File: TabMenu.tsx    From pancake-toolkit with GNU General Public License v3.0 6 votes vote down vote up
ButtonMenu: React.FC<TabMenuProps> = ({ activeIndex = 0, onItemClick, children }) => {
  return (
    <Wrapper p={["0 4px", "0 16px"]}>
      <Inner>
        {Children.map(children, (child: ReactElement, index) => {
          const isActive = activeIndex === index;
          return cloneElement(child, {
            isActive,
            onClick: onItemClick ? () => onItemClick(index) : undefined,
            color: isActive ? "backgroundAlt" : "textSubtle",
            backgroundColor: isActive ? "textSubtle" : "input",
          });
        })}
      </Inner>
    </Wrapper>
  );
}
Example #17
Source File: SecureComponent.tsx    From console with GNU Affero General Public License v3.0 6 votes vote down vote up
SecureComponent = ({
  children,
  RenderError = () => <></>,
  errorProps = null,
  matchAll = false,
  scopes = [],
  resource,
  containsResource = false,
}: ISecureComponentProps) => {
  const permissionGranted = hasPermission(
    resource,
    scopes,
    matchAll,
    containsResource
  );
  if (!permissionGranted && !errorProps) return <RenderError />;
  if (!permissionGranted && errorProps) {
    return Array.isArray(children) ? (
      <>{children.map((child) => cloneElement(child, { ...errorProps }))}</>
    ) : (
      cloneElement(children, { ...errorProps })
    );
  }
  return <>{children}</>;
}
Example #18
Source File: InputGroup.tsx    From pancake-toolkit with GNU General Public License v3.0 6 votes vote down vote up
InputGroup = ({ scale = scales.MD, startIcon, endIcon, children, ...props }: InputGroupProps): JSX.Element => (
  <StyledInputGroup
    scale={scale}
    width="100%"
    position="relative"
    hasStartIcon={!!startIcon}
    hasEndIcon={!!endIcon}
    {...props}
  >
    {startIcon && <InputIcon scale={scale}>{startIcon}</InputIcon>}
    {cloneElement(children, { scale })}
    {endIcon && (
      <InputIcon scale={scale} isEndIcon>
        {endIcon}
      </InputIcon>
    )}
  </StyledInputGroup>
)
Example #19
Source File: Group.tsx    From react-native-wagmi-charts with MIT License 6 votes vote down vote up
export function LineChartGroup({ children, ...props }: Props) {
  const flatChildren = flattenChildren(children);
  const flatChildrenCount = Children.count(flatChildren);
  return (
    <View {...props}>
      {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
      {Children.map(flatChildren, (child: any, index) => {
        const isLast = index === flatChildrenCount - 1;
        if (!isLast && child.type === LineChart) {
          return cloneElement(child, {
            absolute: true,
          });
        }
        return child;
      })}
    </View>
  );
}
Example #20
Source File: index.tsx    From exevo-pan with The Unlicense 6 votes vote down vote up
RadioGroup = ({
  className,
  children,
  indexValue: indexProp,
  onChange,
  ...props
}: RadioGroupProps) => {
  const [innerIndex, setInnerIndex] = useState<number | undefined>(indexProp)
  const derivedActiveIndex = indexProp ?? innerIndex

  return (
    <div
      role="radiogroup"
      aria-activedescendant={indexToId(derivedActiveIndex)}
      className={clsx('grid gap-3', className)}
      {...props}
    >
      {Children.map(children, (child, index) => {
        if (!isValidElement(child)) return child
        if (typeof child.type === 'string') return child

        return cloneElement(child, {
          id: indexToId(index),
          active: derivedActiveIndex === index,
          onClick: () => {
            setInnerIndex((prevInnerIndex) => {
              if (prevInnerIndex !== index) onChange?.(index)
              return index
            })
          },
        })
      })}
    </div>
  )
}
Example #21
Source File: ExportDataPopup.tsx    From Teyvat.moe with GNU General Public License v3.0 6 votes vote down vote up
ExportDataPopup: FunctionComponent<ExportDataPopupProps> = ({
  title,
  message,
  fetchData,
  trigger,
}) => {
  const [data, setData] = useState<string>('');
  const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false);
  const classes = useStyles();

  // When the popup opens, update the contents.
  const performOpen = () => {
    setData(fetchData());
  };

  const onOpen = useCallback(() => setIsDialogOpen(true), []);
  const onClose = useCallback(() => setIsDialogOpen(false), []);

  return (
    <div>
      {cloneElement(trigger, { onClick: onOpen })}
      <Dialog
        PaperProps={{ className: classes.dialog }}
        open={isDialogOpen}
        onEntering={performOpen}
        fullWidth
        maxWidth="lg"
        onClose={onClose}
      >
        <DialogTitle onClose={onClose}>{title}</DialogTitle>
        <DialogContent>
          <DialogContentText>{message}</DialogContentText>
          <CopyTextArea text={data} rows={4} />
        </DialogContent>
      </Dialog>
    </div>
  );
}
Example #22
Source File: TabMenu.tsx    From vvs-ui with GNU General Public License v3.0 6 votes vote down vote up
ButtonMenu: React.FC<TabMenuProps> = ({ activeIndex = 0, onItemClick, children }) => {
  return (
    <Wrapper p={["0 4px", "0 16px"]}>
      <Inner>
        {Children.map(children, (child: ReactElement, index) => {
          const isActive = activeIndex === index;
          return cloneElement(child, {
            isActive,
            onClick: onItemClick ? () => onItemClick(index) : undefined,
            color: isActive ? "backgroundAlt" : "textSubtle",
            backgroundColor: isActive ? "textSubtle" : "input",
          });
        })}
      </Inner>
    </Wrapper>
  );
}
Example #23
Source File: useLoading.tsx    From react-loading with MIT License 6 votes vote down vote up
/**
 * Hook returning Indicator element according to loading argument.
 * @example const { containerProps, indicatorEl } = useLoading({ loading: true })
 */
export function useLoading({
  loading = false,
  indicator,
  loaderProps = {},
}: Props) {
  const containerProps = {
    'aria-busy': loading,
    'aria-live': 'polite' as AriaLive,
  };

  const loaderContext = useLoaderContext();
  const indicatorEl = indicator ?? loaderContext?.indicator;
  invariant(
    isValidElement(indicatorEl),
    'Expected a valid React element as indicator'
  );

  const accessibleLoaderProps = (() => {
    const { valueText, ...rest } = loaderProps;
    return {
      role: 'progressbar',
      'aria-valuetext': valueText,
      ...rest,
    };
  })();
  const accessibleIndicator = indicatorEl
    ? cloneElement(indicatorEl, accessibleLoaderProps)
    : null;

  return {
    containerProps,
    indicatorEl: loading ? accessibleIndicator : null,
  };
}
Example #24
Source File: ButtonMenu.tsx    From vvs-ui with GNU General Public License v3.0 6 votes vote down vote up
ButtonMenu: React.FC<ButtonMenuProps> = ({
  activeIndex = 0,
  scale = scales.MD,
  variant = variants.PRIMARY,
  onItemClick,
  disabled,
  children,
  fullWidth = false,
  ...props
}) => {
  return (
    <StyledButtonMenu disabled={disabled} variant={variant} fullWidth={fullWidth} {...props}>
      {Children.map(children, (child: ReactElement, index) => {
        return cloneElement(child, {
          isActive: activeIndex === index,
          onClick: onItemClick ? () => onItemClick(index) : undefined,
          scale,
          variant,
          disabled,
        });
      })}
    </StyledButtonMenu>
  );
}
Example #25
Source File: Group.tsx    From swiftui-react-native with MIT License 6 votes vote down vote up
Group = ({ children, ...rest }: GroupProps) => {
  const groupId = Math.floor(Math.random()) * 1000;
  return (
    <>
      {Children.map(children as ReactElement<any>[], (child, i) =>
        child
          ? cloneElement(child, {
              key: `group-${groupId}-${i}`,
              ...rest,
              ...child.props,
            })
          : null
      )}
    </>
  );
}
Example #26
Source File: SwitchButton.tsx    From test with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
cloneChild = (child, value, onChange = f => f) => {
  const active = child.props.value === value

  const props = {
    fill: true,
    bg: active ? null : 'transparent',
    border: active ? null : 'none',
    color: active ? 'white' : 'stormdust',
    onClick: () => onChange(child.props.value),
  }

  return cloneElement(child, props)
}
Example #27
Source File: getMenuItems.tsx    From calories-in with MIT License 6 votes vote down vote up
function getMenuItems(children: ReactElement | ReactElement[]) {
  return Children.map(children, (child: ReactElement) => {
    if (child.type === MenuOrDrawerItem) {
      const icon = cloneElement(child.props.icon, { size: 16, mr: 3 })

      return (
        <MenuItem
          disabled={child.props.isDisabled}
          onClick={child.props.onClick}
        >
          {icon}
          {child.props.children}
        </MenuItem>
      )
    } else if (child.type === MenuOrDrawerSeparator) {
      return <MenuDivider />
    }

    return null
  })
}
Example #28
Source File: AnimationManager.tsx    From dnd-kit with MIT License 6 votes vote down vote up
export function AnimationManager({animation, children}: Props) {
  const [
    clonedChildren,
    setClonedChildren,
  ] = useState<React.ReactElement | null>(null);
  const [element, setElement] = useState<HTMLElement | null>(null);
  const previousChildren = usePrevious(children);

  if (!children && !clonedChildren && previousChildren) {
    setClonedChildren(previousChildren);
  }

  useIsomorphicLayoutEffect(() => {
    if (!element) {
      return;
    }

    const key = clonedChildren?.key;
    const id = clonedChildren?.props.id;

    if (key == null || id == null) {
      setClonedChildren(null);
      return;
    }

    Promise.resolve(animation(id, element)).then(() => {
      setClonedChildren(null);
    });
  }, [animation, clonedChildren, element]);

  return (
    <>
      {children}
      {clonedChildren ? cloneElement(clonedChildren, {ref: setElement}) : null}
    </>
  );
}
Example #29
Source File: side-nav.tsx    From website with Apache License 2.0 6 votes vote down vote up
Section = ({ children, title }: SectionProps) => {
  const id = `section--${title.toLowerCase().split(' ').join('-')}`;

  return (
    <VerticalStack gap={2} spacing={6}>
      <Heading id={id} as="div" look="h500">
        {title}
      </Heading>
      {Children.map(children, (child) =>
        cloneElement(child as JSX.Element, { 'aria-labelledby': id })
      )}
    </VerticalStack>
  );
}