Skip to content

Commit

Permalink
feat(Transition): add component
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Fedyashov committed Jun 7, 2017
1 parent 6bf47ab commit e7c5625
Show file tree
Hide file tree
Showing 22 changed files with 1,261 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Once you change the flag, you need to refresh your browser to see the changes in
| ✓ Rail | | | ✓ Sidebar | |
| ✓ Reveal | | | Sticky | |
| ✓ Segment | | | Tab | |
| ✓ Step | | | Transition | |
| ✓ Step | | | Transition | |

## Our Principles

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { Component } from 'react'
import { Button, Form, Grid, Image, Transition } from 'semantic-ui-react'

const transitions = [
'scale',
'fade', 'fade up', 'fade down', 'fade left', 'fade right',
'jiggle', 'flash',
]
const options = transitions.map(transition => ({ text: transition, value: transition }))

export default class TransitionExampleSingleExplorer extends Component {
state = {
duration: 500,
animation: 'scale',
visible: true,
}

handleDuration = (e, { value: duration }) => this.setState({ duration })

handleTransition = (e, { value: animation }) => this.setState({ animation })

handleVisibility = () => {
const { visible } = this.state
this.setState({ visible: !visible })
}

render() {
const { animation, duration, visible } = this.state

return (
<Grid columns={2}>
<Grid.Column as={Form}>
<Form.Select
label='Choose transition'
onChange={this.handleTransition}
options={options}
value={animation}
/>
<Form.Input
label={`Duration: ${duration}ms `}
min={500}
max={5000}
onChange={this.handleDuration}
step={500}
type='range'
value={duration}
/>
<Form.Button
content={visible ? 'Hide' : 'Show'}
onClick={this.handleVisibility}
type='button'
/>
</Grid.Column>

<Grid.Column>
<Transition
animation={animation}
duration={duration}
into={visible}
>
<Image size='medium' src='http://semantic-ui.com/images/leaves/4.png' />
</Transition>
</Grid.Column>
</Grid>
)
}
}
16 changes: 16 additions & 0 deletions docs/app/Examples/modules/Transition/Explorers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react'

import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'

const TransitionTypesExamples = () => (
<ExampleSection title='Explorers'>
<ComponentExample
title='Single item'
description='You can apply different animations and duration with a transition explorer.'
examplePath='modules/Transition/Explorers/TransitionExampleSingleExplorer'
/>
</ExampleSection>
)

export default TransitionTypesExamples
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import _ from 'lodash'
import React, { Component } from 'react'
import { Button, Image, List, Transition } from 'semantic-ui-react'

const users = [
'ade', 'chris', 'christian', 'daniel', 'elliot', 'helen', 'jenny', 'joe', 'justen', 'laura', 'matt', 'nan', 'nom',
'steve', 'stevie', 'tom', 'veronika', 'zoe',
]

export default class TransitionExampleGroup extends Component {
state = { items: users.slice(0, 5) }

handleAdd = () => {
const { items } = this.state
this.setState({ items: users.slice(0, items.length + 1) })
}

handleRemove = () => {
const { items } = this.state
this.setState({ items: items.slice(0, -1) })
}

render() {
const { items } = this.state

return (
<div>
<Transition.Group
as={List}
duration={1000}
divided size='huge'
verticalAlign='middle'
>
{items.map(item => (
<List.Item key={item}>
<Image avatar src={`/assets/images/avatar/small/${item}.jpg`} />
<List.Content header={_.startCase(item)} />
</List.Item>
))}
</Transition.Group>

<Button.Group>
<Button icon='minus' onClick={this.handleRemove} />
<Button icon='plus' onClick={this.handleAdd} />
</Button.Group>
</div>
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { Component } from 'react'
import { Button, Divider, Image, Transition } from 'semantic-ui-react'

export default class TransitionExampleTransition extends Component {
state = { visible: true }

handleVisibility = () => {
const { visible } = this.state
this.setState({ visible: !visible })
}

render() {
const { visible } = this.state

return (
<div>
<Transition
animation='scale'
duration={1500}
into={visible}
>
<Image size='small' src='http://semantic-ui.com/images/leaves/1.png' />
</Transition>
<Divider hidden />
<Button
content={visible ? 'Hide' : 'Show'}
onClick={this.handleVisibility}
type='button'
/>
</div>
)
}
}
21 changes: 21 additions & 0 deletions docs/app/Examples/modules/Transition/Types/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react'

import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'

const TransitionTypesExamples = () => (
<ExampleSection title='Types'>
<ComponentExample
title='Transition'
description='A transition can be applied to single item.'
examplePath='modules/Transition/Types/TransitionExampleTransition'
/>
<ComponentExample
title='Transition Group'
description='A transition can be applied to items group.'
examplePath='modules/Transition/Types/TransitionExampleGroup'
/>
</ExampleSection>
)

export default TransitionTypesExamples
13 changes: 13 additions & 0 deletions docs/app/Examples/modules/Transition/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react'

import Explorers from './Explorers'
import Types from './Types'

const TransitionExamples = () => (
<div>
<Types />
<Explorers />
</div>
)

export default TransitionExamples
3 changes: 3 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ export { default as Sidebar, SidebarProps } from './dist/commonjs/modules/Sideba
export { default as SidebarPushable, SidebarPushableProps } from './dist/commonjs/modules/Sidebar/SidebarPushable';
export { default as SidebarPusher, SidebarPusherProps } from './dist/commonjs/modules/Sidebar/SidebarPusher';

export { default as Transition, TransitionProps, TRANSITION_STATUSES } from './dist/commonjs/modules/Transition';
export { default as TransitionGroup, TransitionGroupProps } from './dist/commonjs/modules/Transition/TransitionGroup';

// Views
export { default as Advertisement, AdvertisementProps } from './dist/commonjs/views/Advertisement';

Expand Down
2 changes: 1 addition & 1 deletion src/collections/Message/Message.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { default as MessageList } from './MessageList';
export interface MessageProps {
[key: string]: any;

/** An element type to render as (string or function). */
/** An element type to render as (string or function). */
as?: any;

/** A message can be formatted to attach itself to other content. */
Expand Down
9 changes: 9 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ export type SemanticCOLORS = 'red' | 'orange' | 'yellow' | 'olive' |'green' | 't
'pink' | 'brown' | 'grey' | 'black';
export type SemanticSIZES = 'mini' | 'tiny' | 'small' | 'medium' | 'large' | 'big' | 'huge' | 'massive';

// ======================================================
// Transitions
// ======================================================

type SemanticENTIRETRANSITIONS = 'scale' | 'fade' | 'fade up' | 'fade down' | 'fade left' | 'fade right';
type SemanticSTATICTRANSITIONS = 'jiggle' | 'flash';

export type SemanticTRANSITIONS = SemanticENTIRETRANSITIONS | SemanticSTATICTRANSITIONS;

// ======================================================
// Widths
// ======================================================
Expand Down
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ export { default as Sidebar } from './modules/Sidebar'
export { default as SidebarPushable } from './modules/Sidebar/SidebarPushable'
export { default as SidebarPusher } from './modules/Sidebar/SidebarPusher'

export { default as Transition } from './modules/Transition'
export { default as TransitionGroup } from './modules/Transition/TransitionGroup'

// Views
export { default as Advertisement } from './views/Advertisement'

Expand Down
9 changes: 9 additions & 0 deletions src/lib/SUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ export const WIDTHS = [
..._.values(numberToWordMap),
]

export const ENTIRE_TRANSITIONS = [
'scale',
'fade', 'fade up', 'fade down', 'fade left', 'fade right',
]
export const STATIC_TRANSITIONS = [
'jiggle', 'flash',
]
export const TRANSITIONS = [...ENTIRE_TRANSITIONS, ...STATIC_TRANSITIONS]

// Generated from:
// https://github.com/Semantic-Org/Semantic-UI/blob/master/dist/components/icon.css
export const WEB_CONTENT_ICONS = [
Expand Down
61 changes: 61 additions & 0 deletions src/lib/childMapping.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import _ from 'lodash'
import { Children } from 'react'

/**
* Given `this.props.children`, return an object mapping key to child.
*
* @param {object} children Element's children
* @return {object} Mapping of key to child
*/
export const getChildMapping = children => _.keyBy(Children.toArray(children), 'key')

/**
* When you're adding or removing children some may be added or removed in the same render pass. We want to show *both*
* since we want to simultaneously animate elements in and out. This function takes a previous set of keys and a new set
* of keys and merges them with its best guess of the correct ordering. In the future we may expose some of the
* utilities in ReactMultiChild to make this easy, but for now React itself does not directly have this concept of the
* union of prevChildren and nextChildren so we implement it here.
*
* @param {object} prev prev children as returned from `ReactTransitionChildMapping.getChildMapping()`.
* @param {object} next next children as returned from `ReactTransitionChildMapping.getChildMapping()`.
* @return {object} a key set that contains all keys in `prev` and all keys in `next` in a reasonable order.
*/
export const mergeChildMappings = (prev = {}, next = {}) => {
function getValueForKey(key) {
return key in next ? next[key] : prev[key]
}

// For each key of `next`, the list of keys to insert before that key in the combined list
const nextKeysPending = {}
let pendingKeys = []

for (const prevKey in prev) {
if (prevKey in next) {
if (pendingKeys.length) {
nextKeysPending[prevKey] = pendingKeys
pendingKeys = []
}
} else {
pendingKeys.push(prevKey)
}
}

let i
const childMapping = {}
for (const nextKey in next) {
if (nextKeysPending[nextKey]) {
for (i = 0; i < nextKeysPending[nextKey].length; i++) {
const pendingNextKey = nextKeysPending[nextKey][i]
childMapping[nextKeysPending[nextKey][i]] = getValueForKey(pendingNextKey)
}
}
childMapping[nextKey] = getValueForKey(nextKey)
}

// Finally, add the keys which didn't appear before any key in `next`
for (i = 0; i < pendingKeys.length; i++) {
childMapping[pendingKeys[i]] = getValueForKey(pendingKeys[i])
}

return childMapping
}
1 change: 1 addition & 0 deletions src/lib/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { default as AutoControlledComponent } from './AutoControlledComponent'
export { getChildMapping, mergeChildMappings } from './childMapping'
export * as childrenUtils from './childrenUtils'

export {
Expand Down
Loading

0 comments on commit e7c5625

Please sign in to comment.