Skip to content

Instantly share code, notes, and snippets.

@xcoderzach
Last active January 11, 2017 15:08
Show Gist options
  • Save xcoderzach/4a77f87b9eb0eced72f85c53525ad8fa to your computer and use it in GitHub Desktop.
Save xcoderzach/4a77f87b9eb0eced72f85c53525ad8fa to your computer and use it in GitHub Desktop.
import { ThemeProvider } from 'styled-components'
export default const ComponentProvider = (namespace, defaultTheme) => (props) => {
const theme = (parentTheme = {}) => {
//If we've never seen a theme object in our namespace before, use the defaultTheme
parentTheme = parentTheme[namespace] || defaultTheme
// If a library consumer passes a function as their theme,
// give them the parentTheme (or defaultTheme) as an argument so they can 🎨decorate🎨.
const userTheme = (typeof props.theme === 'function') ? props.theme(parentTheme) : props.theme
return {
[namespace]: Object.assign({}, parentTheme, userTheme)
}
}
return <ThemeProvider theme={theme}>
{props.children}
</ThemeProvider>
}
import ComponentProvider from './provider'
// I'm doing the interpolation here, because
// the range is a visual concern (pixels).
// The visual part of your code shouldn't be
// logicless, it should only have logic related
// to visuals.
function interp(domain, range, value) {
let domainSize = domain[1] - domain[0]
, rangeSize = range[1] - range[0]
, offset = value - domain[0]
, percentOffset = domainSize * offset
return range[0] + rangeSize * percentOffset
}
const width = 400;
const SliderContainer = styled.div`
width: ${width}px;
`
const SliderBar = styled.div`
width: ${width}px;
height: 5px;
background-color: tomato;
position: relative;
`
const SliderHandleUI = styled.div`
height: 30px;
width: 30px;
transform: translate(-15px -30px);
background-color: tomato;
position: absolute;
left: ${({ domain, value }) => interp(domain, [0, innerWidth], value)}px;
`
const SliderHandle({ ...props, onChange }) => (
<SliderHandleUI
{...props}
onDrag={({ movementX }) => {
let newValue = props.value + interp([0, 360], props.domain, movementX)
this.props.onChange(newValue)
}
/>
)
export default ComponentProvider("simpleSlider", {
SliderHandle,
SliderContainer,
SliderBar
})
import React from 'react'
/*
This is the Semantic Component, notice there is nothing about
the display of the component defined here. 👍Yay SoC👍.
There's nothing preventing this component from being used with
react native, or as part of an svg, because it only describes
the semantics of the slider.
Obviously a full featured slider would probably need to do a lot
more.
*/
export default ({ startValue, stopValue, domain, onStartChange, onStopChange,
theme: {
SliderHandle,
SliderBar,
SliderContainer
}
}) =>
return (
<SliderContainer>
<SliderBar
onStartChange={props.onStartChange}
onStopChange={props.onStopChange}
domain={domain}
start={startValue}
stop={stopValue}
>
<SliderHandle
position="start"
domain={domain}
value={startValue}
onChange={props.onStartChange}
/>
<SliderHandle
position="stop"
domain={domain}
value={stopValue}
onChange={props.onStopChange}
/>
</SliderBar>
</SliderContainer>
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment