@vixoniccom/menu-daily 0.1.2-dev.1 → 0.2.0-dev.1
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.
- package/.claude/settings.local.json +31 -0
- package/.github/workflows/npm-publish.yml +103 -0
- package/.github/workflows/sonarqube.yml +30 -0
- package/.vscode/settings.json +3 -0
- package/CHANGELOG.md +21 -0
- package/build/index.html +1 -0
- package/build/main.js +2 -0
- package/build/main.js.LICENSE.txt +39 -0
- package/build/test/downloads/1234.ttf +0 -0
- package/build/test/downloads/background.jpg +0 -0
- package/build/test/downloads/futura-font.ttf +0 -0
- package/build/test/parameters.json +38 -0
- package/build/test/services.json +871 -0
- package/build.zip +0 -0
- package/configuration/appearanceGroup/AppearanceInputs.ts +94 -0
- package/configuration/appearanceGroup/index.ts +8 -0
- package/configuration/dataGroup/DataInputs.ts +21 -0
- package/configuration/dataGroup/index.ts +8 -0
- package/configuration/index.ts +7 -0
- package/configuration.json +43 -78
- package/package.json +13 -12
- package/sonar-project.properties +1 -0
- package/src/global.d.ts +15 -51
- package/src/index.html +33 -33
- package/src/logger.ts +2 -2
- package/src/main.ts +8 -13
- package/src/parameters.d.ts +31 -0
- package/src/scenes/App.tsx +25 -38
- package/src/scenes/components/FontLoader.tsx +3 -16
- package/src/scenes/components/FormattedText.tsx +3 -4
- package/src/scenes/components/Grid/Grid.tsx +8 -8
- package/src/scenes/components/Grid/GridItem.tsx +1 -0
- package/src/scenes/components/Grid/animation.ts +69 -55
- package/src/scenes/components/MealContainer/components/OptionItem.tsx +1 -2
- package/src/scenes/components/MealContainer/components/Title/index.tsx +17 -20
- package/src/scenes/components/MealContainer/components/Title/styles/Framed.tsx +19 -28
- package/src/scenes/components/MealContainer/components/Title/styles/Modern.tsx +15 -24
- package/src/scenes/components/MealContainer/components/Title/styles/index.tsx +25 -1
- package/src/scenes/components/MealContainer/index.tsx +31 -31
- package/src/test/parameters.json +7 -5
- package/src/test/services.json +871 -0
- package/tsconfig.json +9 -17
- package/src/dataLoader.ts +0 -169
package/src/scenes/App.tsx
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
|
|
3
|
-
import { DataLoader } from '../dataLoader'
|
|
4
2
|
import Grid from './components/Grid'
|
|
5
3
|
import MealContainer from './components/MealContainer'
|
|
6
4
|
import FontLoader, { fontParser } from './components/FontLoader'
|
|
@@ -11,48 +9,38 @@ export type AppProps = {
|
|
|
11
9
|
vixonicData: VixonicData
|
|
12
10
|
}
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
updateTime?: number
|
|
12
|
+
type TodayMenu = {
|
|
13
|
+
status: 'loading' | 'ready'
|
|
17
14
|
data?: Menu
|
|
15
|
+
error?: string
|
|
18
16
|
}
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const resolveTodayMenu = (vixonicData: VixonicData): TodayMenu => {
|
|
19
|
+
const { parameters, services } = vixonicData
|
|
20
|
+
const serviceId = parameters.menuService?.id
|
|
21
|
+
const serviceData = serviceId ? (services?.[serviceId]?.data as MenuAppServiceData | undefined) : undefined
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
let { parameters } = props.vixonicData
|
|
26
|
-
this.state = {
|
|
27
|
-
loading: true
|
|
28
|
-
}
|
|
29
|
-
this.dataLoader = new DataLoader(parameters.url, parameters.pollingInterval)
|
|
30
|
-
}
|
|
23
|
+
if (!serviceData) return { status: 'loading' }
|
|
24
|
+
if (serviceData.errors) return { status: 'ready', error: serviceData.errors }
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const today = new Date()
|
|
36
|
-
today.setHours(0,0,0,0)
|
|
37
|
-
const menu = mealType && data[mealType.toUpperCase()] || data[Object.keys(data)[0]]
|
|
38
|
-
this.setState({loading: false, data: menu[today.getTime()]})
|
|
39
|
-
}
|
|
26
|
+
const menus = serviceData.menus || {}
|
|
27
|
+
const sheet = (parameters.mealType && menus[parameters.mealType.toUpperCase()]) || menus[Object.keys(menus)[0]]
|
|
28
|
+
if (!sheet) return { status: 'ready' }
|
|
40
29
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (this.props.vixonicData.parameters.url !== nextProps.vixonicData.parameters.url) {
|
|
48
|
-
let { parameters } = nextProps.vixonicData
|
|
49
|
-
parameters.url && this.dataLoader.setup(parameters.url, parameters.pollingInterval)
|
|
50
|
-
}
|
|
51
|
-
}
|
|
30
|
+
const now = new Date()
|
|
31
|
+
const todayKey = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate())
|
|
32
|
+
const day = sheet.find((d) => d.date === todayKey)
|
|
33
|
+
const meals = day?.meals.filter((meal) => meal.options.length > 0)
|
|
34
|
+
return { status: 'ready', data: meals }
|
|
35
|
+
}
|
|
52
36
|
|
|
37
|
+
class App extends React.Component<AppProps> {
|
|
53
38
|
render () {
|
|
54
39
|
const { parameters, downloadsPath } = this.props.vixonicData
|
|
55
40
|
let cycle = parameters.animationDuration && parameters.animationDuration * 1000 || 15000
|
|
41
|
+
const { status, data, error } = resolveTodayMenu(this.props.vixonicData)
|
|
42
|
+
const placeholder = error || (status === 'loading' ? 'Cargando...' : parameters.msj0 || 'No hay menu.')
|
|
43
|
+
|
|
56
44
|
return <div style={{
|
|
57
45
|
position: 'absolute',
|
|
58
46
|
top: 0, right: 0, bottom: 0, left: 0,
|
|
@@ -62,11 +50,10 @@ class App extends React.Component<AppProps, AppState> {
|
|
|
62
50
|
padding: parameters.containerGridMargins
|
|
63
51
|
}}>
|
|
64
52
|
{
|
|
65
|
-
|
|
53
|
+
!data?.[0] ?
|
|
66
54
|
<div style={{width: '100%', height: '100%', display: 'flex', fontSize: `${100 / (parameters.itemGridRows || 1)}vmin`, justifyContent: 'center', alignItems: 'center'}}>
|
|
67
55
|
<FormattedText
|
|
68
|
-
text={
|
|
69
|
-
downloadsPath={downloadsPath}
|
|
56
|
+
text={placeholder}
|
|
70
57
|
defaults={{
|
|
71
58
|
alignment: 'center',
|
|
72
59
|
fontColor: 'black',
|
|
@@ -80,7 +67,7 @@ class App extends React.Component<AppProps, AppState> {
|
|
|
80
67
|
id='container'
|
|
81
68
|
animate={this.props.start}
|
|
82
69
|
style={{width: '100%', height: '100%'}}
|
|
83
|
-
items={
|
|
70
|
+
items={data.map((meal) => (<MealContainer key={meal.type} data={meal} interval={cycle} vixonicData={this.props.vixonicData} />))}
|
|
84
71
|
animation={{
|
|
85
72
|
mode: parameters.animationMode || 'fade',
|
|
86
73
|
duration: cycle
|
|
@@ -15,7 +15,7 @@ class FontLoader extends React.Component<Props> {
|
|
|
15
15
|
src: url("${parseFontUrl(this.props.downloadPath, font)}");
|
|
16
16
|
}
|
|
17
17
|
`
|
|
18
|
-
} catch
|
|
18
|
+
} catch {
|
|
19
19
|
return ''
|
|
20
20
|
}
|
|
21
21
|
})
|
|
@@ -24,21 +24,8 @@ class FontLoader extends React.Component<Props> {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export function fontParser (parameters: VixonicParameters): string[] {
|
|
27
|
-
|
|
28
|
-
return
|
|
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
|
-
)
|
|
27
|
+
const keys = ['itemTitleTextFormat', 'itemOptionsTextFormat'] as const
|
|
28
|
+
return keys.map(key => parameters[key]?.font?.filename).filter((filename): filename is string => !!filename)
|
|
42
29
|
}
|
|
43
30
|
|
|
44
31
|
export const parseFontName = (filename: string): string => {
|
|
@@ -9,7 +9,6 @@ const alignments = {
|
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
11
11
|
text: string
|
|
12
|
-
downloadsPath: string
|
|
13
12
|
unit: 'px' | '%' | 'em' | 'vh'
|
|
14
13
|
defaults: {
|
|
15
14
|
fontSize: number,
|
|
@@ -28,15 +27,15 @@ class FormattedText extends React.Component<Props> {
|
|
|
28
27
|
let { alignment, font, fontColor, fontSize } = format
|
|
29
28
|
let containerStyle = Object.assign({
|
|
30
29
|
display: 'inline-flex',
|
|
31
|
-
justifyContent: this.getHorizontalAlignment(alignment
|
|
30
|
+
justifyContent: this.getHorizontalAlignment(alignment?.horizontal || defaults.alignment)
|
|
32
31
|
}, this.props.style)
|
|
33
32
|
return <div style={containerStyle}>
|
|
34
33
|
<span style={{
|
|
35
34
|
color: fontColor || defaults.fontColor,
|
|
36
35
|
width: '100%',
|
|
37
|
-
fontFamily: font
|
|
36
|
+
fontFamily: font?.filename && `"${parseFontName(font.filename)}"` || undefined,
|
|
38
37
|
fontSize: `${fontSize || defaults.fontSize}${this.props.unit}`,
|
|
39
|
-
textAlign: alignment
|
|
38
|
+
textAlign: alignment?.horizontal || defaults.alignment,
|
|
40
39
|
lineHeight: this.props.lineHeight,
|
|
41
40
|
overflow: 'hidden',
|
|
42
41
|
textOverflow: 'ellipsis',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import
|
|
2
|
+
import { AnimationController } from './animation'
|
|
3
3
|
import Item from './GridItem'
|
|
4
4
|
|
|
5
5
|
type GridProps = {
|
|
@@ -35,6 +35,7 @@ type GridState = {
|
|
|
35
35
|
|
|
36
36
|
class Grid extends React.Component<GridProps, GridState> {
|
|
37
37
|
lastIndex: number
|
|
38
|
+
itemKeyCounter: number = 0
|
|
38
39
|
animation: any
|
|
39
40
|
animating: boolean = false
|
|
40
41
|
unmounting: boolean = false
|
|
@@ -56,17 +57,13 @@ class Grid extends React.Component<GridProps, GridState> {
|
|
|
56
57
|
constructor (props: GridProps) {
|
|
57
58
|
super (props)
|
|
58
59
|
this.lastIndex = 0
|
|
59
|
-
this.animation = new
|
|
60
|
+
this.animation = new AnimationController()
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
componentDidMount () {
|
|
63
64
|
this.configure(this.props)
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
componentWillReceiveProps (nextProps: GridProps) {
|
|
67
|
-
this.configure(nextProps)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
67
|
componentWillUnmount () {
|
|
71
68
|
this.unmounting = true
|
|
72
69
|
}
|
|
@@ -96,7 +93,7 @@ class Grid extends React.Component<GridProps, GridState> {
|
|
|
96
93
|
this.lastIndex++
|
|
97
94
|
count++
|
|
98
95
|
return <Item
|
|
99
|
-
key={
|
|
96
|
+
key={`item-${++this.itemKeyCounter}`} containerData={{
|
|
100
97
|
ic_index: index,
|
|
101
98
|
ic_rowIndex: Math.floor(index / this.columns),
|
|
102
99
|
ic_columnIndex: Math.floor(index % this.columns),
|
|
@@ -145,7 +142,10 @@ class Grid extends React.Component<GridProps, GridState> {
|
|
|
145
142
|
</div>
|
|
146
143
|
}
|
|
147
144
|
|
|
148
|
-
componentDidUpdate () {
|
|
145
|
+
componentDidUpdate (prevProps: GridProps) {
|
|
146
|
+
if (prevProps !== this.props) {
|
|
147
|
+
this.configure(this.props)
|
|
148
|
+
}
|
|
149
149
|
if (this.props.animate && this.state.stage === 'prepared') {
|
|
150
150
|
// Start animations.
|
|
151
151
|
this.animation.animate(this.container!.childNodes, () => {
|
|
@@ -1,104 +1,118 @@
|
|
|
1
|
-
|
|
1
|
+
import anime from 'animejs'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
interface Options {
|
|
4
|
+
mode: keyof typeof animationModes
|
|
5
|
+
duration: number
|
|
6
|
+
speed: number
|
|
7
|
+
stagger: number
|
|
8
|
+
reverse: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const animationModes = {
|
|
5
12
|
fade: {
|
|
6
13
|
in: {
|
|
7
14
|
opacity: [0, 1],
|
|
8
|
-
easing: 'linear'
|
|
15
|
+
easing: 'linear',
|
|
9
16
|
},
|
|
10
17
|
out: {
|
|
11
18
|
opacity: [1, 0],
|
|
12
|
-
easing: 'linear'
|
|
19
|
+
easing: 'linear',
|
|
13
20
|
},
|
|
14
21
|
init: {
|
|
15
|
-
opacity: 0
|
|
16
|
-
}
|
|
22
|
+
opacity: 0,
|
|
23
|
+
},
|
|
17
24
|
},
|
|
18
25
|
slideRight: {
|
|
19
26
|
in: {
|
|
20
|
-
translateX: (
|
|
27
|
+
translateX: () => {
|
|
21
28
|
return [`-100vw`, '0vw']
|
|
22
29
|
},
|
|
23
|
-
easing: 'easeOutQuad'
|
|
30
|
+
easing: 'easeOutQuad',
|
|
24
31
|
},
|
|
25
32
|
out: {
|
|
26
|
-
translateX: (
|
|
33
|
+
translateX: () => {
|
|
27
34
|
return ['0vw', `100vw`]
|
|
28
35
|
},
|
|
29
|
-
easing: 'easeInQuad'
|
|
36
|
+
easing: 'easeInQuad',
|
|
30
37
|
},
|
|
31
38
|
init: {
|
|
32
|
-
transform: '
|
|
33
|
-
}
|
|
39
|
+
transform: 'translateX(-100vw)',
|
|
40
|
+
},
|
|
34
41
|
},
|
|
35
42
|
slideLeft: {
|
|
36
43
|
in: {
|
|
37
|
-
translateX: (
|
|
44
|
+
translateX: () => {
|
|
38
45
|
return [`100vw`, '0vw']
|
|
39
46
|
},
|
|
40
|
-
easing: 'easeOutQuad'
|
|
47
|
+
easing: 'easeOutQuad',
|
|
41
48
|
},
|
|
42
49
|
out: {
|
|
43
|
-
translateX: (
|
|
50
|
+
translateX: () => {
|
|
44
51
|
return ['0vw', `-100vw`]
|
|
45
52
|
},
|
|
46
|
-
easing: 'easeInQuad'
|
|
53
|
+
easing: 'easeInQuad',
|
|
47
54
|
},
|
|
48
55
|
init: {
|
|
49
|
-
transform: '
|
|
50
|
-
}
|
|
51
|
-
}
|
|
56
|
+
transform: 'translateX(100vw)',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
52
59
|
}
|
|
53
60
|
|
|
54
|
-
class
|
|
55
|
-
mode: any
|
|
56
|
-
duration: number
|
|
57
|
-
speed: number
|
|
58
|
-
stagger: number
|
|
59
|
-
reverse
|
|
61
|
+
export class AnimationController {
|
|
62
|
+
public mode: any
|
|
63
|
+
public duration: number
|
|
64
|
+
public speed: number
|
|
65
|
+
public stagger: number
|
|
66
|
+
public reverse: boolean
|
|
60
67
|
|
|
61
|
-
|
|
62
|
-
this.mode =
|
|
63
|
-
this.duration =
|
|
64
|
-
this.speed = 1000
|
|
65
|
-
this.stagger =
|
|
66
|
-
this.reverse =
|
|
68
|
+
constructor() {
|
|
69
|
+
this.mode = animationModes.fade
|
|
70
|
+
this.duration = 10000
|
|
71
|
+
this.speed = 1000
|
|
72
|
+
this.stagger = 1000 / 4
|
|
73
|
+
this.reverse = false
|
|
67
74
|
}
|
|
68
75
|
|
|
69
|
-
|
|
76
|
+
configure(options: Partial<Options>) {
|
|
77
|
+
this.mode =
|
|
78
|
+
options.mode && animationModes.hasOwnProperty(options.mode) ? animationModes[options.mode] : animationModes.fade
|
|
79
|
+
this.duration = options.duration ?? 10000
|
|
80
|
+
this.speed = 1000 * (options.speed ?? 1)
|
|
81
|
+
this.stagger = this.speed / (options.stagger ?? 4)
|
|
82
|
+
this.reverse = options.reverse ?? false
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
getInitialStyle() {
|
|
70
86
|
return this.mode.init
|
|
71
87
|
}
|
|
72
88
|
|
|
73
|
-
animate
|
|
74
|
-
let
|
|
75
|
-
let els = [].slice.call(listNodes, 0)
|
|
89
|
+
animate(listNodes: any, finished: any) {
|
|
90
|
+
let els = Array.prototype.slice.call(listNodes, 0)
|
|
76
91
|
if (this.reverse) els = els.reverse()
|
|
77
92
|
if (!els || els.length < 1) return
|
|
78
|
-
let offset = this.duration - ((
|
|
79
|
-
offset = offset
|
|
93
|
+
let offset = this.duration - ((els.length - 1) * this.stagger + this.speed) * 2
|
|
94
|
+
offset = Math.max(offset, 0)
|
|
80
95
|
let animation = anime.timeline({
|
|
81
|
-
autoplay: false
|
|
96
|
+
autoplay: false,
|
|
82
97
|
})
|
|
83
|
-
animation.add(
|
|
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({
|
|
98
|
+
animation.add({
|
|
91
99
|
targets: els,
|
|
92
100
|
duration: this.speed,
|
|
93
|
-
delay:
|
|
94
|
-
|
|
101
|
+
delay: (_el: any, i: any) => i * this.stagger,
|
|
102
|
+
...this.mode.in,
|
|
103
|
+
})
|
|
104
|
+
animation.add(
|
|
105
|
+
{
|
|
106
|
+
targets: els,
|
|
107
|
+
duration: this.speed,
|
|
108
|
+
delay: (_el: any, i: any) => i * this.stagger,
|
|
109
|
+
complete: () => {
|
|
110
|
+
finished()
|
|
111
|
+
},
|
|
112
|
+
...this.mode.out,
|
|
95
113
|
},
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
}, this.mode.out), `+=${offset}`)
|
|
114
|
+
`+=${offset}`
|
|
115
|
+
)
|
|
100
116
|
animation.play()
|
|
101
117
|
}
|
|
102
118
|
}
|
|
103
|
-
|
|
104
|
-
export default Animation
|
|
@@ -8,10 +8,9 @@ type Props = {
|
|
|
8
8
|
|
|
9
9
|
export default class OptionItem extends React.Component<Props> {
|
|
10
10
|
render () {
|
|
11
|
-
|
|
11
|
+
const { vixonicData } = this.props
|
|
12
12
|
return <FormattedText
|
|
13
13
|
text={this.props.data}
|
|
14
|
-
downloadsPath={vixonicData.downloadsPath}
|
|
15
14
|
defaults={{
|
|
16
15
|
fontSize: 10,
|
|
17
16
|
alignment: 'left',
|
|
@@ -8,7 +8,7 @@ type Props = {
|
|
|
8
8
|
getPadding: (padding: string) => void
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
const TitleStyles: {[name: string]: TitleStyle} = {
|
|
11
|
+
const TitleStyles: { [name: string]: TitleStyle } = {
|
|
12
12
|
standard: {
|
|
13
13
|
component: null,
|
|
14
14
|
getPadding: () => ('0'),
|
|
@@ -23,38 +23,35 @@ const defaultFontSize = 20
|
|
|
23
23
|
class Title extends React.Component<Props> {
|
|
24
24
|
style: TitleStyle
|
|
25
25
|
|
|
26
|
-
constructor
|
|
26
|
+
constructor(props: Props) {
|
|
27
27
|
super(props)
|
|
28
28
|
this.style = TitleStyles.standard
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
componentDidMount
|
|
31
|
+
componentDidMount() {
|
|
32
32
|
this.setup(this.props)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
setup
|
|
36
|
-
|
|
35
|
+
setup(props: Props) {
|
|
36
|
+
const { parameters } = props.vixonicData
|
|
37
37
|
if (parameters.itemStyle && TitleStyles[parameters.itemStyle]) {
|
|
38
38
|
this.style = TitleStyles[parameters.itemStyle]
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
const fontSize = parameters.itemTitleTextFormat?.fontSize
|
|
41
41
|
props.getPadding(this.style.getPadding(fontSize || defaultFontSize))
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
render
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
{this.style.component && <this.style.component type='l' color={backgroundColor}/>}
|
|
54
|
-
<div style={{flex: 1, display: 'flex', alignItems: 'center', position: 'relative', width: '100%'}}>
|
|
44
|
+
render() {
|
|
45
|
+
const { text } = this.props
|
|
46
|
+
const { parameters } = this.props.vixonicData
|
|
47
|
+
const backgroundColor = parameters.itemTitleBackgroundColor
|
|
48
|
+
const fontSize = parameters.itemTitleTextFormat?.fontSize && (parameters.itemTitleTextFormat.fontSize / 100)
|
|
49
|
+
|| defaultFontSize / 100
|
|
50
|
+
return <div style={{ display: 'flex', height: `${fontSize * (this.style.heightOffset || 1)}em` }}>
|
|
51
|
+
{this.style.component && <this.style.component type='l' color={backgroundColor} />}
|
|
52
|
+
<div style={{ flex: 1, display: 'flex', alignItems: 'center', position: 'relative', width: '100%' }}>
|
|
55
53
|
<FormattedText
|
|
56
54
|
text={text}
|
|
57
|
-
downloadsPath={downloadsPath}
|
|
58
55
|
defaults={{
|
|
59
56
|
fontSize: defaultFontSize,
|
|
60
57
|
alignment: 'left',
|
|
@@ -72,9 +69,9 @@ class Title extends React.Component<Props> {
|
|
|
72
69
|
height: '100%',
|
|
73
70
|
alignItems: 'center'
|
|
74
71
|
}} />
|
|
75
|
-
{this.style.component && <this.style.component type='c' color={backgroundColor}/>}
|
|
72
|
+
{this.style.component && <this.style.component type='c' color={backgroundColor} />}
|
|
76
73
|
</div>
|
|
77
|
-
{this.style.component && <this.style.component type='r' color={backgroundColor}/>}
|
|
74
|
+
{this.style.component && <this.style.component type='r' color={backgroundColor} />}
|
|
78
75
|
</div>
|
|
79
76
|
}
|
|
80
77
|
}
|
|
@@ -1,49 +1,40 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { TitleStyle,
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { TitleStyle, SideProps, createStyleComponent, createGetPadding } from './'
|
|
3
3
|
|
|
4
|
-
const Left:
|
|
5
|
-
(<svg x='0px' y='0px' style={{flexShrink: 0}} height='100%' viewBox='0 0 40 100'>
|
|
4
|
+
const Left: React.FunctionComponent<SideProps> = (props) =>
|
|
5
|
+
(<svg x='0px' y='0px' style={{ flexShrink: 0 }} height='100%' viewBox='0 0 40 100'>
|
|
6
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'/>
|
|
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
9
|
</g>
|
|
10
10
|
</svg>)
|
|
11
11
|
|
|
12
|
-
const Center:
|
|
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
|
-
|
|
12
|
+
const Center: React.FunctionComponent<SideProps> = (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
16
|
<g>
|
|
17
|
-
<rect fill={props.color} width='40' height='100'/>
|
|
17
|
+
<rect fill={props.color} width='40' height='100' />
|
|
18
18
|
<g fill='#fff'>
|
|
19
|
-
<rect y='95.21' width='40' height='1.37'/>
|
|
20
|
-
<rect y='3.42' width='40' height='1.37'/>
|
|
19
|
+
<rect y='95.21' width='40' height='1.37' />
|
|
20
|
+
<rect y='3.42' width='40' height='1.37' />
|
|
21
21
|
</g>
|
|
22
22
|
</g>
|
|
23
23
|
</svg>
|
|
24
24
|
</div>
|
|
25
25
|
)
|
|
26
26
|
|
|
27
|
-
const Right:
|
|
28
|
-
(<svg x='0px' y='0px' style={{flexShrink: 0, marginLeft: -2}} height='100%' viewBox='0 0 40 100'>
|
|
27
|
+
const Right: React.FunctionComponent<SideProps> = (props) =>
|
|
28
|
+
(<svg x='0px' y='0px' style={{ flexShrink: 0, marginLeft: -2 }} height='100%' viewBox='0 0 40 100'>
|
|
29
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'/>
|
|
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
32
|
</g>
|
|
33
33
|
</svg>)
|
|
34
34
|
|
|
35
|
-
const Framed
|
|
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
|
-
)
|
|
35
|
+
const Framed = createStyleComponent(Left, Center, Right)
|
|
42
36
|
|
|
43
|
-
const getPadding = (
|
|
44
|
-
let height = (fontSize * 2) / 100
|
|
45
|
-
return `0 ${height * (40 / 100)}em 0 ${height * (40 / 100)}em`
|
|
46
|
-
}
|
|
37
|
+
const getPadding = createGetPadding(40 / 100, 40 / 100)
|
|
47
38
|
|
|
48
39
|
export const FramedStyle: TitleStyle = {
|
|
49
40
|
component: Framed,
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { TitleStyle,
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { TitleStyle, SideProps, createStyleComponent, createGetPadding } from './'
|
|
3
3
|
|
|
4
|
-
const Left:
|
|
5
|
-
(<svg x='0px' y='0px' style={{flexShrink: 0}} height='100%' viewBox='0 0 100 79.5'>
|
|
4
|
+
const Left: React.FunctionComponent<SideProps> = (props) =>
|
|
5
|
+
(<svg x='0px' y='0px' style={{ flexShrink: 0 }} height='100%' viewBox='0 0 100 79.5'>
|
|
6
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'/>
|
|
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
9
|
</g>
|
|
10
10
|
</svg>)
|
|
11
11
|
|
|
12
|
-
const Center:
|
|
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
|
-
|
|
12
|
+
const Center: React.FunctionComponent<SideProps> = (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
16
|
<g>
|
|
17
17
|
<rect fill={props.color} width='100' height='79.5' />
|
|
18
18
|
</g>
|
|
@@ -20,25 +20,16 @@ const Center: SFC<{color: string}> = (props) => (
|
|
|
20
20
|
</div>
|
|
21
21
|
)
|
|
22
22
|
|
|
23
|
-
const Right:
|
|
24
|
-
(<svg x='0px' y='0px' style={{flexShrink: 0, marginLeft: -2}} height='100%' viewBox='0 0 44.1 79.5'>
|
|
23
|
+
const Right: React.FunctionComponent<SideProps> = (props) =>
|
|
24
|
+
(<svg x='0px' y='0px' style={{ flexShrink: 0, marginLeft: -2 }} height='100%' viewBox='0 0 44.1 79.5'>
|
|
25
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'/>
|
|
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
27
|
</g>
|
|
28
28
|
</svg>)
|
|
29
29
|
|
|
30
|
-
const Modern
|
|
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
|
-
)
|
|
30
|
+
const Modern = createStyleComponent(Left, Center, Right)
|
|
37
31
|
|
|
38
|
-
const getPadding = (
|
|
39
|
-
let height = (fontSize * 2) / 100
|
|
40
|
-
return `0 ${height * (44.1 / 79.5)}em 0 ${height * (100 / 79.5)}em`
|
|
41
|
-
}
|
|
32
|
+
const getPadding = createGetPadding(100 / 79.5, 44.1 / 79.5)
|
|
42
33
|
|
|
43
34
|
export const ModernStyle: TitleStyle = {
|
|
44
35
|
component: Modern,
|
|
@@ -1,13 +1,37 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
1
3
|
export type StyleProps = {
|
|
2
4
|
color?: string
|
|
3
5
|
type: 'l' | 'c' | 'r'
|
|
4
6
|
}
|
|
5
7
|
|
|
8
|
+
export type SideProps = { color: string }
|
|
9
|
+
|
|
6
10
|
export type TitleStyle = {
|
|
7
|
-
component: React.
|
|
11
|
+
component: React.FunctionComponent<StyleProps> | null
|
|
8
12
|
getPadding: ((height: number) => string)
|
|
9
13
|
heightOffset: number
|
|
10
14
|
}
|
|
11
15
|
|
|
16
|
+
export function createGetPadding(leftRatio: number, rightRatio: number): (fontSize: number) => string {
|
|
17
|
+
return (fontSize) => {
|
|
18
|
+
const height = (fontSize * 2) / 100
|
|
19
|
+
return `0 ${height * rightRatio}em 0 ${height * leftRatio}em`
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function createStyleComponent(
|
|
24
|
+
Left: React.FunctionComponent<SideProps>,
|
|
25
|
+
Center: React.FunctionComponent<SideProps>,
|
|
26
|
+
Right: React.FunctionComponent<SideProps>
|
|
27
|
+
): React.FunctionComponent<StyleProps> {
|
|
28
|
+
return (props) => {
|
|
29
|
+
const color = props.color || 'rgba(0,0,0,0)'
|
|
30
|
+
if (props.type === 'l') return <Left color={color} />
|
|
31
|
+
if (props.type === 'c') return <Center color={color} />
|
|
32
|
+
return <Right color={color} />
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
12
36
|
export { ModernStyle } from './Modern'
|
|
13
37
|
export { FramedStyle } from './Framed'
|