react-bootstrap#Overlay TypeScript Examples
The following examples show how to use
react-bootstrap#Overlay.
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: AddYearPopup.tsx From peterportal-client with MIT License | 5 votes |
AddYearPopup: FC<AddYearPopupProps> = ({ placeholderYear }) => {
const dispatch = useAppDispatch();
const [year, setYear] = useState(placeholderYear);
const [show, setShow] = useState(false);
const target = useRef(null);
useEffect(() => { setYear(placeholderYear) }, [placeholderYear]);
const handleClick = (event: React.MouseEvent) => {
setShow(!show);
};
return (
<div>
<Button variant="light" ref={target} className="add-year-btn" onClick={handleClick}>
<PlusCircleFill className="add-year-icon" />
<div className="add-year-text">Add year</div>
</Button>
<Overlay show={show} target={target} placement="top">
<Popover id=''>
<Popover.Content>
<Form>
<Form.Group>
<Form.Label className="add-year-form-label">
Start Year
</Form.Label>
<Form.Control
type="number"
name="year"
value={year}
onChange={(e) => {
setYear(parseInt(e.target.value));
}}
onKeyDown={(e: React.KeyboardEvent) => {
// prevent submitting form (reloads the page)
if (e.key === 'Enter') {
e.preventDefault();
}
}}
min={1000}
max={9999}
placeholder={placeholderYear.toString()}
></Form.Control>
</Form.Group>
<Button
className="popup-btn"
onClick={() => {
setShow(!show);
dispatch(addYear(
{
yearData: {
startYear: year,
quarters: ['fall', 'winter', 'spring'].map(quarter => { return { name: quarter, courses: [] } })
}
}
));
setYear(placeholderYear);
}}
>
Add Year
</Button>
</Form>
</Popover.Content>
</Popover>
</Overlay>
</div >
);
}
Example #2
Source File: Header.tsx From peterportal-client with MIT License | 5 votes |
Header: FC<HeaderProps> = ({ courseCount, unitCount, saveRoadmap }) => {
const dispatch = useAppDispatch();
const [target, setTarget] = useState<any>(null!);
const [showMenu, setShowMenu] = useState(false);
const buttons = <>
<Button variant={isMobile ? "primary" : 'light'} className={isMobile ? 'my-1' : "header-btn"} onClick={() => dispatch(setShowTransfer(true))}>
Transfer Credits
<ArrowLeftRight className="header-icon" />
</Button>
<Button variant={isMobile ? "primary" : 'light'} className={isMobile ? 'my-1' : "header-btn"} onClick={saveRoadmap}>
Save
<Save className="header-icon" />
</Button>
<Button variant={isMobile ? "primary" : 'light'} className={isMobile ? 'my-1' : "header-btn"} onClick={() => dispatch(clearPlanner())}>
Clear
<Trash className="header-icon" />
</Button>
</>
const onMenuClick = (event: React.MouseEvent) => {
setShowMenu(!showMenu);
setTarget(event.target);
};
return (
<div className="header">
<Transfer />
<div>
<div id="title">
Peter's Roadmap
</div>
<span id="planner-stats">
Total: <span id="course-count">{courseCount}</span>{" "}
{courseCount === 1 ? "course" : "courses"},{" "}
<span id="unit-count">{unitCount}</span>{" "}
{unitCount === 1 ? "unit" : "units"}
</span>
</div>
<div>
{
isMobile && <>
<Button variant="light" className="header-btn add-course" onClick={() => { dispatch(setShowSearch(true)) }}>
<Plus className="header-icon mr-1" />
Add Course
</Button>
<List className='mx-3' onClick={onMenuClick} />
<Overlay show={showMenu} target={target} placement="left">
<Popover id='roadmap-header-buttons'>
<Popover.Content>
<div className='d-flex flex-column'>
{buttons}
</div>
</Popover.Content>
</Popover>
</Overlay>
</>
}
{
isBrowser && <ButtonGroup>
{buttons}
</ButtonGroup>
}
</div>
</div >
)
}
Example #3
Source File: Quarter.tsx From peterportal-client with MIT License | 4 votes |
Quarter: FC<QuarterProps> = ({ year, yearIndex, quarterIndex, data }) => {
const dispatch = useAppDispatch();
let quarterTitle = data.name.charAt(0).toUpperCase() + data.name.slice(1);
const invalidCourses = useAppSelector(state => state.roadmap.invalidCourses);
const [showQuarterMenu, setShowQuarterMenu] = useState(false);
const [target, setTarget] = useState<any>(null!);
const handleQuarterMenuClick = (event: React.MouseEvent) => {
setShowQuarterMenu(!showQuarterMenu);
setTarget(event.target);
}
const calculateQuarterStats = () => {
let unitCount = 0;
let courseCount = 0;
data.courses.forEach(course => {
unitCount += course.units[0];
courseCount += 1;
})
return [unitCount, courseCount];
};
let unitCount = calculateQuarterStats()[0];
const renderCourses = () => {
return data.courses.map((course, index) => {
return <Draggable key={`quarter-course-${index}`} draggableId={`${yearIndex}-${quarterIndex}-${course.id}-${index}`} index={index}>
{(provided, snapshot) => {
let requiredCourses: string[] = null!;
// if this is an invalid course, set the required courses
invalidCourses.forEach(ic => {
let loc = ic.location;
if (loc.courseIndex == index && loc.quarterIndex == quarterIndex && loc.yearIndex == yearIndex) {
requiredCourses = ic.required;
}
});
const onDelete = () => {
dispatch(deleteCourse({
yearIndex,
quarterIndex,
courseIndex: index,
}));
};
return (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
margin: '0rem 2rem 1rem 2rem',
...provided.draggableProps.style
}}
>
<Course key={course.id} {...course}
requiredCourses={requiredCourses}
onDelete={onDelete} />
</div>
);
}}
</Draggable>
})
}
return <div className="quarter">
<span className="quarter-header">
<h2 className="quarter-title">
{quarterTitle} {year}
</h2>
<ThreeDots onClick={handleQuarterMenuClick} className="edit-btn" />
<Overlay show={showQuarterMenu} target={target} placement="bottom">
<Popover id={`quarter-menu-${yearIndex}-${quarterIndex}`}>
<Popover.Content>
<div>
<Button variant="light" className="quarter-menu-btn red-menu-btn" onClick={() => dispatch(clearQuarter({ yearIndex: yearIndex, quarterIndex: quarterIndex }))}>
Clear
</Button>
<Button variant="light" className="quarter-menu-btn red-menu-btn" onClick={() => {
dispatch(deleteQuarter({ yearIndex: yearIndex, quarterIndex: quarterIndex }));
setShowQuarterMenu(false)
}}>
Delete
</Button>
</div>
</Popover.Content>
</Popover>
</Overlay>
</span>
<div className="quarter-units">
{unitCount} {unitCount === 1 ? "unit" : "units"}
</div>
<Droppable droppableId={yearIndex + "-" + quarterIndex} type="COURSE">
{(provided) => {
return (
<div
ref={provided.innerRef}
{...provided.droppableProps}
style={{ paddingBottom: '1rem' }}>
{renderCourses()}
{provided.placeholder}
</div>
);
}}
</Droppable>
</div>
}
Example #4
Source File: Year.tsx From peterportal-client with MIT License | 4 votes |
Year: FC<YearProps> = ({ yearIndex, data }) => {
const dispatch = useAppDispatch();
const [showContent, setShowContent] = useState(true);
const [show, setShow] = useState(false);
const [showAddQuarter, setShowAddQuarter] = useState(false);
const [showEditYear, setShowEditYear] = useState(false);
const [target, setTarget] = useState<any>(null!);
const [addQuarterTarget, setAddQuarterTarget] = useState<any>(null!);
const [editYearTarget, setEditYearTarget] = useState<any>(null!);
const [placeholderYear, setPlaceholderYear] = useState(data.startYear);
const handleEditClick = (event: React.MouseEvent) => {
if (showAddQuarter) {
/* hide both overlays */
setShowAddQuarter(!showAddQuarter);
setShow(!show);
} else if (showEditYear) {
setShowEditYear(!showEditYear);
setShow(!show);
} else {
setShow(!show);
setTarget(event.target);
}
};
const handleShowAddQuarterClick = (event: React.MouseEvent) => {
setShowEditYear(false); // hide any other currently displayed menu bar options
setShowAddQuarter(!showAddQuarter);
setAddQuarterTarget(event.target);
}
const handleAddQuarterClick = (year: number, quarter: string) => {
dispatch(addQuarter({ startYear: year, quarterData: { name: quarter, courses: [] } }));
}
const handleEditYearClick = (event: React.MouseEvent) => {
setShowAddQuarter(false); // hide any other currently displayed menu bar options
setPlaceholderYear(data.startYear); // set default year to current year
setShowEditYear(!showEditYear);
setEditYearTarget(event.target);
}
const calculateYearStats = () => {
let unitCount = 0;
let courseCount = 0;
data.quarters.forEach(quarter => {
quarter.courses.forEach(course => {
unitCount += course.units[0];
courseCount += 1;
})
})
return { unitCount, courseCount };
};
let { unitCount, courseCount } = calculateYearStats();
return (
<div className="year">
<div className="yearTitleBar">
<Button
variant="link"
className="year-accordion"
onClick={() => {
setShowContent(!showContent);
}}
>
<span className="year-accordion-title">
<span id="year-title">
{showContent ? (
<CaretDownFill className="caret-icon" />
) : (
<CaretRightFill className="caret-icon" />
)}
<span id="year-number">Year {yearIndex + 1} </span>
<span id="year-range">
({data.startYear} - {data.startYear + 1})
</span>
</span>
<span id="year-stats">
<span id="course-count">{courseCount}</span>{" "}
{courseCount === 1 ? "course" : "courses"},{" "}
<span id="unit-count">{unitCount}</span>{" "}
{unitCount === 1 ? "unit" : "units"}
</span>
</span>
</Button>
<ThreeDots onClick={handleEditClick} className="edit-btn" />
<Overlay show={show} target={target} placement="bottom">
<Popover id={`year-menu-${yearIndex}`}>
<Popover.Content className="year-settings-popup">
<div>
<Button disabled={!(data.quarters && data.quarters.length < 6)} onClick={handleShowAddQuarterClick} variant="light" className="year-settings-btn">
Add Quarter
</Button>
<Button onClick={handleEditYearClick} variant="light" className="year-settings-btn">
Edit Year
</Button>
<Button
variant="light"
className="year-settings-btn"
id="clear-btn"
onClick={() => {
dispatch(clearYear({
yearIndex: yearIndex
}));
}}
>
Clear
</Button>
<Button
variant="light"
className="year-settings-btn"
id="remove-btn"
onClick={() => {
dispatch(deleteYear({
yearIndex: yearIndex
}));
}}
>
Remove
</Button>
</div>
</Popover.Content>
</Popover>
</Overlay>
<Overlay show={showAddQuarter && data.quarters && data.quarters.length < 6} target={addQuarterTarget} placement="left">
<Popover id={`add-quarter-menu-${yearIndex}`}>
<Popover.Content>
<div>
{!data.quarters.map(quarter => quarter.name).includes("fall") && <Button onClick={() => handleAddQuarterClick(data.startYear, "fall")} variant="light" className="year-settings-btn">Fall</Button>}
{!data.quarters.map(quarter => quarter.name).includes("winter") && <Button onClick={() => handleAddQuarterClick(data.startYear, "winter")} variant="light" className="year-settings-btn">Winter</Button>}
{!data.quarters.map(quarter => quarter.name).includes("spring") && <Button onClick={() => handleAddQuarterClick(data.startYear, "spring")} variant="light" className="year-settings-btn">Spring</Button>}
{!data.quarters.map(quarter => quarter.name).includes("summer I") && <Button onClick={() => handleAddQuarterClick(data.startYear, "summer I")} variant="light" className="year-settings-btn">Summer I</Button>}
{!data.quarters.map(quarter => quarter.name).includes("summer II") && <Button onClick={() => handleAddQuarterClick(data.startYear, "summer II")} variant="light" className="year-settings-btn">Summer II</Button>}
{!data.quarters.map(quarter => quarter.name).includes("summer 10 Week") && <Button onClick={() => handleAddQuarterClick(data.startYear, "summer 10 Week")} variant="light" className="year-settings-btn">Summer 10 Week</Button>}
</div>
</Popover.Content>
</Popover>
</Overlay>
<Overlay show={showEditYear} target={editYearTarget} placement="left">
<Popover id={`edit-year-menu-${yearIndex}`}>
<Popover.Content>
<Form>
<Form.Group>
<Form.Label className="edit-year-form-label">
Start Year
</Form.Label>
<Form.Control
type="number"
name="year"
value={placeholderYear}
onChange={(e) => {
setPlaceholderYear(parseInt(e.target.value));
}}
onKeyDown={(e: React.KeyboardEvent) => {
// prevent submitting form (reloads the page)
if (e.key === 'Enter') {
e.preventDefault();
}
}}
min={1000}
max={9999}
placeholder={placeholderYear.toString()}
></Form.Control>
</Form.Group>
<Button
className="edit-year-popup-btn"
onClick={() => {
setShowEditYear(!showEditYear);
setShow(!show);
if (placeholderYear != data.startYear) {
dispatch(editYear({ startYear: placeholderYear, index: yearIndex }));
}
}}
>
Confirm
</Button>
</Form>
</Popover.Content>
</Popover>
</Overlay>
</div>
{showContent && (
<div className="year-accordion-content">
{
data.quarters.map((quarter, quarterIndex) => {
return <Quarter
key={`year-quarter-${quarterIndex}`}
year={data.startYear + (quarterIndex == 0 ? 0 : 1)}
yearIndex={yearIndex}
quarterIndex={quarterIndex}
data={quarter}
/>
})
}
{/* render blank, non-functional quarters to ensure there are 3 per row */}
{data.quarters.length > 3 && data.quarters.length < 6 && (
[undefined, undefined].slice(data.quarters.length - 4).map(() => {
return <div className="empty-quarter"></div>
})
)
}
</div>
)}
</div>
);
}
Example #5
Source File: index.tsx From react-bootstrap-country-select with MIT License | 4 votes |
CountrySelect = ({
value,
onChange = () => {},
onTextChange,
countries = [ ...COUNTRIES ],
exclusions,
additions,
valueAs = 'object',
flags = true,
flush = true,
disabled = false,
placeholder = 'Type or select country...',
noMatchesText = 'No matches',
size,
sort, // e.g. (c1, c2) => c1.name < c2.name ? -1 : (c1.name > c2.name ? 1 : 0),
matchNameFromStart = true,
matchAbbreviations = false,
countryLabelFormatter = ({ name }) => name,
throwInvalidValueError = false,
listMaxHeight,
closeOnSelect = true,
formControlProps = {},
overlayProps = {},
classPrefix = DEFAULT_CLASS_PREFIX,
className,
}: CountrySelectProps) => {
const inputGroupRef = useRef(null);
const formControlRef = useRef(null);
const hasInitRef = useRef(false);
const [ width, setWidth ] = useState(-1);
const [ {
focused,
inputText,
list,
activeListItemIndex,
combinedCountries,
}, dispatch ] = useReducer(reducer, INITIAL_STATE);
const handleFocus = focus(dispatch);
const handleBlur = blur(dispatch);
const handleTextChange = textChange(dispatch);
const handleListActiveItemChange = activeListItemChange(dispatch);
const handleCountrySelect = countrySelect(dispatch);
const handleClear = clear(dispatch);
const getCountryId = (value: ICountry | string): string => (typeof value === 'string' ? value : value.id);
const selectedCountry = value ? (combinedCountries || []).find(country => country.id === getCountryId(value)) : null;
if (throwInvalidValueError && value && !selectedCountry)
throw new Error(`No matching country for value: ${JSON.stringify(value)}`);
useEffect(() => {
if (hasInitRef.current) return;
const combinedCountries = applyExclusionsAndAdditions(countries, exclusions, additions);
const sorted = getInitialList(combinedCountries, sort);
init(dispatch)(sorted);
hasInitRef.current = true;
}, [ countries, exclusions, additions, sort ]);
useEffect(() => {
setWidth(inputGroupRef.current.offsetWidth);
}, [ inputGroupRef ]);
const select = listItemIndex => {
const country = list[listItemIndex];
handleCountrySelect();
onChange(valueAs === 'id' ? country.id : country);
};
const escape = () => {
handleClear();
onChange(null);
};
const inputChange = (text, ev) => {
if (selectedCountry && flags) {
text = removeEmojiFlag(text);
}
const [ updatedList, updatedActiveListItemIndex ]
= getUpdatedList(text, list, activeListItemIndex, combinedCountries, sort, matchNameFromStart, matchAbbreviations);
handleTextChange(text, updatedList, updatedActiveListItemIndex);
if (onTextChange) onTextChange(text, ev);
if (value) onChange(null);
};
const handleKey = ev => {
if (ev.key === 'ArrowUp') {
ev.preventDefault();
const newIndex = activeListItemIndex <= 0 ? list.length - 1 : activeListItemIndex - 1;
handleListActiveItemChange(newIndex);
} else if (ev.key === 'ArrowDown') {
const newIndex = activeListItemIndex >= list.length - 1 ? 0 : activeListItemIndex + 1;
handleListActiveItemChange(newIndex);
} else if (ev.key === 'Enter') {
if (activeListItemIndex >= 0) select(activeListItemIndex)
} else if (ev.key === 'Escape') {
escape();
}
};
const classes = classNames([
className,
classPrefix,
flush && `${classPrefix}--flush`,
]);
return (
<div className={classes}>
<InputGroup
ref={inputGroupRef}
className={`${classPrefix}__input-group`}
size={size}
>
{ (!flush && flags) &&
<InputGroup.Prepend>
<InputGroup.Text
className={`${classPrefix}__input-group__flag`}
>
{selectedCountry ? selectedCountry.flag : ''}
</InputGroup.Text>
</InputGroup.Prepend>
}
<FormControl
ref={formControlRef}
className={`${classPrefix}__form-control`}
value={selectedCountry ? `${flush && flags ? selectedCountry.flag + ' ' : ''}${selectedCountry.name}` : inputText}
onKeyDown={handleKey}
onChange={ev => inputChange(ev.target.value, ev)}
onFocus={handleFocus}
onBlur={handleBlur}
placeholder={placeholder}
disabled={disabled}
spellCheck={false}
autoComplete='new-value'
{...formControlProps}
/>
</InputGroup>
<Overlay
target={inputGroupRef.current}
rootClose
placement='bottom-start'
show={focused && (!selectedCountry || !closeOnSelect)} // experimental; not documented
onHide={() => {}}
transition
{...overlayProps}
>
{({ placement, arrowProps, show: _show, popper, ...props }) => (
<div
{...props}
style={{
width: (width > 0) ? `${width}px` : 'calc(100% - 10px)',
...props.style,
}}
>
<OverlayContent
classPrefix={classPrefix}
list={list}
activeListItemIndex={activeListItemIndex}
countryLabelFormatter={countryLabelFormatter}
flags={flags}
noMatchesText={noMatchesText}
maxHeight={listMaxHeight}
onListItemClick={select}
/>
</div>
)}
</Overlay>
</div>
);
}