@vixoniccom/menu-daily 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/assets/framed.ai +3330 -4
  3. package/assets/modern.ai +421 -0
  4. package/build.zip +0 -0
  5. package/configuration.json +207 -0
  6. package/icon.png +0 -0
  7. package/package.json +31 -0
  8. package/src/dataLoader.ts +168 -0
  9. package/src/global.d.ts +59 -0
  10. package/src/index.html +33 -0
  11. package/src/logger.ts +11 -0
  12. package/src/main.ts +47 -0
  13. package/src/scenes/App.tsx +103 -0
  14. package/src/scenes/components/FontLoader.tsx +52 -0
  15. package/src/scenes/components/FormattedText.tsx +56 -0
  16. package/src/scenes/components/Grid/Grid.tsx +161 -0
  17. package/src/scenes/components/Grid/GridItem.tsx +79 -0
  18. package/src/scenes/components/Grid/animation.ts +105 -0
  19. package/src/scenes/components/Grid/index.ts +2 -0
  20. package/src/scenes/components/MealContainer/components/OptionItem.tsx +25 -0
  21. package/src/scenes/components/MealContainer/components/Title/index.tsx +82 -0
  22. package/src/scenes/components/MealContainer/components/Title/styles/Framed.tsx +52 -0
  23. package/src/scenes/components/MealContainer/components/Title/styles/Modern.tsx +47 -0
  24. package/src/scenes/components/MealContainer/components/Title/styles/index.tsx +13 -0
  25. package/src/scenes/components/MealContainer/components/index.ts +2 -0
  26. package/src/scenes/components/MealContainer/index.tsx +59 -0
  27. package/src/static/menu-daily-example.xlsx +0 -0
  28. package/src/test/downloads/1234.ttf +0 -0
  29. package/src/test/downloads/background.jpg +0 -0
  30. package/src/test/downloads/futura-font.ttf +0 -0
  31. package/src/test/parameters.json +37 -0
  32. package/tsconfig.json +36 -0
  33. package/tslint.json +5 -0
@@ -0,0 +1,52 @@
1
+ import React from 'react'
2
+
3
+ type Props = {
4
+ fonts: string[]
5
+ downloadPath: string
6
+ }
7
+
8
+ class FontLoader extends React.Component<Props> {
9
+ render () {
10
+ let fonts = this.props.fonts.map((font) => {
11
+ try {
12
+ return `
13
+ @font-face {
14
+ font-family: "${parseFontName(font)}";
15
+ src: url("${parseFontUrl(this.props.downloadPath, font)}");
16
+ }
17
+ `
18
+ } catch (err) {
19
+ return ''
20
+ }
21
+ })
22
+ return <style>{fonts}</style>
23
+ }
24
+ }
25
+
26
+ export function fontParser (parameters: VixonicParameters): string[] {
27
+ let initArr: string[] = []
28
+ return Object.keys(parameters).reduce(
29
+ (fonts, param) => {
30
+ switch (param) {
31
+ case 'itemTitleTextFormat':
32
+ case 'itemOptionsTextFormat':
33
+ if (parameters[param] && parameters[param]!.font && parameters[param]!.font!.filename) {
34
+ fonts.push((parameters[param]!.font!.filename || ''))
35
+ return fonts
36
+ } else return fonts
37
+ default:
38
+ return fonts
39
+ }
40
+ }, initArr
41
+ )
42
+ }
43
+
44
+ export const parseFontName = (filename: string): string => {
45
+ return filename.replace('.','-')
46
+ }
47
+
48
+ export const parseFontUrl = (path: string, filename: string): string => {
49
+ return path + '/' + filename
50
+ }
51
+
52
+ export default FontLoader
@@ -0,0 +1,56 @@
1
+ import React from 'react'
2
+ import { parseFontName } from './FontLoader'
3
+
4
+ const alignments = {
5
+ center: 'center',
6
+ left: 'flex-start',
7
+ right: 'flex-end'
8
+ }
9
+
10
+ type Props = {
11
+ text: string
12
+ downloadsPath: string
13
+ unit: 'px' | '%' | 'em' | 'vh'
14
+ defaults: {
15
+ fontSize: number,
16
+ fontColor: string
17
+ alignment: 'left' | 'center' | 'right'
18
+ }
19
+ format: VixonicTextFormat
20
+ multiline?: boolean
21
+ lineHeight?: number
22
+ style?: React.CSSProperties
23
+ }
24
+
25
+ class FormattedText extends React.Component<Props> {
26
+ render () {
27
+ let { format, defaults } = this.props
28
+ let { alignment, font, fontColor, fontSize } = format
29
+ let containerStyle = Object.assign({
30
+ display: 'inline-flex',
31
+ justifyContent: this.getHorizontalAlignment(alignment && alignment.horizontal || defaults.alignment)
32
+ }, this.props.style)
33
+ return <div style={containerStyle}>
34
+ <span style={{
35
+ color: fontColor || defaults.fontColor,
36
+ width: '100%',
37
+ fontFamily: font && font.filename && `"${parseFontName(font.filename)}"` || undefined,
38
+ fontSize: `${fontSize || defaults.fontSize}${this.props.unit}`,
39
+ textAlign: alignment && alignment.horizontal || defaults.alignment,
40
+ lineHeight: this.props.lineHeight,
41
+ overflow: 'hidden',
42
+ textOverflow: 'ellipsis',
43
+ whiteSpace: this.props.multiline ? 'normal' : 'nowrap'
44
+ }}>{this.props.text}</span>
45
+ </div>
46
+ }
47
+
48
+ getHorizontalAlignment (alignment: any) {
49
+ if (alignment) {
50
+ return alignments.hasOwnProperty(alignment) ? (alignments as any)[alignment] : 'flex-start'
51
+ }
52
+ return 'flex-start'
53
+ }
54
+ }
55
+
56
+ export default FormattedText
@@ -0,0 +1,161 @@
1
+ import React from 'react'
2
+ import Animation from './animation'
3
+ import Item from './GridItem'
4
+
5
+ type GridProps = {
6
+ animate: boolean,
7
+ animation: {
8
+ mode: 'fade' | 'slideLeft' | 'slideRight',
9
+ duration: number,
10
+ speed?: number,
11
+ stagger?: number,
12
+ reverse?: boolean
13
+ },
14
+ layout: {
15
+ rows: number,
16
+ rowsGap?: number,
17
+ columns: number,
18
+ columnsGap?: number,
19
+ alignment: {
20
+ h: 'start' | 'center' | 'end',
21
+ v: 'start' | 'center' | 'end'
22
+ }
23
+ }
24
+ style?: React.CSSProperties
25
+ fontSize?: string
26
+ id: string
27
+ items: React.ReactNode[]
28
+ }
29
+
30
+ type GridState = {
31
+ show: boolean,
32
+ stage: 'idle' | 'preparing' | 'prepared' | 'animating',
33
+ items: React.ReactNode[]
34
+ }
35
+
36
+ class Grid extends React.Component<GridProps, GridState> {
37
+ lastIndex: number
38
+ animation: any
39
+ animating: boolean = false
40
+ unmounting: boolean = false
41
+
42
+ container: HTMLDivElement | null = null
43
+
44
+ columns: number = 1
45
+ columnsGap: number = 1
46
+ rows: number = 1
47
+ rowsGap: number = 1
48
+ itemsCount: number = 1
49
+
50
+ state: GridState = {
51
+ show: false,
52
+ stage: 'idle',
53
+ items: []
54
+ }
55
+
56
+ constructor () {
57
+ super ()
58
+ this.lastIndex = 0
59
+ this.animation = new Animation()
60
+ }
61
+
62
+ componentDidMount () {
63
+ this.configure(this.props)
64
+ }
65
+
66
+ componentWillReceiveProps (nextProps: GridProps) {
67
+ this.configure(nextProps)
68
+ }
69
+
70
+ componentWillUnmount () {
71
+ this.unmounting = true
72
+ }
73
+
74
+ configure (props: GridProps) {
75
+ this.animation.configure(props.animation)
76
+ this.columns = props.layout.columns || 1
77
+ this.columnsGap = props.layout.columnsGap || 0
78
+ this.rows = props.layout.rows || 1
79
+ this.rowsGap = props.layout.rowsGap || 0
80
+ this.itemsCount = this.rows * this.columns
81
+ if (props.animate && !this.animating && this.state.stage === 'idle') {
82
+ this.animating = true
83
+ this.createItems(props)
84
+ }
85
+ }
86
+
87
+ // Filter items by index and create the proper item within its container.
88
+ createItems (props: GridProps) {
89
+ if (!props.items) return
90
+ let count = 0
91
+ this.lastIndex = this.lastIndex < props.items.length ? this.lastIndex : 0
92
+ let newItems = props.items.filter((_item, index) => {
93
+ return index >= this.lastIndex
94
+ }).map((item, index, arr) => {
95
+ if (count >= this.itemsCount) return null
96
+ this.lastIndex++
97
+ count++
98
+ return <Item
99
+ key={`${Math.random()}${Math.random()}`} containerData={{
100
+ ic_index: index,
101
+ ic_rowIndex: Math.floor(index / this.columns),
102
+ ic_columnIndex: Math.floor(index % this.columns),
103
+ ic_firstChild: index === 0,
104
+ ic_lastChild: index === (arr.length - 1)
105
+ }} style={this.animation.getInitialStyle()}
106
+ // Item alignment. By default is center - center.
107
+ alignment={props.layout.alignment}
108
+ // Setup item width based on columns count.
109
+ width={(100 - (this.columnsGap * (this.columns - 1))) / this.columns}
110
+ // Setup item height based on rows count. If 0 set up on auto.
111
+ height={(100 - (this.rowsGap * (this.rows - 1))) / this.rows}
112
+ // Setup horizontal gap
113
+ horizontalGap={this.columnsGap}
114
+ // Setup vertical gap
115
+ verticalGap={this.rowsGap}
116
+ // Optional fontSize
117
+ fontSize={this.props.fontSize}>
118
+ {item}
119
+ </Item>
120
+ })
121
+ if (newItems.length > 0) {
122
+ this.setState({
123
+ show: true,
124
+ stage: 'prepared',
125
+ items: newItems
126
+ })
127
+ } else {
128
+ this.setState({
129
+ show: false,
130
+ stage: 'idle'
131
+ })
132
+ }
133
+ }
134
+
135
+ render () {
136
+ return <div ref={(container) => { this.container = container }} style={{
137
+ opacity: this.state.show ? 1 : 0,
138
+ position: 'relative',
139
+ display: 'flex',
140
+ flexWrap: 'wrap',
141
+ alignContent: 'flex-start',
142
+ ...this.props.style
143
+ }}>
144
+ {this.state.items}
145
+ </div>
146
+ }
147
+
148
+ componentDidUpdate () {
149
+ if (this.props.animate && this.state.stage === 'prepared') {
150
+ // Start animations.
151
+ this.animation.animate(this.container!.childNodes, () => {
152
+ !this.unmounting && this.createItems(this.props)
153
+ })
154
+ this.setState({
155
+ stage: 'animating'
156
+ })
157
+ }
158
+ }
159
+ }
160
+
161
+ export default Grid
@@ -0,0 +1,79 @@
1
+ import React from 'react'
2
+
3
+ const aligments: {[alignment: string]: 'flex-start' | 'center' | 'flex-end'} = {
4
+ start: 'flex-start',
5
+ center: 'center',
6
+ end: 'flex-end'
7
+ }
8
+
9
+ type GridItemProps = {
10
+ style: React.CSSProperties,
11
+ alignment: {
12
+ h: 'start' | 'center' | 'end',
13
+ v: 'start' | 'center' | 'end'
14
+ }
15
+ width: number,
16
+ height: number,
17
+ horizontalGap: number,
18
+ verticalGap: number,
19
+ containerData: ContainerDataProps
20
+ fontSize?: string
21
+ }
22
+
23
+ export type ContainerDataProps = {
24
+ ic_index: number
25
+ ic_rowIndex: number,
26
+ ic_columnIndex: number,
27
+ ic_firstChild: boolean,
28
+ ic_lastChild: boolean
29
+ }
30
+
31
+ class GridItem extends React.Component<GridItemProps, any> {
32
+ el: any
33
+
34
+ constructor () {
35
+ super()
36
+ this.state = {}
37
+ }
38
+
39
+ componentDidMount () {
40
+ this.setState({height: this.el.offsetHeight})
41
+ }
42
+
43
+ componentWillReceiveProps () {
44
+ this.setState({ height: this.el.offsetHeight })
45
+ }
46
+
47
+ render () {
48
+ let props = this.props
49
+ let style: React.CSSProperties = {
50
+ overflow: 'hidden',
51
+ display: 'flex',
52
+ position: 'relative',
53
+ alignItems: aligments[props.alignment ? props.alignment.v : 'center'],
54
+ justifyContent: aligments[props.alignment ? props.alignment.h : 'center'],
55
+ width: `${props.width}%`,
56
+ height: `${props.height}%`,
57
+ fontSize: this.props.fontSize || this.state.height && `${this.state.height}px`,
58
+ top: props.containerData.ic_rowIndex === 0
59
+ ? '0'
60
+ : props.verticalGap
61
+ ? `${props.verticalGap * props.containerData.ic_rowIndex}%`
62
+ : '0',
63
+ paddingLeft: props.containerData.ic_columnIndex === 0
64
+ ? '0'
65
+ : props.horizontalGap
66
+ ? `${props.horizontalGap}%`
67
+ : '0',
68
+ ...props.style
69
+ }
70
+ return <div style={style}
71
+ ref={(el) => this.el = el}>
72
+ {
73
+ React.cloneElement<any, any>(props.children as React.ReactElement<any>, props.containerData)
74
+ }
75
+ </div>
76
+ }
77
+ }
78
+
79
+ export default GridItem
@@ -0,0 +1,105 @@
1
+ let anime = require('animejs')
2
+
3
+ // Predefined animation modes.
4
+ const animationModes: {[mode: string]: any} = {
5
+ fade: {
6
+ in: {
7
+ opacity: [0, 1],
8
+ easing: 'linear'
9
+ },
10
+ out: {
11
+ opacity: [1, 0],
12
+ easing: 'linear'
13
+ },
14
+ init: {
15
+ opacity: 0
16
+ }
17
+ },
18
+ slideRight: {
19
+ in: {
20
+ translateX: (_el: any, _i: any) => {
21
+ return [`-100vw`, '0vw']
22
+ },
23
+ easing: 'easeOutQuad'
24
+ },
25
+ out: {
26
+ translateX: (_el: any, _i: any) => {
27
+ return ['0vw', `100vw`]
28
+ },
29
+ easing: 'easeInQuad'
30
+ },
31
+ init: {
32
+ transform: 'translate(0vw)'
33
+ }
34
+ },
35
+ slideLeft: {
36
+ in: {
37
+ translateX: (_el: any, _i: any) => {
38
+ return [`100vw`, '0vw']
39
+ },
40
+ easing: 'easeOutQuad'
41
+ },
42
+ out: {
43
+ translateX: (_el: any, _i: any) => {
44
+ return ['0vw', `-100vw`]
45
+ },
46
+ easing: 'easeInQuad'
47
+ },
48
+ init: {
49
+ transform: 'translate(0vw)'
50
+ }
51
+ }
52
+ }
53
+
54
+ class Animation {
55
+ mode: any = animationModes.fade
56
+ duration: number = 10000
57
+ speed: number = 1000
58
+ stagger: number = 1000 / 4
59
+ reverse?: boolean = false
60
+
61
+ configure (options: { mode?: string, duration?: number, speed?: number, stagger?: number, reverse?: boolean }) {
62
+ this.mode = options.mode && animationModes.hasOwnProperty(options.mode) && animationModes[options.mode] || animationModes.fade
63
+ this.duration = options.duration && options.duration > 1000 && options.duration || 10000
64
+ this.speed = 1000 * (options.speed || 1)
65
+ this.stagger = this.speed / (options.stagger || 4)
66
+ this.reverse = options.reverse
67
+ }
68
+
69
+ getInitialStyle () {
70
+ return this.mode.init
71
+ }
72
+
73
+ animate (listNodes: any, finished: Function) {
74
+ let self = this
75
+ let els = [].slice.call(listNodes, 0)
76
+ if (this.reverse) els = els.reverse()
77
+ if (!els || els.length < 1) return
78
+ let offset = this.duration - (((els.length - 1) * this.stagger) + this.speed) * 2
79
+ offset = offset < 0 ? 0 : offset
80
+ let animation = anime.timeline({
81
+ autoplay: false
82
+ })
83
+ animation.add(Object.assign({
84
+ targets: els,
85
+ duration: this.speed,
86
+ delay: function (_el: any, _i: any, _l: any) {
87
+ return _i * self.stagger
88
+ }
89
+ }, this.mode.in))
90
+ animation.add(Object.assign({
91
+ targets: els,
92
+ duration: this.speed,
93
+ delay: function (_el: any, _i: any, _l: any) {
94
+ return _i * self.stagger
95
+ },
96
+ offset: `+=${offset}`,
97
+ complete: () => {
98
+ finished()
99
+ }
100
+ }, this.mode.out))
101
+ animation.play()
102
+ }
103
+ }
104
+
105
+ export default Animation
@@ -0,0 +1,2 @@
1
+ import Grid from './Grid'
2
+ export default Grid
@@ -0,0 +1,25 @@
1
+ import React from 'react'
2
+ import FormattedText from '../../FormattedText'
3
+
4
+ type Props = {
5
+ data: string
6
+ vixonicData: VixonicData
7
+ }
8
+
9
+ export default class OptionItem extends React.Component<Props> {
10
+ render () {
11
+ let { vixonicData } = this.props
12
+ return <FormattedText
13
+ text={this.props.data}
14
+ downloadsPath={vixonicData.downloadsPath}
15
+ defaults={{
16
+ fontSize: 10,
17
+ alignment: 'left',
18
+ fontColor: 'black'
19
+ }}
20
+ format={vixonicData.parameters.itemOptionsTextFormat || {}}
21
+ unit='%'
22
+ multiline
23
+ style={{width: '100%', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}} />
24
+ }
25
+ }
@@ -0,0 +1,82 @@
1
+ import React from 'react'
2
+ import FormattedText from '../../../FormattedText'
3
+ import { ModernStyle, FramedStyle, TitleStyle } from './styles'
4
+
5
+ type Props = {
6
+ text: string
7
+ vixonicData: VixonicData
8
+ getPadding: (padding: string) => void
9
+ }
10
+
11
+ const TitleStyles: {[name: string]: TitleStyle} = {
12
+ standard: {
13
+ component: null,
14
+ getPadding: () => ('0'),
15
+ heightOffset: 1
16
+ },
17
+ modern: ModernStyle,
18
+ framed: FramedStyle
19
+ }
20
+
21
+ const defaultFontSize = 20
22
+
23
+ class Title extends React.Component<Props> {
24
+ style: TitleStyle
25
+
26
+ constructor () {
27
+ super()
28
+ this.style = TitleStyles.standard
29
+ }
30
+
31
+ componentDidMount () {
32
+ this.setup(this.props)
33
+ }
34
+
35
+ setup (props: Props) {
36
+ let { parameters } = props.vixonicData
37
+ if (parameters.itemStyle && TitleStyles[parameters.itemStyle]) {
38
+ this.style = TitleStyles[parameters.itemStyle]
39
+ }
40
+ let fontSize = parameters.itemTitleTextFormat && parameters.itemTitleTextFormat.fontSize
41
+ props.getPadding(this.style.getPadding(fontSize || defaultFontSize))
42
+ }
43
+
44
+ render () {
45
+ let { text } = this.props
46
+ let { parameters, downloadsPath } = this.props.vixonicData
47
+ let backgroundColor = parameters.itemTitleBackgroundColor
48
+ let fontSize = parameters.itemTitleTextFormat
49
+ && parameters.itemTitleTextFormat.fontSize
50
+ && (parameters.itemTitleTextFormat.fontSize / 100)
51
+ || defaultFontSize / 100
52
+ return <div style={{display: 'flex', height: `${fontSize * (this.style.heightOffset || 1)}em`}}>
53
+ {this.style.component && <this.style.component type='l' color={backgroundColor}/>}
54
+ <div style={{flex: 1, display: 'flex', alignItems: 'center', position: 'relative', width: '100%'}}>
55
+ <FormattedText
56
+ text={text}
57
+ downloadsPath={downloadsPath}
58
+ defaults={{
59
+ fontSize: defaultFontSize,
60
+ alignment: 'left',
61
+ fontColor: 'black'
62
+ }}
63
+ format={parameters.itemTitleTextFormat || {}}
64
+ unit='%'
65
+ style={{
66
+ overflow: 'hidden',
67
+ position: 'absolute',
68
+ zIndex: 1,
69
+ width: '100%',
70
+ textOverflow: 'ellipsis',
71
+ whiteSpace: 'nowrap',
72
+ height: '100%',
73
+ alignItems: 'center'
74
+ }} />
75
+ {this.style.component && <this.style.component type='c' color={backgroundColor}/>}
76
+ </div>
77
+ {this.style.component && <this.style.component type='r' color={backgroundColor}/>}
78
+ </div>
79
+ }
80
+ }
81
+
82
+ export default Title
@@ -0,0 +1,52 @@
1
+ import React, { SFC } from 'react'
2
+ import { TitleStyle, StyleProps } from './'
3
+
4
+ const Left: SFC<{color: string}> = (props) =>
5
+ (<svg x='0px' y='0px' style={{flexShrink: 0}} height='100%' viewBox='0 0 40 100'>
6
+ <g>
7
+ <path fill={props.color} d='M40,0H37.75C26.43,0,17.25,8.33,17.25,18.59v1.33a34.85,34.85,0,0,0,0,60.16v1.33c0,10.27,9.18,18.59,20.51,18.59H40ZM23.89,54.94A4.94,4.94,0,1,1,28.83,50,4.94,4.94,0,0,1,23.89,54.94Z'/>
8
+ <path fill='#fff' d='M40,95.21H37.75C29.08,95.21,22,89,22,81.41V77.34L19.67,76a30.07,30.07,0,0,1,0-51.9L22,22.66V18.59C22,11,29.08,4.79,37.75,4.79H40V3.42H37.75c-9.42,0-17.09,6.81-17.09,15.17v3.29l-1.69,1a31.44,31.44,0,0,0,0,54.26l1.69,1v3.29c0,8.37,7.67,15.17,17.09,15.17H40Z'/>
9
+ </g>
10
+ </svg>)
11
+
12
+ const Center: SFC<{color: string}> = (props) => (
13
+ <div style={{position: 'absolute', left: -1, right: 0, top: 0, bottom: 0}}>
14
+ <svg x='0px' y='0px' style={{position: 'absolute'}} width='100%' height='100%'
15
+ viewBox='0 0 40 100' preserveAspectRatio='none'>
16
+ <g>
17
+ <rect fill={props.color} width='40' height='100'/>
18
+ <g fill='#fff'>
19
+ <rect y='95.21' width='40' height='1.37'/>
20
+ <rect y='3.42' width='40' height='1.37'/>
21
+ </g>
22
+ </g>
23
+ </svg>
24
+ </div>
25
+ )
26
+
27
+ const Right: SFC<{color: string}> = (props) =>
28
+ (<svg x='0px' y='0px' style={{flexShrink: 0, marginLeft: -2}} height='100%' viewBox='0 0 40 100'>
29
+ <g>
30
+ <path fill={props.color} d='M0,100H2.25c11.33,0,20.51-8.33,20.51-18.59V80.08a34.85,34.85,0,0,0,0-60.16V18.59C22.75,8.32,13.57,0,2.25,0H0ZM16.11,45.06A4.94,4.94,0,1,1,11.17,50,4.94,4.94,0,0,1,16.11,45.06Z'/>
31
+ <path fill='#fff' d='M0,4.79H2.25C10.92,4.79,18,11,18,18.59v4.07L20.33,24a30.07,30.07,0,0,1,0,51.9L18,77.34v4.07C18,89,10.92,95.21,2.25,95.21H0v1.37H2.25c9.42,0,17.09-6.81,17.09-15.17V78.12l1.69-1a31.44,31.44,0,0,0,0-54.26l-1.69-1V18.59c0-8.37-7.67-15.17-17.09-15.17H0Z'/>
32
+ </g>
33
+ </svg>)
34
+
35
+ const Framed: SFC<StyleProps> = (props) => (
36
+ props.type === 'l'
37
+ ? <Left color={props.color || 'rgba(0,0,0,0)'} />
38
+ : props.type === 'c'
39
+ ? <Center color={props.color || 'rgba(0,0,0,0)'} />
40
+ : <Right color={props.color || 'rgba(0,0,0,0)'} />
41
+ )
42
+
43
+ const getPadding = (fontSize: number) => {
44
+ let height = (fontSize * 2) / 100
45
+ return `0 ${height * (40 / 100)}em 0 ${height * (40 / 100)}em`
46
+ }
47
+
48
+ export const FramedStyle: TitleStyle = {
49
+ component: Framed,
50
+ getPadding,
51
+ heightOffset: 2
52
+ }
@@ -0,0 +1,47 @@
1
+ import React, { SFC } from 'react'
2
+ import { TitleStyle, StyleProps } from './'
3
+
4
+ const Left: SFC<{color: string}> = (props) =>
5
+ (<svg x='0px' y='0px' style={{flexShrink: 0}} height='100%' viewBox='0 0 100 79.5'>
6
+ <g>
7
+ <polygon fill='#666665' points='14.7,17.5 14.4,17.1 0,17.1 0.3,17.5 16.8,39.4 0.3,61.4 14.7,61.4 31.2,39.4 '/>
8
+ <path fill={props.color} d='M100,0h-4.3C73.8,0,55.9,17.9,55.9,39.8v0c0,21.9,17.9,39.8,39.8,39.8h4.3V0z'/>
9
+ </g>
10
+ </svg>)
11
+
12
+ const Center: SFC<{color: string}> = (props) => (
13
+ <div style={{position: 'absolute', left: -1, right: 0, top: 0, bottom: 0}}>
14
+ <svg x='0px' y='0px' style={{position: 'absolute'}} width='100%' height='100%'
15
+ viewBox='0 0 100 79.5' preserveAspectRatio='none'>
16
+ <g>
17
+ <rect fill={props.color} width='100' height='79.5' />
18
+ </g>
19
+ </svg>
20
+ </div>
21
+ )
22
+
23
+ const Right: SFC<{color: string}> = (props) =>
24
+ (<svg x='0px' y='0px' style={{flexShrink: 0, marginLeft: -2}} height='100%' viewBox='0 0 44.1 79.5'>
25
+ <g>
26
+ <path fill={props.color} d='M0,79.5h4.3c21.9,0,39.8-17.9,39.8-39.8v0C44.1,17.9,26.2,0,4.3,0H0V79.5z'/>
27
+ </g>
28
+ </svg>)
29
+
30
+ const Modern: SFC<StyleProps> = (props) => (
31
+ props.type === 'l'
32
+ ? <Left color={props.color || 'rgba(0,0,0,0)'} />
33
+ : props.type === 'c'
34
+ ? <Center color={props.color || 'rgba(0,0,0,0)'} />
35
+ : <Right color={props.color || 'rgba(0,0,0,0)'} />
36
+ )
37
+
38
+ const getPadding = (fontSize: number) => {
39
+ let height = (fontSize * 2) / 100
40
+ return `0 ${height * (44.1 / 79.5)}em 0 ${height * (100 / 79.5)}em`
41
+ }
42
+
43
+ export const ModernStyle: TitleStyle = {
44
+ component: Modern,
45
+ getPadding,
46
+ heightOffset: 2
47
+ }
@@ -0,0 +1,13 @@
1
+ export type StyleProps = {
2
+ color?: string
3
+ type: 'l' | 'c' | 'r'
4
+ }
5
+
6
+ export type TitleStyle = {
7
+ component: React.StatelessComponent<StyleProps> | null
8
+ getPadding: ((height: number) => string)
9
+ heightOffset: number
10
+ }
11
+
12
+ export { ModernStyle } from './Modern'
13
+ export { FramedStyle } from './Framed'
@@ -0,0 +1,2 @@
1
+ export { default as OptionItem } from './OptionItem'
2
+ export { default as Title } from './Title'