@material-ui/core#Portal TypeScript Examples

The following examples show how to use @material-ui/core#Portal. 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: context_menu.tsx    From jupyter-extensions with Apache License 2.0 6 votes vote down vote up
render() {
    const children = React.Children.map(
      this.props.children,
      (child: React.ReactElement) => {
        return React.cloneElement(child, {
          onContextMenu: this.openContextMenu,
        });
      }
    );

    return (
      <>
        {children}
        <Portal>
          <ContextMenuContainer
            transitionDuration={0}
            open={this.state.isOpen}
            anchorReference="anchorPosition"
            anchorPosition={{ top: this.state.mouseY, left: this.state.mouseX }}
          >
            <div ref={this.myRef}>
              {this.props.items.map(option => (
                <ContextMenuItem key={option.label} onClick={option.onClick}>
                  {option.label}
                </ContextMenuItem>
              ))}
            </div>
          </ContextMenuContainer>
        </Portal>
      </>
    );
  }
Example #2
Source File: TechDocsReaderPageContentAddons.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
TechDocsReaderPageContentAddons = () => {
  const addons = useTechDocsAddons();

  const { shadowRoot } = useTechDocsReaderPage();

  const contentElement = shadowRoot?.querySelector(
    '[data-md-component="content"]',
  );

  const primarySidebarElement = shadowRoot?.querySelector(
    'div[data-md-component="sidebar"][data-md-type="navigation"], div[data-md-component="navigation"]',
  );
  let primarySidebarAddonLocation = primarySidebarElement?.querySelector(
    '[data-techdocs-addons-location="primary sidebar"]',
  );
  if (!primarySidebarAddonLocation) {
    primarySidebarAddonLocation = document.createElement('div');
    primarySidebarAddonLocation.setAttribute(
      'data-techdocs-addons-location',
      'primary sidebar',
    );
    primarySidebarElement?.prepend(primarySidebarAddonLocation);
  }

  const secondarySidebarElement = shadowRoot?.querySelector(
    'div[data-md-component="sidebar"][data-md-type="toc"], div[data-md-component="toc"]',
  );
  let secondarySidebarAddonLocation = secondarySidebarElement?.querySelector(
    '[data-techdocs-addons-location="secondary sidebar"]',
  );
  if (!secondarySidebarAddonLocation) {
    secondarySidebarAddonLocation = document.createElement('div');
    secondarySidebarAddonLocation.setAttribute(
      'data-techdocs-addons-location',
      'secondary sidebar',
    );
    secondarySidebarElement?.prepend(secondarySidebarAddonLocation);
  }

  return (
    <>
      <Portal container={primarySidebarAddonLocation}>
        {addons.renderComponentsByLocation(locations.PrimarySidebar)}
      </Portal>
      <Portal container={contentElement}>
        {addons.renderComponentsByLocation(locations.Content)}
      </Portal>
      <Portal container={secondarySidebarAddonLocation}>
        {addons.renderComponentsByLocation(locations.SecondarySidebar)}
      </Portal>
    </>
  );
}
Example #3
Source File: ReportIssue.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
ReportIssueAddon = ({
  debounceTime = 500,
  templateBuilder: buildTemplate,
}: ReportIssueProps) => {
  const classes = useStyles();
  const [style, setStyle] = useState<Style>();

  const repository = useGitRepository();

  const defaultTemplate = useGitTemplate(debounceTime);

  const selection = useShadowRootSelection(debounceTime);

  const [mainContent, feedbackLink] = useShadowRootElements([
    PAGE_MAIN_CONTENT_SELECTOR,
    PAGE_FEEDBACK_LINK_SELECTOR,
  ]);

  let [feedbackContainer] = useShadowRootElements([
    ADDON_FEEDBACK_CONTAINER_SELECTOR,
  ]);

  if (feedbackLink) {
    feedbackLink.style.display = 'none';
  }

  // calculates the position of the selected text to be able to set the position of the addon
  useEffect(() => {
    if (
      // todo(backstage/techdocs-core) handle non-repo rendering
      !repository ||
      !selection ||
      !selection.containsNode(mainContent!, true) ||
      selection?.containsNode(feedbackContainer!, true)
    ) {
      return;
    }

    const mainContentPosition = mainContent!.getBoundingClientRect();
    const selectionPosition = selection.getRangeAt(0).getBoundingClientRect();

    setStyle({
      top: `${selectionPosition.top - mainContentPosition.top - 16}px`,
      left: `${selectionPosition.left + selectionPosition.width / 2}px`,
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selection, mainContent, feedbackContainer]);

  if (!selection || !repository) return null;

  if (!feedbackContainer) {
    feedbackContainer = document.createElement('div');
    feedbackContainer.setAttribute('id', ADDON_FEEDBACK_CONTAINER_ID);
    mainContent!.prepend(feedbackContainer);
  }

  return (
    <Portal container={feedbackContainer}>
      <Paper
        data-testid="report-issue-addon"
        className={classes.root}
        style={style}
      >
        <IssueLink
          repository={repository}
          template={
            buildTemplate ? buildTemplate({ selection }) : defaultTemplate
          }
        />
      </Paper>
    </Portal>
  );
}
Example #4
Source File: Layout.tsx    From clearflask with Apache License 2.0 4 votes vote down vote up
render() {
    const stackedSectionsForName: { [name: string]: Section[] } = {};
    const breakActionForName: { [name: string]: BreakAction } = {};
    this.props.sections.forEach(section => {
      const breakAction = (section.breakAlways
        ? section.breakAction
        : (this.props.mediaQueries[section.name] === false && section.breakAction))
        || 'show';
      breakActionForName[section.name] = breakAction;
      if (breakAction === 'stack' && section.breakAction === 'stack') {
        stackedSectionsForName[section.stackWithSectionName] = stackedSectionsForName[section.stackWithSectionName] || [];
        stackedSectionsForName[section.stackWithSectionName].push(section);
      }
    });
    const layoutState: LayoutState = {
      isShown: name => breakActionForName[name] || 'show',
      enableBoxLayout: this.props.mediaQueries.enableBoxLayout,
    };

    const sectionPreview = this.props.sections.find(s => s.breakAction === 'drawer');
    const contentPreview = !sectionPreview || layoutState.isShown(sectionPreview.name) !== 'drawer'
      ? null : this.renderStackedSections(layoutState, sectionPreview, 'drawer', stackedSectionsForName[sectionPreview.name]);
    const sectionMenu = this.props.sections.find(s => s.breakAction === 'menu');
    const contentMenu = !sectionMenu || layoutState.isShown(sectionMenu.name) !== 'menu'
      ? null : this.renderStackedSections(layoutState, sectionMenu, 'menu', stackedSectionsForName[sectionMenu.name]);

    const contents: React.ReactNode[] = [];
    this.props.sections.forEach(section => {
      const breakAction = breakActionForName[section.name];
      if (breakAction !== 'show') return;
      const content = this.renderStackedSections(layoutState, section, breakAction, stackedSectionsForName[section.name]);
      if (!content) return;
      contents.push(content);
    });

    return (
      <div>
        {!!this.props.toolbarShow && (
          <Portal>
            <AppBar elevation={0} color='default' className={this.props.classes.appBar}>
              <Toolbar>
                {!!contentMenu && (
                  <IconButton
                    color="inherit"
                    aria-label="Open drawer"
                    onClick={this.handleDrawerToggle.bind(this)}
                    className={this.props.classes.menuButton}
                  >
                    <MenuIcon />
                  </IconButton>
                )}
                {this.props.toolbarLeft}
                <div className={this.props.classes.grow} />
                {this.props.toolbarRight}
              </Toolbar>
              <Divider />
            </AppBar>
          </Portal>
        )}
        {!!contentMenu && (
          <Drawer
            variant='temporary'
            open={this.state.mobileMenuOpen}
            onClose={this.handleDrawerToggle.bind(this)}
            classes={{
              paper: classNames(this.props.classes.menuPaper),
            }}
            style={{
              width: sectionMenu?.size?.maxWidth || sectionMenu?.size?.width || sectionMenu?.size?.breakWidth || '100%',
            }}
            ModalProps={{
              keepMounted: true,
            }}
          >
            {!!this.props.toolbarShow && (<div className={this.props.classes.toolbarSpacer} />)}
            {contentMenu}
          </Drawer>
        )}
        {!!contentPreview && (
          <Drawer
            variant='temporary'
            SlideProps={{ mountOnEnter: true }}
            anchor='right'
            open={!!this.props.previewShow}
            onClose={this.handlePreviewClose.bind(this)}
            classes={{
              modal: this.props.classes.previewMobileModal,
              paper: this.props.classes.previewMobilePaper,
            }}
            style={{
              width: sectionPreview?.size?.maxWidth || sectionPreview?.size?.width || sectionPreview?.size?.breakWidth || '100%',
            }}
          >
            {!!this.props.toolbarShow && (<div className={this.props.classes.toolbarSpacer} />)}
            {contentPreview}
          </Drawer>
        )}
        <div className={classNames(this.props.classes.page, this.props.classes.flexVertical)}>
          {!!this.props.toolbarShow && (<div className={this.props.classes.toolbarSpacer} />)}
          <div className={classNames(
            this.props.classes.sections,
            layoutState.enableBoxLayout ? this.props.classes.sectionsBox : this.props.classes.sectionsNobox,
            this.props.classes.grow,
            this.props.classes.flexHorizontal,
          )}>
            {contents}
          </div>
        </div>
      </div>
    );
  }