@startlibs/core 1.0.7 → 1.2.0-rc.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.
Files changed (173) hide show
  1. package/lib/SlotFill.mjs +232 -0
  2. package/lib/SlotFill.mjs.map +1 -0
  3. package/lib/StartlibsProvider.mjs +62 -0
  4. package/lib/StartlibsProvider.mjs.map +1 -0
  5. package/lib/hocs/WithLazyResource.mjs +74 -0
  6. package/lib/hocs/WithLazyResource.mjs.map +1 -0
  7. package/lib/hocs/WithRef.mjs +20 -0
  8. package/lib/hocs/WithRef.mjs.map +1 -0
  9. package/lib/hocs/consumes.mjs +22 -0
  10. package/lib/hocs/consumes.mjs.map +1 -0
  11. package/lib/hocs/withDialogError.mjs +22 -0
  12. package/lib/hocs/withDialogError.mjs.map +1 -0
  13. package/lib/hocs/withGroupEvent.mjs +45 -0
  14. package/lib/hocs/withGroupEvent.mjs.map +1 -0
  15. package/lib/hooks/WithConstant.mjs +13 -0
  16. package/lib/hooks/WithConstant.mjs.map +1 -0
  17. package/lib/hooks/WithEffect.mjs +12 -0
  18. package/lib/hooks/WithEffect.mjs.map +1 -0
  19. package/lib/hooks/useAsyncEffect.mjs +14 -0
  20. package/lib/hooks/useAsyncEffect.mjs.map +1 -0
  21. package/lib/hooks/useCallState.mjs +21 -0
  22. package/lib/hooks/useCallState.mjs.map +1 -0
  23. package/lib/hooks/useCallbackStable.mjs +17 -0
  24. package/lib/hooks/useCallbackStable.mjs.map +1 -0
  25. package/lib/hooks/useConstant.mjs +21 -0
  26. package/lib/hooks/useConstant.mjs.map +1 -0
  27. package/lib/hooks/useConsumerCatalog.mjs +25 -0
  28. package/lib/hooks/useConsumerCatalog.mjs.map +1 -0
  29. package/lib/hooks/useEnsureRef.mjs +9 -0
  30. package/lib/hooks/useEnsureRef.mjs.map +1 -0
  31. package/lib/hooks/useForceUpdate.mjs +28 -0
  32. package/lib/hooks/useForceUpdate.mjs.map +1 -0
  33. package/lib/hooks/useIsUnmounted.mjs +15 -0
  34. package/lib/hooks/useIsUnmounted.mjs.map +1 -0
  35. package/lib/hooks/usePopupToggle.mjs +33 -0
  36. package/lib/hooks/usePopupToggle.mjs.map +1 -0
  37. package/lib/hooks/usePrevious.mjs +28 -0
  38. package/lib/hooks/usePrevious.mjs.map +1 -0
  39. package/lib/hooks/useRecycleFocus.mjs +36 -0
  40. package/lib/hooks/useRecycleFocus.mjs.map +1 -0
  41. package/lib/hooks/useRefMemo.mjs +13 -0
  42. package/lib/hooks/useRefMemo.mjs.map +1 -0
  43. package/lib/hooks/useRefState.mjs +29 -0
  44. package/lib/hooks/useRefState.mjs.map +1 -0
  45. package/lib/hooks/useSignal.mjs +271 -0
  46. package/lib/hooks/useSignal.mjs.map +1 -0
  47. package/lib/hooks/useTitle.mjs +17 -0
  48. package/lib/hooks/useTitle.mjs.map +1 -0
  49. package/lib/hooks/useToggle.mjs +152 -0
  50. package/lib/hooks/useToggle.mjs.map +1 -0
  51. package/lib/hooks/useUpdateEffect.mjs +15 -0
  52. package/lib/hooks/useUpdateEffect.mjs.map +1 -0
  53. package/lib/hooks/useUpdateOnResize.mjs +18 -0
  54. package/lib/hooks/useUpdateOnResize.mjs.map +1 -0
  55. package/lib/hooks/useWithTransition.mjs +18 -0
  56. package/lib/hooks/useWithTransition.mjs.map +1 -0
  57. package/lib/hooks/willUseLayers.mjs +55 -0
  58. package/lib/hooks/willUseLayers.mjs.map +1 -0
  59. package/lib/hooks/willUseSharedCallback.mjs +70 -0
  60. package/lib/hooks/willUseSharedCallback.mjs.map +1 -0
  61. package/lib/hooks/willUseSharedState.mjs +41 -0
  62. package/lib/hooks/willUseSharedState.mjs.map +1 -0
  63. package/lib/hooks/willUseSpreadState.mjs +119 -0
  64. package/lib/hooks/willUseSpreadState.mjs.map +1 -0
  65. package/lib/index.cjs +1474 -0
  66. package/lib/index.cjs.map +1 -0
  67. package/lib/index.mjs +33 -0
  68. package/lib/index.mjs.map +1 -0
  69. package/lib-yak/SlotFill.mjs +230 -0
  70. package/lib-yak/SlotFill.mjs.map +1 -0
  71. package/lib-yak/StartlibsProvider.mjs +62 -0
  72. package/lib-yak/StartlibsProvider.mjs.map +1 -0
  73. package/lib-yak/hocs/WithLazyResource.mjs +74 -0
  74. package/lib-yak/hocs/WithLazyResource.mjs.map +1 -0
  75. package/lib-yak/hocs/WithRef.mjs +20 -0
  76. package/lib-yak/hocs/WithRef.mjs.map +1 -0
  77. package/lib-yak/hocs/consumes.mjs +22 -0
  78. package/lib-yak/hocs/consumes.mjs.map +1 -0
  79. package/lib-yak/hocs/withDialogError.mjs +22 -0
  80. package/lib-yak/hocs/withDialogError.mjs.map +1 -0
  81. package/lib-yak/hocs/withGroupEvent.mjs +45 -0
  82. package/lib-yak/hocs/withGroupEvent.mjs.map +1 -0
  83. package/lib-yak/hooks/WithConstant.mjs +13 -0
  84. package/lib-yak/hooks/WithConstant.mjs.map +1 -0
  85. package/lib-yak/hooks/WithEffect.mjs +12 -0
  86. package/lib-yak/hooks/WithEffect.mjs.map +1 -0
  87. package/lib-yak/hooks/useAsyncEffect.mjs +14 -0
  88. package/lib-yak/hooks/useAsyncEffect.mjs.map +1 -0
  89. package/lib-yak/hooks/useCallState.mjs +21 -0
  90. package/lib-yak/hooks/useCallState.mjs.map +1 -0
  91. package/lib-yak/hooks/useCallbackStable.mjs +17 -0
  92. package/lib-yak/hooks/useCallbackStable.mjs.map +1 -0
  93. package/lib-yak/hooks/useConstant.mjs +21 -0
  94. package/lib-yak/hooks/useConstant.mjs.map +1 -0
  95. package/lib-yak/hooks/useConsumerCatalog.mjs +25 -0
  96. package/lib-yak/hooks/useConsumerCatalog.mjs.map +1 -0
  97. package/lib-yak/hooks/useEnsureRef.mjs +9 -0
  98. package/lib-yak/hooks/useEnsureRef.mjs.map +1 -0
  99. package/lib-yak/hooks/useForceUpdate.mjs +28 -0
  100. package/lib-yak/hooks/useForceUpdate.mjs.map +1 -0
  101. package/lib-yak/hooks/useIsUnmounted.mjs +15 -0
  102. package/lib-yak/hooks/useIsUnmounted.mjs.map +1 -0
  103. package/lib-yak/hooks/usePopupToggle.mjs +33 -0
  104. package/lib-yak/hooks/usePopupToggle.mjs.map +1 -0
  105. package/lib-yak/hooks/usePrevious.mjs +28 -0
  106. package/lib-yak/hooks/usePrevious.mjs.map +1 -0
  107. package/lib-yak/hooks/useRecycleFocus.mjs +34 -0
  108. package/lib-yak/hooks/useRecycleFocus.mjs.map +1 -0
  109. package/lib-yak/hooks/useRefMemo.mjs +13 -0
  110. package/lib-yak/hooks/useRefMemo.mjs.map +1 -0
  111. package/lib-yak/hooks/useRefState.mjs +29 -0
  112. package/lib-yak/hooks/useRefState.mjs.map +1 -0
  113. package/lib-yak/hooks/useSignal.mjs +271 -0
  114. package/lib-yak/hooks/useSignal.mjs.map +1 -0
  115. package/lib-yak/hooks/useTitle.mjs +17 -0
  116. package/lib-yak/hooks/useTitle.mjs.map +1 -0
  117. package/lib-yak/hooks/useToggle.mjs +152 -0
  118. package/lib-yak/hooks/useToggle.mjs.map +1 -0
  119. package/lib-yak/hooks/useUpdateEffect.mjs +15 -0
  120. package/lib-yak/hooks/useUpdateEffect.mjs.map +1 -0
  121. package/lib-yak/hooks/useUpdateOnResize.mjs +18 -0
  122. package/lib-yak/hooks/useUpdateOnResize.mjs.map +1 -0
  123. package/lib-yak/hooks/useWithTransition.mjs +18 -0
  124. package/lib-yak/hooks/useWithTransition.mjs.map +1 -0
  125. package/lib-yak/hooks/willUseLayers.mjs +55 -0
  126. package/lib-yak/hooks/willUseLayers.mjs.map +1 -0
  127. package/lib-yak/hooks/willUseSharedCallback.mjs +70 -0
  128. package/lib-yak/hooks/willUseSharedCallback.mjs.map +1 -0
  129. package/lib-yak/hooks/willUseSharedState.mjs +41 -0
  130. package/lib-yak/hooks/willUseSharedState.mjs.map +1 -0
  131. package/lib-yak/hooks/willUseSpreadState.mjs +119 -0
  132. package/lib-yak/hooks/willUseSpreadState.mjs.map +1 -0
  133. package/lib-yak/index.mjs +33 -0
  134. package/lib-yak/index.mjs.map +1 -0
  135. package/package.json +53 -30
  136. package/src/SlotFill.jsx +166 -0
  137. package/src/StartlibsProvider.jsx +62 -0
  138. package/src/hocs/WithLazyResource.jsx +32 -0
  139. package/src/hocs/WithRef.js +20 -0
  140. package/src/hocs/Wrapper.jsx +40 -0
  141. package/src/hocs/consumes.jsx +16 -0
  142. package/src/hocs/withDialogError.jsx +16 -0
  143. package/src/hocs/withGroupEvent.jsx +43 -0
  144. package/src/hooks/WithConstant.jsx +7 -0
  145. package/src/hooks/WithEffect.jsx +6 -0
  146. package/src/hooks/useAsyncEffect.jsx +11 -0
  147. package/src/hooks/useCallState.js +15 -0
  148. package/src/hooks/useCallbackStable.jsx +12 -0
  149. package/src/hooks/useConstant.js +20 -0
  150. package/src/hooks/useConsumerCatalog.jsx +21 -0
  151. package/src/hooks/useEnsureRef.js +6 -0
  152. package/src/hooks/useForceUpdate.jsx +16 -0
  153. package/src/hooks/useIsUnmounted.jsx +12 -0
  154. package/src/hooks/usePopupToggle.js +30 -0
  155. package/src/hooks/usePrevious.jsx +27 -0
  156. package/src/hooks/useRecycleFocus.jsx +26 -0
  157. package/src/hooks/useRefMemo.jsx +10 -0
  158. package/src/hooks/useRefState.js +26 -0
  159. package/src/hooks/useSignal.jsx +193 -0
  160. package/src/hooks/useTitle.jsx +12 -0
  161. package/src/hooks/useToggle.js +126 -0
  162. package/src/hooks/useUpdateEffect.js +14 -0
  163. package/src/hooks/useUpdateOnResize.jsx +14 -0
  164. package/src/hooks/useWithTransition.jsx +14 -0
  165. package/src/hooks/willUseLayers.jsx +42 -0
  166. package/src/hooks/willUseSharedCallback.jsx +60 -0
  167. package/src/hooks/willUseSharedState.jsx +34 -0
  168. package/src/hooks/willUseSpreadState.jsx +103 -0
  169. package/src/index.js +32 -0
  170. package/.babelrc +0 -27
  171. package/lib/index.js +0 -1921
  172. package/rollup.config.js +0 -53
  173. package/yarn-error.log +0 -3374
@@ -0,0 +1,193 @@
1
+ import React, {startTransition, use, useMemo, useCallback, useContext, useEffect, useRef, useState} from 'react'
2
+ import {useConstant, useLazyConstant} from './useConstant'
3
+ import {useForceUpdate} from './useForceUpdate'
4
+ import {_s, callIfFunction} from '@startlibs/utils'
5
+ import _ from 'lodash/fp'
6
+
7
+ const IS_ARRAY_ITEMS_EQUALS = (a,b) => a.length === b.length && !a.some((x, i) => !Object.is(x, b[i]));
8
+ const IS_DEPS_EQUALS = (a = [],b = []) => Object.is(a,b) || IS_ARRAY_ITEMS_EQUALS(a,b)
9
+
10
+ const SHALLOW_IS_EQUAL = (a,b) => Object.is(a,b) || (_.isArray(a) && _.isArray(b) && IS_ARRAY_ITEMS_EQUALS(a,b))
11
+
12
+ const EMPTY_DEPS = []
13
+ const EMPTY_VALUE = {"EMPTY":true}
14
+ export const useUpdateSignal = (initialValue) => {
15
+ const value = useRef(initialValue)
16
+ value.current = initialValue
17
+ return useLazyConstant(() => {
18
+ let registered = []
19
+ const register = (selector = _.identity, isEqual = SHALLOW_IS_EQUAL, withTransition = false) => {
20
+ const selectorRef = useRef()
21
+ selectorRef.current = selector
22
+ const update = useForceUpdate()
23
+ const lastValueRef = useRef(_s.select(selectorRef.current, value.current))
24
+ useEffect(() => {
25
+ const item = [update, selectorRef, isEqual, lastValueRef, withTransition]
26
+ registered = [...registered, item]
27
+ return () => {
28
+ registered = registered.filter(v => v !== item)
29
+ }
30
+ }, [])
31
+ if (value.current === EMPTY_VALUE) {
32
+ return EMPTY_VALUE
33
+ }
34
+ return lastValueRef.current
35
+ }
36
+ const call = (...args) =>
37
+ registered.forEach(([fn, selectorRef, isEqual, lastValueRef, withTransition]) => {
38
+ const nextValue = _s.select(selectorRef.current, ...args)
39
+ if (!callIfFunction(isEqual,nextValue,lastValueRef.current)) {
40
+ lastValueRef.current = nextValue
41
+ if (withTransition) {
42
+ (withTransition === true ? startTransition : withTransition)(() => fn(nextValue))
43
+ } else {
44
+ fn(nextValue)
45
+ }
46
+ }
47
+ })
48
+ return [register, call]
49
+ })
50
+ }
51
+
52
+ const useSelectorSignal = (value) => {
53
+ const prevValue = useRef(value)
54
+ const [_register, call] = useUpdateSignal(value)
55
+ const register = useCallback((selector, deps, isEqual, withTransition) => {
56
+ const prevDeps = useRef(EMPTY_DEPS)
57
+ if (prevDeps.current !== EMPTY_DEPS && !IS_DEPS_EQUALS(deps, prevDeps.current)) {
58
+ call(prevValue.current)
59
+ }
60
+ prevDeps.current = deps
61
+ return _register(selector, isEqual, withTransition)
62
+ }, [])
63
+ useEffect(() => {
64
+ if (prevValue.current !== value) {
65
+ prevValue.current = value
66
+ call(value)
67
+ }
68
+ },[value])
69
+ return register
70
+ }
71
+
72
+ const updateStateFn = (path,update) => state =>
73
+ path
74
+ ? _.update(path,(v) => callIfFunction(update,v),state)
75
+ : callIfFunction(update,state)
76
+
77
+
78
+ export const createStatefulContext = (v,defaultIsEqual) => {
79
+ const Ctx = React.createContext(v)
80
+ const Provider = ({value, setValue, utils,children}) => {
81
+ const register = useSelectorSignal(value)
82
+ const v = useLazyConstant(() => [register,setValue, utils])
83
+ return <Ctx.Provider value={v}>{children}</Ctx.Provider>
84
+ }
85
+ const useCtx = () => useContext(Ctx)
86
+
87
+ const useSelectValue = (selector,deps,defaultIsEqual, withTransition) => {
88
+ const [useRegister] = useCtx()
89
+ if (deps === true) {
90
+ return useRegister(selector,[],undefined,startTransition)
91
+ } else if (_.isPlainObject(deps)) {
92
+ return useRegister(selector,deps.deps,deps.isEqual, deps.withTransition)
93
+ } else {
94
+ return useRegister(selector,_.isArray(deps) ? deps : deps?.deps,defaultIsEqual, withTransition)
95
+ }
96
+ }
97
+ const useSetValue = (path) => {
98
+ const [reg,set ] = useCtx()
99
+ return useConstant((update) => set(updateStateFn(path,update)))
100
+ }
101
+ const useUtils = (path,deps) => {
102
+ const [reg,set, utils ] = useCtx()
103
+ return utils
104
+ }
105
+ return [Provider,[useSelectValue, useSetValue, useUtils, useCtx]]
106
+ }
107
+
108
+ export const createSelfStatefulContext = (v,defaultIsEqual) => {
109
+ const [Provider,[useSelectValue, useSetValue, useUtils, useCtx]] = createStatefulContext(v,defaultIsEqual)
110
+
111
+ const StateFullProvider = ({init = {}, utils,children}) => {
112
+ const [state,setState] = useState(init)
113
+ return <Provider value={state} setValue={setState} utils={utils}>
114
+ {children}
115
+ </Provider>
116
+ }
117
+ return [StateFullProvider,[useSelectValue, useSetValue, useUtils, useCtx]]
118
+ }
119
+
120
+
121
+ export const createLazyStatefulContext = (toPromise,defaultIsEqual) => {
122
+ const [Provider,[useSelectValue, useSetValue, useUtils, useCtx]] = createStatefulContext(EMPTY_VALUE,defaultIsEqual)
123
+ const useSelectLazyValue = (selector,deps,isEqual = defaultIsEqual,withTransition) => {
124
+ const value = useSelectValue(selector,deps,isEqual,withTransition)
125
+ const utils = useUtils()
126
+ if (value === EMPTY_VALUE) {
127
+ const loadedValue = use(utils._lazyValue())
128
+ return _s.select(selector,loadedValue)
129
+ }
130
+ return value
131
+ }
132
+ const useSetLazyValue = (path) => {
133
+ const [,setValue,utils] = useCtx()
134
+ return useConstant((update) => {
135
+ return setValue(value =>
136
+ value === EMPTY_VALUE
137
+ ? updateStateFn(path,update)(utils.loadedValue())
138
+ : updateStateFn(path,update)(value)
139
+ )
140
+ })
141
+ }
142
+
143
+ const useValuePromise = (selector,deps,isEqual,withTransition) => {
144
+ const value = useSelectValue(selector,deps,isEqual,withTransition)
145
+ const utils = useUtils()
146
+ return useCallback(() => {
147
+ if (value === EMPTY_VALUE) {
148
+ return utils._lazyValue().then(v => console.log(v,_s.select(selector,v),selector) || _s.select(selector,v))
149
+ }
150
+ return new Promise(value)
151
+ },[value,deps])
152
+ }
153
+ const LazyStateFullProvider = ({value, utils,children, fallback = null}) => {
154
+ const [state,setState] = useState(EMPTY_VALUE)
155
+ const promise = useRef()
156
+ const loadedValue = useRef()
157
+ const lazyUtils = useMemo(() => ({
158
+ ...utils,
159
+ _lazyValue: () => {
160
+ promise.current ??= callIfFunction(toPromise || _.identity,value)
161
+ promise.current.then((value) => {
162
+ loadedValue.current = value
163
+ })
164
+ return promise.current
165
+ },
166
+ loadedValue: () => loadedValue.current
167
+ }),[value,utils])
168
+ return <Provider value={state} setValue={setState} utils={lazyUtils}>
169
+ {
170
+ fallback===false
171
+ ? children
172
+ : <React.Suspense fallback={fallback}>{children}</React.Suspense>
173
+ }
174
+ </Provider>
175
+ }
176
+
177
+ return [LazyStateFullProvider,[useSelectLazyValue, useSetLazyValue, useValuePromise]]
178
+ }
179
+
180
+ export const createSelectableContext = (v) => {
181
+ const [Provider,[useSelectValue]] = createStatefulContext(v)
182
+ return [Provider,useSelectValue]
183
+ }
184
+ export const createTriggerUpdateContext = (v) => {
185
+ const [Provider,[useSelectValue]] = createStatefulContext(v)
186
+ const TriggerProvider = React.forwardRef(({children},ref) => {
187
+ const [v,setV] = useState(0)
188
+ const trigger = React.useMemo(() => () => setV(v => v+1),[v])
189
+ React.useImperativeHandle(ref, () => ({trigger}) , [])
190
+ return <Provider value={trigger}>{children}</Provider>
191
+ })
192
+ return [TriggerProvider,useSelectValue]
193
+ }
@@ -0,0 +1,12 @@
1
+ import React from 'react'
2
+ import {willUseLayers} from './willUseLayers'
3
+
4
+ const [useTitleLayers] = willUseLayers()
5
+
6
+ export const useTitle = (title) => {
7
+ const layer = useTitleLayers({
8
+ onTop: () => {
9
+ document.title = title
10
+ }
11
+ })
12
+ }
@@ -0,0 +1,126 @@
1
+ import React, {useRef, useMemo} from 'react'
2
+ import {callIfFunction} from '@startlibs/utils'
3
+ import {useCallState} from './useCallState'
4
+ import {useIsUnmounted} from './useIsUnmounted'
5
+ import {useRefState} from './useRefState'
6
+
7
+ const useToggleInternal = (startWith = false, useStore, callback, key) => {
8
+
9
+ const isOpen = useStore(startWith)
10
+ const closing = useStore(false)
11
+ const refIsOpen = useRefState(isOpen.get())
12
+ const refIsClosing = useRefState(closing.get())
13
+ const timerId = useRef()
14
+
15
+ const isUnmounted = useIsUnmounted()
16
+
17
+ const clearClosing = () => {
18
+ if (refIsClosing.get() !== false) {
19
+ closing.set(false)
20
+ refIsClosing.set(false)
21
+ window.clearTimeout(timerId.current)
22
+ }
23
+ }
24
+
25
+ const toggleWith = (value = true) => {
26
+ const calledValue = callIfFunction(value,refIsOpen.get())
27
+ const newValue = refIsOpen.get() === calledValue ? !calledValue : calledValue
28
+ if (!isUnmounted() && refIsOpen.get() !== newValue) {
29
+ const result = callIfFunction(callback,newValue,refIsOpen.get())
30
+ if (result === false) { return }
31
+ isOpen.set(newValue)
32
+ refIsOpen.set(newValue)
33
+ clearClosing()
34
+ }
35
+ }
36
+
37
+ const openWith = (value) => {
38
+ if (process.env.NODE_ENV !== 'production' && key) {
39
+ console.log(key,refIsOpen.get()!==value ? "toggle":"clear", refIsOpen.get(),value)
40
+ }
41
+ const nextValue = callIfFunction(value,refIsOpen.get())
42
+ if (refIsOpen.get() !== nextValue) {
43
+ toggleWith(() => nextValue)
44
+ } else {
45
+ clearClosing()
46
+ }
47
+ }
48
+
49
+ const nextClosingTick = (ticks, tickIndex) => {
50
+ if (ticks.length) {
51
+ if (isNaN(ticks[0])) {
52
+ clearClosing()
53
+ } else if (!isNaN(ticks[0])) {
54
+ closing.set(tickIndex + 1)
55
+ refIsClosing.set(tickIndex + 1)
56
+ timerId.current = setTimeout(() => nextClosingTick(ticks.slice(1), tickIndex + 1), Number(ticks[0]))
57
+ }
58
+ } else {
59
+ openWith(false)
60
+ }
61
+ }
62
+ const closeAfter = (...millisecs) => {
63
+ if (process.env.NODE_ENV !== 'production' && key) {
64
+ console.log(key,!refIsOpen.get() || refIsClosing.get() ? "addCLosing" : "closing" )
65
+ }
66
+ if (!refIsOpen.get() || refIsClosing.get()) return
67
+ nextClosingTick(millisecs, 0)
68
+ }
69
+
70
+ const _wait = (promise, start = true, end = false) => async (...args) => {
71
+ openWith(start)
72
+ try {
73
+ return await callIfFunction(promise,...args)
74
+ } finally {
75
+ openWith(end)
76
+ }
77
+ }
78
+
79
+ const setters = useMemo(()=>({
80
+ wait: (promise,start = true, end = false) => _wait(promise,start, end)(),
81
+ willWait: _wait,
82
+ open: (e) => {
83
+ if (process.env.NODE_ENV !== 'production') {
84
+ if (['string', 'number', 'boolean'].indexOf(typeof e) >= 0) {
85
+ console.log(`You are trying to open toggle with ${e}. Please, use openWith to open with a value`)
86
+ }
87
+ }
88
+ return openWith(true)
89
+ },
90
+ close: () => openWith(false),
91
+ toggle: (e) => {
92
+ if (process.env.NODE_ENV !== 'production') {
93
+ if (['string', 'number', 'boolean'].indexOf(typeof e) >= 0) {
94
+ console.log(`You are trying to toogle a toggle with ${e}. Please, use openWith to open with a value`)
95
+ }
96
+ }
97
+ toggleWith(true)
98
+ },
99
+ willOpenWith: (value) => () => openWith(value),
100
+ willCloseAfter: (...millsecs) => () => closeAfter(...millsecs),
101
+ willToggleWith: (value) => () => toggleWith(value),
102
+ openWith,
103
+ closeAfter,
104
+ toggleWith,
105
+ get: refIsOpen.get
106
+ }),[])
107
+ const settersWithNewRef = {...setters}
108
+ if (closing.val) {
109
+ return Object.assign(settersWithNewRef, {isOpen: isOpen.val, closing: closing.val})
110
+ } else {
111
+ Object.defineProperties(settersWithNewRef, {
112
+ isOpen: {
113
+ enumerable: true,
114
+ get: isOpen.get
115
+ },
116
+ closing: {
117
+ enumerable: true,
118
+ get: closing.get
119
+ }
120
+ })
121
+ return settersWithNewRef
122
+ }
123
+ }
124
+
125
+ export const useToggle = (startWith, callback,key) => useToggleInternal(startWith, useCallState, callback,key)
126
+ export const useRefToggle = (startWith) => useToggleInternal(startWith, useRefState)
@@ -0,0 +1,14 @@
1
+ import React, {useRef, useEffect} from 'react'
2
+
3
+ export const useUpdateEffect = (effect,inputs) => {
4
+
5
+ const pastFirstTime = useRef()
6
+
7
+ useEffect(() => {
8
+ if (pastFirstTime.current) {
9
+ return effect()
10
+ } else {
11
+ pastFirstTime.current = true
12
+ }
13
+ },inputs)
14
+ }
@@ -0,0 +1,14 @@
1
+ import {useEffect} from 'react'
2
+ import {useForceUpdate} from './useForceUpdate'
3
+ import _ from 'lodash/fp'
4
+
5
+ export const useUpdateOnResize = (debounceInterval = 200) => {
6
+ const update = useForceUpdate()
7
+ useEffect(() => {
8
+ const trigger = _.debounce(debounceInterval, update)
9
+ window.addEventListener('resize', trigger)
10
+ return () => {
11
+ window.removeEventListener('resize', trigger)
12
+ }
13
+ },[])
14
+ }
@@ -0,0 +1,14 @@
1
+ import {startTransition, useEffect, useState} from "react";
2
+
3
+
4
+ export const useWithTransition = (value) => {
5
+ const [state,setState] = useState(value)
6
+
7
+ useEffect(() => {
8
+ startTransition(() => {
9
+ setState(value)
10
+ })
11
+ },[value])
12
+
13
+ return state
14
+ }
@@ -0,0 +1,42 @@
1
+ import React, {useState, useCallback} from 'react'
2
+ import {willUseSharedCallback} from './willUseSharedCallback'
3
+ import {callIfFunction} from '@startlibs/utils'
4
+
5
+
6
+ export const willUseLayers = (useEffect = React.useEffect) => {
7
+ const [useRegisterSharedCallback,callGroup,getSize] = willUseSharedCallback(useEffect)
8
+ const useLayer = ({onFirst, onEmpty, onTop, onRemove} = {}, listener) => {
9
+
10
+ const resetIndex = useCallback(() => {
11
+ setIndex(getIndex())
12
+ if (getIndex()+1 === getSize()) {
13
+ callIfFunction(onTop,getIndex)
14
+ }
15
+ },[])
16
+
17
+ const getIndex = useRegisterSharedCallback(resetIndex, listener)
18
+ const [index,setIndex] = useState(getIndex())
19
+
20
+ useEffect(() => {
21
+ if (getIndex() === 0) {
22
+ callIfFunction(onFirst)
23
+ }
24
+ resetIndex()
25
+ return () => {
26
+ callIfFunction(onRemove,getSize())
27
+ if (getSize() === 0) {
28
+ callIfFunction(onEmpty)
29
+ }
30
+ callGroup()
31
+ }
32
+ },[])
33
+
34
+ return [index,{
35
+ isFirst: ()=> getIndex() === 1,
36
+ isTop: () => getIndex() === getSize()-1,
37
+ isEmpty: () => getSize() === 0,
38
+ getSize: () => getSize()
39
+ }]
40
+ }
41
+ return [useLayer,getSize]
42
+ }
@@ -0,0 +1,60 @@
1
+ import React, {useRef} from 'react'
2
+
3
+
4
+ const callList = (list, firstArg, ...args) => list.map(({current}) => typeof firstArg === 'function' ? firstArg(current) : current(firstArg,...args))
5
+
6
+ export const willUseSharedCallback = (useEffect = React.useEffect) => {
7
+ let mountedCallbacks = []
8
+ let listenerCallbacks = []
9
+ const remove = (ref) => mountedCallbacks = mountedCallbacks.filter(_ => _ !== ref)
10
+ const add = (ref) => mountedCallbacks = mountedCallbacks.concat([ref])
11
+ const get = () => mountedCallbacks
12
+
13
+ const removeListener = (ref) => listenerCallbacks = listenerCallbacks.filter(_ => _ !== ref)
14
+ const addListener = (ref) => listenerCallbacks = listenerCallbacks.concat([ref])
15
+ const getListeners = (ref) => listenerCallbacks
16
+
17
+ const lastCall = {current:null,index:0}
18
+
19
+ const call = (...args) => {
20
+ const resp = callList(get(), ...args)
21
+ callList(getListeners(), ...args)
22
+ lastCall.current = args
23
+ lastCall.index++
24
+ return resp
25
+ }
26
+ const getSize = () => get().length
27
+
28
+ const useRegister = (callback, listener = false) => {
29
+ const ref = useRef(callback)
30
+ if (ref.current !== callback) {
31
+ ref.current = callback
32
+ }
33
+ const lastCallIndex = lastCall.index
34
+ useEffect(() => {
35
+ if (!ref.current) { return }
36
+ if (listener) {
37
+ addListener(ref)
38
+ } else {
39
+ add(ref)
40
+ if (lastCallIndex !== lastCall.index && lastCall.current) {
41
+ callList([ref],...lastCall.current)
42
+ }
43
+ }
44
+ return () => {
45
+ if (listener) {
46
+ removeListener(ref)
47
+ } else {
48
+ remove(ref)
49
+ }
50
+ }
51
+ }, [])
52
+ return () => get().indexOf(ref)
53
+ }
54
+
55
+ return [
56
+ useRegister,
57
+ call,
58
+ getSize
59
+ ]
60
+ }
@@ -0,0 +1,34 @@
1
+ import React, {useState} from 'react'
2
+ import {callIfFunction, ifUndefined} from '@startlibs/utils'
3
+ import {willUseSharedCallback} from './willUseSharedCallback'
4
+
5
+ const notDefined = {}
6
+
7
+ export const willUseSharedState = (initialValue) => {
8
+ const [useRegisterGroupCallback,callGroup,getSize] = willUseSharedCallback()
9
+ let sharedValue = ifUndefined(initialValue,notDefined)
10
+
11
+ const setGroupState = (newValue) => {
12
+ sharedValue = callIfFunction(newValue,sharedValue)
13
+ callGroup(sharedValue)
14
+ }
15
+
16
+ const refState = () => {
17
+ useRegisterGroupCallback()
18
+ return [()=>sharedValue,setGroupState]
19
+ }
20
+
21
+ const valueState = (defaultValue) => {
22
+ const prevValue = sharedValue !== notDefined ? sharedValue : defaultValue
23
+ if (prevValue === defaultValue) {
24
+ sharedValue = defaultValue
25
+ }
26
+ const [value, setValue] = useState(prevValue)
27
+ useRegisterGroupCallback(setValue)
28
+ return [value,setGroupState]
29
+ }
30
+ const clear = () => {
31
+ sharedValue = notDefined
32
+ }
33
+ return [valueState,refState,setGroupState,()=>sharedValue,clear]
34
+ }
@@ -0,0 +1,103 @@
1
+ import React, {useCallback, useContext, useEffect, useMemo, useState} from 'react'
2
+ import {_s, formatPath} from '@startlibs/utils'
3
+ import _ from 'lodash/fp'
4
+ import {useCatalogManager, useConsumerCatalog} from './useConsumerCatalog'
5
+ import {useIsUnmounted} from './useIsUnmounted'
6
+ import {useRefState} from './useRefState'
7
+
8
+ const updateAllInputsState = (inputs, values) => {
9
+ const deferedUndefined = []
10
+ inputs.forEach((input) => {
11
+ const [setValue, selector] = input
12
+ const newValue = selector(values)
13
+ if (newValue === undefined) {
14
+ deferedUndefined.push([setValue,newValue])
15
+ } else {
16
+ setValue(newValue)
17
+ }
18
+ })
19
+ deferedUndefined.forEach(([set,value])=> set(value))
20
+ }
21
+
22
+ const pathSelector = (path) => _s.get(path || [])
23
+ const parsePathOrSelector = (pathOrSelector) => {
24
+ const isNotSelector = typeof pathOrSelector !== 'function'
25
+ if (isNotSelector) {
26
+ return [formatPath(pathOrSelector), pathSelector(pathOrSelector)]
27
+ } else {
28
+ return ['', pathOrSelector]
29
+ }
30
+ }
31
+ export const willUseSpreadState = (defaultContextValue,options = {}) => {
32
+
33
+ const Context = React.createContext(defaultContextValue)
34
+ const EMPTY_GLOBAL = {}
35
+ let prevInitState = EMPTY_GLOBAL
36
+ let globalState = EMPTY_GLOBAL
37
+ const getGlobalState = (key) => _.isString(key) || _.isArray(key) ? _.get(key,globalState) : globalState
38
+
39
+ const useProvideSpreadState = (initState, setCallback) => {
40
+ const [consumerList, manager] = useConsumerCatalog((input) => updateAllInputsState([input], state.get()))
41
+ const state = useRefState(initState, setCallback)
42
+
43
+ if (options.initRefCheck) {
44
+ if (prevInitState !== initState) {
45
+ globalState = initState
46
+ }
47
+ prevInitState = initState
48
+ }
49
+
50
+ if (globalState === EMPTY_GLOBAL) {
51
+ globalState = initState
52
+ }
53
+ useEffect(() => {
54
+ globalState = state.get()
55
+ },[])
56
+
57
+ const setState = (newState, fastPath, config) => {
58
+ // console.log("Fastpath noop:"+fastPath)
59
+ state.set(newState, config)
60
+ globalState = state.get()
61
+ updateAllInputsState(consumerList(), state.get())
62
+ }
63
+ const contextValue = useMemo(() => [state.get, setState, manager], [])
64
+
65
+ return [Context.Provider, contextValue, [state.get, setState]]
66
+ }
67
+
68
+ const useSpreadState = (pathOrSelector, inputs) => {
69
+ const [getSpreadState, setSpreadState, manager] = useContext(Context)
70
+ const [path, selector] = parsePathOrSelector(pathOrSelector)
71
+ const pathOrInput = [path] || inputs || []
72
+ const [value, setValue] = useState(selector(getSpreadState()))
73
+
74
+ const isUnmounted = useIsUnmounted()
75
+
76
+ const currentPath = useRefState(path)
77
+ if (path !== currentPath.get()) {
78
+ /* when path changes, the consumerCatalogCallback will update the new value
79
+ * another solution would be to call setValue here directly
80
+ * the return value will still be the old, but will be changed before render, just like getDerivedStateFromProps
81
+ *
82
+ * if there's a need for the return value to be the same, the value or, if enters here new value,
83
+ * can be returned in an temp variable
84
+ * */
85
+ currentPath.set(path)
86
+ }
87
+
88
+ const input = useMemo(() => [(v) => {
89
+ /* noop for elements that may be unregistered while looping through consumerList */
90
+ if (path === currentPath.get() && !isUnmounted()) {
91
+ setValue(v)
92
+ }
93
+ }, selector], pathOrInput)
94
+
95
+ useCatalogManager(manager, input)
96
+ const setState = useCallback((v) => setSpreadState((_.isFunction(v) ? (pathOrSelector === undefined ? () => v : _.update) : _.set)(path, v), path), pathOrInput)
97
+ const getValue = () => selector(getGlobalState())
98
+ return [value, setState, getValue]
99
+ }
100
+
101
+
102
+ return [useProvideSpreadState, useSpreadState, Context, getGlobalState]
103
+ }
package/src/index.js ADDED
@@ -0,0 +1,32 @@
1
+ export * from './StartlibsProvider'
2
+ export * from './hooks/willUseLayers'
3
+ export * from './hooks/willUseSharedCallback'
4
+ export * from './hooks/willUseSharedState'
5
+ export * from './hooks/willUseSpreadState'
6
+ export * from './SlotFill'
7
+ export * from './hocs/consumes'
8
+ export * from './hocs/withDialogError'
9
+ export * from './hocs/withGroupEvent'
10
+ export * from './hocs/WithRef'
11
+ export * from './hocs/WithLazyResource'
12
+ export * from './hooks/useCallbackStable'
13
+ export * from './hooks/WithEffect'
14
+ export * from './hooks/useToggle'
15
+ export * from './hooks/usePopupToggle'
16
+ export * from './hooks/useCallState'
17
+ export * from './hooks/useRefState'
18
+ export * from './hooks/useConsumerCatalog'
19
+ export * from './hooks/useTitle'
20
+ export * from './hooks/useRecycleFocus'
21
+ export * from './hooks/usePrevious'
22
+ export * from './hooks/useIsUnmounted'
23
+ export * from './hooks/useEnsureRef'
24
+ export * from './hooks/useConstant'
25
+ export * from './hooks/useForceUpdate'
26
+ export * from './hooks/useUpdateOnResize'
27
+ export * from './hooks/useAsyncEffect'
28
+ export * from './hooks/useUpdateEffect'
29
+ export * from './hooks/useRefMemo'
30
+ export * from './hooks/useSignal'
31
+ export * from './hooks/WithConstant'
32
+ export * from './hooks/useWithTransition'
package/.babelrc DELETED
@@ -1,27 +0,0 @@
1
- // .babelrc
2
- {
3
- "presets": [
4
- "@babel/preset-react",
5
- "@babel/preset-flow",
6
- [
7
- "@babel/preset-env",
8
- {
9
- "modules": false
10
- }
11
- ]
12
- ],
13
- "plugins": [
14
- "lodash",
15
- "macros",
16
- "fbjs-scripts/babel-6/dev-expression",
17
- "@babel/plugin-proposal-export-namespace-from",
18
- "@babel/plugin-proposal-throw-expressions",
19
- "@babel/plugin-syntax-import-meta",
20
- "@babel/plugin-proposal-json-strings",
21
- "@babel/plugin-syntax-dynamic-import",
22
- "@babel/plugin-transform-arrow-functions",
23
- "@babel/plugin-transform-spread",
24
- "@babel/plugin-proposal-object-rest-spread",
25
- ["@babel/plugin-proposal-class-properties", {"loose": true}]
26
- ]
27
- }