@startlibs/utils 1.0.3 → 1.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.
- package/lib/ActionUtils.mjs +117 -0
- package/lib/ActionUtils.mjs.map +1 -0
- package/lib/FetchUtils.mjs +100 -0
- package/lib/FetchUtils.mjs.map +1 -0
- package/lib/createPressEvent.mjs +74 -0
- package/lib/createPressEvent.mjs.map +1 -0
- package/lib/fixMediaQuery.mjs +64 -0
- package/lib/fixMediaQuery.mjs.map +1 -0
- package/lib/formatDate.mjs +110 -0
- package/lib/formatDate.mjs.map +1 -0
- package/lib/formatUtils.mjs +64 -0
- package/lib/formatUtils.mjs.map +1 -0
- package/lib/getClosestOffsetScroll.mjs +15 -0
- package/lib/getClosestOffsetScroll.mjs.map +1 -0
- package/lib/hooks/useEventListener.mjs +27 -0
- package/lib/hooks/useEventListener.mjs.map +1 -0
- package/lib/index.cjs +1811 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.mjs +19 -0
- package/lib/index.mjs.map +1 -0
- package/lib/lodashUtils.mjs +131 -0
- package/lib/lodashUtils.mjs.map +1 -0
- package/lib/promiseUtils.mjs +92 -0
- package/lib/promiseUtils.mjs.map +1 -0
- package/lib/reactUtils.mjs +12 -0
- package/lib/reactUtils.mjs.map +1 -0
- package/lib/reduceUtils.mjs +14 -0
- package/lib/reduceUtils.mjs.map +1 -0
- package/lib/smoothScroll.mjs +59 -0
- package/lib/smoothScroll.mjs.map +1 -0
- package/lib/styled.mjs +234 -0
- package/lib/styled.mjs.map +1 -0
- package/lib/timeUtils.mjs +81 -0
- package/lib/timeUtils.mjs.map +1 -0
- package/lib/timerUtils.mjs +11 -0
- package/lib/timerUtils.mjs.map +1 -0
- package/lib/utils.mjs +386 -0
- package/lib/utils.mjs.map +1 -0
- package/lib/wrapLazy.mjs +132 -0
- package/lib/wrapLazy.mjs.map +1 -0
- package/package.json +44 -30
- package/src/ActionUtils.js +90 -0
- package/src/FetchUtils.js +87 -0
- package/src/createPressEvent.jsx +79 -0
- package/src/fixMediaQuery.js +71 -0
- package/src/formatDate.js +121 -0
- package/src/formatUtils.jsx +63 -0
- package/src/getClosestOffsetScroll.js +12 -0
- package/src/hooks/useEventListener.js +26 -0
- package/src/index.js +19 -0
- package/src/lodashUtils.jsx +110 -0
- package/src/promiseUtils.jsx +75 -0
- package/src/reactUtils.jsx +7 -0
- package/src/reduceUtils.jsx +6 -0
- package/src/smoothScroll.js +58 -0
- package/src/styled.js +177 -0
- package/src/timeUtils.jsx +57 -0
- package/src/timerUtils.jsx +10 -0
- package/src/utils.jsx +342 -0
- package/src/wrapLazy.jsx +122 -0
- package/.babelrc +0 -26
- package/lib/index.js +0 -2382
- package/rollup.config.js +0 -44
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import _ from 'lodash/fp'
|
|
2
|
+
import {callIfFunction} from './utils'
|
|
3
|
+
|
|
4
|
+
const moveElement = _.curry((from, to, list) => {
|
|
5
|
+
const el = list[from]
|
|
6
|
+
const without = _.pullAt(from, list)
|
|
7
|
+
without.splice(to, 0, el)
|
|
8
|
+
return without
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
const unsetOrRemoveAt = _.curry((path, value) => {
|
|
12
|
+
const pathArr = toPath(path)
|
|
13
|
+
const [lastKey] = pathArr.slice(-1)
|
|
14
|
+
return update(pathArr.slice(0, -1), (v) => Array.isArray(v) ? removeAt(lastKey, v) : unset(lastKey, v), value)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const pathToString = (path) => toPath(path).join(".")
|
|
18
|
+
|
|
19
|
+
const sanitizePath = (path) =>
|
|
20
|
+
Array.isArray(path)
|
|
21
|
+
? path.map(sanitizePath)
|
|
22
|
+
: typeof path === 'number'
|
|
23
|
+
? path.toString()
|
|
24
|
+
: path === undefined
|
|
25
|
+
? []
|
|
26
|
+
: path
|
|
27
|
+
|
|
28
|
+
const toPath = (path) => _.toPath(sanitizePath(path))
|
|
29
|
+
|
|
30
|
+
const isEmptyPath = (path) => (path && !path.length)
|
|
31
|
+
|
|
32
|
+
const update = _.curry((path, updater, state) => {
|
|
33
|
+
const sanitizedPath = sanitizePath(path)
|
|
34
|
+
if (isEmptyPath(sanitizedPath)) {
|
|
35
|
+
return updater(state)
|
|
36
|
+
} else {
|
|
37
|
+
return _.update(sanitizedPath, updater, state)
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const get = _.curry((path, state) => {
|
|
42
|
+
const sanitizedPath = sanitizePath(path)
|
|
43
|
+
if (isEmptyPath(sanitizedPath)) {
|
|
44
|
+
return state
|
|
45
|
+
} else {
|
|
46
|
+
return _.get(sanitizedPath, state)
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const set = _.curry((path, value, state) => {
|
|
51
|
+
const sanitizedPath = sanitizePath(path)
|
|
52
|
+
if (isEmptyPath(sanitizedPath)) {
|
|
53
|
+
return value
|
|
54
|
+
} else {
|
|
55
|
+
return _.set(sanitizedPath, value, state)
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
const unset = _.curry((path, state) => {
|
|
59
|
+
const sanitizedPath = sanitizePath(path)
|
|
60
|
+
if (isEmptyPath(sanitizedPath)) {
|
|
61
|
+
return undefined
|
|
62
|
+
} else {
|
|
63
|
+
return _.unset(sanitizedPath, state)
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
const removeNAt = _.curry((pos, n, value) => [...value.slice(0, Number(pos)), ...value.slice(Number(pos)+n)])
|
|
68
|
+
const removeAt = removeNAt(_.__,1)
|
|
69
|
+
|
|
70
|
+
const when = _.curry((cond,fn,value) => callIfFunction(cond,value) ? fn(value) : value)
|
|
71
|
+
const assign = _.curry((a,b) => _.assign(b,a))
|
|
72
|
+
const concat = _.curry((a,b) => _.concat(b,a))
|
|
73
|
+
|
|
74
|
+
const each = _.each.convert({cap:false})
|
|
75
|
+
const find = _.find.convert({cap:false})
|
|
76
|
+
const filter = _.filter.convert({cap:false})
|
|
77
|
+
const map = _.map.convert({cap:false})
|
|
78
|
+
const mapValues = _.mapValues.convert({cap:false})
|
|
79
|
+
const flatMap = _.flatMap.convert({cap:false})
|
|
80
|
+
|
|
81
|
+
const insertAt = _.curry((pos, newElements, value) => [...value.slice(0, pos).concat(newElements), ...value.slice(pos)])
|
|
82
|
+
|
|
83
|
+
const select = _.curry((selector,value) => (_.isFunction(selector) ? selector : (selector ? _.get(selector) : _.identity))(value))
|
|
84
|
+
const itemToggle = _.curry((item,list ) => (list||[]).indexOf(item)>=0 ? _.without([item],list) : [...(list||[]),item])
|
|
85
|
+
|
|
86
|
+
export const _s = {
|
|
87
|
+
moveElement,
|
|
88
|
+
unsetOrRemoveAt,
|
|
89
|
+
pathToString,
|
|
90
|
+
toPath,
|
|
91
|
+
update,
|
|
92
|
+
get,
|
|
93
|
+
set,
|
|
94
|
+
select,
|
|
95
|
+
unset,
|
|
96
|
+
removeNAt,
|
|
97
|
+
removeAt,
|
|
98
|
+
itemToggle,
|
|
99
|
+
when,
|
|
100
|
+
assign,
|
|
101
|
+
concat,
|
|
102
|
+
each,
|
|
103
|
+
find,
|
|
104
|
+
filter,
|
|
105
|
+
map,
|
|
106
|
+
flatMap,
|
|
107
|
+
mapValues,
|
|
108
|
+
insertAt,
|
|
109
|
+
flowEach: (...args) => _.flow(...args.filter(Boolean))
|
|
110
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import _ from "lodash/fp";
|
|
3
|
+
|
|
4
|
+
export const createPromiseResolverPair = () => {
|
|
5
|
+
let res, rej;
|
|
6
|
+
const promise = new Promise((res2,rej2) => {
|
|
7
|
+
res = res2;
|
|
8
|
+
rej = rej2;
|
|
9
|
+
})
|
|
10
|
+
return [promise,[res,rej]]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export const createSimplePromiseLock = () => {
|
|
15
|
+
let promiseQueue = Promise.resolve()
|
|
16
|
+
return () => {
|
|
17
|
+
let resolve = _.identity
|
|
18
|
+
const nextPromise = new Promise(res => {
|
|
19
|
+
resolve = res
|
|
20
|
+
})
|
|
21
|
+
const prevPromise = promiseQueue
|
|
22
|
+
promiseQueue = nextPromise
|
|
23
|
+
return prevPromise.then(() => resolve)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function* createSinglePromiseQueue() {
|
|
27
|
+
let lastPromise = Promise.resolve()
|
|
28
|
+
/* eslint-disable no-await-in-loop */
|
|
29
|
+
while (true) {
|
|
30
|
+
await lastPromise
|
|
31
|
+
let resolve = _.identity
|
|
32
|
+
lastPromise = new Promise(res => {
|
|
33
|
+
resolve = res
|
|
34
|
+
})
|
|
35
|
+
yield resolve
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
export async function* createPromiseQueue(parallel = 1) {
|
|
41
|
+
const queues = _.times(createSinglePromiseQueue, parallel)
|
|
42
|
+
const promises = queues.map(q => q.next())
|
|
43
|
+
const locks = await Promise.all(promises)
|
|
44
|
+
|
|
45
|
+
const getNextAvailableLock = async () => {
|
|
46
|
+
const index = locks.findIndex(Boolean)
|
|
47
|
+
if (index >= 0) {
|
|
48
|
+
const lock = locks[index]
|
|
49
|
+
locks[index] = null
|
|
50
|
+
promises[index] = queues[index].next().then(result => {
|
|
51
|
+
locks[index] = result
|
|
52
|
+
})
|
|
53
|
+
return [lock.value, locks.filter(Boolean).length]
|
|
54
|
+
}
|
|
55
|
+
await Promise.race(promises)
|
|
56
|
+
return getNextAvailableLock()
|
|
57
|
+
}
|
|
58
|
+
while (true) {
|
|
59
|
+
const lock = await getNextAvailableLock()
|
|
60
|
+
yield lock
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const promiseMapReduce = (arr, callback) =>
|
|
65
|
+
arr.reduce((acc, item) => acc.then(seq => callback(item).then(res => [...seq, res])), Promise.resolve([]))
|
|
66
|
+
|
|
67
|
+
export const asyncDebounce = (fn, delay = 200) => {
|
|
68
|
+
let timeout
|
|
69
|
+
return (...args) => {
|
|
70
|
+
clearTimeout(timeout)
|
|
71
|
+
return new Promise(res => {
|
|
72
|
+
timeout = setTimeout(() => res(fn(...args)), delay)
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import _ from 'lodash/fp'
|
|
2
|
+
|
|
3
|
+
export const compareBest = (compare) => (best,next) => best ? (compare(best,next) ? next : best) : next
|
|
4
|
+
|
|
5
|
+
export const toLowest = (getValue = _.identity) => compareBest((best,next) => (getValue(next) < getValue(best)))
|
|
6
|
+
export const toHighest = (getValue = _.identity) => compareBest((best,next) => (getValue(next) > getValue(best)))
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
// Get the top position of an element in the document
|
|
3
|
+
const getTop = function(element, start) {
|
|
4
|
+
// return value of html.getBoundingClientRect().top ... IE : 0, other browsers : -pageYOffset
|
|
5
|
+
if(!element || element.nodeName === 'HTML') return -start
|
|
6
|
+
return element.getBoundingClientRect().top + start
|
|
7
|
+
}
|
|
8
|
+
// ease in out function thanks to:
|
|
9
|
+
// http://blog.greweb.fr/2012/02/bezier-curve-based-easing-functions-from-concept-to-implementation/
|
|
10
|
+
const easeInOutCubic = function (t) { return t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1 }
|
|
11
|
+
|
|
12
|
+
// calculate the scroll position we should be in
|
|
13
|
+
// given the start and end point of the scroll
|
|
14
|
+
// the time elapsed from the beginning of the scroll
|
|
15
|
+
// and the total duration of the scroll (default 500ms)
|
|
16
|
+
const position = function(start, end, elapsed, duration) {
|
|
17
|
+
if (elapsed > duration) return end;
|
|
18
|
+
return start + (end - start) * easeInOutCubic(elapsed / duration); // <-- you can change the easing funtion there
|
|
19
|
+
// return start + (end - start) * (elapsed / duration); // <-- this would give a linear scroll
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// we use requestAnimationFrame to be called by the browser before every repaint
|
|
23
|
+
// if the first argument is an element then scroll to the top of this element
|
|
24
|
+
// if the first argument is numeric then scroll to this location
|
|
25
|
+
// if the callback exist, it is called when the scrolling is finished
|
|
26
|
+
// if context is set then scroll that element, else scroll window
|
|
27
|
+
export const smoothScroll = (el, duration = 500, callback, ctx) => {
|
|
28
|
+
const context = ctx || window;
|
|
29
|
+
const start = context.scrollTop || window.pageYOffset;
|
|
30
|
+
const offset = el instanceof HTMLElement ? 0 : el.offset||0
|
|
31
|
+
|
|
32
|
+
const end = offset + (typeof el === 'number' ? Math.round(el) :
|
|
33
|
+
el instanceof HTMLElement ? getTop(el, start) : getTop(el.target,start))
|
|
34
|
+
|
|
35
|
+
const clock = Date.now();
|
|
36
|
+
const requestAnimationFrame = window.requestAnimationFrame ||
|
|
37
|
+
window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
|
|
38
|
+
function(fn){window.setTimeout(fn, 15);};
|
|
39
|
+
|
|
40
|
+
const step = () => {
|
|
41
|
+
const elapsed = Date.now() - clock;
|
|
42
|
+
if (context !== window) {
|
|
43
|
+
context.scrollTop = position(start, end, elapsed, duration);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
window.scroll(window.pageXOffset, position(start, end, elapsed, duration));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (elapsed > duration) {
|
|
50
|
+
if (typeof callback === 'function') {
|
|
51
|
+
callback(el);
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
requestAnimationFrame(step);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
step();
|
|
58
|
+
}
|
package/src/styled.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import _ from 'lodash/fp'
|
|
3
|
+
import {darken} from 'polished'
|
|
4
|
+
import React from 'react'
|
|
5
|
+
import styled, {css} from 'styled-components'
|
|
6
|
+
import createEmotion from 'create-emotion'
|
|
7
|
+
import {scrollWidth} from './fixMediaQuery'
|
|
8
|
+
import {_s} from './lodashUtils'
|
|
9
|
+
import {callIfFunction} from './utils'
|
|
10
|
+
|
|
11
|
+
export const getColor = (propsOrColor, hover) => {
|
|
12
|
+
if (propsOrColor === undefined) {
|
|
13
|
+
return ({theme})=>theme.colors.gray150
|
|
14
|
+
}
|
|
15
|
+
if (typeof propsOrColor==='string') {
|
|
16
|
+
return ({theme})=>theme.colors[propsOrColor] || propsOrColor
|
|
17
|
+
}
|
|
18
|
+
const {theme,...props} = propsOrColor
|
|
19
|
+
if (props.dark) {
|
|
20
|
+
return darken(0.1, getColor({theme, ..._.unset( 'dark', props)}))
|
|
21
|
+
} else if (hover && props.hover) {
|
|
22
|
+
return getColor({theme, color: props.hover})
|
|
23
|
+
} else if (props.color) {
|
|
24
|
+
return theme.colors[props.color] || props.color
|
|
25
|
+
} else if (props.highlight) {
|
|
26
|
+
return theme.colors.main
|
|
27
|
+
} else if (props.alert) {
|
|
28
|
+
return theme.colors.alert
|
|
29
|
+
} else if (props.success) {
|
|
30
|
+
return theme.colors.success
|
|
31
|
+
} else {
|
|
32
|
+
return theme.colors.gray150
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const getMargin = (enumeratedMargins) => (props) => enumeratedMargins[props.margin] || props.margin || enumeratedMargins['default'] || 0
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Returns the value of `props[path]` or `defaultValue`
|
|
40
|
+
* @example
|
|
41
|
+
* const Button = styled.button`
|
|
42
|
+
* color: ${prop('color', 'red')};
|
|
43
|
+
* `
|
|
44
|
+
*/
|
|
45
|
+
export const prop = (path,defaultValue) =>
|
|
46
|
+
(props = {}) => _.get(path.trim(), props) || defaultValue
|
|
47
|
+
|
|
48
|
+
export const customTheme = (type) =>
|
|
49
|
+
(props = {}) => _.get(["theme","startlibs",type], props) || ''
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Returns `pass` if prop is truthy. Otherwise returns `fail`
|
|
53
|
+
* @example
|
|
54
|
+
* // usage with styled-theme
|
|
55
|
+
* import styled from 'styled-components'
|
|
56
|
+
* import { ifProp } from 'styled-tools'
|
|
57
|
+
* import { palette } from 'styled-theme'
|
|
58
|
+
*
|
|
59
|
+
* const Button = styled.button`
|
|
60
|
+
* background-color: ${ifProp('transparent', 'transparent', palette(0))};
|
|
61
|
+
* color: ${ifProp(['transparent', 'accent'], palette('secondary', 0))};
|
|
62
|
+
* font-size: ${ifProp({ size: 'large' }, '20px', ifProp({ size: 'medium' }, '16px', '12px'))};
|
|
63
|
+
*`
|
|
64
|
+
*/
|
|
65
|
+
export const ifProp = (path, pass, fail) => {
|
|
66
|
+
if (pass && !_.isFunction(pass)) { // old version
|
|
67
|
+
return (props = {}) => {
|
|
68
|
+
let result = false
|
|
69
|
+
if (Array.isArray(path)) {
|
|
70
|
+
result = path.every(p=> testSinglePath(props,p))
|
|
71
|
+
} else if (typeof path === 'object') {
|
|
72
|
+
result = !Object.entries(path).find(([k,v])=>props[k]!==v)
|
|
73
|
+
} else {
|
|
74
|
+
result = testSinglePath(props,path)
|
|
75
|
+
}
|
|
76
|
+
return result ? pass : fail
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
return (...argsTrue) => {
|
|
80
|
+
const check = pass || _.identity
|
|
81
|
+
const fn = props => check(_.get(path,props)) ? css(...argsTrue) : ''
|
|
82
|
+
fn.orElse = (...argsFalse) => (props) => check(_.get(path,props)) ? css(...argsTrue) : css(...argsFalse)
|
|
83
|
+
return fn
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export const ifPropEquals = (path,str) => ifProp(path,_.isEqual(str))
|
|
88
|
+
export const ifNotProp = (path) => ifProp(path,v => !v)
|
|
89
|
+
|
|
90
|
+
const checkCustomScreenWidth = (sizeParis,customWidth) => {
|
|
91
|
+
const currentWidth = callIfFunction(customWidth)
|
|
92
|
+
return !sizeParis.find(([size,type]) => {
|
|
93
|
+
if (type === "min-width") {
|
|
94
|
+
return currentWidth < size
|
|
95
|
+
}
|
|
96
|
+
if (type === "max-width") {
|
|
97
|
+
return currentWidth > size
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const media = (...sizePairs) => (...args) => {
|
|
103
|
+
return css`
|
|
104
|
+
${props =>
|
|
105
|
+
props.theme?.overrideMediaWidth
|
|
106
|
+
? (checkCustomScreenWidth(sizePairs,props.theme?.overrideMediaWidth) ? css(...args) : "")
|
|
107
|
+
: css`@media ${sizePairs.map(([size,type]) => `(${type}: ${size+scrollWidth}px)`).join(' and ')} {
|
|
108
|
+
${ css(...args) }
|
|
109
|
+
}`
|
|
110
|
+
}`
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
media.mobile = media([600,'max-width'])
|
|
114
|
+
media.between = (min,max) => media([min,'min-width'],[max,'max-width'])
|
|
115
|
+
media.max = (n) => media([n,'max-width'])
|
|
116
|
+
media.min = (n) => media([n,'min-width'])
|
|
117
|
+
media.desktop = media([601,'min-width'])
|
|
118
|
+
|
|
119
|
+
export const vheight = (strings,size) => {
|
|
120
|
+
const propType = strings[0]
|
|
121
|
+
const calc = (strings[1]||"").replace(";","").trim()
|
|
122
|
+
return `
|
|
123
|
+
${propType} ${calc ? `calc(${size}vh ${calc})` : `${size}vh`};
|
|
124
|
+
${propType} ${calc ? `calc(calc(var(--vh, 1vh) * ${size}) ${calc})` : `calc(var(--vh, 1vh) * ${size})`};
|
|
125
|
+
`
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function testSinglePath(props,path) {
|
|
129
|
+
if (typeof path === 'string') {
|
|
130
|
+
return !!_s.get(path, props)
|
|
131
|
+
} else if (typeof path === 'number') {
|
|
132
|
+
return !!props[path]
|
|
133
|
+
} else {
|
|
134
|
+
return false
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const getFrameOffset = (i,total) => Math.round(i*100/(total-1))
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
const emotion = createEmotion({
|
|
142
|
+
nonce: (typeof document !== 'undefined' &&
|
|
143
|
+
(document.querySelector('meta[property="csp-nonce"]') || {}).content) || 'animation_nonce'
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
export const oneWayAnimation = (...frames) => {
|
|
147
|
+
return emotion.keyframes`
|
|
148
|
+
${frames.map((frame,i) =>
|
|
149
|
+
!frame ? '' : `${getFrameOffset(i,frames.length)}% {
|
|
150
|
+
${frame}
|
|
151
|
+
}`
|
|
152
|
+
)}`
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export const twoWayAnimation = (...frames) => [frames,_.reverse(frames)].map((frames)=>oneWayAnimation(...frames))
|
|
156
|
+
|
|
157
|
+
export const animationTiming = (props) => (...animations) => animations.filter(_=>_).map(_=>_+' '+props).join(',')
|
|
158
|
+
|
|
159
|
+
export const identityTranslateFrames = oneWayAnimation('transform: translateY(0);', 'transform: translateY(0);')
|
|
160
|
+
export const identityOpacityFrames = oneWayAnimation('opacity: 1;', 'opacity:1;')
|
|
161
|
+
|
|
162
|
+
export const styledExtend = ({target,componentStyle}) => (...template) => {
|
|
163
|
+
const wasStatic = !_.find(_.isFunction,componentStyle.rules)
|
|
164
|
+
const v = styled(target)(...template,...(wasStatic ? [] : [() => ""]))
|
|
165
|
+
v.componentStyle.rules = [...componentStyle.rules,...v.componentStyle.rules]
|
|
166
|
+
return v
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export const printerMedia = (...args) => (props) =>
|
|
170
|
+
props.theme.printMode
|
|
171
|
+
? css(...args)
|
|
172
|
+
: css`@media print { ${css(...args)} }`
|
|
173
|
+
|
|
174
|
+
export const notPrinterMedia = (...args) => (props) =>
|
|
175
|
+
props.theme.printMode
|
|
176
|
+
? ''
|
|
177
|
+
: css`@media screen { ${css(...args)} }`
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
export const SECOND = 1000
|
|
4
|
+
export const MINUTE = SECOND * 60
|
|
5
|
+
export const HOUR = MINUTE * 60
|
|
6
|
+
export const DAY = HOUR * 24
|
|
7
|
+
export const WEEK = DAY * 7
|
|
8
|
+
export const MONTH = DAY * 31
|
|
9
|
+
export const YEAR = DAY * 366
|
|
10
|
+
|
|
11
|
+
export const getStartOfDay = (d,utc = false) => {
|
|
12
|
+
const date = new Date(d)
|
|
13
|
+
if (utc) {
|
|
14
|
+
date.setUTCHours(0,0,0,0)
|
|
15
|
+
} else {
|
|
16
|
+
date.setHours(0,0,0,0)
|
|
17
|
+
}
|
|
18
|
+
return date
|
|
19
|
+
}
|
|
20
|
+
export const isSameDay = (a,b,utc = false) => getStartOfDay(a,utc).getTime() === getStartOfDay(b,utc).getTime()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
export const intervalsIntersect = ([a1, a2], [b1, b2]) =>
|
|
25
|
+
(b2 >= a1) && (b1 <= a2)
|
|
26
|
+
|
|
27
|
+
export const intervalsIntersectExclusive = ([a1, a2], [b1, b2]) =>
|
|
28
|
+
(b2 > a1) && (b1 < a2)
|
|
29
|
+
|
|
30
|
+
export const intervalsIntersection = (a, b) => {
|
|
31
|
+
if (!intervalsIntersect(a,b)) {
|
|
32
|
+
return []
|
|
33
|
+
}
|
|
34
|
+
return [[Math.max(a[0], b[0]), Math.min(a[1], b[1])]]
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const diffIntervals = ([a1, a2], [b1, b2]) => {
|
|
38
|
+
if (
|
|
39
|
+
a1 >= b2 || // a after b
|
|
40
|
+
b1 >= a2 // a before b
|
|
41
|
+
) {
|
|
42
|
+
return [[a1, a2]]
|
|
43
|
+
} else if (a1 > b1 && a2 < b2) { // a inside b
|
|
44
|
+
return []
|
|
45
|
+
}
|
|
46
|
+
if (b1 > a1 && b2 < a2) { // b inside a
|
|
47
|
+
return [[a1, b1], [b2, a2]]
|
|
48
|
+
}
|
|
49
|
+
if (b1 <= a1) { // b intersecting left of a
|
|
50
|
+
return [[b2, a2]]
|
|
51
|
+
} else { // b intersecting right of a
|
|
52
|
+
return [[a1, b1]]
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const blockDiffIntervals = (a, b) => intervalsIntersect(a, b) ? [] : [a]
|
|
57
|
+
export const startBlockDiffIntervals = (a, b) => intervalsIntersectExclusive(a, b) && a[0] >= b[0] ? [] : [a]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import styled from 'styled-components/macro'
|
|
3
|
+
|
|
4
|
+
styled
|
|
5
|
+
export const timerPromise = (time) => new Promise((res) => setTimeout(res,time))
|
|
6
|
+
|
|
7
|
+
export const cancelableTimer = (res,time) => {
|
|
8
|
+
const v = setTimeout(res,time)
|
|
9
|
+
return () => clearTimeout(v)
|
|
10
|
+
}
|