@mui/material#InputBase TypeScript Examples

The following examples show how to use @mui/material#InputBase. 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: DesktopSearch.tsx    From GTAV-NativeDB with MIT License 6 votes vote down vote up
StyledInputBase = styled(InputBase)(({ theme }) => ({
  color: 'inherit',
  width: '100%',
  '& .MuiInputBase-input': {
    padding: theme.spacing(1, 1, 1, 0),
    paddingLeft: `calc(1em + ${theme.spacing(4)})`,
    transition: theme.transitions.create('width'),
    width: '100%'
  }
}))
Example #2
Source File: MobileSearch.tsx    From GTAV-NativeDB with MIT License 6 votes vote down vote up
StyledInputBase = styled(InputBase)(({ theme }) => ({
  color: 'inherit',
  flex: 1,
  padding: theme.spacing(0, 1),
  '& .MuiInputBase-input': {
    transition: theme.transitions.create('width'),
    width: '100%'
  }
}))
Example #3
Source File: Search.tsx    From abrechnung with GNU Affero General Public License v3.0 6 votes vote down vote up
StyledInputBase = styled(InputBase)(({ theme }: { theme: Theme }) => ({
    color: "inherit",
    "& .MuiInputBase-input": {
        padding: theme.spacing(1, 1, 1, 0),
        // vertical padding + font size from searchIcon
        paddingLeft: `calc(1em + ${theme.spacing(4)})`,
        transition: theme.transitions.create("width"),
        width: "100%",
        [theme.breakpoints.up("md")]: {
            width: "20ch",
        },
    },
}))
Example #4
Source File: SetupScreen.tsx    From rewind with MIT License 6 votes vote down vote up
function DirectorySelection({ value, onChange, placeHolder, badgeOnEmpty }: DirectorySelectionProps) {
  const handleSelectFolderClick = useCallback(() => {
    window.api.selectDirectory(value ?? "").then((path) => {
      if (path !== null) {
        onChange(path);
      }
    });
  }, [onChange, value]);

  const onInputChange = useCallback(
    (event) => {
      onChange(event.target.value);
    },
    [onChange],
  );

  const invisibleBadge = !badgeOnEmpty || !!value;
  return (
    <Paper sx={{ px: 2, py: 1, display: "flex", alignItems: "center", width: 400 }} elevation={2}>
      {/*<span className={"text-gray-400 select-none w-96"}>{value ?? placeHolder}</span>*/}
      <InputBase sx={{ flex: 1 }} placeholder={placeHolder} value={value} onChange={onInputChange} disabled={true} />
      <IconButton onClick={handleSelectFolderClick}>
        <Badge invisible={invisibleBadge} color={"primary"} variant={"dot"}>
          <FolderIcon />
        </Badge>
      </IconButton>
    </Paper>
  );
}
Example #5
Source File: CustomNumberInput.tsx    From genshin-optimizer with MIT License 6 votes vote down vote up
StyledInputBase = styled(InputBase)(({ theme }) => ({
  backgroundColor: theme.palette.primary.main,
  transition: "all 0.5s ease",
  "&:hover": {
    backgroundColor: theme.palette.primary.dark,
  },
  "&.Mui-focused": {
    backgroundColor: theme.palette.primary.dark,
  },
  "&.Mui-disabled": {
    backgroundColor: theme.palette.primary.dark,
  },
}))
Example #6
Source File: SelectWrapper.tsx    From console with GNU Affero General Public License v3.0 6 votes vote down vote up
SelectStyled = withStyles((theme: Theme) =>
  createStyles({
    root: {
      height: 38,
      lineHeight: 1,
      "label + &": {
        marginTop: theme.spacing(3),
      },
    },
    input: {
      height: 38,
      position: "relative",
      color: "#07193E",
      fontSize: 13,
      fontWeight: 600,
      padding: "8px 20px 10px 10px",
      border: "#e5e5e5 1px solid",
      borderRadius: 4,
      display: "flex",
      alignItems: "center",
      "&:hover": {
        borderColor: "#393939",
      },
      "&:focus": {
        backgroundColor: "#fff",
      },
    },
  })
)(InputBase)
Example #7
Source File: Heal.tsx    From console with GNU Affero General Public License v3.0 6 votes vote down vote up
SelectStyled = withStyles((theme: Theme) =>
  createStyles({
    root: {
      lineHeight: "50px",
      marginRight: 15,
      "label + &": {
        marginTop: theme.spacing(3),
      },
      "& .MuiSelect-select:focus": {
        backgroundColor: "transparent",
      },
    },
  })
)(InputBase)
Example #8
Source File: ErrorLogs.tsx    From console with GNU Affero General Public License v3.0 6 votes vote down vote up
SelectStyled = withStyles((theme: Theme) =>
  createStyles({
    root: {
      lineHeight: "50px",
      "label + &": {
        marginTop: theme.spacing(3),
      },
      "& .MuiSelect-select:focus": {
        backgroundColor: "transparent",
      },
    },
  })
)(InputBase)
Example #9
Source File: Watch.tsx    From console with GNU Affero General Public License v3.0 6 votes vote down vote up
SelectStyled = withStyles((theme: Theme) =>
  createStyles({
    root: {
      lineHeight: "50px",
      "label + &": {
        marginTop: theme.spacing(3),
      },
      "& .MuiSelect-select:focus": {
        backgroundColor: "transparent",
      },
    },
    input: {
      height: 50,
      fontSize: 13,
      lineHeight: "50px",
    },
  })
)(InputBase)
Example #10
Source File: searchInput.tsx    From Search-Next with GNU General Public License v3.0 6 votes vote down vote up
function SearchInput() {
  return (
    <Paper
      component="form"
      sx={{ p: '2px 4px', display: 'flex', alignItems: 'center', width: 400 }}
    >
      <IconButton sx={{ p: '10px' }} aria-label="menu">
        <Menu />
      </IconButton>
      <InputBase
        sx={{ ml: 1, flex: 1 }}
        placeholder="Search Google Maps"
        inputProps={{ 'aria-label': 'search google maps' }}
      />
      <IconButton type="submit" sx={{ p: '10px' }} aria-label="search">
        <Search />
      </IconButton>
    </Paper>
  );
}
Example #11
Source File: MessageInput.tsx    From airmessage-web with Apache License 2.0 5 votes vote down vote up
export default function MessageInput(props: Props) {
	const theme = useTheme();
	const colorBG = theme.palette.messageIncoming.main;
	
	const {
		onMessageChange: propsOnMessageChange,
		onMessageSubmit: propsOnMessageSubmit,
		message: propsMessage,
		attachments: propsAttachments,
		onAttachmentAdd: propsOnAttachmentAdd
	} = props;
	
	const handleChange = useCallback((event: ChangeEvent<HTMLTextAreaElement>) => {
		propsOnMessageChange(event.target.value);
	}, [propsOnMessageChange]);
	
	const submitInput = useCallback(() => {
		propsOnMessageSubmit(propsMessage, propsAttachments);
	}, [propsOnMessageSubmit, propsMessage, propsAttachments]);
	
	const handleKeyPress = useCallback((event: React.KeyboardEvent<HTMLElement>) => {
		if(!event.shiftKey && event.key === "Enter") {
			event.preventDefault();
			submitInput();
		}
	}, [submitInput]);
	
	const handlePaste = useCallback((event: React.ClipboardEvent<HTMLElement>) => {
		propsOnAttachmentAdd(Array.from(event.clipboardData.files));
	}, [propsOnAttachmentAdd]);
	
	return (
		<div className={styles.root} style={{backgroundColor: colorBG}}>
			<Flipper flipKey={props.attachments.map(attachment => attachment.id).join(" ")}>
				{props.attachments.length > 0 &&
					<div className={styles.attachmentqueue}>
						{props.attachments.map((file) => {
							const queueData: QueuedAttachmentProps = {
								file: file.file,
								onRemove: () => props.onAttachmentRemove(file)
							};
							
							let component: React.ReactNode;
							if(file.file.type.startsWith("image/")) component = <QueuedAttachmentImage queueData={queueData} />;
							else component = <QueuedAttachmentGeneric queueData={queueData} />;
							
							return (<Flipped flipId={"attachmentqueue-" + file.id} key={file.id} onAppear={onAttachmentAppear} onExit={onAttachmentExit}>
								{component}
							</Flipped>);
						})}
					</div>
				}
				<div className={styles.control}>
					<InputBase className={styles.textfield} maxRows="5" multiline fullWidth autoFocus placeholder={props.placeholder} value={props.message} onChange={handleChange} onKeyPress={handleKeyPress} onPaste={handlePaste} />
					<IconButton size="small" color="primary" disabled={props.message.trim() === "" && props.attachments.length === 0} onClick={submitInput}><PushIcon /></IconButton>
				</div>
			</Flipper>
		</div>
	);
}
Example #12
Source File: index.tsx    From genshin-optimizer with MIT License 5 votes vote down vote up
function ResinCounter() {
  const [{ resin, date }, setResinState] = useDBState("ToolsDisplayResin", initToolsDisplayResin)
  const resinIncrement = useRef(undefined as undefined | NodeJS.Timeout)

  const setResin = (newResin: number) => {
    if (newResin >= RESIN_MAX) {
      resinIncrement.current && clearTimeout(resinIncrement.current)
      resinIncrement.current = undefined
    } else
      resinIncrement.current = setTimeout(() => console.log("set resin", newResin + 1), RESIN_RECH_MS);
    setResinState({ resin: newResin, date: new Date().getTime() })
  }

  useEffect(() => {
    if (resin < RESIN_MAX) {
      const now = Date.now()
      const resinToMax = RESIN_MAX - resin
      const resinSinceLastDate = Math.min(Math.floor((now - date) / (RESIN_RECH_MS)), resinToMax)
      const catchUpResin = resin + resinSinceLastDate
      const newDate = date + resinSinceLastDate * RESIN_RECH_MS
      setResinState({ resin: catchUpResin, date: newDate })
      if (catchUpResin < RESIN_MAX)
        resinIncrement.current = setTimeout(() => setResin(catchUpResin + 1), now - newDate);
    }
    return () => resinIncrement.current && clearTimeout(resinIncrement.current)
    // eslint-disable-next-line
  }, [])

  const nextResinDateNum = resin >= RESIN_MAX ? date : date + RESIN_RECH_MS;

  const resinFullDateNum = resin >= RESIN_MAX ? date : (date + (RESIN_MAX - resin) * RESIN_RECH_MS)
  const resinFullDate = new Date(resinFullDateNum)

  const nextDeltaString = timeString(Math.abs(nextResinDateNum - Date.now()))

  return <CardDark>
    <Grid container sx={{ px: 2, py: 1 }} spacing={2} >
      <Grid item>
        <ImgIcon src={Assets.resin.fragile} sx={{ fontSize: "2em" }} />
      </Grid>
      <Grid item >
        <Typography variant="h6">Resin Counter</Typography>
      </Grid>
    </Grid>
    <Divider />
    <CardContent>
      <Grid container spacing={2}>
        <Grid item>
          <Typography variant="h2">
            <ImgIcon src={Assets.resin.fragile} />
            <InputBase type="number" sx={{ width: "2em", fontSize: "4rem" }} value={resin} inputProps={{ min: 0, max: 999, sx: { textAlign: "right" } }} onChange={(e => setResin(parseInt(e.target.value)))} />
            <span>/{RESIN_MAX}</span>
          </Typography>
        </Grid>
        <Grid item flexGrow={1}>
          <ButtonGroup fullWidth >
            <Button onClick={() => setResin(0)} disabled={resin === 0}>0</Button>
            <Button onClick={() => setResin(resin - 1)} disabled={resin === 0}>-1</Button>
            <Button onClick={() => setResin(resin - 20)} disabled={resin < 20}>-20</Button>
            <Button onClick={() => setResin(resin - 40)} disabled={resin < 40}>-40</Button>
            <Button onClick={() => setResin(resin - 60)} disabled={resin < 60}>-60</Button>
            <Button onClick={() => setResin(resin + 1)}>+1</Button>
            <Button onClick={() => setResin(resin + 60)}>+60</Button>
            <Button onClick={() => setResin(RESIN_MAX)} disabled={resin === RESIN_MAX}>MAX {RESIN_MAX}</Button>
          </ButtonGroup>
          <Typography variant="subtitle1" sx={{ mt: 2 }}>
            {resin < RESIN_MAX ? <span>Next resin in {nextDeltaString}, full Resin at {resinFullDate.toLocaleTimeString()} {resinFullDate.toLocaleDateString()}</span> :
              <span>Resin has been full for at least {nextDeltaString}, since {resinFullDate.toLocaleTimeString()} {resinFullDate.toLocaleDateString()}</span>}
          </Typography>
        </Grid>
        <Grid item xs={12}>
          <Typography variant="caption">Because we do not provide a mechanism to synchronize resin time, actual resin recharge time might be as much as 8 minutes earlier than predicted.</Typography>
        </Grid>
      </Grid>
    </CardContent>
  </CardDark>
}
Example #13
Source File: CollectionTableToolbar.tsx    From firecms with MIT License 4 votes vote down vote up
export function CollectionTableToolbar<M extends { [Key: string]: any }>(props: CollectionTableToolbarProps) {
    const classes = useStyles();

    const theme = useTheme();
    const largeLayout = useMediaQuery(theme.breakpoints.up("md"));

    const filterView = props.filterIsSet &&
        <Box display={"flex"}
             alignItems="center">

            <Tooltip title="Clear filter">
                <IconButton
                    style={{ height: "fit-content" }}
                    aria-label="filter clear"
                    onClick={props.clearFilter}
                    size="large">
                    <ClearIcon/>
                </IconButton>
            </Tooltip>

        </Box>;

    const sizeSelect = (
        <Select
            variant={"standard"}
            value={props.size}
            style={{ width: 56 }}
            onChange={(evt: any) => {
                props.onSizeChanged(evt.target.value);
            }}
            MenuProps={{
                MenuListProps: {
                    disablePadding: true,
                    style: {
                        borderRadius: 4
                    }
                },
                elevation: 1
            }}
            input={<InputBase classes={{
                root: classes.selectRoot,
                input: classes.input
            }}/>}
            renderValue={(value: any) => value.toUpperCase()}
        >
            {["xs", "s", "m", "l", "xl"].map((value) => (
                <MenuItem
                    classes={{
                        root: classes.item
                    }}
                    key={`size-select-${value}`} value={value}>
                    {value.toUpperCase()}
                </MenuItem>
            ))}
        </Select>
    );

    return (
        <div
            className={classes.toolbar}
        >

            <Box display={"flex"}
                 alignItems="center">

                {props.title && <Hidden lgDown>
                    <Box mr={2}>
                        {props.title}
                    </Box>
                </Hidden>}

                {sizeSelect}

                {filterView}


            </Box>


            <div className={classes.actions}>

                {largeLayout && <Box width={22}>
                    {props.loading &&
                    <CircularProgress size={16} thickness={8}/>}
                </Box>}

                {props.onTextSearch &&
                <SearchBar
                    key={"search-bar"}
                    onTextSearch={props.onTextSearch}/>
                }

                {props.actions}

            </div>

        </div>
    );
}
Example #14
Source File: DetailCreate.tsx    From airmessage-web with Apache License 2.0 4 votes vote down vote up
export default function DetailCreate(props: {onConversationCreated: (conversation: Conversation) => void}) {
	const [query, setQuery] = useState<string>("");
	const [peopleSelection, setPeopleSelection] = useState<SelectionData[]>([]);
	const [peoplePool, setPeoplePool] = useState<PersonData[]>();
	const [isLoading, setLoading] = useState(false);
	
	const displaySnackbar = useContext(SnackbarContext);
	
	const theme = useTheme();
	
	useEffect(() => {
		//Loading the people
		getPeople().then((people) => {
			setPeoplePool(people);
		});
	}, []);
	
	const groupedPeople = peoplePool ? filterAndGroup(peoplePool, query) : undefined;
	
	function handleTextChange(event: React.ChangeEvent<HTMLInputElement>) {
		const text = event.target.value;
		
		//Updating the query text
		setQuery(text);
	}
	
	function handleKeyDown(event: React.KeyboardEvent<any>) {
		if(event.key === "Backspace") {
			//Removing the last person
			if(query.length === 0 && peopleSelection.length > 0) {
				setPeopleSelection(peopleSelection.slice(0, peopleSelection.length - 1));
				event.preventDefault();
			}
		} else if(event.key === "Enter") {
			//Manually entering the query
			handleDirectEntry();
		}
	}
	
	function handleAddressClick(person: PersonData, address: AddressData) {
		//Clearing the query text
		setQuery("");
		
		//Toggling the item
		const index = peopleSelection.findIndex((selection) => selection.address === address.value);
		if(index === -1) {
			setPeopleSelection(peopleSelection.concat({
				name: person.name,
				avatar: person.avatar,
				address: address.value,
				displayAddress: address.displayValue,
				addressLabel: address.label
			}));
		} else {
			setPeopleSelection([...peopleSelection.slice(0, index), ...peopleSelection.slice(index + 1)]);
		}
	}
	
	function findPersonInfo(address: string): [PersonData, AddressData] | undefined {
		if(!peoplePool) return undefined;
		
		for(const person of peoplePool) {
			for(const personAddress of person.addresses) {
				if(personAddress.value === address) {
					return [person, personAddress];
				}
			}
		}
		
		return undefined;
	}
	
	function handleDirectEntry() {
		const address = query;
		
		//Checking if the item is an email address
		if(address.match(regexEmail)) {
			//Clearing the query text
			setQuery("");
			
			//Returning if the addition will conflict with any existing entries
			if(peopleSelection.find((selection) => selection.address === address)) return;
			
			//Searching for the user in the listings
			const [personData, addressData] = findPersonInfo(query) ?? [undefined, undefined];
			
			//Adding the item
			setPeopleSelection(peopleSelection.concat({
				name: personData?.name,
				avatar: personData?.avatar,
				address: address,
				displayAddress: address,
				addressLabel: addressData?.label
			}));
		} else {
			//Checking if the item is a phone number
			const phone = parsePhoneNumberFromString(query, "US");
			const formatted = phone?.number.toString();
			if(phone && phone.isValid()) {
				//Clearing the query text
				setQuery("");
				
				//Returning if the addition will conflict with any existing entries
				if(peopleSelection.find((selection) => selection.address === formatted!)) return;
				
				//Searching for the user in the listings
				const [personData, addressData] = findPersonInfo(formatted!) ?? [undefined, undefined];
				
				//Adding the item
				setPeopleSelection(peopleSelection.concat({
					name: personData?.name,
					avatar: personData?.avatar,
					address: formatted!,
					displayAddress: phone.formatNational(),
					addressLabel: addressData?.label
				}));
			}
		}
	}
	
	function handleRemoveSelection(selection: SelectionData) {
		setPeopleSelection(peopleSelection.filter((value) => value !== selection));
	}
	
	function confirmParticipants() {
		//Starting the loading view
		setLoading(true);
		
		//Mapping the people selection to their addresses
		const chatMembers = peopleSelection.map((selection) => selection.address);
		ConnectionManager.createChat(chatMembers, messagingService)
			.then((chatGUID) => {
				//Adding the chat
				props.onConversationCreated({
					localID: generateConversationLocalID(),
					guid: chatGUID,
					service: messagingService,
					members: chatMembers,
					preview: {
						type: ConversationPreviewType.ChatCreation,
						date: new Date()
					},
					localOnly: false,
					unreadMessages: false
				});
			}).catch(([errorCode, errorDesc]: [CreateChatErrorCode, string | undefined]) => {
				if(errorCode === CreateChatErrorCode.NotSupported) {
					//If the server doesn't support creating chats,
					//create this chat locally and defer its creation
					//until the user sends a message
					props.onConversationCreated({
						localID: generateConversationLocalID(),
						service: messagingService,
						members: chatMembers,
						preview: {
							type: ConversationPreviewType.ChatCreation,
							date: new Date()
						},
						localOnly: true,
						unreadMessages: false
					});
					
					return;
				}
				
				//Cancelling loading
				setLoading(false);
				
				//Displaying a snackbar
				displaySnackbar({message: "Failed to create conversation"});
				
				//Logging the error
				console.warn(`Failed to create chat: ${errorCode} / ${errorDesc}`);
			});
	}
	
	let queryDirectState: boolean; //Is the current input query a valid address that can be added directly?
	let queryDirectDisplay: string;
	{
		//Checking email address
		if(query.match(regexEmail)) {
			queryDirectState = true;
			queryDirectDisplay = query;
		} else {
			//Checking phone number
			const phone = parsePhoneNumberFromString(query, "US");
			if(phone && phone.isValid()) {
				queryDirectState = true;
				queryDirectDisplay = phone.formatNational();
			} else {
				queryDirectState = false;
				queryDirectDisplay = query;
			}
		}
	}
	
	return (
		<DetailFrame title="New conversation">
			<div className={styles.content}>
				<div className={`${isLoading ? styles.scrimShown : styles.scrimHidden} ${styles.progressContainer}`} style={{backgroundColor: theme.palette.mode === "light" ? "rgba(255, 255, 255, 0.7)" : "rgba(0, 0, 0, 0.7)"}}>
					<CircularProgress />
				</div>
				
				<div className={styles.participantInputWrapper}>
					<div className={styles.participantInputLayout} style={{backgroundColor: theme.palette.messageIncoming.main}}>
						<div className={styles.participantInputFlow}>
							<SelectionList className={styles.participantInputChip} selections={peopleSelection} onRemove={handleRemoveSelection} />
							<InputBase className={styles.participantInputField} placeholder={peopleSelection.length > 0 ? undefined : "Type a name, email address, or phone number"} value={query} onChange={handleTextChange} onKeyDown={handleKeyDown} autoFocus />
						</div>
						<Button className={styles.participantInputButton} variant="contained" color="primary" disabled={peopleSelection.length === 0} disableElevation onClick={confirmParticipants}>Done</Button>
					</div>
				</div>
				
				{
					groupedPeople ? <div className={styles.listWrapper}>
						<div className={styles.list}>
							{queryDirectState && <DirectSendButton address={queryDirectDisplay} onClick={handleDirectEntry} />}
							{Object.entries(groupedPeople).map(([firstLetter, people]) => (
								<React.Fragment key={`section-${firstLetter}`}>
									<ListSubheader>{firstLetter}</ListSubheader>
									{people.map((person) => (
										<div key={person.id} className={styles.contactRoot}>
											<Avatar src={person.avatar} alt={person.name} />
											<div className={styles.contactText}>
												<Typography variant="body1" color="textPrimary">{person.name}</Typography>
												<div className={styles.contactAddresses}>
													{person.addresses.map((address) => (
														<AddressButton key={address.value + "/" + address.label} address={address} selected={peopleSelection.find((selection) => selection.address === address.value) !== undefined} onClick={() => handleAddressClick(person, address)} />
													))}
												</div>
											</div>
										</div>
									))}
								</React.Fragment>
							))}
						</div>
					</div> : <div className={`${styles.listWrapper} ${styles.progressContainer}`}>
						<CircularProgress />
					</div>
				}
			</div>
		</DetailFrame>
	);
}