UNPKG

3.66 kBJavaScriptView Raw
1/** @jsx h */
2import { h } from 'preact'
3import { connect } from 'redux-bundler-preact'
4import getComponent from '../utils/get-component'
5import { Crate } from './crate'
6const Wrapper = getComponent('relative border-box')
7
8const defaultMargin = 2
9const defaultWidth = 18
10const defaultHeight = 18
11
12const toPixels = amount => amount * 16
13
14const getStylesForIndex = (
15 numColumns,
16 index,
17 width = defaultWidth,
18 height = defaultHeight,
19 margin = defaultMargin
20) => {
21 const column = index % numColumns
22 const row = Math.floor(index / numColumns)
23 const isSingle = numColumns === 1
24 const totalHeight = height + margin
25 const totalWidth = width + margin
26 return {
27 position: 'absolute',
28 top: 0,
29 left: 0,
30 width: isSingle ? '100%' : `${width}rem`,
31 height: `${height}rem`,
32 transform: `translate(${column * totalWidth}rem, ${row * totalHeight}rem)`
33 }
34}
35
36const getContainerStyles = (
37 numColumns,
38 numItems,
39 width = defaultWidth,
40 height = defaultHeight,
41 margin = defaultMargin
42) => {
43 const singleColumn = numColumns === 1
44 return {
45 width: singleColumn
46 ? '100%'
47 : `${numColumns * (width + margin) - margin}rem`,
48 height: `${Math.ceil(numItems / numColumns) * (width + margin) - margin}rem`
49 }
50}
51
52const getTotalWidth = (count, widthInPixels, marginInPixels) =>
53 widthInPixels * count + marginInPixels * (count - 1)
54
55const getColumnInfo = (
56 viewportWidth,
57 widthToIgnore = 0,
58 width = defaultWidth,
59 margin = defaultMargin,
60 maxColumns = 3
61) => {
62 const marginInPixels = toPixels(margin)
63 const widthInPixels = toPixels(width)
64 const totalPixelWidthToIgnore = marginInPixels * 2 + toPixels(widthToIgnore)
65 const maxAvailableWidth = viewportWidth - totalPixelWidthToIgnore
66
67 let count = 1
68 let numColumns = count
69
70 while (count <= maxColumns) {
71 const totalWidth = getTotalWidth(count, widthInPixels, marginInPixels)
72 if (totalWidth > maxAvailableWidth) {
73 break
74 } else {
75 numColumns = count
76 }
77 count++
78 }
79
80 return {
81 numColumns,
82 internalContainerWidth: getTotalWidth(
83 numColumns,
84 widthInPixels,
85 marginInPixels
86 )
87 }
88}
89
90export default connect('selectViewportWidth', props => {
91 const {
92 children,
93 className,
94 height,
95 introComponent,
96 margin,
97 viewportWidth,
98 width,
99 widthToIgnore
100 } = props
101
102 const { numColumns, internalContainerWidth } = getColumnInfo(
103 viewportWidth,
104 widthToIgnore,
105 width,
106 height,
107 margin
108 )
109
110 const externalContainerWidth =
111 internalContainerWidth + toPixels((margin || defaultMargin) * 2)
112
113 const newChildren = children.map((comp, index) => (
114 <Crate
115 className='tr-tr'
116 style={getStylesForIndex(numColumns, index, width, height, margin)}
117 >
118 {comp}
119 </Crate>
120 ))
121
122 const newProps = Object.assign({}, props, {
123 introComponent: null,
124 children: null,
125 width: null,
126 height: null,
127 margin: null,
128 viewportWidth: null,
129 numColumns: null,
130 widthToIgnore: null,
131 className: null
132 })
133
134 const containerStyles = getContainerStyles(
135 numColumns,
136 newChildren.length,
137 width,
138 height,
139 margin
140 )
141
142 const isSingle = numColumns === 1
143
144 const outsideMargin = toPixels(margin || defaultMargin)
145
146 return (
147 <div
148 style={{
149 padding: outsideMargin + 'px',
150 width: isSingle ? '100%' : externalContainerWidth + 'px'
151 }}
152 className={`center ${className || ''}`}
153 >
154 {introComponent}
155 <Wrapper
156 {...newProps}
157 style={{ width: containerStyles.width, height: containerStyles.height }}
158 >
159 {newChildren}
160 </Wrapper>
161 </div>
162 )
163})