@startlibs/utils 1.0.4 → 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 -2399
- package/rollup.config.js +0 -44
- package/yarn-error.log +0 -3643
package/src/utils.jsx
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import {scrollWidth} from './fixMediaQuery'
|
|
2
|
+
import _ from 'lodash/fp'
|
|
3
|
+
|
|
4
|
+
export const formatPath = (...paths) => paths.map(path=>Array.isArray(path) ? path.join('.') : ( path ? path.toString().replace(/\[/g,'.').replace(/^\./,'').replace(/]/g,'') : '')).filter(_=>_).join('.')
|
|
5
|
+
|
|
6
|
+
export const identityFn = (n=0) => (...e) => e[n]
|
|
7
|
+
|
|
8
|
+
export const will = (fn,...props) => (...more) => fn(...props,...more)
|
|
9
|
+
|
|
10
|
+
export const lazyValue = (v) => () => v
|
|
11
|
+
export const callIfFunction = (prop,...args) => typeof prop === "function" ? prop(...args) : prop
|
|
12
|
+
export const callIfFunctions = (prop,...args) => typeof prop === "function" ? prop(...args.map((e)=>callIfFunction(e))) : prop
|
|
13
|
+
export const callMany = (...many) => (...args) => many.map(_=> callIfFunction(_,...args))
|
|
14
|
+
export const ifUndefined = (v,...or) => v !== undefined ? v : (or.length === 1 ? or[0] : ifUndefined(or[0],...or.slice(1)))
|
|
15
|
+
export const using = (...v) => (fn) => fn(...v.map((v) => callIfFunction(v)))
|
|
16
|
+
|
|
17
|
+
export const stopPropagation = (cb) => (e) => { (e && e.stopPropagation && e.stopPropagation()); callIfFunction(cb,e) }
|
|
18
|
+
export const preventDefault = (cb) => (e) => { (e && e.preventDefault && e.preventDefault()); callIfFunction(cb,e) }
|
|
19
|
+
export const constrainEvent = (cb) => (e) => { e?.preventDefault(); e.stopPropagation(); callIfFunction(cb,e) }
|
|
20
|
+
|
|
21
|
+
export const mapGetOrSet = (map,key,value) => (map.has(key) ? map : map.set(key, value)).get(key);
|
|
22
|
+
|
|
23
|
+
export const intToHour = (hour, autoFill = true) => {
|
|
24
|
+
if (hour === undefined || hour === null) return ''
|
|
25
|
+
if (hour === 0) { return "00:00"}
|
|
26
|
+
|
|
27
|
+
//const [h,m] = ('000' + hour.toString().replace(":","")).slice(-4).replace(/(\d\d)(\d\d)/, '$1:$2').split(":")
|
|
28
|
+
|
|
29
|
+
const h = hour.toString().replace(":","").slice(-4, -2)
|
|
30
|
+
const m = hour.toString().replace(":","").slice(-2)
|
|
31
|
+
if (callIfFunction(autoFill,hour)) {
|
|
32
|
+
return ('000' + (h ? parseInt(h,10) % 24 : '') + m).slice(-4).replace(/(\d\d)(\d\d)/, '$1:$2')
|
|
33
|
+
}
|
|
34
|
+
if (h) return (parseInt(h, 10) > 23 ? h.slice(1) : h) + ':' + m
|
|
35
|
+
return m
|
|
36
|
+
}
|
|
37
|
+
export const formatHour = (hour = "") => {
|
|
38
|
+
if (!hour) { return ""}
|
|
39
|
+
const h = hour.toString().replace(":","").slice(-4, -2)
|
|
40
|
+
const m = hour.toString().replace(":","").slice(-2)
|
|
41
|
+
if (!h && parseInt(m) < 24 && !_.isFinite(hour)) {
|
|
42
|
+
return m+":00"
|
|
43
|
+
} else if (h) {
|
|
44
|
+
return (parseInt(h, 10) > 23 ? h.slice(1) : h) + ':' + m
|
|
45
|
+
}
|
|
46
|
+
return ('000' + hour.toString().replace(":","")).slice(-4).replace(/(\d\d)(\d\d)/, '$1:$2')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
export const willRafThrottle = () => {
|
|
51
|
+
let ticking = false;
|
|
52
|
+
return (fn) => {
|
|
53
|
+
if (!ticking) {
|
|
54
|
+
window.requestAnimationFrame(() => {
|
|
55
|
+
fn()
|
|
56
|
+
ticking = false;
|
|
57
|
+
});
|
|
58
|
+
ticking = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const rafThrottle = (fn) => {
|
|
64
|
+
const throttle = willRafThrottle()
|
|
65
|
+
return () => {
|
|
66
|
+
throttle(fn)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const intsToHour = ({open, close}) => intToHour(open) + ' - ' + intToHour(close)
|
|
71
|
+
|
|
72
|
+
export function isSmallDevice(width=600) {
|
|
73
|
+
const smallDeviceQuery = window.matchMedia ? window.matchMedia( `(max-width: ${width+scrollWidth}px)` ) : {matches:false}
|
|
74
|
+
return smallDeviceQuery.matches;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function isHighDensity() {
|
|
78
|
+
return ((window.matchMedia && (window.matchMedia('only screen and (min-resolution: 124dpi), only screen and (min-resolution: 1.3dppx), only screen and (min-resolution: 48.8dpcm)').matches || window.matchMedia('only screen and (-webkit-min-device-pixel-ratio: 1.3), only screen and (-o-min-device-pixel-ratio: 2.6/2), only screen and (min--moz-device-pixel-ratio: 1.3), only screen and (min-device-pixel-ratio: 1.3)').matches)) || (window.devicePixelRatio && window.devicePixelRatio > 1.3))
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function isRetina() {
|
|
82
|
+
return ((window.matchMedia && (window.matchMedia('only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx), only screen and (min-resolution: 75.6dpcm)').matches || window.matchMedia('only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min--moz-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio: 2)').matches)) || (window.devicePixelRatio && window.devicePixelRatio >= 2)) && /(iPad|iPhone|iPod)/g.test(navigator.userAgent)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function isMobile() {
|
|
86
|
+
if (typeof navigator === 'undefined') return false
|
|
87
|
+
|
|
88
|
+
const ua = navigator.userAgent
|
|
89
|
+
|
|
90
|
+
const isAndroid = /android/i.test(ua)
|
|
91
|
+
const isiOS = /iphone|ipod|ipad/i.test(ua)
|
|
92
|
+
|
|
93
|
+
// iPadOS 13+ reports "Macintosh" but has touch
|
|
94
|
+
const isIPadOS =
|
|
95
|
+
navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1
|
|
96
|
+
|
|
97
|
+
return isAndroid || isiOS || isIPadOS
|
|
98
|
+
}
|
|
99
|
+
export function isAndroid() {
|
|
100
|
+
if (navigator.userAgentData) {
|
|
101
|
+
return navigator.userAgentData.platform === "Android"
|
|
102
|
+
}
|
|
103
|
+
return /Android/i.test(navigator.userAgent)
|
|
104
|
+
}
|
|
105
|
+
export const isPWA = () => {
|
|
106
|
+
return (window.matchMedia && window.matchMedia("(display-mode: standalone)").matches)
|
|
107
|
+
|| !!window.hasWebviewBridge
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function isTouchDevice() {
|
|
111
|
+
return window.document && 'ontouchstart' in window.document.documentElement;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export const isIOS = () => {
|
|
115
|
+
return /iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
|
|
116
|
+
}
|
|
117
|
+
export const isIPad = () => {
|
|
118
|
+
return navigator.userAgent.match(/iPad/i) != null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export const getNumberInputType2 = () => {
|
|
122
|
+
const isIOS = (/iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1))
|
|
123
|
+
return isMobile() ? (isIOS ? "tel" : "number") : "text"
|
|
124
|
+
}
|
|
125
|
+
export const getNumberInputType = () => {
|
|
126
|
+
return "tel"
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function addHttp(s,secure) {
|
|
130
|
+
s = (s || '').trim()
|
|
131
|
+
if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) {
|
|
132
|
+
return s
|
|
133
|
+
} else {
|
|
134
|
+
return `http${secure ? 's': ''}://` + s
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const protocols = '(^|\\s|\u00a0)(https?://)?(www\\.)?'
|
|
139
|
+
const subdomains = '([a-zA-Z0-9][a-zA-Z0-9-_]*[a-zA-Z0-9]?\\.)*'
|
|
140
|
+
const domain = '(([a-zA-Z]{1})|([a-zA-Z]{1}[a-zA-Z]{1})|([a-zA-Z]{1}[0-9]{1})|([0-9]{1}[a-zA-Z]{1})|([a-zA-Z0-9][a-zA-Z0-9-_]{1,61}[a-zA-Z0-9]))\\.([a-zA-Z]{2,6}|[a-zA-Z0-9-]{2,30}\\.[a-zA-Z]{2,3})'
|
|
141
|
+
const resource = '[\u00A1-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEFa-zA-Z0-9-._~:/?#%[\\]@!$&\'()*+,;=]*'
|
|
142
|
+
export const linkRegex = new RegExp(protocols + subdomains + domain + resource)
|
|
143
|
+
|
|
144
|
+
export function isUrl(url) {
|
|
145
|
+
return linkRegex.test(addHttp(url))
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function ellipsis(str = "", length) {
|
|
149
|
+
if (str.length > length) {
|
|
150
|
+
let words = str.slice(0, length).split(' ')
|
|
151
|
+
if (str.split(' ').indexOf(words[words.length - 1]) < 0)
|
|
152
|
+
words = words.slice(0, words.length - 1)
|
|
153
|
+
return words.join(' ') + '...'
|
|
154
|
+
} else
|
|
155
|
+
return str
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function safeNewLineToBr(str,keepMany) {
|
|
159
|
+
const result = (str||"").replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"')
|
|
160
|
+
if (keepMany===true) {
|
|
161
|
+
return result.replace(/\n/g,'<br/>')
|
|
162
|
+
}
|
|
163
|
+
return result.replace(/\n+/g,'<br/>')
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function padGroups(pattern,value) {
|
|
167
|
+
return pattern.split('').reduce(([acc,value],char,i) => {
|
|
168
|
+
if (char === '0') {
|
|
169
|
+
const shouldHave = pattern.slice(i).search(/[^0#?*]/)
|
|
170
|
+
const has = value.slice(i).search(/\D/)
|
|
171
|
+
if (has > 0 && shouldHave > has) {
|
|
172
|
+
return [acc.concat('0'),acc.join('')+'0'+value.slice(i)]
|
|
173
|
+
} else {
|
|
174
|
+
return [acc.concat(value[i]),value]
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
return [acc.concat(value[i]),value]
|
|
178
|
+
}
|
|
179
|
+
},[[],value])[0].join('')
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export const digitsToPattern = (patternWithLimit,optValue) => {
|
|
183
|
+
const value = optValue || ""
|
|
184
|
+
if (patternWithLimit[0] === '>' && Number(patternWithLimit.replace(/^>(\d*).*/g,"$1"))>value.length) return value
|
|
185
|
+
const pattern = patternWithLimit.replace(/^>\d+/,'')
|
|
186
|
+
const digits = padGroups(pattern,value).replace(/\D/g,'')
|
|
187
|
+
const totalRequired = pattern.split(/[0#]/).length-1
|
|
188
|
+
const totalOptional = pattern.split(/[?*]/).length-1
|
|
189
|
+
const available = digits.length-totalRequired
|
|
190
|
+
|
|
191
|
+
if (available>0 && totalOptional>0) {
|
|
192
|
+
let i = 0;
|
|
193
|
+
return digitsToPattern(
|
|
194
|
+
pattern
|
|
195
|
+
.replace(/\?/g,()=>i++<available?'#':'')
|
|
196
|
+
.replace('*',new Array(Math.max(0,available-i+1)).join("#")),
|
|
197
|
+
value
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
let i = 0
|
|
201
|
+
return pattern.replace(/^>\d*/,'').split('').reduce((acc,char)=> {
|
|
202
|
+
if (!digits[Math.max(i-1,0)] || char === '?' || char === '*') return acc
|
|
203
|
+
if (char==='#' || char=== '0') {
|
|
204
|
+
return acc+(digits[i++]||'')
|
|
205
|
+
} else {
|
|
206
|
+
return acc+char
|
|
207
|
+
}
|
|
208
|
+
},'')
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export const normalizeTouch = (fn, endFn) => (e) => {
|
|
212
|
+
const touch = e.touches[0]
|
|
213
|
+
if (e.touches.length > 1 && e.type !== 'touchend') {
|
|
214
|
+
callIfFunction(endFn,e,touch)
|
|
215
|
+
} else {
|
|
216
|
+
callIfFunction(fn,e, touch)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
export const normalizeMouse = (fn,endFn) => (e) => {
|
|
220
|
+
if (e.buttons>1 && e.type !== 'mouseup') {
|
|
221
|
+
callIfFunction(endFn,e,e)
|
|
222
|
+
} else {
|
|
223
|
+
callIfFunction(fn,e, e)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export const normalizePress = (fn,endFn) => (e) => {
|
|
228
|
+
if (e.touches) {
|
|
229
|
+
normalizeTouch(fn,endFn)(e)
|
|
230
|
+
} else {
|
|
231
|
+
normalizeMouse(fn,endFn)(e)
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
export const touchClick = (cb,sensibility = 5) => (e) => {
|
|
237
|
+
if (e.touches?.length !== 1) { return }
|
|
238
|
+
const target = e.target
|
|
239
|
+
const originalX = e.touches[0].screenX
|
|
240
|
+
const originalY = e.touches[0].screenY
|
|
241
|
+
const isInsideBounds = (touch) => Math.sqrt( Math.pow((originalX-touch.screenX), 2) + Math.pow((originalY-touch.screenY), 2) ) < sensibility
|
|
242
|
+
|
|
243
|
+
const checkBounds = (e) => {
|
|
244
|
+
if (e.touches.length !== 1) { return }
|
|
245
|
+
if (!isInsideBounds(e.changedTouches[0])) {
|
|
246
|
+
maybeClick()
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const maybeClick = (e) => {
|
|
250
|
+
target.removeEventListener('touchend',maybeClick)
|
|
251
|
+
target.removeEventListener('touchmove',checkBounds)
|
|
252
|
+
if (e?.changedTouches?.length !== 1) { return }
|
|
253
|
+
if (isInsideBounds(e.changedTouches[0])) {
|
|
254
|
+
e.preventDefault()
|
|
255
|
+
cb(e)
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
target.addEventListener('touchend',maybeClick)
|
|
259
|
+
target.addEventListener('touchmove',checkBounds)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
export const isEmptyHtml = (__html = "") => {
|
|
264
|
+
const a = document.createElement('span')
|
|
265
|
+
a.innerHTML = __html
|
|
266
|
+
return a.textContent.replace(/\s/g,'').length === 0
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
export const getScrollParent = (node) => {
|
|
271
|
+
if (!node) {
|
|
272
|
+
return window
|
|
273
|
+
}
|
|
274
|
+
const overflowY = window.getComputedStyle(node).overflowY
|
|
275
|
+
const isScrollable = overflowY !== 'visible' && overflowY !== 'hidden'
|
|
276
|
+
if (isScrollable && (node.scrollHeight > node.clientHeight || overflowY === 'scroll')) {
|
|
277
|
+
return node
|
|
278
|
+
} else {
|
|
279
|
+
return getScrollParent((node.offsetParent))
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export const scrollIntoViewWithOffset = (el,offset) => {
|
|
284
|
+
const scrollOffset = getScrollParent(el)
|
|
285
|
+
const scrollY = scrollOffset === window ? window.pageYOffset : scrollOffset.scrollTop
|
|
286
|
+
|
|
287
|
+
const elTop = el.getBoundingClientRect().top
|
|
288
|
+
const computedOffset = callIfFunction(offset,elTop > 0)
|
|
289
|
+
|
|
290
|
+
const y = el.getBoundingClientRect().top + scrollY + computedOffset;
|
|
291
|
+
|
|
292
|
+
scrollOffset.scrollTo({top: y, behavior: 'smooth'});
|
|
293
|
+
}
|
|
294
|
+
export const isElementInView = async (element) => {
|
|
295
|
+
if (!element) return false;
|
|
296
|
+
if (1 !== element.nodeType) return false;
|
|
297
|
+
|
|
298
|
+
var html = document.documentElement;
|
|
299
|
+
var rect = element.getBoundingClientRect();
|
|
300
|
+
if (IntersectionObserver) {
|
|
301
|
+
return new Promise(resolve => {
|
|
302
|
+
const o = new IntersectionObserver(([entry]) => {
|
|
303
|
+
resolve(entry.intersectionRatio === 1);
|
|
304
|
+
o.disconnect();
|
|
305
|
+
});
|
|
306
|
+
o.observe(element);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
return !!rect &&
|
|
310
|
+
rect.bottom >= 0 &&
|
|
311
|
+
rect.right >= 0 &&
|
|
312
|
+
rect.left <= html.clientWidth &&
|
|
313
|
+
rect.top <= html.clientHeight;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
let i = 0
|
|
318
|
+
export const getUID = () => Date.now().toString(36)+Math.random().toString(36).slice(2)+(i++).toString(36)
|
|
319
|
+
|
|
320
|
+
export const getUrlParams = () => _.fromPairs(Array.from(new URLSearchParams(location.search).entries()))
|
|
321
|
+
|
|
322
|
+
export const isShallowEqualSameKeys = (a, b) => {
|
|
323
|
+
for(var key in a) {
|
|
324
|
+
if(a[key] !== b[key]) {
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
export const isShallowEqual = (a, b) => {
|
|
331
|
+
for(var key in a) {
|
|
332
|
+
if(!(key in b) || a[key] !== b[key]) {
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
for(var key in b) {
|
|
337
|
+
if(!(key in a) || a[key] !== b[key]) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return true;
|
|
342
|
+
}
|
package/src/wrapLazy.jsx
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import _ from 'lodash/fp'
|
|
3
|
+
import {callIfFunction} from './utils'
|
|
4
|
+
|
|
5
|
+
// Suspense integrations like Relay implement
|
|
6
|
+
// a contract like this to integrate with React.
|
|
7
|
+
// Real implementations can be significantly more complex.
|
|
8
|
+
// Don't copy-paste this into your project!
|
|
9
|
+
const EMPTY_ARGS = []
|
|
10
|
+
const UNDEFINED_CURRENT_VALUE = {}
|
|
11
|
+
const innerWrapLazy = (refreshCallback) => (maybePromise, ...rootArgs) => {
|
|
12
|
+
let status;
|
|
13
|
+
let awaitReadResolver;
|
|
14
|
+
let checker = _.isEqual;
|
|
15
|
+
let lazyArgs = EMPTY_ARGS;
|
|
16
|
+
let uid = Math.random().toString()+Date.now();
|
|
17
|
+
let result;
|
|
18
|
+
let currentValue = UNDEFINED_CURRENT_VALUE
|
|
19
|
+
|
|
20
|
+
const promisify = (maybePromise,resolveNow) => {
|
|
21
|
+
return ((_.isFunction(maybePromise) && !resolveNow) ? new Promise(res => awaitReadResolver = res) : Promise.resolve())
|
|
22
|
+
.then((...args) => callIfFunction(maybePromise, ...rootArgs, ...lazyArgs, ...args))
|
|
23
|
+
}
|
|
24
|
+
const onPromiseSuccess = (returnedPromise) => r => {
|
|
25
|
+
if (returnedPromise !== suspender) {
|
|
26
|
+
return suspender
|
|
27
|
+
}
|
|
28
|
+
status = "success";
|
|
29
|
+
currentValue = r
|
|
30
|
+
result = r;
|
|
31
|
+
return r
|
|
32
|
+
}
|
|
33
|
+
const onPromiseError = (returnedPromise) => (e) => {
|
|
34
|
+
if (returnedPromise !== suspender) {
|
|
35
|
+
return suspender
|
|
36
|
+
}
|
|
37
|
+
status = "error";
|
|
38
|
+
result = e;
|
|
39
|
+
return Promise.reject(e)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const suspend = (maybePromise) => {
|
|
43
|
+
status = "pending"
|
|
44
|
+
awaitReadResolver = _.identity
|
|
45
|
+
const returnedPromise = promisify(maybePromise)
|
|
46
|
+
returnedPromise.then(onPromiseSuccess(returnedPromise), onPromiseError(returnedPromise));
|
|
47
|
+
return returnedPromise;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let suspender = suspend(maybePromise)
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
read() {
|
|
54
|
+
awaitReadResolver()
|
|
55
|
+
if (status === "pending") {
|
|
56
|
+
throw suspender;
|
|
57
|
+
} else if (status === "error") {
|
|
58
|
+
throw result;
|
|
59
|
+
} else if (status === "success") {
|
|
60
|
+
return currentValue;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
promise() {
|
|
64
|
+
awaitReadResolver()
|
|
65
|
+
return suspender
|
|
66
|
+
},
|
|
67
|
+
refresh(force) {
|
|
68
|
+
if (status !== "pending" || force) {
|
|
69
|
+
suspender = suspend(maybePromise)
|
|
70
|
+
uid = Math.random().toString()+Date.now();
|
|
71
|
+
callIfFunction(refreshCallback,this)
|
|
72
|
+
}
|
|
73
|
+
return this
|
|
74
|
+
},
|
|
75
|
+
next(...args) {
|
|
76
|
+
return wrapLazy(maybePromise, ...rootArgs, ...args).checkWith(checker)
|
|
77
|
+
},
|
|
78
|
+
use(...args) {
|
|
79
|
+
if (!checker(args, lazyArgs)) {
|
|
80
|
+
if (lazyArgs !== EMPTY_ARGS) {
|
|
81
|
+
uid = Math.random().toString()+Date.now();
|
|
82
|
+
}
|
|
83
|
+
lazyArgs = args
|
|
84
|
+
suspender = suspend(maybePromise)
|
|
85
|
+
}
|
|
86
|
+
return this
|
|
87
|
+
},
|
|
88
|
+
_getCurrentValue() {
|
|
89
|
+
return currentValue
|
|
90
|
+
},
|
|
91
|
+
silentRefresh() {
|
|
92
|
+
const currentSuspender = suspender
|
|
93
|
+
const suspended = promisify(maybePromise,true).then((v) => {
|
|
94
|
+
if (currentSuspender === suspender) {
|
|
95
|
+
suspender = suspended
|
|
96
|
+
}
|
|
97
|
+
return v
|
|
98
|
+
})
|
|
99
|
+
suspended.then(onPromiseSuccess(suspended),onPromiseError(suspended))
|
|
100
|
+
uid = Math.random().toString()+Date.now();
|
|
101
|
+
callIfFunction(refreshCallback,this)
|
|
102
|
+
return suspended
|
|
103
|
+
},
|
|
104
|
+
and(lazy) {
|
|
105
|
+
|
|
106
|
+
},
|
|
107
|
+
checkWith(isEqual) {
|
|
108
|
+
checker = isEqual
|
|
109
|
+
return this
|
|
110
|
+
},
|
|
111
|
+
localUpdate(updater) {
|
|
112
|
+
currentValue = callIfFunction(updater,currentValue)
|
|
113
|
+
return this
|
|
114
|
+
},
|
|
115
|
+
uid() {
|
|
116
|
+
return uid
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const UNMOUNTED = {}
|
|
121
|
+
|
|
122
|
+
export const wrapLazy = innerWrapLazy()
|
package/.babelrc
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// .babelrc
|
|
2
|
-
{
|
|
3
|
-
"presets": [
|
|
4
|
-
"@babel/preset-react",
|
|
5
|
-
"@babel/preset-flow",
|
|
6
|
-
["@babel/preset-env", {
|
|
7
|
-
"exclude": ["@babel/plugin-proposal-unicode-property-regex", "@babel/plugin-transform-unicode-regex"],
|
|
8
|
-
"modules": false
|
|
9
|
-
}
|
|
10
|
-
]
|
|
11
|
-
],
|
|
12
|
-
"plugins": [
|
|
13
|
-
"lodash",
|
|
14
|
-
"macros",
|
|
15
|
-
"fbjs-scripts/babel-6/dev-expression",
|
|
16
|
-
"@babel/plugin-proposal-export-namespace-from",
|
|
17
|
-
"@babel/plugin-proposal-throw-expressions",
|
|
18
|
-
"@babel/plugin-syntax-import-meta",
|
|
19
|
-
"@babel/plugin-proposal-json-strings",
|
|
20
|
-
"@babel/plugin-syntax-dynamic-import",
|
|
21
|
-
"@babel/plugin-transform-arrow-functions",
|
|
22
|
-
"@babel/plugin-transform-spread",
|
|
23
|
-
"@babel/plugin-proposal-object-rest-spread",
|
|
24
|
-
["@babel/plugin-proposal-class-properties", {"loose": true}]
|
|
25
|
-
]
|
|
26
|
-
}
|