Remove bloomer from packages/client
This commit is contained in:
parent
2d4cb2d275
commit
a3578e35ba
@ -2,11 +2,12 @@ import styled from 'styled-components'
|
||||
import { getColor, ColorSchemeProps, getBorder } from '../theme'
|
||||
|
||||
export const Button = styled.button<ColorSchemeProps>`
|
||||
font-size: 1rem;
|
||||
padding: 0.5rem;
|
||||
background: transparent;
|
||||
color: ${getColor};
|
||||
border: ${getBorder};
|
||||
border-radius: ${props => props.theme.border.radius}px;
|
||||
border-radius: ${props => props.theme.border.radius};
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
@ -17,4 +18,8 @@ export const Button = styled.button<ColorSchemeProps>`
|
||||
&:hover:active {
|
||||
box-shadow: 0 0 3px ${getColor};
|
||||
}
|
||||
|
||||
& > * {
|
||||
vertical-align: middle;
|
||||
}
|
||||
`
|
||||
|
||||
7
packages/client/src/components/Heading.ts
Normal file
7
packages/client/src/components/Heading.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const Heading = styled.h1`
|
||||
text-transform: uppercase;
|
||||
font-weight: 300;
|
||||
font-size: 1.6rem;
|
||||
`
|
||||
6
packages/client/src/components/Help.tsx
Normal file
6
packages/client/src/components/Help.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import styled from 'styled-components'
|
||||
import { ColorSchemeProps, getColor } from '../theme'
|
||||
|
||||
export const Help = styled.div<ColorSchemeProps>`
|
||||
color: ${getColor};
|
||||
`
|
||||
@ -1,9 +1,11 @@
|
||||
import React from 'react'
|
||||
import {IconType} from 'react-icons'
|
||||
import styled from 'styled-components'
|
||||
import { Help } from './Help'
|
||||
|
||||
export interface InputProps {
|
||||
name: string
|
||||
error?: string
|
||||
type: 'text' | 'password' | 'hidden' | 'submit' | 'email'
|
||||
value?: string
|
||||
onChange?: (name: this['name'], value: string) => void
|
||||
@ -14,20 +16,20 @@ export interface InputProps {
|
||||
required?: boolean
|
||||
}
|
||||
|
||||
const Field = styled.div`
|
||||
export const Field = styled.div`
|
||||
margin-bottom: 1em;
|
||||
`
|
||||
|
||||
const Label = styled('label')`
|
||||
export const Label = styled('label')`
|
||||
text-transform: uppercase;
|
||||
font-size: 11px;
|
||||
font-size: 0.8rem;
|
||||
`
|
||||
|
||||
const Control = styled.div`
|
||||
export const Control = styled.div`
|
||||
position: relative;
|
||||
`
|
||||
|
||||
const Icon = styled.span`
|
||||
export const Icon = styled.span`
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -43,7 +45,11 @@ const Icon = styled.span`
|
||||
color: ${props => props.theme.grey.light};
|
||||
`
|
||||
|
||||
const TextInput = styled.input<{hasIconLeft?: boolean}>`
|
||||
export const TextInput = styled.input<{hasIconLeft?: boolean}>`
|
||||
font-size: 1rem;
|
||||
border-radius: ${props => props.theme.border.radius};
|
||||
border: ${props => props.theme.border.width}
|
||||
solid ${props => props.theme.grey.light};
|
||||
padding: 0.5rem 0.75rem;
|
||||
padding-left: ${props => props.hasIconLeft ? '2.5rem' : '0.75rem'}
|
||||
width: 100%;
|
||||
@ -75,6 +81,9 @@ export class Input extends React.PureComponent<InputProps> {
|
||||
required={this.props.required}
|
||||
/>
|
||||
{this.props.Icon && <Icon><this.props.Icon /></Icon>}
|
||||
{this.props.error && (
|
||||
<Help colorScheme='danger'>{this.props.error}</Help>
|
||||
)}
|
||||
</Control>
|
||||
</Field>
|
||||
)
|
||||
|
||||
@ -1,47 +1,47 @@
|
||||
import React from 'react'
|
||||
import T from 'react-dom/test-utils'
|
||||
import {Modal} from './Modal'
|
||||
import {TestUtils} from '../test-utils'
|
||||
|
||||
describe('Modal', () => {
|
||||
|
||||
class TestToggle extends React.PureComponent<{}, {visible: boolean}> {
|
||||
constructor(props: {}) {
|
||||
super(props)
|
||||
this.state = {
|
||||
visible: false,
|
||||
}
|
||||
}
|
||||
toggle = () => {
|
||||
this.setState({
|
||||
visible: !this.state.visible,
|
||||
})
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<button onClick={this.toggle}>Toggle</button>
|
||||
<Modal isActive={this.state.visible}>
|
||||
hi!
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
describe('isActive', () => {
|
||||
const t = new TestUtils()
|
||||
|
||||
it('toggles is-active via isActive property', () => {
|
||||
const {node} = t.render(<TestToggle />)
|
||||
expect(node.innerHTML).toContain('hi!')
|
||||
const modal = node.querySelector('.modal') as HTMLElement
|
||||
expect(modal.className).toEqual('modal')
|
||||
T.Simulate.click(node.querySelector('button') as HTMLElement)
|
||||
expect(modal.className).toEqual('modal is-active')
|
||||
T.Simulate.click(node.querySelector('button') as HTMLElement)
|
||||
expect(modal.className).toEqual('modal')
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
// import React from 'react'
|
||||
// import T from 'react-dom/test-utils'
|
||||
// import {Modal} from './Modal'
|
||||
// import {TestUtils} from '../test-utils'
|
||||
//
|
||||
// describe('Modal', () => {
|
||||
//
|
||||
// class TestToggle extends React.PureComponent<{}, {visible: boolean}> {
|
||||
// constructor(props: {}) {
|
||||
// super(props)
|
||||
// this.state = {
|
||||
// visible: false,
|
||||
// }
|
||||
// }
|
||||
// toggle = () => {
|
||||
// this.setState({
|
||||
// visible: !this.state.visible,
|
||||
// })
|
||||
// }
|
||||
// render() {
|
||||
// return (
|
||||
// <div>
|
||||
// <button onClick={this.toggle}>Toggle</button>
|
||||
// <Modal isActive={this.state.visible}>
|
||||
// hi!
|
||||
// </Modal>
|
||||
// </div>
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// describe('isActive', () => {
|
||||
// const t = new TestUtils()
|
||||
//
|
||||
// it('toggles is-active via isActive property', () => {
|
||||
// const {node} = t.render(<TestToggle />)
|
||||
// expect(node.innerHTML).toContain('hi!')
|
||||
// const modal = node.querySelector('.modal') as HTMLElement
|
||||
// expect(modal.className).toEqual('modal')
|
||||
// T.Simulate.click(node.querySelector('button') as HTMLElement)
|
||||
// expect(modal.className).toEqual('modal is-active')
|
||||
// T.Simulate.click(node.querySelector('button') as HTMLElement)
|
||||
// expect(modal.className).toEqual('modal')
|
||||
// })
|
||||
// })
|
||||
//
|
||||
// })
|
||||
|
||||
@ -1,20 +1,21 @@
|
||||
import {Modal as M, ModalBackground, ModalContent, ModalClose} from 'bloomer'
|
||||
import React from 'react'
|
||||
|
||||
export interface ModalProps {
|
||||
isActive?: boolean
|
||||
}
|
||||
|
||||
export class Modal extends React.PureComponent<ModalProps> {
|
||||
render() {
|
||||
return (
|
||||
<M isActive={this.props.isActive}>
|
||||
<ModalBackground />
|
||||
<ModalContent>
|
||||
{this.props.children}
|
||||
</ModalContent>
|
||||
<ModalClose />
|
||||
</M>
|
||||
)
|
||||
}
|
||||
}
|
||||
// import {Modal as M, ModalBackground, ModalContent, ModalClose} from 'bloomer'
|
||||
// import React from 'react'
|
||||
//
|
||||
// export interface ModalProps {
|
||||
// isActive?: boolean
|
||||
// }
|
||||
//
|
||||
// export class Modal extends React.PureComponent<ModalProps> {
|
||||
// render() {
|
||||
// return (
|
||||
// <M isActive={this.props.isActive}>
|
||||
// <ModalBackground />
|
||||
// <ModalContent>
|
||||
// {this.props.children}
|
||||
// </ModalContent>
|
||||
// <ModalClose />
|
||||
// </M>
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
export {}
|
||||
|
||||
15
packages/client/src/components/Panel.tsx
Normal file
15
packages/client/src/components/Panel.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const Panel = styled.div`
|
||||
border: ${props => props.theme.border.width}
|
||||
solid ${props => props.theme.grey.lighter};
|
||||
`
|
||||
|
||||
export const PanelHeading = styled.div`
|
||||
background-color: ${props => props.theme.grey.lighter};
|
||||
padding: 1rem;
|
||||
`
|
||||
|
||||
export const PanelBlock = styled.div`
|
||||
padding: 1rem;
|
||||
`
|
||||
6
packages/client/src/components/Well.tsx
Normal file
6
packages/client/src/components/Well.tsx
Normal file
@ -0,0 +1,6 @@
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const Well = styled.div`
|
||||
background-color: ${props => props.theme.grey.lighter};
|
||||
border-radius: ${props => props.theme.border.radius};
|
||||
`
|
||||
@ -1,9 +1,13 @@
|
||||
export * from './Button'
|
||||
export * from './Heading'
|
||||
export * from './Help'
|
||||
export * from './Input'
|
||||
export * from './Link'
|
||||
export * from './Modal'
|
||||
export * from './Panel'
|
||||
export * from './Redirect'
|
||||
export * from './ReturnHere'
|
||||
export * from './TimeAgo'
|
||||
export * from './Well'
|
||||
export * from './withHistory'
|
||||
export * from './WithRouterProps'
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import {Control, Field, Heading, Icon, Input} from 'bloomer'
|
||||
import {Control, Field, Heading, Icon, TextInput} from '../components'
|
||||
import {CRUDChangeParams} from './CRUDActions'
|
||||
|
||||
export type CRUDFieldType = 'text' | 'password' | 'number' | 'email' | 'tel'
|
||||
@ -53,15 +53,15 @@ export class CRUDField<T> extends React.PureComponent<CRUDFieldProps<T>> {
|
||||
return (
|
||||
<Field>
|
||||
<Heading>{label}</Heading>
|
||||
<Control hasIcons={!!this.props.Icon}>
|
||||
<Input
|
||||
<Control>
|
||||
<TextInput
|
||||
name={name}
|
||||
onChange={this.handleChange}
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
/>
|
||||
{!!this.props.Icon && (
|
||||
<Icon isSize='small' isAlign='left'>
|
||||
<Icon>
|
||||
<this.props.Icon />
|
||||
</Icon>
|
||||
)}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import {Button, Panel, PanelHeading, PanelBlock} from 'bloomer'
|
||||
import {Button, Panel, PanelHeading, PanelBlock} from '../components'
|
||||
import {FaPlus, FaEdit, FaTimes} from 'react-icons/fa'
|
||||
import {Link} from '../components'
|
||||
|
||||
@ -66,7 +66,7 @@ export class CRUDItemRow<T> extends React.PureComponent<CRUDItemRowProps<T>> {
|
||||
|
||||
{!!editLink && (
|
||||
<Link to={editLink}>
|
||||
<Button isInverted isColor='link' aria-label='Edit'>
|
||||
<Button colorScheme='primary' aria-label='Edit'>
|
||||
<FaEdit />
|
||||
</Button>
|
||||
</Link>
|
||||
@ -76,8 +76,7 @@ export class CRUDItemRow<T> extends React.PureComponent<CRUDItemRowProps<T>> {
|
||||
<Button
|
||||
aria-label='Remove'
|
||||
onClick={this.handleRemove}
|
||||
isColor='danger'
|
||||
isInverted
|
||||
colorScheme='danger'
|
||||
>
|
||||
<FaTimes />
|
||||
</Button>
|
||||
|
||||
@ -1,7 +1,23 @@
|
||||
import { Breadcrumb, BreadcrumbItem } from 'bloomer'
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { CrumbLink } from './CrumbLink'
|
||||
import styled from 'styled-components'
|
||||
|
||||
const Breadcrumb = styled.ul`
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
`
|
||||
|
||||
const BreadcrumbItem = styled.li`
|
||||
display: inline-block;
|
||||
padding: 1rem 0.5rem 1rem 0;
|
||||
|
||||
& + &:before {
|
||||
padding-right: 0.5rem;
|
||||
color: ${props => props.theme.grey.light};
|
||||
content: '»';
|
||||
}
|
||||
`
|
||||
|
||||
export interface CrumbProps {
|
||||
links: CrumbLink[]
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Button, Control, Heading, Help, Input } from 'bloomer'
|
||||
import { Button, Heading, Help, Input } from '../components'
|
||||
import React from 'react'
|
||||
import { FaCheck, FaEdit, FaPlusSquare } from 'react-icons/fa'
|
||||
import { TeamActions, Team } from '@rondo.dev/common'
|
||||
@ -34,9 +34,8 @@ extends React.PureComponent<TeamEditorProps, TeamEditorState> {
|
||||
getName(team?: Team) {
|
||||
return team ? team.name : ''
|
||||
}
|
||||
handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const name = event.target.value
|
||||
this.setState({name})
|
||||
handleChange = (name: string, value: string) => {
|
||||
this.setState({name: value})
|
||||
}
|
||||
handleSubmit = async (event: React.FormEvent) => {
|
||||
event.preventDefault()
|
||||
@ -54,8 +53,6 @@ extends React.PureComponent<TeamEditorProps, TeamEditorState> {
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const {error} = this.state
|
||||
|
||||
return (
|
||||
<form
|
||||
autoComplete='off'
|
||||
@ -64,27 +61,19 @@ extends React.PureComponent<TeamEditorProps, TeamEditorState> {
|
||||
<Heading>
|
||||
{this.props.type === 'update' ? 'Edit team' : 'Add team'}
|
||||
</Heading>
|
||||
<Control hasIcons='left'>
|
||||
<Input
|
||||
placeholder='Team Name'
|
||||
type='text'
|
||||
value={this.state.name}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<span className='icon is-left'>
|
||||
{this.props.type === 'update' ? <FaEdit /> : <FaPlusSquare />}
|
||||
</span>
|
||||
{error && (
|
||||
<Help isColor='danger'>{error}</Help>
|
||||
)}
|
||||
</Control>
|
||||
<div className='text-right mt-1'>
|
||||
<Button
|
||||
isColor='dark'
|
||||
className='button'
|
||||
type='submit'
|
||||
>
|
||||
<FaCheck className='mr-1' /> Save
|
||||
<Input
|
||||
error={this.state.error}
|
||||
name='name'
|
||||
label='Team Name'
|
||||
placeholder='Team Name'
|
||||
type='text'
|
||||
value={this.state.name}
|
||||
onChange={this.handleChange}
|
||||
Icon={this.props.type === 'update' ? FaEdit : FaPlusSquare}
|
||||
/>
|
||||
<div className='text-right'>
|
||||
<Button type='submit'>
|
||||
<FaCheck /> Save
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { ReadonlyRecord, Team, TeamActions } from '@rondo.dev/common'
|
||||
import { Button, Panel, PanelBlock, PanelHeading } from 'bloomer'
|
||||
import { Button, Panel, PanelBlock, PanelHeading } from '../components'
|
||||
import React from 'react'
|
||||
import { FaEdit, FaPlus, FaTimes } from 'react-icons/fa'
|
||||
import { Link } from 'react-router-dom'
|
||||
@ -34,16 +34,15 @@ export class TeamRow extends React.PureComponent<TeamProps> {
|
||||
{!!ListButtons && <ListButtons team={team} />}
|
||||
|
||||
<Link to={`/teams/${team.id}/users`}>
|
||||
<Button isInverted isColor='link' aria-label='Edit Team'>
|
||||
<Button colorScheme='primary' aria-label='Edit Team'>
|
||||
<FaEdit />
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
<Button
|
||||
aria-label='Remove'
|
||||
colorScheme='danger'
|
||||
onClick={this.handleRemove}
|
||||
isColor='danger'
|
||||
isInverted
|
||||
>
|
||||
<FaTimes />
|
||||
</Button>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { UserInTeam, ReadonlyRecord, TeamActions, UserActions, Team } from '@rondo.dev/common'
|
||||
import { Panel, PanelBlock, PanelHeading } from 'bloomer'
|
||||
import { ReadonlyRecord, Team, TeamActions, UserActions, UserInTeam } from '@rondo.dev/common'
|
||||
import { History, Location } from 'history'
|
||||
import React from 'react'
|
||||
import { match as Match } from 'react-router'
|
||||
import { Route, Switch } from 'react-router-dom'
|
||||
import { Panel, PanelBlock, PanelHeading } from '../components'
|
||||
import { TeamEditor } from './TeamEditor'
|
||||
import { TeamList } from './TeamList'
|
||||
import { TeamUserList } from './TeamUserList'
|
||||
@ -67,7 +67,7 @@ export class TeamManager extends React.PureComponent<TeamManagerProps> {
|
||||
<>
|
||||
<Panel>
|
||||
<PanelHeading>Edit Team: {team && team.name}</PanelHeading>
|
||||
<PanelBlock isDisplay='block'>
|
||||
<PanelBlock>
|
||||
{team && <TeamEditor
|
||||
key={team.id}
|
||||
type='update'
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { User, UserInTeam, ReadonlyRecord, TeamActions, UserActions, Team } from '@rondo.dev/common'
|
||||
import { Button, Control, Heading, Help, Input, Panel, PanelBlock, PanelHeading } from 'bloomer'
|
||||
import { Button, Input, Panel, PanelBlock, PanelHeading, Heading } from '../components'
|
||||
import React from 'react'
|
||||
import { FaCheck, FaTimes, FaUser } from 'react-icons/fa'
|
||||
|
||||
@ -52,8 +52,7 @@ export class TeamUser extends React.PureComponent<TeamUserProps> {
|
||||
<div className='ml-auto'>
|
||||
<Button
|
||||
aria-label='Remove'
|
||||
isColor='danger'
|
||||
isInverted
|
||||
colorScheme='danger'
|
||||
className='team-user-remove'
|
||||
onClick={this.handleRemoveUser}
|
||||
>
|
||||
@ -74,8 +73,7 @@ export class AddUser extends React.PureComponent<AddUserProps, AddUserState> {
|
||||
user: undefined,
|
||||
}
|
||||
}
|
||||
handleChangeEmail = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const email = event.target.value
|
||||
handleChangeEmail = (name: string, email: string) => {
|
||||
this.setState({email})
|
||||
}
|
||||
handleAddUser = async (event: React.FormEvent) => {
|
||||
@ -97,33 +95,22 @@ export class AddUser extends React.PureComponent<AddUserProps, AddUserState> {
|
||||
this.setState({error: '', email: '', user: undefined})
|
||||
}
|
||||
render() {
|
||||
const {error} = this.state
|
||||
|
||||
return (
|
||||
<form autoComplete='off' onSubmit={this.handleAddUser}>
|
||||
<Heading>Add User</Heading>
|
||||
<Control hasIcons='left'>
|
||||
<Input
|
||||
isColor={error ? 'danger' : ''}
|
||||
onChange={this.handleChangeEmail}
|
||||
placeholder='Email'
|
||||
type='email'
|
||||
value={this.state.email}
|
||||
/>
|
||||
<span className='icon is-left'>
|
||||
<FaUser />
|
||||
</span>
|
||||
{error && (
|
||||
<Help isColor='danger'>{error}</Help>
|
||||
)}
|
||||
</Control>
|
||||
<Input
|
||||
label='Search by email'
|
||||
error={this.state.error}
|
||||
name='email'
|
||||
onChange={this.handleChangeEmail}
|
||||
placeholder='Email'
|
||||
type='email'
|
||||
value={this.state.email}
|
||||
Icon={FaUser}
|
||||
/>
|
||||
<div className='mt-1 text-right'>
|
||||
<Button
|
||||
isColor='dark'
|
||||
type='submit'
|
||||
>
|
||||
<FaCheck className='mr-1' />
|
||||
Add
|
||||
<Button type='submit'>
|
||||
<FaCheck /> Add
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
@ -166,7 +153,7 @@ export class TeamUserList extends React.PureComponent<TeamUsersProps> {
|
||||
)
|
||||
})}
|
||||
|
||||
<PanelBlock isDisplay='block'>
|
||||
<PanelBlock>
|
||||
<AddUser
|
||||
onAddUser={this.props.onAddUser}
|
||||
onSearchUser={this.props.findUserByEmail}
|
||||
|
||||
@ -5,5 +5,5 @@ export function getColor(props: ColorSchemeProps) {
|
||||
}
|
||||
|
||||
export function getBorder(props: ColorSchemeProps) {
|
||||
return `${props.theme.border.width}px solid ${getColor(props)};`
|
||||
return `${props.theme.border.width} solid ${getColor(props)};`
|
||||
}
|
||||
|
||||
@ -12,10 +12,11 @@ declare module 'styled-components' {
|
||||
grey: {
|
||||
dark: string
|
||||
light: string
|
||||
lighter: string
|
||||
}
|
||||
border: {
|
||||
width: 1
|
||||
radius: 3
|
||||
width: string
|
||||
radius: string
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -31,10 +32,11 @@ export const theme: DefaultTheme = {
|
||||
grey: {
|
||||
dark: 'darkgrey',
|
||||
light: 'lightgrey',
|
||||
lighter: 'whitesmoke',
|
||||
},
|
||||
border: {
|
||||
width: 1,
|
||||
radius: 3,
|
||||
width: '1px',
|
||||
radius: '3px',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user