Refactor styling of multiple screens and NavBar
- Add the title to the navbar - Add react-helmet and Title component to help change tab/page title - Improve layout of Schedule screen - Add a "clear selection" button to Schedule screen - Improve readability of forms
This commit is contained in:
parent
a97f8dc1c3
commit
27e0889737
@ -19,6 +19,7 @@
|
|||||||
"react": "^16.13.1",
|
"react": "^16.13.1",
|
||||||
"react-app-rewired": "^2.1.6",
|
"react-app-rewired": "^2.1.6",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
|
"react-helmet": "^6.0.0",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "3.4.1",
|
"react-scripts": "3.4.1",
|
||||||
"rsuite": "^4.5.0"
|
"rsuite": "^4.5.0"
|
||||||
|
@ -9,10 +9,10 @@ export default function TimezonePicker() {
|
|||||||
<InputPicker
|
<InputPicker
|
||||||
data={timezones}
|
data={timezones}
|
||||||
// cleanable={false}
|
// cleanable={false}
|
||||||
style={{ width: 320 }}
|
style={{ width: "100%" }}
|
||||||
labelKey='timezone'
|
labelKey='timezone'
|
||||||
groupBy='area'
|
groupBy='area'
|
||||||
placeholder='Type to search and select your timezone'
|
placeholder='type to search your timezone'
|
||||||
onSelect={(value, item, event) => setTimezone(item.timezone)}
|
onSelect={(value, item, event) => setTimezone(item.timezone)}
|
||||||
onClean={(event) => setTimezone('')}
|
onClean={(event) => setTimezone('')}
|
||||||
value={timezone}
|
value={timezone}
|
||||||
|
11
src/components/General/Title.js
Normal file
11
src/components/General/Title.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
|
export default function TitleComponent({ title }) {
|
||||||
|
var defaultTitle = 'Meeting Planner';
|
||||||
|
return (
|
||||||
|
<Helmet>
|
||||||
|
<title>{title ? `${title} | Meeting Planner` : defaultTitle}</title>
|
||||||
|
</Helmet>
|
||||||
|
);
|
||||||
|
}
|
@ -1,17 +1,28 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Header, Navbar } from 'rsuite';
|
import { Header, Navbar, Nav } from 'rsuite';
|
||||||
import MenuDropdown from './MenuDropdown';
|
import MenuDropdown from './MenuDropdown';
|
||||||
|
import Title from './../General/Title';
|
||||||
|
|
||||||
const headerStyle = {
|
export default function NavBar({ title }) {
|
||||||
borderRadius: '7px 7px 0 0',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function NavBar() {
|
|
||||||
return (
|
return (
|
||||||
<Header>
|
<Header>
|
||||||
<Navbar appearance='inverse' style={headerStyle}>
|
<Title title={title} />
|
||||||
<Navbar.Body>
|
<Navbar appearance='inverse' >
|
||||||
|
<Navbar.Body
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Nav style={{ visibility: 'hidden' }}>
|
||||||
|
{/* This hidden nav is a hack to have the title perfectly centered. */}
|
||||||
|
<MenuDropdown />
|
||||||
|
</Nav>
|
||||||
|
<div>
|
||||||
|
<h3>{title}</h3>
|
||||||
|
</div>
|
||||||
<MenuDropdown />
|
<MenuDropdown />
|
||||||
</Navbar.Body>
|
</Navbar.Body>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
|
@ -3,13 +3,17 @@ import FullCalendar from '@fullcalendar/react';
|
|||||||
import dayGridPlugin from '@fullcalendar/daygrid';
|
import dayGridPlugin from '@fullcalendar/daygrid';
|
||||||
import interaction from '@fullcalendar/interaction';
|
import interaction from '@fullcalendar/interaction';
|
||||||
|
|
||||||
|
import './DaySelector.less';
|
||||||
|
|
||||||
export default function DaySelector({ eventsList, handleSelect, handleClear }) {
|
export default function DaySelector({ eventsList, handleSelect, handleClear }) {
|
||||||
return (
|
return (
|
||||||
<FullCalendar
|
<FullCalendar
|
||||||
initialView='dayGridMonth'
|
|
||||||
plugins={[dayGridPlugin, interaction]}
|
plugins={[dayGridPlugin, interaction]}
|
||||||
|
initialView='dayGridMonth'
|
||||||
|
// showNonCurrentDates={false}
|
||||||
selectable={true}
|
selectable={true}
|
||||||
unselectAuto={false}
|
// unselectAuto={false}
|
||||||
|
longPressDelay={150}
|
||||||
select={(info) => handleSelect(info)}
|
select={(info) => handleSelect(info)}
|
||||||
defaultAllDay={true}
|
defaultAllDay={true}
|
||||||
events={eventsList}
|
events={eventsList}
|
||||||
|
3
src/components/Schedule/DaySelector.less
Normal file
3
src/components/Schedule/DaySelector.less
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.fc-view-harness {
|
||||||
|
padding-bottom: 100% !important
|
||||||
|
}
|
@ -5,7 +5,6 @@ import { Divider, Icon, IconButton } from 'rsuite';
|
|||||||
export default function SelectedDates({ datesList, handleDelete }) {
|
export default function SelectedDates({ datesList, handleDelete }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h3>Dates selected</h3>
|
|
||||||
<ul>
|
<ul>
|
||||||
{datesList.map((date) => (
|
{datesList.map((date) => (
|
||||||
<li key={date}>
|
<li key={date}>
|
||||||
|
@ -3,27 +3,33 @@ import 'rsuite/lib/styles/index.less';
|
|||||||
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
|
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
|
||||||
|
|
||||||
import Dashboard from './Dashboard';
|
import Dashboard from './Dashboard';
|
||||||
import Schedule from './Schedule';
|
import Schedule from './Schedule/Schedule';
|
||||||
import Login from './Login';
|
import Login from './Login';
|
||||||
import Register from './Register';
|
import Register from './Register';
|
||||||
import NavBar from '../components/Navbar/NavBar';
|
|
||||||
|
const titles = {
|
||||||
|
schedule: 'Schedule a meeting',
|
||||||
|
dashboard: 'Dashboard',
|
||||||
|
login: 'Login',
|
||||||
|
register: 'Registration',
|
||||||
|
settings: 'Settings'
|
||||||
|
};
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<NavBar />
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path='/' exact>
|
<Route path='/' exact>
|
||||||
<Schedule />
|
<Schedule title={titles.schedule} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path='/dashboard'>
|
<Route path='/dashboard'>
|
||||||
<Dashboard />
|
<Dashboard title={titles.dashboard}/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path='/login'>
|
<Route path='/login'>
|
||||||
<Login />
|
<Login title={titles.login}/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path='/register'>
|
<Route path='/register'>
|
||||||
<Register />
|
<Register title={titles.register} />
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Router>
|
</Router>
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import {
|
import { Panel, Form, FormGroup, FormControl, ControlLabel, HelpBlock, Button } from 'rsuite';
|
||||||
FlexboxGrid,
|
|
||||||
Form,
|
|
||||||
FormGroup,
|
|
||||||
FormControl,
|
|
||||||
// HelpBlock,
|
|
||||||
Button,
|
|
||||||
} from 'rsuite';
|
|
||||||
|
|
||||||
|
import NavBar from './../components/Navbar/NavBar';
|
||||||
|
|
||||||
|
// TODO Move to a .less file
|
||||||
const boxStyle = {
|
const boxStyle = {
|
||||||
maxWidth: 373,
|
maxWidth: 373,
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
@ -19,37 +15,34 @@ const boxStyle = {
|
|||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
};
|
};
|
||||||
|
|
||||||
const h3Style = { margin: '1rem' };
|
export default function Login({ title }) {
|
||||||
|
|
||||||
export default function Login() {
|
|
||||||
return (
|
return (
|
||||||
<FlexboxGrid justify='center' style={boxStyle}>
|
<>
|
||||||
<h3 style={h3Style}>Login</h3>
|
<NavBar title={title} />
|
||||||
<Form horizontal>
|
<Panel bordered style={boxStyle}>
|
||||||
<FormGroup>
|
<Form>
|
||||||
<FormControl
|
<FormGroup>
|
||||||
name='email'
|
<ControlLabel>Email</ControlLabel>
|
||||||
type='email'
|
<FormControl
|
||||||
placeholder='email'
|
name='email'
|
||||||
/>
|
type='email'
|
||||||
</FormGroup>
|
/>
|
||||||
<FormGroup>
|
</FormGroup>
|
||||||
<FormControl
|
<ControlLabel>Password</ControlLabel>
|
||||||
name='password'
|
<FormGroup>
|
||||||
type='password'
|
<FormControl
|
||||||
placeholder='password'
|
name='password'
|
||||||
/>
|
type='password'
|
||||||
{/* <HelpBlock tooltip>
|
/>
|
||||||
Minimum password length is 8 characters
|
</FormGroup>
|
||||||
</HelpBlock> */}
|
<FormGroup>
|
||||||
</FormGroup>
|
<Button appearance='primary' block size="lg">
|
||||||
<FormGroup>
|
Sign in
|
||||||
<Button appearance='primary' block>
|
</Button>
|
||||||
Sign in
|
</FormGroup>
|
||||||
</Button>
|
<Button appearance='link'>Forgot password?</Button>
|
||||||
</FormGroup>
|
</Form>
|
||||||
<Button appearance='link'>Forgot password?</Button>
|
</Panel>
|
||||||
</Form>
|
</>
|
||||||
</FlexboxGrid>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import {
|
import { Form, FormGroup, FormControl, ControlLabel, HelpBlock, Button, Panel } from 'rsuite';
|
||||||
FlexboxGrid,
|
|
||||||
Form,
|
|
||||||
FormGroup,
|
|
||||||
FormControl,
|
|
||||||
HelpBlock,
|
|
||||||
Button,
|
|
||||||
} from 'rsuite';
|
|
||||||
|
|
||||||
|
import NavBar from './../components/Navbar/NavBar';
|
||||||
import TimezonePicker from '../components/General/TimezonePicker';
|
import TimezonePicker from '../components/General/TimezonePicker';
|
||||||
|
|
||||||
|
// TODO Move to a .less file
|
||||||
const boxStyle = {
|
const boxStyle = {
|
||||||
maxWidth: 373,
|
maxWidth: 373,
|
||||||
margin: '0 auto',
|
margin: '0 auto',
|
||||||
@ -21,46 +16,47 @@ const boxStyle = {
|
|||||||
padding: '1rem',
|
padding: '1rem',
|
||||||
};
|
};
|
||||||
|
|
||||||
const h3Style = { margin: '1rem' };
|
export default function Register({ title }) {
|
||||||
|
|
||||||
export default function Register() {
|
|
||||||
return (
|
return (
|
||||||
<FlexboxGrid justify='center' style={boxStyle}>
|
<>
|
||||||
<h3 style={h3Style}>Register</h3>
|
<NavBar title={title} />
|
||||||
<Form horizontal>
|
<Panel bordered style={boxStyle}>
|
||||||
<FormGroup>
|
<Form>
|
||||||
<FormControl
|
<FormGroup>
|
||||||
name='username'
|
<ControlLabel>Username</ControlLabel>
|
||||||
type='text'
|
<FormControl
|
||||||
placeholder='username'
|
name='username'
|
||||||
/>
|
type='text'
|
||||||
</FormGroup>
|
/>
|
||||||
<FormGroup>
|
</FormGroup>
|
||||||
<FormControl
|
<FormGroup>
|
||||||
name='email'
|
<ControlLabel>Email</ControlLabel>
|
||||||
type='email'
|
<FormControl
|
||||||
placeholder='email'
|
name='email'
|
||||||
/>
|
type='email'
|
||||||
</FormGroup>
|
/>
|
||||||
<FormGroup>
|
</FormGroup>
|
||||||
<TimezonePicker />
|
<ControlLabel>Timezone</ControlLabel>
|
||||||
</FormGroup>
|
<FormGroup>
|
||||||
<FormGroup>
|
<TimezonePicker />
|
||||||
<FormControl
|
</FormGroup>
|
||||||
name='password'
|
<ControlLabel>Password</ControlLabel>
|
||||||
type='password'
|
<FormGroup>
|
||||||
placeholder='password'
|
<FormControl
|
||||||
/>
|
name='password'
|
||||||
<HelpBlock tooltip>
|
type='password'
|
||||||
Minimum password length is 8 characters
|
/>
|
||||||
</HelpBlock>
|
<HelpBlock>
|
||||||
</FormGroup>
|
Minimum password length is 8 characters
|
||||||
<FormGroup>
|
</HelpBlock>
|
||||||
<Button appearance='primary' block>
|
</FormGroup>
|
||||||
Register
|
<FormGroup>
|
||||||
</Button>
|
<Button appearance='primary' block size="lg">
|
||||||
</FormGroup>
|
Register
|
||||||
</Form>
|
</Button>
|
||||||
</FlexboxGrid>
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
</Panel>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,31 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Container, Form, FormControl, FormGroup, Input, Button } from 'rsuite';
|
import {
|
||||||
|
Panel,
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
ControlLabel,
|
||||||
|
Input,
|
||||||
|
HelpBlock,
|
||||||
|
Button,
|
||||||
|
ButtonGroup,
|
||||||
|
Message,
|
||||||
|
FormGroup,
|
||||||
|
} from 'rsuite';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
|
|
||||||
import TimezonePicker from '../components/General/TimezonePicker';
|
import NavBar from '../../components/Navbar/NavBar';
|
||||||
import DaySelector from '../components/Schedule/DaySelector';
|
import TimezonePicker from '../../components/General/TimezonePicker';
|
||||||
import DurationSelector from '../components/Schedule/DurationSelector';
|
import DaySelector from '../../components/Schedule/DaySelector';
|
||||||
import SelectedDates from '../components/Schedule/SelectedDates';
|
import DurationSelector from '../../components/Schedule/DurationSelector';
|
||||||
|
import SelectedDates from '../../components/Schedule/SelectedDates';
|
||||||
|
|
||||||
export default function Schedule() {
|
import './Schedule.less';
|
||||||
|
|
||||||
|
export default function Schedule({ title }) {
|
||||||
const [eventsList, setEventsList] = useState([]);
|
const [eventsList, setEventsList] = useState([]);
|
||||||
const [datesList, setDatesList] = useState(eventsToDates(eventsList));
|
const [datesList, setDatesList] = useState(eventsToDates(eventsList));
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Update selected dates
|
|
||||||
let updatedDates = eventsToDates(eventsList).sort();
|
let updatedDates = eventsToDates(eventsList).sort();
|
||||||
setDatesList(updatedDates);
|
setDatesList(updatedDates);
|
||||||
}, [eventsList]);
|
}, [eventsList]);
|
||||||
@ -104,45 +117,80 @@ export default function Schedule() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<>
|
||||||
<h3>Schedule a meeting</h3>
|
<NavBar title={title} />
|
||||||
<Form>
|
<Panel style={containerStyle}>
|
||||||
<FormGroup>
|
<Form className={'meeting-container'}>
|
||||||
<FormControl name='title' type='text' placeholder='title' />
|
<div className={'meeting-info'}>
|
||||||
</FormGroup>
|
<FormGroup>
|
||||||
<FormGroup>
|
<ControlLabel>Title</ControlLabel>
|
||||||
<Input
|
<FormControl name='title' type='text' />
|
||||||
name='description'
|
<HelpBlock>This field is required</HelpBlock>
|
||||||
componentClass='textarea'
|
</FormGroup>
|
||||||
type='text'
|
<FormGroup>
|
||||||
rows={3}
|
<ControlLabel>Description</ControlLabel>
|
||||||
placeholder='Description'
|
<Input
|
||||||
/>
|
name='description'
|
||||||
</FormGroup>
|
componentClass='textarea'
|
||||||
<FormGroup>
|
type='text'
|
||||||
<TimezonePicker />
|
rows={3}
|
||||||
</FormGroup>
|
placeholder='(optional)'
|
||||||
<FormGroup style={{ width: 200 }}>
|
/>
|
||||||
<DurationSelector />
|
</FormGroup>
|
||||||
</FormGroup>
|
<div className='meeting-options-inline'>
|
||||||
<FormGroup>
|
<FormGroup className='meeting-timezone'>
|
||||||
<DaySelector
|
<ControlLabel>Timezone</ControlLabel>
|
||||||
eventsList={eventsList}
|
<TimezonePicker />
|
||||||
handleSelect={handleSelect}
|
</FormGroup>
|
||||||
handleClear={handleClear}
|
<FormGroup className='meeting-duration'>
|
||||||
/>
|
<ControlLabel>Duration</ControlLabel>
|
||||||
</FormGroup>
|
<DurationSelector />
|
||||||
{datesList.length > 0 && (
|
</FormGroup>
|
||||||
<FormGroup>
|
</div>
|
||||||
<SelectedDates
|
<ButtonGroup justified>
|
||||||
datesList={datesList}
|
<Button
|
||||||
handleDelete={handleDelete}
|
appearance='ghost'
|
||||||
|
block
|
||||||
|
size='lg'
|
||||||
|
disabled={datesList.length === 0}
|
||||||
|
onClick={() => handleClear()}
|
||||||
|
>
|
||||||
|
Clear selection
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
appearance='primary'
|
||||||
|
size='lg'
|
||||||
|
block
|
||||||
|
disabled={datesList.length === 0}
|
||||||
|
>
|
||||||
|
Confirm dates
|
||||||
|
</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
<div className={'selected-dates'}></div>
|
||||||
|
{datesList.length > 0 && (
|
||||||
|
<>
|
||||||
|
<SelectedDates
|
||||||
|
datesList={datesList}
|
||||||
|
handleDelete={handleDelete}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className={'day-selector'}>
|
||||||
|
<Message
|
||||||
|
showIcon
|
||||||
|
type='info'
|
||||||
|
description='Select possible meetings dates on the calendar.'
|
||||||
/>
|
/>
|
||||||
<Button>Confirm dates</Button>
|
<DaySelector
|
||||||
</FormGroup>
|
eventsList={eventsList}
|
||||||
)}
|
handleSelect={handleSelect}
|
||||||
</Form>
|
handleClear={handleClear}
|
||||||
</Container>
|
/>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</Panel>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,3 +202,10 @@ const eventsToDates = (events) => {
|
|||||||
});
|
});
|
||||||
return dates;
|
return dates;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const containerStyle = {
|
||||||
|
// TODO Move to a .less file
|
||||||
|
maxWidth: '1200px',
|
||||||
|
margin: '30px auto',
|
||||||
|
backgroundColor: 'rgba(255,255,255,0.6)',
|
||||||
|
};
|
46
src/screens/Schedule/Schedule.less
Normal file
46
src/screens/Schedule/Schedule.less
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
.meeting-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 6fr 5fr;
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
grid-template-areas:
|
||||||
|
'selector info';
|
||||||
|
column-gap: 2em;
|
||||||
|
row-gap: 2em;
|
||||||
|
grid-column-gap: 2em;
|
||||||
|
grid-row-gap: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meeting-info {
|
||||||
|
grid-area: info;
|
||||||
|
margin: 1em 0 3em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.day-selector {
|
||||||
|
grid-area: selector;
|
||||||
|
margin: 1em 0 3em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-dates {
|
||||||
|
grid-area: selected;
|
||||||
|
ul {
|
||||||
|
column-count: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.meeting-options-inline {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.meeting-timezone {
|
||||||
|
width: 65%
|
||||||
|
}
|
||||||
|
|
||||||
|
.meeting-duration {
|
||||||
|
width:30%
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix button alignment bug
|
||||||
|
.rs-btn-block + .rs-btn-block {
|
||||||
|
margin-top: unset;
|
||||||
|
}
|
20
yarn.lock
20
yarn.lock
@ -8795,6 +8795,21 @@ react-error-overlay@^6.0.7:
|
|||||||
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108"
|
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.7.tgz#1dcfb459ab671d53f660a991513cb2f0a0553108"
|
||||||
integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA==
|
integrity sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA==
|
||||||
|
|
||||||
|
react-fast-compare@^2.0.4:
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
||||||
|
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
||||||
|
|
||||||
|
react-helmet@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.0.0.tgz#fcb93ebaca3ba562a686eb2f1f9d46093d83b5f8"
|
||||||
|
integrity sha512-My6S4sa0uHN/IuVUn0HFmasW5xj9clTkB9qmMngscVycQ5vVG51Qp44BEvLJ4lixupTwDlU9qX1/sCrMN4AEPg==
|
||||||
|
dependencies:
|
||||||
|
object-assign "^4.1.1"
|
||||||
|
prop-types "^15.7.2"
|
||||||
|
react-fast-compare "^2.0.4"
|
||||||
|
react-side-effect "^2.1.0"
|
||||||
|
|
||||||
react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4:
|
react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||||
@ -8894,6 +8909,11 @@ react-scripts@3.4.1:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "2.1.2"
|
fsevents "2.1.2"
|
||||||
|
|
||||||
|
react-side-effect@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.0.tgz#1ce4a8b4445168c487ed24dab886421f74d380d3"
|
||||||
|
integrity sha512-IgmcegOSi5SNX+2Snh1vqmF0Vg/CbkycU9XZbOHJlZ6kMzTmi3yc254oB1WCkgA7OQtIAoLmcSFuHTc/tlcqXg==
|
||||||
|
|
||||||
react-virtualized@^9.21.0:
|
react-virtualized@^9.21.0:
|
||||||
version "9.21.2"
|
version "9.21.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.2.tgz#02e6df65c1e020c8dbf574ec4ce971652afca84e"
|
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.2.tgz#02e6df65c1e020c8dbf574ec4ce971652afca84e"
|
||||||
|
Loading…
Reference in New Issue
Block a user