lodash#debounce JavaScript Examples

The following examples show how to use lodash#debounce. 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: node-details-table.js    From ThreatMapper with Apache License 2.0 6 votes vote down vote up
constructor(props, context) {
    super(props, context);

    this.state = {
      limit: props.limit,
      sortedDesc: this.props.sortedDesc,
      sortedBy: this.props.sortedBy
    };
    this.focusState = {};

    this.updateSorted = this.updateSorted.bind(this);
    this.handleLimitClick = this.handleLimitClick.bind(this);
    this.onMouseLeaveRow = this.onMouseLeaveRow.bind(this);
    this.onMouseEnterRow = this.onMouseEnterRow.bind(this);
    this.saveTableContentRef = this.saveTableContentRef.bind(this);
    // Use debouncing to prevent event flooding when e.g. crossing fast with mouse cursor
    // over the whole table. That would be expensive as each focus causes table to rerender.
    this.debouncedFocusRow = debounce(this.focusRow, TABLE_ROW_FOCUS_DEBOUNCE_INTERVAL);
    this.debouncedBlurRow = debounce(this.blurRow, TABLE_ROW_FOCUS_DEBOUNCE_INTERVAL);
  }
Example #2
Source File: change-value.js    From jafar with MIT License 6 votes vote down vote up
export default function changeValue(formId, fieldId, value) {
  return (dispatch, getState) => new Promise((resolve) => {
    const dependencies = [];

    const { model, settings } = getState().forms[formId];

    if (!verifyValidValue(fieldId, model, value, resolve)) return;

    value = evaluateValue(fieldId, model, value);

    // set value to form
    setViewValueToStore(formId, fieldId, value, dependencies)(dispatch, getState);

    addCachedDebounceResolve(formId, fieldId, 'value', resolve);

    // evaluate field and run field dependencies
    debouncedChangeValue = debouncedChangeValue || debounce(debounceFunc, settings.changeValueDebounceWait,
      { maxWait: settings.changeValueDebounceMaxWait });
    handleDebounceFlush(formId, fieldId, 'lastUpdatedFieldValue', debouncedChangeValue);
    debouncedChangeValue(resolve, dispatch, getState, formId, fieldId, value, dependencies);
  });
}
Example #3
Source File: change-state.js    From jafar with MIT License 6 votes vote down vote up
export default function changeState(formId, fieldId, state) {
  return (dispatch, getState) => new Promise((resolve) => {
    const stateChangesStates = [];

    const { model, settings } = getState().forms[formId];

    state = evaluateState(fieldId, model, state);

    // set component state in the form
    setStateToStore(formId, fieldId, state, stateChangesStates)(dispatch);

    addCachedDebounceResolve(formId, fieldId, 'state', resolve);

    debouncedChangeState = debouncedChangeState || debounce(debounceFunc, settings.changeStateDebounceWait,
      { maxWait: settings.changeStateDebounceMaxWait });
    handleDebounceFlush(formId, fieldId, 'lastUpdatedFieldState', debouncedChangeState);
    debouncedChangeState(resolve, dispatch, getState, formId, fieldId, state, stateChangesStates);
  });
}
Example #4
Source File: actionCreator.js    From techno-broadlink with MIT License 6 votes vote down vote up
deboucedRequestRenameDevice = debounce(
  async (ipAddress, deviceName, dispatch) => {
    dispatch(setIsBusy(true));
    await dispatch({
      type: RENAME_DEVICE,
      payload: renameDevice(ipAddress, deviceName),
    }).then(data => {
      batch(() => {
        dispatch(setIsBusy(false));
      });
    });
  },
  1500
)
Example #5
Source File: NextScrollBehavior.browser.js    From next-router-scroll with MIT License 6 votes vote down vote up
_savePosition(key, element) {
        // Override _savePosition so that writes to storage are debounced.
        // See: https://github.com/taion/scroll-behavior/issues/136
        let savePosition = this._debounceSavePositionMap.get(key);

        if (!savePosition) {
            savePosition = debounce(
                super._savePosition.bind(this),
                SAVE_POSITION_DEBOUNCE_TIME,
                { leading: true },
            );

            this._debounceSavePositionMap.set(key, savePosition);
        }

        savePosition(key, element);
    }
Example #6
Source File: Form.jsx    From kube-design with MIT License 6 votes vote down vote up
constructor(props) {
    super(props);
    this.descriptor = {};

    this.state = { errors: [], formData: props.data || {} };

    this.triggerFormChange = props.onChange
      ? debounce(props.onChange, 500)
      : null;

    this.customValidator = null;
  }
Example #7
Source File: index.jsx    From QuickFabric with Apache License 2.0 6 votes vote down vote up
constructor(props) {
    super(props)
    this.state = {
      data: this.props.data,
      show: false,
      primaryTab: 'all',
      primaryAction: 'allClusters',
      tabHeading: 'View All Clusters',
      uiListData: this.props.uiListData,
      clusterId: ''
    }

    this.createGroupState = this.createGroupState.bind(this)
    this.dataStateChange = this.dataStateChange.bind(this)
    this.expandChange = this.expandChange.bind(this)
    this.export = this.export.bind(this)
    this.handlePrimaryTabChange = this.handlePrimaryTabChange.bind(this)
    this.renderEMRTable = this.renderEMRTable.bind(this)
    GridCell.role = this.props.role
    GridCell.fullName= this.props.fullName
    GridCell.postAddSteps = this.postAddSteps.bind(this)
    GridCell.postTerminateCluster = this.postTerminateCluster.bind(this)
    GridCell.postRotateAMI = this.postRotateAMI.bind(this)
    GridCell.postDNSFlip = this.postDNSFlip.bind(this);
    this.postCreateCluster= this.props.postCreateCluster
    this.handleActionBtnClick = this.handleActionBtnClick.bind(this);
    this.fetchAllClusterMetaData = this.fetchAllClusterMetaData.bind(this);
    this.fetchClusterWiseMetaData = this.fetchClusterWiseMetaData.bind(this);
    this.handleTabs = this.handleTabs.bind(this);
    this.getUIDropdownData = debounce(this.getUIDropdownData.bind(this), 2500false);
    this.getRefreshButton = this.getRefreshButton.bind(this);
  }
Example #8
Source File: Enrollment.js    From SaraAlert with Apache License 2.0 6 votes vote down vote up
constructor(props) {
    super(props);
    this.state = {
      index: this.props.editMode ? 6 : 0,
      direction: null,
      enrollmentState: {
        patient: pickBy(this.props.patient, identity),
        propagatedFields: {},
      },
    };
    this.setEnrollmentState = debounce(this.setEnrollmentState.bind(this), 1000);
    this.submit = this.submit.bind(this);
    this.next = this.next.bind(this);
    this.previous = this.previous.bind(this);
    this.handleConfirmDuplicate = this.handleConfirmDuplicate.bind(this);
    this.goto = this.goto.bind(this);
  }
Example #9
Source File: zoomable-canvas.js    From ThreatMapper with Apache License 2.0 6 votes vote down vote up
constructor(props, context) {
    super(props, context);

    this.state = {
      contentMaxX: 0,
      contentMaxY: 0,
      contentMinX: 0,
      contentMinY: 0,
      isPanning: false,
      maxScale: 1,
      minScale: 1,
      scaleX: 1,
      scaleY: 1,
      translateX: 0,
      translateY: 0,
    };

    this.debouncedCacheZoom = debounce(this.cacheZoom.bind(this), ZOOM_CACHE_DEBOUNCE_INTERVAL);
    this.handleZoomControlAction = this.handleZoomControlAction.bind(this);
    this.canChangeZoom = this.canChangeZoom.bind(this);

    this.handleZoom = this.handleZoom.bind(this);
    this.handlePanStart = this.handlePanStart.bind(this);
    this.handlePanEnd = this.handlePanEnd.bind(this);
    this.handlePan = this.handlePan.bind(this);
  }
Example #10
Source File: terminal.js    From ThreatMapper with Apache License 2.0 6 votes vote down vote up
constructor(props, context) {
    super(props, context);

    this.reconnectTimeout = null;
    this.resizeTimeout = null;

    this.state = {
      cols: DEFAULT_COLS,
      connected: false,
      detached: false,
      rows: DEFAULT_ROWS,
    };

    this.handleCloseClick = this.handleCloseClick.bind(this);
    this.handlePopoutTerminal = this.handlePopoutTerminal.bind(this);
    this.saveInnerFlexRef = this.saveInnerFlexRef.bind(this);
    this.saveNodeRef = this.saveNodeRef.bind(this);
    this.handleResize = this.handleResize.bind(this);
    this.handleResizeDebounced = debounce(this.handleResize, 500);
  }
Example #11
Source File: node-details-table.js    From ThreatMapper with Apache License 2.0 6 votes vote down vote up
constructor(props, context) {
    super(props, context);

    this.state = {
      limit: props.limit,
      sortedBy: this.props.sortedBy,
      sortedDesc: this.props.sortedDesc
    };
    this.focusState = {};

    this.updateSorted = this.updateSorted.bind(this);
    this.handleLimitClick = this.handleLimitClick.bind(this);
    this.onMouseLeaveRow = this.onMouseLeaveRow.bind(this);
    this.onMouseEnterRow = this.onMouseEnterRow.bind(this);
    this.saveTableContentRef = this.saveTableContentRef.bind(this);
    this.saveTableHeadRef = this.saveTableHeadRef.bind(this);
    // Use debouncing to prevent event flooding when e.g. crossing fast with mouse cursor
    // over the whole table. That would be expensive as each focus causes table to rerender.
    this.debouncedFocusRow = debounce(this.focusRow, TABLE_ROW_FOCUS_DEBOUNCE_INTERVAL);
    this.debouncedBlurRow = debounce(this.blurRow, TABLE_ROW_FOCUS_DEBOUNCE_INTERVAL);
  }
Example #12
Source File: app.js    From ThreatMapper with Apache License 2.0 6 votes vote down vote up
constructor(props, context) {
    super(props, context);

    this.props.dispatch(setMonitorState(this.props.monitor));
    this.props.dispatch(setStoreViewState(!this.props.disableStoreViewState));

    this.setViewportDimensions = this.setViewportDimensions.bind(this);
    this.handleResize = debounce(this.setViewportDimensions, VIEWPORT_RESIZE_DEBOUNCE_INTERVAL);
    this.handleRouteChange = debounce(props.onRouteChange, 50);

    this.saveAppRef = this.saveAppRef.bind(this);
    this.onKeyPress = this.onKeyPress.bind(this);
    this.onKeyUp = this.onKeyUp.bind(this);
  }
Example #13
Source File: index.js    From react-native-segmented-text-input with MIT License 6 votes vote down vote up
SegmentedTextInput.propTypes = {
  value: PropTypes.arrayOf(PropTypes.any),
  onChange: PropTypes.func,
  patterns: PropTypes.shape({}),
  placeholder: PropTypes.string,
  placeholderTextColor: PropTypes.string,
  disabled: PropTypes.bool,
  textStyle: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.number]),
  textInputStyle: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.number]),
  invalidTextStyle: PropTypes.oneOfType([
    PropTypes.shape({}),
    PropTypes.number,
  ]),
  segmentContainerStyle: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.number]),
  suggestionsContainerStyle: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.number]),
  shouldRenderInvalid: PropTypes.func,
  max: PropTypes.number,
  onSuggest: PropTypes.func,
  minSuggestionLength: PropTypes.number,
  debounce: PropTypes.number,
  renderSuggestions: PropTypes.func,
  multiline: PropTypes.bool,
  numberOfLines: PropTypes.number,
};
Example #14
Source File: index.js    From react-native-segmented-text-input with MIT License 5 votes vote down vote up
SegmentedTextInput.defaultProps = {
  value: ['', []],
  onChange: Promise.resolve,
  patterns: {
    /* a twitter @mention */
    [PATTERN_MENTION]: ({style, onRequestDelete, children, ...extraProps}) => (
      <TouchableOpacity
        onPress={onRequestDelete}
      >
        <Text
          {...extraProps}
          style={[style, { fontWeight: "bold" }]}
          children={`${children} `}
        />
      </TouchableOpacity>
    ),
  },
  placeholder: "Add some @mentions...",
  placeholderTextColor: undefined,
  disabled: false,
  textStyle: {
    fontSize: 28,
  },
  textInputStyle: {
    minWidth: 100,
  },
  invalidTextStyle: {
    color: "red",
  },
  segmentContainerStyle: {},
  suggestionsContainerStyle: {},
  /* don't mark the first character as an invalid animation */
  shouldRenderInvalid: str => !str.startsWith("@"),
  max: 3,
  onSuggest: text => Promise.resolve([]),
  minSuggestionLength: 2,
  debounce: 350,
  renderSuggestions: ({loadingSuggestions, suggestions, pickSuggestion}) => (
    <View
      pointerEvents={loadingSuggestions ? "none" : "auto"}
      style={{
        flexDirection: "row",
        alignItems: "center",
      }}
    > 
      {!!loadingSuggestions && (
        <ActivityIndicator />
      )}
      {suggestions.map(
        (suggestion, i) => (
          <TouchableOpacity
            key={i}
            style={{
              opacity: loadingSuggestions ? 0.4 : 1.0,
            }}
            onPress={() => pickSuggestion([suggestion, PATTERN_MENTION.toString()])}
          >
            <Text
              style={{
                fontSize: 14,
              }}
              children={`${suggestion} `}
            />
          </TouchableOpacity>
        ),
      )} 
    </View>
  ),
  multiline: false,
  numberOfLines: 1,
};
Example #15
Source File: MessageSectionContainer.js    From airdnd-frontend with MIT License 5 votes vote down vote up
MessageSectionContainer = () => {
  // ! redux
  const { msgDetailSectionState, msgListSectionState } = useSelector(
    state => state.message.mediaState,
  );
  const dispatch = useDispatch();

  // ! variable
  const onResizeMedia = () => {
    if (window.innerWidth <= 1127) {
      dispatch(changeMediaSize('medium'));
    }
  };

  const onResizeLarge = () => {
    if (window.innerWidth > 1128) {
      dispatch(changeMediaSize('large'));
    }
  };

  useEffect(() => {
    window.addEventListener('resize', debounce(onResizeMedia, 200));
    window.addEventListener('resize', debounce(onResizeLarge, 200));
    return () => {
      window.removeEventListener('resize', onResizeMedia);
      window.removeEventListener('resize', onResizeLarge);
    };
  }, [dispatch]);

  useEffect(() => {
    if (window.innerWidth <= 1127) {
      dispatch(changeMediaSize('medium'));
    }
  }, [dispatch]);

  return (
    <MessageSection
      msgDetailSectionState={msgDetailSectionState}
      msgListSectionState={msgListSectionState}
    />
  );
}
Example #16
Source File: useQueryString.jsx    From ResoBin with MIT License 5 votes vote down vote up
useQueryString = () => {
  const location = useLocation()
  const navigate = useNavigate()

  const setQueryString = (key, value) => {
    const queryString = new URLSearchParams(location.search)

    // ? No change
    if (value === undefined || value === queryString.get(key)) return

    // ? update query string (or clear query string if query is empty)
    if (isEmpty(value) && !isFinite(value)) queryString.delete(key)
    else queryString.set(key, value)

    location.search = queryString.toString()
    navigate(location, { replace: true })
  }

  // ? Debouncing is necessary to avoid unnecessary API calls
  const setQueryStringDebounced = useCallback(
    memoize((key) => debounce(setQueryString, 500)),
    [location.search]
  )

  const getQueryString = useCallback(
    (key) => {
      const queryString = new URLSearchParams(location.search)
      if (key) return queryString.get(key)

      return Object.fromEntries(queryString)
    },
    [location.search]
  )

  // ? If keys are passed, removes keys from qs. Else clears qs
  const deleteQueryString = useCallback(
    (...keys) => {
      const queryString = new URLSearchParams(location.search)

      if (isEmpty(keys)) {
        location.search = ''
      } else {
        keys.forEach((key) => {
          queryString.delete(key)
        })
        location.search = queryString.toString()
      }

      navigate(location, { replace: true })
    },
    [location.search]
  )

  return {
    deleteQueryString,
    getQueryString,
    setQueryString: (key, value) => setQueryStringDebounced(key)(key, value),
  }
}
Example #17
Source File: AddAssets.js    From RRWallet with MIT License 5 votes vote down vote up
constructor(props) {
    super(props);
    this.onSearchBarTextChange = debounce(this.onSearchBarTextChange, 500);
  }
Example #18
Source File: _app.js    From nextjs-todo-list with MIT License 5 votes vote down vote up
start = debounce(NProgress.start, 200)
Example #19
Source File: index.jsx    From mui-phone-input-ssr with MIT License 5 votes vote down vote up
constructor(props) {
    super(props);
    let filteredCountries = countryData.allCountries;

    if (props.disableAreaCodes) filteredCountries = this.deleteAreaCodes(filteredCountries);
    if (props.regions) filteredCountries = this.filterRegions(props.regions, filteredCountries);

    const onlyCountries = this.excludeCountries(
      this.getOnlyCountries(props.onlyCountries, filteredCountries), props.excludeCountries,
    );

    const preferredCountries = filter(filteredCountries, (country) => some(props.preferredCountries, (preferredCountry) => preferredCountry === country.iso2));

    const inputNumber = props.value || '';

    let countryGuess;
    if (inputNumber.length > 1) {
      // Country detect by value field
      countryGuess = this.guessSelectedCountry(inputNumber.replace(/\D/g, '').substring(0, 6), onlyCountries, props.defaultCountry) || 0;
    } else if (props.defaultCountry) {
      // Default country
      countryGuess = find(onlyCountries, { iso2: props.defaultCountry }) || 0;
    } else {
      // Empty params
      countryGuess = 0;
    }

    const countryGuessIndex = findIndex(this.allCountries, countryGuess);
    const dialCode = (
      inputNumber.length < 2
      && countryGuess
      && !startsWith(inputNumber.replace(/\D/g, ''), countryGuess.dialCode)
    ) ? countryGuess.dialCode : '';

    const formattedNumber = (inputNumber === '' && countryGuess === 0) ? ''
      : this.formatNumber(
        (props.disableCountryCode ? '' : dialCode) + inputNumber.replace(/\D/g, ''),
        countryGuess.name ? countryGuess.format : undefined,
      );

    this.state = {
      formattedNumber,
      placeholder: props.placeholder,
      onlyCountries,
      preferredCountries,
      defaultCountry: props.defaultCountry,
      selectedCountry: countryGuess,
      highlightCountryIndex: countryGuessIndex,
      queryString: '',
      freezeSelection: false,
      debouncedQueryStingSearcher: debounce(this.searchCountry, 100),
      anchorEl: null,
    };
  }
Example #20
Source File: SubmitActionButtonCell.jsx    From QuickFabric with Apache License 2.0 5 votes vote down vote up
constructor(props) {
    super(props)

    var startTime = new Date();
    startTime.setHours(this.props.dataItem.autopilotWindowStart);
    var endTime = new Date();
    endTime.setHours(this.props.dataItem.autopilotWindowEnd);
    this.state = {
      ModalAddSteps: false,
      ModalTerminateCluster: false,
      ModalRotateAMI: false,
      ModalTestSuite: false,
      ModalCreatClusterWorkflow: false,
      ModalRotateAMIWorkflow: false,
      ModalDNSFlip: false,
      modalState: {},
      rotateamialert: false,
      workflowalert: false,
      autoAMIRotation: this.props.dataItem.autoAmiRotation,
      showAlert: false,
      alertMessage: '',
      alertTitle: '',
      alertIcon: '',
      showConfirmButton: false,
      autopilot_window_start: startTime,
      autopilot_window_end: endTime,
      autopilot_error: false,
      doTerminate: this.props.dataItem.doTerminate,
      ami_rotation_sla: this.props.dataItem.amiRotationSlaDays,
      autopilot_sla_alert: false,
      auto_ami_rotation_alert: false
    }

    this.handleAddStepsButtonClick= this.handleAddStepsButtonClick.bind(this)
    this.handleTerminateClusterButtonClick = this.handleTerminateClusterButtonClick.bind(this)
    this.handleRotateAMIButtonClick = this.handleRotateAMIButtonClick.bind(this)
    this.handleModalSubmitAddSteps = this.handleModalSubmitAddSteps.bind(this)
    this.handleModalSubmitTerminateCluster = this.handleModalSubmitTerminateCluster.bind(this)
    this.handleModalSubmitRotateAMI = this.handleModalSubmitRotateAMI.bind(this)
    this.handleModalClose = this.handleModalClose.bind(this)
    this.handleTestSuiteButtonClick = this.handleTestSuiteButtonClick.bind(this);
    this.handleCreateClusterWorkflowClick = this.handleCreateClusterWorkflowClick.bind(this);
    this.handleStepsStatusData = this.handleStepsStatusData.bind(this);
    this.handleRotateAMIWorkflowClick = this.handleRotateAMIWorkflowClick.bind(this);
    this.handleRotateAMIAlert = this.handleRotateAMIAlert.bind(this);
    this.handleDNSFlipButtonClick = this.handleDNSFlipButtonClick.bind(this);
    this.handleModalSubmitDNSFlip = this.handleModalSubmitDNSFlip.bind(this);
    this.handleWorkflowAlert = this.handleWorkflowAlert.bind(this);
    this.handleAutoAMIRotation = debounce(this.handleAutoAMIRotation.bind(this), 1000, false);
    this.toggleAutoAMIRotation = this.toggleAutoAMIRotation.bind(this);
    this.handleAlert = this.handleAlert.bind(this);
    this.handleConfirm = this.handleConfirm.bind(this);
    this.setAlert = this.setAlert.bind(this);
    this.rotateToggle = this.rotateToggle.bind(this);
    this.handleTimeChange = this.handleTimeChange.bind(this);
    this.handleAutoPilotWindowAlert = this.handleAutoPilotWindowAlert.bind(this);
    this.toggleTerminateCluster = this.toggleTerminateCluster.bind(this);
    this.handleDoTerminate = this.handleDoTerminate.bind(this);
    this.handleAMIRotationSLA = this.handleAMIRotationSLA.bind(this);
    this.handleCloneClusterButtonClick = this.handleCloneClusterButtonClick.bind(this);
    this.handleAutoPilotSLAAlert = this.handleAutoPilotSLAAlert.bind(this);
    this.handleAutoAMIRotationAlert = this.handleAutoAMIRotationAlert.bind(this);
    this.handleCustomAlertAutoAMI = this.handleCustomAlertAutoAMI.bind(this);
  }
Example #21
Source File: index.js    From aircon with GNU General Public License v3.0 5 votes vote down vote up
constructor() {
    super();
    this.updateTargetTemp = debounce(this.updateTargetTemp, 1000);
  }
Example #22
Source File: NavAppBar.js    From yasn with MIT License 4 votes vote down vote up
export default function NavAppBar(props) {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = React.useState(null);
  const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null);

  const isMenuOpen = Boolean(anchorEl);
  const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);

  const [mobileOpen, setMobileOpen] = React.useState(false);

  const handleDrawerToggle = () => {
    setMobileOpen(!mobileOpen);
  };

  const handleProfileMenuOpen = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const handleMobileMenuClose = () => {
    setMobileMoreAnchorEl(null);
  };

  const handleMenuClose = () => {
    setAnchorEl(null);
    handleMobileMenuClose();
  };

  const handleMobileMenuOpen = (event) => {
    setMobileMoreAnchorEl(event.currentTarget);
  };

  const handleLogOut = () => {
    setMobileMoreAnchorEl(null);
    cookies.remove("userCookie");
    cookies.remove("userDetails");
    window.location.reload();
  };

  const menuId = "primary-search-account-menu";
  const renderMenu = (
    <Menu
      anchorEl={anchorEl}
      anchorOrigin={{ vertical: "top", horizontal: "right" }}
      id={menuId}
      keepMounted
      transformOrigin={{ vertical: "top", horizontal: "right" }}
      open={isMenuOpen}
      onClose={handleMenuClose}
    >
      <Link to={`/profile`} className={classes.link}>
        <MenuItem onClick={handleMenuClose}>Profile</MenuItem>
      </Link>
      <MenuItem onClick={handleMenuClose} onClick={handleLogOut}>
        Log Out
      </MenuItem>
    </Menu>
  );

  const mobileMenuId = "primary-search-account-menu-mobile";
  const renderMobileMenu = (
    <Menu
      anchorEl={mobileMoreAnchorEl}
      anchorOrigin={{ vertical: "top", horizontal: "right" }}
      id={mobileMenuId}
      keepMounted
      transformOrigin={{ vertical: "top", horizontal: "right" }}
      open={isMobileMenuOpen}
      onClose={handleMobileMenuClose}
    >
      <Link to="/chat" className={classes.link}>
        <MenuItem onClick={handleMobileMenuClose}>
          <IconButton aria-label="show 4 new mails" color="inherit">
            <Badge badgeContent={"ßeta"} color="secondary">
              <MailIcon />
            </Badge>
          </IconButton>
          <p>Messages</p>
        </MenuItem>
      </Link>
      <Link to="/add" className={classes.link}>
        <MenuItem onClick={handleMobileMenuClose}>
          <IconButton aria-label="show 11 new notifications" color="inherit">
            {/* <Badge badgeContent={11} color="secondary"> */}
            <PostAddIcon />
            {/* </Badge> */}
          </IconButton>
          <p>Add Post</p>
        </MenuItem>
      </Link>

      <Link to={`/profile`} className={classes.link}>
        <MenuItem onClick={handleMobileMenuClose}>
          <IconButton
            aria-label="account of current user"
            aria-controls="primary-search-account-menu"
            aria-haspopup="true"
            color="inherit"
          >
            <AccountCircle />
          </IconButton>
          <p>Profile</p>
        </MenuItem>
      </Link>
      <MenuItem onClick={handleLogOut}>
        <IconButton aria-label="show 11 new notifications" color="inherit">
          <ExitToAppIcon />
        </IconButton>
        <p>Log Out</p>
      </MenuItem>
    </Menu>
  );

  const { container } = props;

  const theme = useTheme();

  const drawer = (
    <div>
      <div className={classes.toolbar} />
      <List>
        <ListItem>
          <Typography>Browse by Category</Typography>
        </ListItem>
      </List>

      <Divider />
      <List>
        {/* <Link to="/home/Project"> */}
        <a href="/home/Project">
          <ListItem button key={"Projects"}>
            <ListItemIcon>
              <GitHubIcon />
            </ListItemIcon>
            <ListItemText primary={"Projects"} />
          </ListItem>
        </a>
        {/* </Link> */}

        {/* <Link to="/home/Writings"> */}
        <a href="/home/Writings">
          <ListItem button key={"Writings"}>
            <ListItemIcon>
              <CreateIcon />
            </ListItemIcon>
            <ListItemText primary={"Writings"} />
          </ListItem>
        </a>
        {/* </Link> */}

        {/* <Link to="/home/Artwork" onClick={handleTagLink}> */}
        <a href="/home/Artwork">
          <ListItem button key={"Artwork"}>
            <ListItemIcon>
              <GestureIcon />
            </ListItemIcon>
            <ListItemText primary={"Artwork"} />
          </ListItem>
        </a>
        {/* </Link> */}
      </List>
      <Divider />

      <List>
        {/* <Link to="/home/Music"> */}
        <a href="/home/Music">
          <ListItem button key={"Music"}>
            <ListItemIcon>
              <MusicNoteIcon />
            </ListItemIcon>
            <ListItemText primary={"Music"} />
          </ListItem>
        </a>
        {/* </Link> */}

        {/* <Link to="/home/Dance"> */}
        <a href="/home/Dance">
          <ListItem button key={"Dance"}>
            <ListItemIcon>
              <DirectionsWalkIcon />
            </ListItemIcon>
            <ListItemText primary={"Dance"} />
          </ListItem>
        </a>
        {/* </Link> */}

        {/* <Link to="/home/Other"> */}
        <a href="/home/Other">
          <ListItem button key={"Other"}>
            <ListItemIcon>
              <CallSplitIcon />
            </ListItemIcon>
            <ListItemText primary={"Other"} />
          </ListItem>
        </a>
        {/* </Link> */}
      </List>
      <Divider />
    </div>
  );

  const userCookie = cookies.get("userCookie");
  const googleToken = userCookie.Token;
  const email = userCookie.Email;

  const [searchResults, setSearchResults] = useState([]);

  const searchUsers = debounce((searchString) => {
    axios
      .get(
        `${ConnectServerUrl}/searchUsers?` +
          queryString.stringify(
            { searchString, googleToken, email },
            { withCredentials: true }
          )
      )
      .then((res) => {
        setSearchResults(res.data);
      })
      .catch(console.log);
  }, 400);

  const onSearchInputChange = (event) => {
    const searchString = event.target.value;
    if (searchString) {
      searchUsers(searchString);
    }
  };

  return (
    <div className={classes.root}>
      <CssBaseline />
      <div className={classes.grow}>
        <AppBar position="fixed" className={classes.appBar}>
          <Toolbar>
            <IconButton
              edge="start"
              className={handleDrawerToggle}
              color="inherit"
              aria-label="open drawer"
              onClick={handleDrawerToggle}
              // eslint-disable-next-line
              className={classes.menuButton}
            >
              <MenuIcon />
            </IconButton>
            <Link to="/">
              <IconButton edge="start">
                <DonutSmallIcon style={{ color: "white" }} />
              </IconButton>
            </Link>
            <Typography className={classes.title} variant="h6" noWrap>
              Connect
            </Typography>
            <div className={classes.search}>
              <div className={classes.searchIcon}>
                <SearchIcon />
              </div>
              <Autocomplete
                id="free-solo-demo"
                freeSolo
                clearOnBlur
                options={searchResults}
                className="searchBox"
                classes={{
                  root: classes.inputRoot,
                  input: classes.inputInput,
                  endAdornment: classes.endAdornment,
                }}
                getOptionLabel={(option) => option.name}
                renderOption={(option, state) => (
                  <Link to={`/user/${option.username}`}>
                    <Typography>{option.name}</Typography>
                  </Link>
                )}
                renderInput={(params) => (
                  <TextField
                    {...params}
                    onChange={onSearchInputChange}
                    placeholder="Search DAIICTians"
                  />
                )}
              />
            </div>
            <div className={classes.grow} />
            <div className={classes.sectionDesktop}>
              <Link to="/chat">
                <IconButton aria-label="show 4 new mails" color="inherit">
                  <Badge badgeContent={"ßeta"} color="secondary">
                    <MailIcon />
                  </Badge>
                </IconButton>
              </Link>
              <Link to="/add">
                <IconButton
                  aria-label="show 17 new notifications"
                  color="inherit"
                >
                  {/* <Badge badgeContent={17} color="secondary"> */}
                  <PostAddIcon />
                  {/* </Badge> */}
                </IconButton>
              </Link>
              <IconButton
                edge="end"
                aria-label="account of current user"
                aria-controls={menuId}
                aria-haspopup="true"
                onClick={handleProfileMenuOpen}
                color="inherit"
              >
                <AccountCircle />
              </IconButton>
            </div>
            <div className={classes.sectionMobile}>
              <IconButton
                aria-label="show more"
                aria-controls={mobileMenuId}
                aria-haspopup="true"
                onClick={handleMobileMenuOpen}
                color="inherit"
              >
                <MoreIcon />
              </IconButton>
            </div>
          </Toolbar>
        </AppBar>
        {renderMobileMenu}
        {renderMenu}
      </div>
      <nav className={classes.drawer} aria-label="mailbox folders">
        {/* The implementation can be swapped with js to avoid SEO duplication of links. */}
        <Hidden smUp implementation="css">
          <Drawer
            container={container}
            variant="temporary"
            anchor={theme.direction === "rtl" ? "right" : "left"}
            open={mobileOpen}
            onClose={handleDrawerToggle}
            classes={{
              paper: classes.drawerPaper,
            }}
            ModalProps={{
              keepMounted: true, // Better open performance on mobile.
            }}
          >
            {drawer}
          </Drawer>
        </Hidden>
        <Hidden xsDown implementation="css">
          <Drawer
            classes={{
              paper: classes.drawerPaper,
            }}
            variant="permanent"
            open
          >
            {drawer}
          </Drawer>
        </Hidden>
      </nav>
      <main className={classes.content}>
        {props.children}
        {/* <div className={classes.toolbar} /> */}
      </main>
    </div>
  );
}
Example #23
Source File: search-autocomplete.jsx    From amadeus-airport-city-search-mern with MIT License 4 votes vote down vote up
SearchAutocomplete = (props) => {
  const [open, setOpen] = React.useState(false);
  const [options, setOptions] = React.useState([]);
  const [search, setSearch] = React.useState('')
  const [keyword, setKeyword] = React.useState('')
  const [loading, setLoading] = React.useState(false)

  // Configure options format for proper displaying on the UI
  const names = options.map(i => ({ type: i.subType, name: i.name }));

  // Debounce func prevents extra unwanted keystrokes, when user triggers input events 
  const debounceLoadData = useCallback(debounce(setKeyword, 1000), []);

  useEffect(() => {
    debounceLoadData(search);
  }, [search]);

  // Same example as in *SearchRoot* component
  React.useEffect(() => {

    setLoading(true)
    const { out, source } = getAmadeusData({ ...props.search, page: 0, keyword });

    out.then(res => {
      if (!res.data.code) {
        setOptions(res.data.data);
      }
      setLoading(false)
    }).catch(err => {
      axios.isCancel(err);
      setOptions([]);
      setLoading(false)

    });

    return () => {
      source.cancel()
    };
  }, [keyword]);

  // Desctructuring our props
  const { city, airport } = props.search

  const label = city && airport ? "City and Airports" : city ? "City" : airport ? "Airports" : ""

  return (
    // This is Material-UI component that also has it's own props
    <>
      <Autocomplete
        id="asynchronous-demo"
        style={{ width: 300, marginBottom: "1rem" }}
        open={open}
        onOpen={() => {
          setOpen(true);
        }}
        onClose={() => {
          setOpen(false);
        }}
        getOptionSelected={(option, value) =>
          option.name === value.name && option.type === value.type
        }
        onChange={(e, value) => {
          if (value && value.name) {
            props.setSearch((p) => ({ ...p, keyword: value.name, page: 0 }))
            setSearch(value.name)
            return;
          }
          setSearch("")
          props.setSearch((p) => ({ ...p, keyword: "a", page: 0 }))

        }}
        getOptionLabel={option => {
          return option.name;
        }}
        options={names}
        loading={loading}
        renderInput={params => {
          return (
            <TextField
              label={label}
              fullWidth
              onChange={e => {
                e.preventDefault();
                setSearch(e.target.value);
              }}
              variant="outlined"
              inputProps={{
                ...params.inputProps,
                value: search
              }}
              InputProps={{
                ...params.InputProps,
                endAdornment: (
                  <React.Fragment>
                    {loading ? (
                      <CircularProgress color="inherit" size={20} />
                    ) : null}
                    {params.InputProps.endAdornment}
                  </React.Fragment>
                )
              }}
            />
          );
        }}
      />
    </>
  )
}
Example #24
Source File: index.js    From gobench with Apache License 2.0 4 votes vote down vote up
Sidebar = ({
  dispatch,
  isSidebarOpen,
  isMenuCollapsed,
  isMenuShadow,
  isMenuUnfixed,
  menuLayoutType,
  menuColor,
  authPagesColor,
  isTopbarFixed,
  isContentMaxWidth,
  isAppMaxWidth,
  isGrayBackground,
  isGrayTopbar,
  isCardShadow,
  isSquaredBorders,
  isBorderless,
  routerAnimation,
  locale,
  theme,
  primaryColor,
  leftMenuWidth,
  logo,
}) => {
  const [defaultColor] = useState('#4b7cf3')

  const selectColor = debounce(color => {
    dispatch({
      type: 'settings/SET_PRIMARY_COLOR',
      payload: {
        color,
      },
    })
  }, 200)

  const setTheme = nextTheme => {
    dispatch({
      type: 'settings/SET_THEME',
      payload: {
        theme: nextTheme,
      },
    })
    dispatch({
      type: 'settings/CHANGE_SETTING',
      payload: {
        setting: 'menuColor',
        value: nextTheme === 'dark' ? 'dark' : 'light',
      },
    })
  }

  const resetColor = () => {
    dispatch({
      type: 'settings/SET_PRIMARY_COLOR',
      payload: {
        color: defaultColor,
      },
    })
  }

  const changeSetting = (setting, value) => {
    dispatch({
      type: 'settings/CHANGE_SETTING',
      payload: {
        setting,
        value,
      },
    })
  }

  const toggleSettings = e => {
    e.preventDefault()
    dispatch({
      type: 'settings/CHANGE_SETTING',
      payload: {
        setting: 'isSidebarOpen',
        value: !isSidebarOpen,
      },
    })
  }

  const selectMenuLayoutType = e => {
    const { value } = e.target
    dispatch({
      type: 'settings/CHANGE_SETTING',
      payload: {
        setting: 'menuLayoutType',
        value,
      },
    })
  }

  const colorPickerHandler = (e, setting, value) => {
    e.preventDefault()
    dispatch({
      type: 'settings/CHANGE_SETTING',
      payload: {
        setting,
        value,
      },
    })
  }

  const selectRouterAnimation = value => {
    dispatch({
      type: 'settings/CHANGE_SETTING',
      payload: {
        setting: 'routerAnimation',
        value,
      },
    })
  }

  const selectLocale = value => {
    dispatch({
      type: 'settings/CHANGE_SETTING',
      payload: {
        setting: 'locale',
        value,
      },
    })
  }

  const ColorPicker = props => {
    return props.colors.map(item => {
      return (
        <a
          href="#"
          key={item}
          onClick={e => colorPickerHandler(e, props.setting, item)}
          className={classNames(`${style.cui__sidebar__select__item}`, {
            [style.cui__sidebar__select__item__active]: props.value === item,
            [style.cui__sidebar__select__item__black]: item === 'dark',
            [style.cui__sidebar__select__item__white]: item === 'white',
            [style.cui__sidebar__select__item__gray]: item === 'gray',
            [style.cui__sidebar__select__item__blue]: item === 'blue',
            [style.cui__sidebar__select__item__img]: item === 'image',
          })}
        />
      )
    })
  }

  return (
    <div>
      <div
        className={classNames(style.cui__sidebar, {
          [style.cui__sidebar__toggled]: isSidebarOpen,
        })}
      >
        <PerfectScrollbar>
          <div className={style.cui__sidebar__inner}>
            <a
              href="#"
              className={`fe fe-x-circle ${style.cui__sidebar__close}`}
              onClick={toggleSettings}
            />
            <h5>
              <strong>Theme Settings</strong>
            </h5>
            <div className="cui__utils__line" style={{ marginTop: 25, marginBottom: 30 }} />
            <div>
              <div className={`${style.cui__sidebar__type} mb-4`}>
                <div className={style.cui__sidebar__type__title}>
                  <span>Application Name</span>
                </div>
                <div className={style.cui__sidebar__type__items}>
                  <Input
                    value={logo}
                    onChange={e => {
                      const { value } = e.target
                      changeSetting('logo', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__type}>
                <div className={style.cui__sidebar__type__title}>
                  <span>Menu Layout</span>
                </div>
                <div className={style.cui__sidebar__type__items}>
                  <Radio.Group onChange={selectMenuLayoutType} defaultValue={menuLayoutType}>
                    <div className="row">
                      <div className="col-6">
                        <div className="mb-2">
                          <Radio value="left">Left Menu</Radio>
                        </div>
                        <div className="mb-2">
                          <Radio value="top">Top Menu</Radio>
                        </div>
                      </div>
                      <div className="col-6">
                        <div className="mb-2">
                          <Radio value="nomenu">No menu</Radio>
                        </div>
                      </div>
                    </div>
                  </Radio.Group>
                </div>
              </div>
              <div className={`${style.cui__sidebar__type} mb-4`}>
                <div className={style.cui__sidebar__type__title}>
                  <span>Router Animation</span>
                </div>
                <div className={style.cui__sidebar__type__items}>
                  <Select
                    defaultValue={routerAnimation}
                    style={{ width: '100%' }}
                    onChange={selectRouterAnimation}
                  >
                    <Select.Option value="none">None</Select.Option>
                    <Select.Option value="slide-fadein-up">Slide Up</Select.Option>
                    <Select.Option value="slide-fadein-right">Slide Right</Select.Option>
                    <Select.Option value="fadein">Fade In</Select.Option>
                    <Select.Option value="zoom-fadein">Zoom</Select.Option>
                  </Select>
                </div>
              </div>
              <div className={`${style.cui__sidebar__type} mb-4`}>
                <div className={style.cui__sidebar__type__title}>
                  <span>Internationalization</span>
                </div>
                <div className={style.cui__sidebar__type__items}>
                  <Select value={locale} style={{ width: '100%' }} onChange={selectLocale}>
                    <Select.Option value="en-US">English (en-US)</Select.Option>
                    <Select.Option value="fr-FR">French (fr-FR)</Select.Option>
                    <Select.Option value="ru-RU">Русский (ru-RU)</Select.Option>
                    <Select.Option value="zh-CN">简体中文 (zh-CN)</Select.Option>
                  </Select>
                </div>
              </div>
              <div className={`${style.cui__sidebar__type} mb-2`}>
                <div className={style.cui__sidebar__type__title}>
                  <span>Left Menu Width</span>
                </div>
                <div className={style.cui__sidebar__type__items}>
                  <Slider
                    value={leftMenuWidth}
                    min={256}
                    max={330}
                    onChange={value => {
                      changeSetting('leftMenuWidth', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>Left Menu: Collapsed</div>
                <div className={style.cui__sidebar__container}>
                  <Switch
                    checked={isMenuCollapsed}
                    disabled={menuLayoutType !== 'left'}
                    onChange={value => {
                      changeSetting('isMenuCollapsed', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>Left Menu: Unfixed</div>
                <div className={style.cui__sidebar__container}>
                  <Switch
                    checked={isMenuUnfixed}
                    disabled={menuLayoutType !== 'left'}
                    onChange={value => {
                      changeSetting('isMenuUnfixed', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>Left Menu: Shadow</div>
                <div className={style.cui__sidebar__container}>
                  <Switch
                    checked={isMenuShadow}
                    onChange={value => {
                      changeSetting('isMenuShadow', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>Menu: Color</div>
                <div className={style.cui__sidebar__container}>
                  <ColorPicker
                    setting="menuColor"
                    value={menuColor}
                    colors={['white', 'gray', 'dark']}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>Auth: Background</div>
                <div className={style.cui__sidebar__container}>
                  <ColorPicker
                    setting="authPagesColor"
                    value={authPagesColor}
                    colors={['white', 'gray', 'image']}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>Topbar: Fixed</div>
                <div className={style.cui__sidebar__container}>
                  <Switch
                    checked={isTopbarFixed}
                    onChange={value => {
                      changeSetting('isTopbarFixed', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>Topbar: Gray Background</div>
                <div className={style.cui__sidebar__container}>
                  <Switch
                    checked={isGrayTopbar}
                    onChange={value => {
                      changeSetting('isGrayTopbar', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>App: Content Max-Width</div>
                <div className={style.cui__sidebar__container}>
                  <Switch
                    checked={isContentMaxWidth}
                    onChange={value => {
                      changeSetting('isContentMaxWidth', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>App: Max-Width</div>
                <div className={style.cui__sidebar__container}>
                  <Switch
                    checked={isAppMaxWidth}
                    onChange={value => {
                      changeSetting('isAppMaxWidth', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>App: Gray Background</div>
                <div className={style.cui__sidebar__container}>
                  <Switch
                    checked={isGrayBackground}
                    onChange={value => {
                      changeSetting('isGrayBackground', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>Cards: Squared Borders</div>
                <div className={style.cui__sidebar__container}>
                  <Switch
                    checked={isSquaredBorders}
                    onChange={value => {
                      changeSetting('isSquaredBorders', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>Cards: Shadow</div>
                <div className={style.cui__sidebar__container}>
                  <Switch
                    checked={isCardShadow}
                    onChange={value => {
                      changeSetting('isCardShadow', value)
                    }}
                  />
                </div>
              </div>
              <div className={style.cui__sidebar__item}>
                <div className={style.cui__sidebar__label}>Cards: Borderless</div>
                <div className={style.cui__sidebar__container}>
                  <Switch
                    checked={isBorderless}
                    onChange={value => {
                      changeSetting('isBorderless', value)
                    }}
                  />
                </div>
              </div>
            </div>
          </div>
        </PerfectScrollbar>
      </div>
      <Tooltip title="Settings" placement="left">
        <a
          role="button"
          tabIndex="0"
          onFocus={e => {
            e.preventDefault()
          }}
          onKeyPress={toggleSettings}
          onClick={toggleSettings}
          style={{ bottom: 'calc(50% + 120px)' }}
          className={style.cui__sidebar__toggleButton}
        >
          <i className="fe fe-settings" />
        </a>
      </Tooltip>
      <Tooltip title="Switch Dark / Light Theme" placement="left">
        <a
          role="button"
          tabIndex="0"
          onFocus={e => {
            e.preventDefault()
          }}
          onKeyPress={() => setTheme(theme === 'default' ? 'dark' : 'default')}
          onClick={() => setTheme(theme === 'default' ? 'dark' : 'default')}
          style={{ bottom: 'calc(50% + 60px)' }}
          className={style.cui__sidebar__toggleButton}
        >
          {theme === 'default' && <i className="fe fe-moon" />}
          {theme !== 'default' && <i className="fe fe-sun" />}
        </a>
      </Tooltip>
      <Tooltip title="Set Primary Color" placement="left">
        <a
          style={{ bottom: 'calc(50%)' }}
          className={`${style.cui__sidebar__toggleButton} ${style.color} ${
            primaryColor === defaultColor ? style.reset : ''
          }`}
        >
          <button
            type="button"
            tabIndex="0"
            onFocus={e => {
              e.preventDefault()
            }}
            onKeyPress={resetColor}
            onClick={resetColor}
          >
            <i className="fe fe-x-circle" />
          </button>
          <input
            type="color"
            id="colorPicker"
            onChange={e => selectColor(e.target.value)}
            value={primaryColor}
          />
          <i className="fe fe-package" />
        </a>
      </Tooltip>
      <Tooltip title="Documentation" placement="left">
        <a
          href="https://docs.cleanuitemplate.com"
          target="_blank"
          rel="noopener noreferrer"
          style={{ bottom: 'calc(50% - 60px)' }}
          className={style.cui__sidebar__toggleButton}
        >
          <i className="fe fe-book-open" />
        </a>
      </Tooltip>
    </div>
  )
}
Example #25
Source File: ApiTree.js    From hzero-front with Apache License 2.0 4 votes vote down vote up
apiTree = (props) => {
  const treeDs = useMemo(() => new DataSet(treeDS), []);

  const [value, setValue] = useState('');
  const [treeData, setTreeData] = useState([]);
  const [expandedKeys, setExpandedKeys] = useState([]);
  const [selectedKeys] = useState([]);
  const [autoExpandParent, setAutoExpandParent] = useState(false);

  const { onClose, getDetail, setCurrentNode, setDetailFlag } = props;

  useEffect(() => {
    treeDs
      .query()
      .then((res) => {
        setTreeData(res);
        // if (res.length) {
        //   setExpandedKeys(['0', '0-0', '0-0-0']);
        //   const node = [res[0].children[0].children[0].children[0]];
        //   getDetail(node);
        //   setCurrentNode(node);
        // }
      })
      .catch((err) => {
        notification.error({
          message: err.message,
        });
      });
  }, []);

  const renderTreeNodes = (data = []) => {
    let icon = (
      <Icon style={{ color: 'rgba(0,0,0,0.65)', fontSize: '.14rem' }} type="folder_open" />
    );

    return data.map((item) => {
      const index = item.title.indexOf(value);
      const beforeStr = item.title.substr(0, index);
      const afterStr = item.title.substr(index + value.length);
      const titleLength = item.title.length;
      const splitNum = 24;
      let apiWrapper;
      if (titleLength < splitNum) {
        apiWrapper = 'c7n-iam-apitest-api-wrapper-1';
      } else if (titleLength >= splitNum && titleLength < splitNum * 2) {
        apiWrapper = 'c7n-iam-apitest-api-wrapper-2';
      } else if (titleLength >= splitNum * 2 && titleLength < splitNum * 3) {
        apiWrapper = 'c7n-iam-apitest-api-wrapper-3';
      } else if (titleLength >= splitNum * 3 && titleLength < splitNum * 4) {
        apiWrapper = 'c7n-iam-apitest-api-wrapper-4';
      } else {
        apiWrapper = 'c7n-iam-apitest-api-wrapper-5';
      }

      const title =
        index > -1 ? (
          <span>
            {beforeStr}
            <span style={{ color: '#f50' }}>{value}</span>
            {afterStr}
          </span>
        ) : (
          <span>{item.title}</span>
        );
      if (item.method) {
        icon = (
          <div
            className={classnames(
              `c7n-iam-apitest-tree-${item.key}`,
              'c7n-iam-apitest-tree-methodTag',
              `c7n-iam-apitest-tree-methodTag-${item.method}`
            )}
          >
            <div>{item.method}</div>
          </div>
        );
      }

      if (item.children) {
        const icon2 = (
          <Icon
            style={{ color: 'rgba(0,0,0,0.65)', fontSize: '.14rem' }}
            type={expandedKeys.includes(item.key) ? 'folder_open2' : 'folder_open'}
            className={`c7n-iam-apitest-tree-${item.key}`}
          />
        );
        return (
          <TreeNode
            title={
              <Tooltip
                title={title}
                getPopupContainer={() =>
                  document.getElementsByClassName(`c7n-iam-apitest-tree-${item.key}`)[0]
                }
              >
                <div className="c7n-tree-title-ellipsis">{title}</div>
              </Tooltip>
            }
            key={item.key}
            dataRef={item}
            icon={icon2}
          >
            {renderTreeNodes(item.children)}
          </TreeNode>
        );
      }
      return (
        <TreeNode
          {...item}
          title={
            <Tooltip
              title={item.description || title}
              getPopupContainer={() =>
                document.getElementsByClassName(`c7n-iam-apitest-tree-${item.key}`)[0].parentNode
                  .parentNode
              }
            >
              <div>{title}</div>
            </Tooltip>
          }
          dataRef={item}
          icon={icon}
          className={classnames({ [apiWrapper]: item.method })}
        />
      );
    });
  };

  // 展开或关闭树节点
  const onExpand = (newExpandedKeys) => {
    setExpandedKeys(newExpandedKeys);
    setAutoExpandParent(false);
  };

  const onSelect = (selectedKey, info) => {
    const arr = expandedKeys.includes(selectedKey[0])
      ? expandedKeys.filter((item) => item !== selectedKey[0])
      : expandedKeys.concat(selectedKey);
    setExpandedKeys(arr);

    if (
      info.selectedNodes[0] &&
      info.selectedNodes[0].children &&
      !info.selectedNodes[0].children.length
    ) {
      setCurrentNode(null);
      setDetailFlag('empty');
      return;
    }
    if (info.selectedNodes[0] && !info.selectedNodes[0].children) {
      setCurrentNode(info.selectedNodes);
      getDetail(info.selectedNodes);
    }
  };

  const getParentKey = (key, tree) => {
    let parentKey;
    for (let i = 0; i < tree.length; i += 1) {
      const node = tree[i];
      if (node.children) {
        if (node.children.some((item) => item.key === key)) {
          parentKey = node.key;
        } else if (getParentKey(key, node.children)) {
          parentKey = getParentKey(key, node.children);
        }
      }
    }
    return parentKey;
  };

  const getItem = (arr = [], target) => {
    arr.forEach((item) => {
      const temp = item;
      temp.parentKey = temp.key
        .split('-')
        .slice(0, temp.key.split('-').length - 1)
        .join('-');
      target.push(temp);
      if (Array.isArray(item.children)) {
        getItem(item.children, target);
      }
    });
  };

  const filterApi = debounce((e) => {
    const data = [];
    getItem(treeData, data);
    const expandedKey = data
      .map((item) => {
        if (item.title.indexOf(e) > -1) {
          return getParentKey(item.key, data);
        }
        return null;
      })
      .filter((item, i, self) => item && self.indexOf(item) === i);
    setValue(e);
    setAutoExpandParent(true);
    setExpandedKeys(e.length ? expandedKey : []);
  }, 1000);

  return (
    <div className="c7n-iam-apitest-tree-content">
      <Spin dataSet={treeDs} wrapperClassName="c7n-iam-apitest-tree-content-spin">
        <div className="c7n-iam-apitest-tree-top">
          <Input
            prefix={<Icon type="search" style={{ color: 'black' }} />}
            onChange={(e) => filterApi.call(null, e.target.value)}
          />
          <div role="none" className="c7n-iam-apitest-tree-top-button" onClick={onClose}>
            <Icon type="navigate_before" />
          </div>
        </div>
        <div className="c7n-iam-apitest-tree-main">
          <Tree
            expandedKeys={expandedKeys}
            selectedKeys={selectedKeys}
            showIcon
            onSelect={onSelect}
            onExpand={onExpand}
            autoExpandParent={autoExpandParent}
          >
            {renderTreeNodes(treeData)}
          </Tree>
        </div>
      </Spin>
    </div>
  );
}
Example #26
Source File: FilterInput.js    From edge-frontend with Apache License 2.0 4 votes vote down vote up
FilterInput = ({ filterValues, setFilterValues, input }) => {
  const selectedFilter = filterValues.find((filter) => filter.label === input);
  const [isOpen, setIsOpen] = useState(false);

  const handleFilterChange = () => (value, checkboxValue) => {
    setFilterValues((prevState) => {
      const selectedIndex = prevState.findIndex(
        (filter) => filter.label === selectedFilter.label
      );
      const checkedType = prevState.find(
        (filter) => filter.label === selectedFilter.label
      );
      const checkboxIndex =
        selectedFilter.type === 'checkbox'
          ? checkedType.value.findIndex((i) => i.option === checkboxValue)
          : 0;
      const newValueArray = Object.values({
        ...checkedType.value,
        [checkboxIndex]: {
          ...checkedType.value[checkboxIndex],
          isChecked: !checkedType?.value[checkboxIndex]?.isChecked,
        },
      });
      const newTextValue = value;

      return Object.values({
        ...prevState,
        [selectedIndex]: {
          ...prevState[selectedIndex],
          value:
            selectedFilter.type === 'checkbox' ? newValueArray : newTextValue,
        },
      });
    });
  };

  const handleDeleteTextInput = () => {
    const filterLabelIndex = filterValues.findIndex(
      (value) => value.type === 'text'
    );
    setFilterValues((prevState) => {
      const changedValue = prevState[filterLabelIndex];
      if (changedValue.type === 'text') {
        return [
          ...prevState.slice(0, filterLabelIndex),
          { ...prevState[filterLabelIndex], value: '' },
          ...prevState.slice(filterLabelIndex + 1, prevState.length),
        ];
      }
      return prevState;
    });
  };

  if (selectedFilter.type === 'text') {
    return (
      <ToolbarItem data-testid="filter-input-testid">
        <InputGroup>
          <SearchInput
            name="textInput1"
            id="textInput1"
            type="search"
            aria-label={`Select input for ${selectedFilter.label.toLowerCase()}`}
            placeholder={`Filter by ${selectedFilter.label.toLowerCase()}`}
            onChange={debounce(handleFilterChange(), 500)}
            onClear={handleDeleteTextInput}
            value={filterValues.find((filter) => filter.type === 'text').value}
          />
        </InputGroup>
      </ToolbarItem>
    );
  }

  if (selectedFilter.type === 'checkbox') {
    return (
      <ToolbarItem data-testid="filter-input-testid">
        <InputGroup>
          <Select
            variant="checkbox"
            aria-label={`Select input for ${selectedFilter.label.toLowerCase()}`}
            width="11rem"
            placeholderText={`Filter by ${selectedFilter.label.toLowerCase()}`}
            isCheckboxSelectionBadgeHidden
            onToggle={() => setIsOpen((prevState) => !prevState)}
            onSelect={handleFilterChange()}
            selections={selectedFilter.value
              .filter((value) => value.isChecked == true)
              .map((arr) => arr.option)}
            isOpen={isOpen}
          >
            {selectedFilter.value.map((filter, index) => (
              <SelectOption
                key={index}
                value={filter.option}
                isChecked={filter.isChecked}
              />
            ))}
          </Select>
        </InputGroup>
      </ToolbarItem>
    );
  }
}
Example #27
Source File: Projects.js    From gitlab-lint-react with BSD 3-Clause "New" or "Revised" License 4 votes vote down vote up
Projects = () => {
  const classes = useStyles();

  const [page, setPage] = useState(1);
  const [searchInput, setSearchInput] = useState("");
  const handleChange = (event, value) => {
    setPage(value);
    fetchData({ query: { page: value, q: searchInput } });
  };
  const debouncedSearch = useCallback(
    () => debounce((value) => fetchData({ query: { page, q: value } }), 500),
    [page]
  );
  const handleChangeSearch = (value) => {
    setSearchInput(value);
    debouncedSearch(value);
  };
  const [rows, setData] = useState({});
  const [meta, setMeta] = useState({});
  const fetchData = ({ query }) => {
    GitlabLintHttpClient("GET_ALL", { entity: "projects", query: query })
      .then((data) => {
        setData(data.data);
        setMeta(data.meta);
      })
      .catch((err) => console.error(err));
  };

  useEffect(() => {
    fetchData({ query: { page: 1 } });
  }, []);

  if (Object.keys(rows).length === 0 && rows.constructor === Object) {
    return <Loading />;
  }

  return (
    <React.Fragment>
      <div className={classes.header}>
        <Typography variant="h4" paragraph>
          Projects
        </Typography>
        <form noValidate autoComplete="off">
          <Input
            placeholder="Find a project..."
            value={searchInput}
            onChange={(e) => handleChangeSearch(e.target.value)}
          />
        </form>
      </div>
      <List>
        {rows.map((row) => {
          return (
            <ListItem
              button
              component={Link}
              to={`/projects/${row.id}`}
              key={row.id}
            >
              <ListItemText primary={row.path_with_namespace} />
              <div className={classes.levels}>
                {Object.keys(row.rules).map((key, index) => {
                  return (
                    <Tooltip key={key} title={key} placement="top-start">
                      <Chip
                        className={`${classes.level} ${classes[key]}`}
                        label={row.rules[key]}
                        size="small"
                      />
                    </Tooltip>
                  );
                })}
              </div>
            </ListItem>
          );
        })}
      </List>
      <div className={classes.pagination}>
        <Pagination
          boundaryCount={2}
          color="primary"
          count={meta.totalOfPages}
          onChange={handleChange}
          page={page}
          siblingCount={2}
        />
      </div>
    </React.Fragment>
  );
}
Example #28
Source File: index.js    From react-native-segmented-text-input with MIT License 4 votes vote down vote up
SegmentedTextInput = React.forwardRef(
  (
    {
      style,
      textStyle,
      textInputStyle,
      invalidTextStyle,
      segmentContainerStyle,
      value: [value, segments],
      onChange,
      patterns,
      placeholder,
      placeholderTextColor,
      disabled,
      shouldRenderInvalid,
      max,
      onSuggest,
      suggestionsContainerStyle,
      minSuggestionLength,
      debounce: suggestionDebounce,
      renderSuggestions,
      multiline,
      numberOfLines,
      ...extraProps
    },
    providedRef,
  ) => {
    const localRef = useRef();
    const ref = providedRef || localRef;
    const [loadingSuggestions, setLoadingSuggestions] = useState(false);
    const [suggestions, setSuggestions] = useState([]);
    const [debouncedLoading] = useDebounce(loadingSuggestions, suggestionDebounce * 0.5);
    const [debouncedSuggestions, {flush}] = useDebounce(suggestions, suggestionDebounce * 0.5);

    const [debouncedSuggestion] = useState(
      () => debounce(
        async (str) => {
          try {
            setLoadingSuggestions(true);
            setSuggestions(await onSuggest(str));
          } catch (e) {
            console.error(e);
          } finally {
            setLoadingSuggestions(false);
          }
        },
        suggestionDebounce,
      ),
    );

    const nextSegments = React.useMemo(
      () => {
        return ((typeCheck("String", value) && value)  || "")
          .split(/[ ,]+/)
          .map(
            str => [
              str,
              Object.keys(patterns)
                .reduce(
                  (selected, regExp) => (selected || (new RegExp(regExp, "gm").test(str)) && regExp),
                  null,
              ),
            ],
          );
      },
      [value, patterns],
    );

    // XXX: Latch the final segment (this is text that's in-dev).
    const [lastSegmentText, isValidLastSegment] = nextSegments[nextSegments.length - 1];

    // XXX: Filter all previous segments that didn't match.
    const existingSegmentText = React.useMemo(() => segments .map(([text]) => text), [segments]);

    const validSegments = React.useMemo(() => {
      return [
        ...nextSegments
          .filter(([_, match], i, orig) => (i !== (orig.length - 1) && !!match))
          .filter(([text]) => existingSegmentText.indexOf(text) < 0),
      ];
    }, [nextSegments, existingSegmentText]);

    React.useEffect(() => {
      lastSegmentText.trim().length === 0 && suggestions.length && setSuggestions([]);
    }, [lastSegmentText, suggestions, setSuggestions]);

    // XXX: Prevent duplicates.
    const onChangeTextCallback = useCallback(
      (nextValue) => {
        debouncedSuggestion.cancel();
        if (!isEqual(value, nextValue)) {
          const nextSegments = [...segments, ...validSegments]
            .filter((e, i, orig) => (orig.indexOf(e) === i));
          return onChange([nextValue, nextSegments]);
        }
        return undefined;
      },
      [onChange, value, segments, validSegments, debouncedSuggestion],
    ); 

    const renderLastSegmentAsInvalid = lastSegmentText.length > 0 && (!isValidLastSegment && !!shouldRenderInvalid(lastSegmentText));
    const segmentsToRender = React.useMemo(() => {
      return [...(segments || []), ...validSegments];
    }, [segments, validSegments]);
    const shouldDisable = disabled || (segmentsToRender.length >= max);

    useEffect(
      () => {
        if (shouldDisable) { /* blur if disabled */
          debouncedSuggestion.cancel();
          setSuggestions([]);
          ref.current.isFocused() && ref.current.blur();
        }
        return undefined;
      },
      [shouldDisable],
    );

    /* suggestion handling */
    useEffect(
      () => {
        if (!shouldDisable && !renderLastSegmentAsInvalid && lastSegmentText.length >= minSuggestionLength) {
          debouncedSuggestion.cancel();
          /* request suggestion debounce */
          debouncedSuggestion(lastSegmentText);
        }
        return undefined;
      },
      [renderLastSegmentAsInvalid, lastSegmentText, minSuggestionLength, debouncedSuggestion],
    );

    useEffect(
      () => {
        if (!isEqual(segmentsToRender, segments)) {
          onChange([lastSegmentText, segmentsToRender]);
        }
      },
      [segmentsToRender, segments, onChange],
    );

    const renderedSegments = React.useMemo(() => {
      return segmentsToRender.map(([str, regexp], i) => {
        const Component = patterns[regexp] || React.Fragment;
        return (
          <Component
            key={str}
            style={textStyle}
            children={str}
            onRequestDelete={() => {
              const filteredSegments = segmentsToRender.filter(
                ([t]) => t !== str
              );
              onChange([lastSegmentText, filteredSegments]);
              ref.current.focus(); /* refocus the field */
            }}
          />
        );
      });
    }, [patterns, segmentsToRender, lastSegmentText, onChange]);

    const onKeyPress = React.useCallback((e) => {
      const {
        nativeEvent: { key: keyValue },
      } = e;
      /* delete old segments */
      if (lastSegmentText.length === 0 && segmentsToRender.length > 0) {
        if (keyValue === "Backspace") {
          //debouncedSuggestion.cancel();
          onChange([
            lastSegmentText,
            segmentsToRender.filter((_, i, orig) => i < orig.length - 1),
          ]);
        }
      }
      return undefined;
    }, [lastSegmentText, segmentsToRender, onChange]);

    React.useEffect(() => {
      if ((renderLastSegmentAsInvalid || !value.length) && suggestions.length > 0) {
        setSuggestions([]);
        debouncedSuggestion.cancel();
        flush();
      }
    }, [renderLastSegmentAsInvalid, debouncedSuggestion, setSuggestions, flush]);

    const computedTextInputStyle = React.useMemo(() => {
      return [
        textStyle,
        textInputStyle,
        !!renderLastSegmentAsInvalid && invalidTextStyle,
        /* hide text field when disabled */
        !!shouldDisable && { height: 0 },
      ].filter((e) => !!e);
    }, [textStyle, textInputStyle, renderLastSegmentAsInvalid, invalidTextStyle, shouldDisable]);

    const onSubmitEditing = React.useCallback(() => {
      onChange([`${lastSegmentText} `, segmentsToRender]);
    }, [lastSegmentText, segmentsToRender]);

    //const shouldRenderSuggestions = React.useMemo(() => {
    //  return !shouldDisable && suggestions.length > 0;
    //  //return ((!shouldDisable && lastSegmentText.length >= minSuggestionLength && Array.isArray(suggestions) && suggestions.length > 0) || loadingSuggestions);
    //}, [shouldDisable, lastSegmentText, minSuggestionLength, suggestions, loadingSuggestions]);

    const shouldPickSuggestion = React.useCallback(([suggestion, regexp]) => {
      if (!typeCheck("String", suggestion)) {
        throw new Error(
          `Expected String suggestion, encountered ${suggestion}.`
        );
      } else if (!typeCheck("String", regexp)) {
        throw new Error(`Expected String regexp, encountered ${regexp}.`);
      }

      debouncedSuggestion.cancel();

      setSuggestions([]);
      onChange(["", [...segmentsToRender, [suggestion, regexp]]]);
    }, [debouncedSuggestion, setSuggestions, onChange, segmentsToRender]);
    return (
      <>
        <View {...extraProps} style={[styles.segments, style]}>
          <View style={[styles.segments, segmentContainerStyle]}>
            {renderedSegments}
          </View>
          <TextInput
            multiline={multiline}
            numberOfLines={numberOfLines}
            pointerEvents={shouldDisable ? "none" : "auto"}
            onKeyPress={onKeyPress}
            ref={ref}
            disabled={shouldDisable}
            style={computedTextInputStyle}
            placeholder={shouldDisable ? "" : placeholder}
            placeholderTextColor={placeholderTextColor}
            value={lastSegmentText}
            onChangeText={onChangeTextCallback}
            onSubmitEditing={onSubmitEditing}
          />
        </View>
        {/* TODO since the request must conform to a selected regexp, we can be the ones to pick it */}
        <View style={suggestionsContainerStyle}>
          {renderSuggestions({
            loadingSuggestions: debouncedLoading,
            suggestions: debouncedSuggestions,
            pickSuggestion: shouldPickSuggestion,
          })}
        </View>
      </>
    );
  },
)
Example #29
Source File: SearchFormContainer.js    From airdnd-frontend with MIT License 4 votes vote down vote up
SearchFormContainer = ({ isSearchBtnClicked }) => {
  let history = useHistory();
  const dispatch = useDispatch();
  const searchData = useSelector(state => state.searchForm);
  const [locationResult, setLocationResult] = useState([]);
  const [type, setType] = useState(null);
  const latestType = useRef(type);

  latestType.current = type;

  const {
    location,
    checkIn,
    checkOut,
    dateDiff,
    flexibleDate,
    guests,
  } = searchData;

  const searchFormRef = useRef();
  const locationWrapperRef = useRef();
  const checkInWrapperRef = useRef();
  const checkOutWrapperRef = useRef();
  const guestsWrapperRef = useRef();

  const locationListRef = useRef();
  const calendarPopupRef = useRef();
  const checkOutPopupRef = useRef();
  const guestsPopupRef = useRef();

  const locationResetBtnRef = useRef();
  const checkInResetBtnRef = useRef();
  const checkOutResetBtnRef = useRef();
  const guestsResetBtnRef = useRef();

  const refObj = {
    searchFormRef,
    locationWrapperRef,
    checkInWrapperRef,
    checkOutWrapperRef,
    guestsWrapperRef,
    locationListRef,
    calendarPopupRef,
    checkOutPopupRef,
    guestsPopupRef,
    locationResetBtnRef,
    checkInResetBtnRef,
    checkOutResetBtnRef,
    guestsResetBtnRef,
  };

  const changeType = newType => {
    setType(newType);
  };

  const handleSubmit = e => {
    e.preventDefault();

    let newCheckIn = checkIn;
    let newCheckOut = checkOut;
    if (checkIn && !checkOut) {
      const checkInDate = new Date(checkIn);
      const checkOutDate = new Date();
      checkOutDate.setDate(checkInDate.getDate() + 1);
      const year = checkOutDate.getFullYear();
      const month = `0${checkOutDate.getMonth() + 1}`.slice(-2);
      const date = `0${checkOutDate.getDate()}`.slice(-2);
      const payload = `${year}.${month}.${date}`;
      newCheckOut = payload;
      changeSearchData('checkOut', payload);
    } else if (!checkIn && checkOut) {
      const checkOutDate = new Date(checkIn);
      const checkInDate = new Date();
      checkInDate.setDate(checkOutDate.getDate() - 1);
      const year = checkOutDate.getFullYear();
      const month = `0${checkOutDate.getMonth() + 1}`.slice(-2);
      const date = `0${checkOutDate.getDate()}`.slice(-2);
      const payload = `${year}.${month}.${date}`;
      newCheckIn = payload;
      changeSearchData('checkIn', payload);
    }
    const { adult, child, infant } = guests;
    const guestCount = +adult + +child + +infant;
    const url = `/search?location=${location}&checkIn=${newCheckIn}&checkOut=${newCheckOut}&dateDiff=${dateDiff}&flexibleDate=${flexibleDate}&guests=${guestCount}&adult=${adult}&child=${child}&infant=${infant}`;
    history.push(url);
    window.scrollTo({ top: 0 });
  };

  const changeSearchData = (name, value) => {
    const data = { name, value };
    dispatch(setSearchData(data));
  };

  const debounceGetAutoCompleteResult = useCallback(
    debounce(async value => {
      const result = await getLocationAutoComplete(value);
      setLocationResult(result || []);
    }, 300),
    [],
  );

  const changeAutoComplete = value => {
    if (!value) {
      changeSearchData('location', '');
      setLocationResult([]);
      return;
    } else {
      changeSearchData('location', value);
      debounceGetAutoCompleteResult(value);
      setType('location');
    }
  };

  const setCheckIn = date => {
    changeSearchData('checkIn', date);
    changeType('checkOut');
  };

  const setCheckOut = date => {
    changeSearchData('checkOut', date);
    changeType('guests');
  };

  const increaseGuestCount = (guestsData, guestType) => {
    let { adult, child, infant } = guestsData;
    if (guestType === 'adult' || !adult) adult++;
    if (guestType === 'child') {
      child++;
    } else if (guestType === 'infant') {
      infant++;
    }
    const value = { adult, child, infant };
    changeSearchData('guests', value);
  };

  const decreaseGuestCount = (guestsData, guestType) => {
    let { adult, child, infant } = guestsData;
    if (guestType === 'adult') adult--;
    else if (guestType === 'child') child--;
    else if (guestType === 'infant') infant--;
    const value = { adult, child, infant };
    changeSearchData('guests', value);
  };

  const changeFocus = () => {
    if (latestType.current === 'checkIn') checkInWrapperRef.current.focus();
    else if (latestType.current === 'checkOut')
      checkOutWrapperRef.current.focus();
    else if (latestType.current === 'guests') guestsWrapperRef.current.focus();
  };

  const handlePopup = useCallback(
    ({ target }) => {
      if (locationListRef.current && locationListRef.current.contains(target)) {
        changeType('checkIn');
      } else if (locationWrapperRef.current.contains(target)) {
        changeType('location');
      } else if (
        checkInWrapperRef.current.contains(target) &&
        !calendarPopupRef.current.contains(target)
      ) {
        changeType('checkIn');
      } else if (
        checkOutWrapperRef.current.contains(target) &&
        !calendarPopupRef.current.contains(target)
      ) {
        changeType('checkOut');
      } else if (guestsWrapperRef.current.contains(target)) {
        changeType('guests');
      } else if (type === 'checkOut' && latestType.current === 'guests') {
        changeType('guests');
      } else if (
        latestType.current &&
        !searchFormRef.current.contains(target) &&
        !calendarPopupRef.current.contains(target)
      ) {
        changeType(null);
      }
    },
    [latestType.current],
  );
  useEffect(() => {
    document.addEventListener('click', handlePopup);
    return () => {
      document.removeEventListener('click', handlePopup);
    };
  }, [handlePopup]);

  useEffect(() => {
    if (type) changeFocus();
  });

  return (
    <SearchForm
      isSearchBtnClicked={isSearchBtnClicked}
      type={type}
      refObj={refObj}
      changeType={changeType}
      searchData={searchData}
      changeSearchData={changeSearchData}
      changeAutoComplete={changeAutoComplete}
      locationResult={locationResult}
      handleSubmit={handleSubmit}
      setCheckIn={setCheckIn}
      setCheckOut={setCheckOut}
      increaseGuestCount={increaseGuestCount}
      decreaseGuestCount={decreaseGuestCount}
    ></SearchForm>
  );
}