react-sync-ui 0.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Jakub Švehla
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # React sync ui
@@ -0,0 +1,14 @@
1
+ /// <reference types="react" />
2
+ export declare const syncUIFactory: () => {
3
+ makeSyncUI: <ArgData, ResolveValue = void>(SyncUserComp: import("react").FC<{
4
+ data: ArgData;
5
+ resolve: (value: ResolveValue) => void;
6
+ reject: (reason?: any) => void;
7
+ }>) => (input: ArgData) => Promise<ResolveValue>;
8
+ RegisterSyncUI: () => JSX.Element;
9
+ };
10
+ export declare const makeSyncUI: <ArgData, ResolveValue = void>(SyncUserComp: import("react").FC<{
11
+ data: ArgData;
12
+ resolve: (value: ResolveValue) => void;
13
+ reject: (reason?: any) => void;
14
+ }>) => (input: ArgData) => Promise<ResolveValue>, RegisterSyncUI: () => JSX.Element;
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+
2
+ 'use strict'
3
+
4
+ if (process.env.NODE_ENV === 'production') {
5
+ module.exports = require('./react-sync-ui.cjs.production.min.js')
6
+ } else {
7
+ module.exports = require('./react-sync-ui.cjs.development.js')
8
+ }
@@ -0,0 +1,128 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
+
7
+ var React = require('react');
8
+ var React__default = _interopDefault(React);
9
+
10
+ var useComponentDidMount = function useComponentDidMount(fn) {
11
+ React.useEffect(fn, []);
12
+ };
13
+
14
+ var getSingletonCompCheck = function getSingletonCompCheck(errorMsg) {
15
+ var globalMountCounter = 0;
16
+ return function () {
17
+ useComponentDidMount(function () {
18
+ if (globalMountCounter > 0) throw new Error(errorMsg);
19
+ globalMountCounter++;
20
+ });
21
+ return React__default.createElement(React__default.Fragment, null);
22
+ };
23
+ }; // TODO: add docs + add tests
24
+
25
+
26
+ var useAsyncQueue = function useAsyncQueue() {
27
+ var _asyncQueue$, _asyncQueue$2;
28
+
29
+ var _useState = React.useState([]),
30
+ asyncQueue = _useState[0],
31
+ setAsyncQueue = _useState[1];
32
+
33
+ var registerToQueue = React.useCallback(function (type, data) {
34
+ return new Promise(function (resolve, reject) {
35
+ return setAsyncQueue(function (p) {
36
+ return [].concat(p, [{
37
+ type: type,
38
+ data: data,
39
+ resolve: resolve,
40
+ reject: reject
41
+ }]);
42
+ });
43
+ });
44
+ }, []);
45
+ var resolveHeadItem = React.useCallback(function (value) {
46
+ setAsyncQueue(function (queue) {
47
+ var first = queue[0],
48
+ rest = queue.slice(1);
49
+ first == null ? void 0 : first.resolve(value);
50
+ return rest;
51
+ });
52
+ }, []);
53
+ var rejectHeadItem = React.useCallback(function (reason) {
54
+ setAsyncQueue(function (queue) {
55
+ var first = queue[0],
56
+ rest = queue.slice(1);
57
+ first == null ? void 0 : first.reject(reason);
58
+ return rest;
59
+ });
60
+ }, []);
61
+ return {
62
+ head: asyncQueue[0] ? {
63
+ data: (_asyncQueue$ = asyncQueue[0]) == null ? void 0 : _asyncQueue$.data,
64
+ type: (_asyncQueue$2 = asyncQueue[0]) == null ? void 0 : _asyncQueue$2.type,
65
+ resolve: resolveHeadItem,
66
+ reject: rejectHeadItem
67
+ } : undefined,
68
+ registerToQueue: registerToQueue
69
+ };
70
+ };
71
+ var syncUIFactory = function syncUIFactory() {
72
+ var mutSyncUIComponentsRenderQueue = [];
73
+ var ThrowIfMoreInstances = getSingletonCompCheck("You have to init <RegisterSyncUI /> just one time");
74
+ return {
75
+ makeSyncUI: function makeSyncUI(SyncUserComp) {
76
+ var _ref, _SyncUserComp$display;
77
+
78
+ var _debugName = (_ref = (_SyncUserComp$display = SyncUserComp.displayName) != null ? _SyncUserComp$display : SyncUserComp.name) != null ? _ref : "uniqSymbolMessageType";
79
+
80
+ var syncUIComponentType = Symbol(_debugName); // object with the registerToQueue key has to be there to change returned mutable reference object while the function is already called
81
+
82
+ var singletonSyncUIRef = {
83
+ registerToQueue: undefined
84
+ };
85
+
86
+ var SyncUISingletonComp = function SyncUISingletonComp(props) {
87
+ useComponentDidMount(function () {
88
+ singletonSyncUIRef.registerToQueue = props.registerToQueue;
89
+ return function () {
90
+ return singletonSyncUIRef.registerToQueue = undefined;
91
+ };
92
+ });
93
+ if (!props.head) return null;
94
+ if (props.head.type !== syncUIComponentType) return null;
95
+ return React__default.createElement(SyncUserComp, {
96
+ data: props.head.data,
97
+ resolve: props.head.resolve,
98
+ reject: props.head.reject
99
+ });
100
+ };
101
+
102
+ mutSyncUIComponentsRenderQueue.push(SyncUISingletonComp);
103
+ return function (input) {
104
+ if (!singletonSyncUIRef.registerToQueue) throw new Error("You have to initialize <RegisterSyncUI />");
105
+ return singletonSyncUIRef.registerToQueue(syncUIComponentType, input);
106
+ };
107
+ },
108
+ RegisterSyncUI: function RegisterSyncUI() {
109
+ var queue = useAsyncQueue();
110
+ return React__default.createElement(React__default.Fragment, null, React__default.createElement(ThrowIfMoreInstances, null), mutSyncUIComponentsRenderQueue.map(function (SyncComp, key) {
111
+ return React__default.createElement(React__default.Fragment, {
112
+ key: key
113
+ }, React__default.createElement(SyncComp, Object.assign({}, queue)));
114
+ }));
115
+ }
116
+ };
117
+ };
118
+
119
+ var syncUIFactory$1 = syncUIFactory;
120
+
121
+ var _syncUIFactory2 = /*#__PURE__*/syncUIFactory$1(),
122
+ makeSyncUI = _syncUIFactory2.makeSyncUI,
123
+ RegisterSyncUI = _syncUIFactory2.RegisterSyncUI;
124
+
125
+ exports.RegisterSyncUI = RegisterSyncUI;
126
+ exports.makeSyncUI = makeSyncUI;
127
+ exports.syncUIFactory = syncUIFactory$1;
128
+ //# sourceMappingURL=react-sync-ui.cjs.development.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-sync-ui.cjs.development.js","sources":["../src/syncUI.tsx","../src/index.ts"],"sourcesContent":["import React, { useCallback, useEffect, useState } from \"react\";\n\nexport const useComponentDidMount = (fn: Parameters<typeof useEffect>[0]) => {\n useEffect(fn, []);\n};\n\nconst getSingletonCompCheck = (errorMsg: string) => {\n let globalMountCounter = 0;\n\n return () => {\n useComponentDidMount(() => {\n if (globalMountCounter > 0) throw new Error(errorMsg);\n globalMountCounter++;\n });\n return <React.Fragment />;\n };\n};\n\n// TODO: add docs + add tests\nexport const useAsyncQueue = <Data, ResolveValue = void>() => {\n const [asyncQueue, setAsyncQueue] = useState(\n [] as {\n // TODO: rename type into typeId\n type: Symbol;\n data: Data;\n resolve: (arg: ResolveValue) => void;\n reject: (arg: any) => void;\n }[]\n );\n\n const registerToQueue = useCallback((type: Symbol, data: Data) => {\n return new Promise<ResolveValue>((resolve, reject) => setAsyncQueue(p => [...p, { type, data, resolve, reject }]));\n }, []);\n\n const resolveHeadItem = useCallback((value: ResolveValue) => {\n setAsyncQueue(queue => {\n const [first, ...rest] = queue;\n first?.resolve(value);\n return rest;\n });\n }, []);\n\n const rejectHeadItem = useCallback((reason?: any) => {\n setAsyncQueue(queue => {\n const [first, ...rest] = queue;\n first?.reject(reason);\n return rest;\n });\n }, []);\n\n return {\n head: asyncQueue[0]\n ? {\n data: asyncQueue[0]?.data,\n type: asyncQueue[0]?.type,\n resolve: resolveHeadItem,\n reject: rejectHeadItem\n }\n : undefined,\n registerToQueue\n };\n};\n// https://github.com/jaredpalmer/tsdx/issues/200???\n// TODO: there is tsdx old typescript parser and new ts fancy syntax is not working...\n// type QueueItem<Data, ResolveValue> = ReturnType<typeof useAsyncQueue<any, any>>\ntype QueueItem<Data, ResolveValue> = {\n head:\n | {\n data: Data;\n type: Symbol;\n resolve: (value: ResolveValue) => void;\n reject: (reason?: any) => void;\n }\n | undefined;\n registerToQueue: (type: Symbol, data: Data) => Promise<ResolveValue>;\n};\n\nexport const syncUIFactory = () => {\n const mutSyncUIComponentsRenderQueue = [] as React.FC<QueueItem<any, any>>[];\n\n const ThrowIfMoreInstances = getSingletonCompCheck(\"You have to init <RegisterSyncUI /> just one time\");\n\n return {\n makeSyncUI: <ArgData, ResolveValue = void>(\n SyncUserComp: React.FC<{\n data: ArgData;\n resolve: (value: ResolveValue) => void;\n reject: (reason?: any) => void;\n }>\n ) => {\n const _debugName = SyncUserComp.displayName ?? SyncUserComp.name ?? \"uniqSymbolMessageType\";\n\n const syncUIComponentType = Symbol(_debugName);\n\n // object with the registerToQueue key has to be there to change returned mutable reference object while the function is already called\n const singletonSyncUIRef = {\n registerToQueue: undefined as undefined | QueueItem<ArgData, ResolveValue>[\"registerToQueue\"]\n };\n\n const SyncUISingletonComp = (props: QueueItem<ArgData, ResolveValue>) => {\n useComponentDidMount(() => {\n singletonSyncUIRef.registerToQueue = props.registerToQueue;\n return () => (singletonSyncUIRef.registerToQueue = undefined);\n });\n\n if (!props.head) return null;\n if (props.head.type !== syncUIComponentType) return null;\n\n return <SyncUserComp data={props.head.data} resolve={props.head.resolve} reject={props.head.reject} />;\n };\n\n mutSyncUIComponentsRenderQueue.push(SyncUISingletonComp);\n\n return (input: ArgData) => {\n if (!singletonSyncUIRef.registerToQueue) throw new Error(`You have to initialize <RegisterSyncUI />`);\n return singletonSyncUIRef.registerToQueue(syncUIComponentType, input);\n };\n },\n RegisterSyncUI: () => {\n const queue = useAsyncQueue();\n return (\n <>\n <ThrowIfMoreInstances />\n {mutSyncUIComponentsRenderQueue.map((SyncComp, key) => (\n <React.Fragment key={key}>\n <SyncComp {...queue} />\n </React.Fragment>\n ))}\n </>\n );\n }\n };\n};\n","import { syncUIFactory as _syncUIFactory } from \"./syncUI\";\nexport const syncUIFactory = _syncUIFactory;\nexport const { makeSyncUI, RegisterSyncUI } = syncUIFactory();\n"],"names":["useComponentDidMount","fn","useEffect","getSingletonCompCheck","errorMsg","globalMountCounter","Error","React","Fragment","useAsyncQueue","useState","asyncQueue","setAsyncQueue","registerToQueue","useCallback","type","data","Promise","resolve","reject","p","resolveHeadItem","value","queue","first","rest","rejectHeadItem","reason","head","undefined","syncUIFactory","mutSyncUIComponentsRenderQueue","ThrowIfMoreInstances","makeSyncUI","SyncUserComp","_debugName","displayName","name","syncUIComponentType","Symbol","singletonSyncUIRef","SyncUISingletonComp","props","push","input","RegisterSyncUI","map","SyncComp","key","_syncUIFactory"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=require("react"),r=(e=t)&&"object"==typeof e&&"default"in e?e.default:e,n=function(e){t.useEffect(e,[])},u=function(){var e,u=[],o=(e=0,function(){return n((function(){if(e>0)throw new Error("You have to init <RegisterSyncUI /> just one time");e++})),r.createElement(r.Fragment,null)});return{makeSyncUI:function(e){var t,o,a=null!=(t=null!=(o=e.displayName)?o:e.name)?t:"uniqSymbolMessageType",i=Symbol(a),c={registerToQueue:void 0};return u.push((function(t){return n((function(){return c.registerToQueue=t.registerToQueue,function(){return c.registerToQueue=void 0}})),t.head?t.head.type!==i?null:r.createElement(e,{data:t.head.data,resolve:t.head.resolve,reject:t.head.reject}):null})),function(e){if(!c.registerToQueue)throw new Error("You have to initialize <RegisterSyncUI />");return c.registerToQueue(i,e)}},RegisterSyncUI:function(){var e,n,a,i,c,l,s,f,d=(i=(a=t.useState([]))[0],c=a[1],l=t.useCallback((function(e,t){return new Promise((function(r,n){return c((function(u){return[].concat(u,[{type:e,data:t,resolve:r,reject:n}])}))}))}),[]),s=t.useCallback((function(e){c((function(t){var r=t[0],n=t.slice(1);return null==r||r.resolve(e),n}))}),[]),f=t.useCallback((function(e){c((function(t){var r=t[0],n=t.slice(1);return null==r||r.reject(e),n}))}),[]),{head:i[0]?{data:null==(e=i[0])?void 0:e.data,type:null==(n=i[0])?void 0:n.type,resolve:s,reject:f}:void 0,registerToQueue:l});return r.createElement(r.Fragment,null,r.createElement(o,null),u.map((function(e,t){return r.createElement(r.Fragment,{key:t},r.createElement(e,Object.assign({},d)))})))}}},o=u(),a=o.makeSyncUI;exports.RegisterSyncUI=o.RegisterSyncUI,exports.makeSyncUI=a,exports.syncUIFactory=u;
2
+ //# sourceMappingURL=react-sync-ui.cjs.production.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-sync-ui.cjs.production.min.js","sources":["../src/syncUI.tsx","../src/index.ts"],"sourcesContent":["import React, { useCallback, useEffect, useState } from \"react\";\n\nexport const useComponentDidMount = (fn: Parameters<typeof useEffect>[0]) => {\n useEffect(fn, []);\n};\n\nconst getSingletonCompCheck = (errorMsg: string) => {\n let globalMountCounter = 0;\n\n return () => {\n useComponentDidMount(() => {\n if (globalMountCounter > 0) throw new Error(errorMsg);\n globalMountCounter++;\n });\n return <React.Fragment />;\n };\n};\n\n// TODO: add docs + add tests\nexport const useAsyncQueue = <Data, ResolveValue = void>() => {\n const [asyncQueue, setAsyncQueue] = useState(\n [] as {\n // TODO: rename type into typeId\n type: Symbol;\n data: Data;\n resolve: (arg: ResolveValue) => void;\n reject: (arg: any) => void;\n }[]\n );\n\n const registerToQueue = useCallback((type: Symbol, data: Data) => {\n return new Promise<ResolveValue>((resolve, reject) => setAsyncQueue(p => [...p, { type, data, resolve, reject }]));\n }, []);\n\n const resolveHeadItem = useCallback((value: ResolveValue) => {\n setAsyncQueue(queue => {\n const [first, ...rest] = queue;\n first?.resolve(value);\n return rest;\n });\n }, []);\n\n const rejectHeadItem = useCallback((reason?: any) => {\n setAsyncQueue(queue => {\n const [first, ...rest] = queue;\n first?.reject(reason);\n return rest;\n });\n }, []);\n\n return {\n head: asyncQueue[0]\n ? {\n data: asyncQueue[0]?.data,\n type: asyncQueue[0]?.type,\n resolve: resolveHeadItem,\n reject: rejectHeadItem\n }\n : undefined,\n registerToQueue\n };\n};\n// https://github.com/jaredpalmer/tsdx/issues/200???\n// TODO: there is tsdx old typescript parser and new ts fancy syntax is not working...\n// type QueueItem<Data, ResolveValue> = ReturnType<typeof useAsyncQueue<any, any>>\ntype QueueItem<Data, ResolveValue> = {\n head:\n | {\n data: Data;\n type: Symbol;\n resolve: (value: ResolveValue) => void;\n reject: (reason?: any) => void;\n }\n | undefined;\n registerToQueue: (type: Symbol, data: Data) => Promise<ResolveValue>;\n};\n\nexport const syncUIFactory = () => {\n const mutSyncUIComponentsRenderQueue = [] as React.FC<QueueItem<any, any>>[];\n\n const ThrowIfMoreInstances = getSingletonCompCheck(\"You have to init <RegisterSyncUI /> just one time\");\n\n return {\n makeSyncUI: <ArgData, ResolveValue = void>(\n SyncUserComp: React.FC<{\n data: ArgData;\n resolve: (value: ResolveValue) => void;\n reject: (reason?: any) => void;\n }>\n ) => {\n const _debugName = SyncUserComp.displayName ?? SyncUserComp.name ?? \"uniqSymbolMessageType\";\n\n const syncUIComponentType = Symbol(_debugName);\n\n // object with the registerToQueue key has to be there to change returned mutable reference object while the function is already called\n const singletonSyncUIRef = {\n registerToQueue: undefined as undefined | QueueItem<ArgData, ResolveValue>[\"registerToQueue\"]\n };\n\n const SyncUISingletonComp = (props: QueueItem<ArgData, ResolveValue>) => {\n useComponentDidMount(() => {\n singletonSyncUIRef.registerToQueue = props.registerToQueue;\n return () => (singletonSyncUIRef.registerToQueue = undefined);\n });\n\n if (!props.head) return null;\n if (props.head.type !== syncUIComponentType) return null;\n\n return <SyncUserComp data={props.head.data} resolve={props.head.resolve} reject={props.head.reject} />;\n };\n\n mutSyncUIComponentsRenderQueue.push(SyncUISingletonComp);\n\n return (input: ArgData) => {\n if (!singletonSyncUIRef.registerToQueue) throw new Error(`You have to initialize <RegisterSyncUI />`);\n return singletonSyncUIRef.registerToQueue(syncUIComponentType, input);\n };\n },\n RegisterSyncUI: () => {\n const queue = useAsyncQueue();\n return (\n <>\n <ThrowIfMoreInstances />\n {mutSyncUIComponentsRenderQueue.map((SyncComp, key) => (\n <React.Fragment key={key}>\n <SyncComp {...queue} />\n </React.Fragment>\n ))}\n </>\n );\n }\n };\n};\n","import { syncUIFactory as _syncUIFactory } from \"./syncUI\";\nexport const syncUIFactory = _syncUIFactory;\nexport const { makeSyncUI, RegisterSyncUI } = syncUIFactory();\n"],"names":["useComponentDidMount","fn","useEffect","syncUIFactory","globalMountCounter","mutSyncUIComponentsRenderQueue","ThrowIfMoreInstances","Error","React","Fragment","makeSyncUI","SyncUserComp","_debugName","displayName","name","syncUIComponentType","Symbol","singletonSyncUIRef","registerToQueue","undefined","push","props","head","type","data","resolve","reject","input","RegisterSyncUI","asyncQueue","setAsyncQueue","resolveHeadItem","rejectHeadItem","queue","useState","useCallback","Promise","p","value","first","rest","reason","_asyncQueue$","_asyncQueue$2","map","SyncComp","key"],"mappings":"oJAEaA,EAAuB,SAACC,GACnCC,YAAUD,EAAI,KCFHE,ED4EgB,eAtEvBC,EAuEEC,EAAiC,GAEjCC,GAzEFF,EAAqB,EAElB,kBACLJ,GAAqB,cACfI,EAAqB,EAAG,MAAM,IAAIG,MAqES,qDApE/CH,OAEKI,gBAACA,EAAMC,uBAoET,CACLC,WAAY,SACVC,WAMMC,oBAAaD,EAAaE,eAAeF,EAAaG,QAAQ,wBAE9DC,EAAsBC,OAAOJ,GAG7BK,EAAqB,CACzBC,qBAAiBC,UAenBd,EAA+Be,MAZH,SAACC,UAC3BrB,GAAqB,kBACnBiB,EAAmBC,gBAAkBG,EAAMH,gBACpC,kBAAOD,EAAmBC,qBAAkBC,MAGhDE,EAAMC,KACPD,EAAMC,KAAKC,OAASR,EAA4B,KAE7CP,gBAACG,GAAaa,KAAMH,EAAMC,KAAKE,KAAMC,QAASJ,EAAMC,KAAKG,QAASC,OAAQL,EAAMC,KAAKI,SAHpE,QAQnB,SAACC,OACDV,EAAmBC,gBAAiB,MAAM,IAAIX,0DAC5CU,EAAmBC,gBAAgBH,EAAqBY,KAGnEC,eAAgB,qBAlGXC,EAAYC,EAUbZ,EAIAa,EAQAC,EA6EIC,GAnGHJ,KAA6BK,WAClC,QADiBJ,OAUbZ,EAAkBiB,eAAY,SAACZ,EAAcC,UAC1C,IAAIY,SAAsB,SAACX,EAASC,UAAWI,GAAc,SAAAO,mBAASA,GAAG,CAAEd,KAAAA,EAAMC,KAAAA,EAAMC,QAAAA,EAASC,OAAAA,aACtG,IAEGK,EAAkBI,eAAY,SAACG,GACnCR,GAAc,SAAAG,OACLM,EAAkBN,KAARO,EAAQP,wBACzBM,GAAAA,EAAOd,QAAQa,GACRE,OAER,IAEGR,EAAiBG,eAAY,SAACM,GAClCX,GAAc,SAAAG,OACLM,EAAkBN,KAARO,EAAQP,wBACzBM,GAAAA,EAAOb,OAAOe,GACPD,OAER,IAEI,CACLlB,KAAMO,EAAW,GACb,CACEL,cAAMK,EAAW,WAAXa,EAAelB,KACrBD,cAAMM,EAAW,WAAXc,EAAepB,KACrBE,QAASM,EACTL,OAAQM,QAEVb,EACJD,gBAAAA,WA8DIV,gCACEA,gBAACF,QACAD,EAA+BuC,KAAI,SAACC,EAAUC,UAC7CtC,gBAACA,EAAMC,UAASqC,IAAKA,GACnBtC,gBAACqC,mBAAaZ,cC3HkB9B,IAA/BO,IAAAA,oCAAYkB"}
@@ -0,0 +1,119 @@
1
+ import React, { useState, useCallback, useEffect } from 'react';
2
+
3
+ var useComponentDidMount = function useComponentDidMount(fn) {
4
+ useEffect(fn, []);
5
+ };
6
+
7
+ var getSingletonCompCheck = function getSingletonCompCheck(errorMsg) {
8
+ var globalMountCounter = 0;
9
+ return function () {
10
+ useComponentDidMount(function () {
11
+ if (globalMountCounter > 0) throw new Error(errorMsg);
12
+ globalMountCounter++;
13
+ });
14
+ return React.createElement(React.Fragment, null);
15
+ };
16
+ }; // TODO: add docs + add tests
17
+
18
+
19
+ var useAsyncQueue = function useAsyncQueue() {
20
+ var _asyncQueue$, _asyncQueue$2;
21
+
22
+ var _useState = useState([]),
23
+ asyncQueue = _useState[0],
24
+ setAsyncQueue = _useState[1];
25
+
26
+ var registerToQueue = useCallback(function (type, data) {
27
+ return new Promise(function (resolve, reject) {
28
+ return setAsyncQueue(function (p) {
29
+ return [].concat(p, [{
30
+ type: type,
31
+ data: data,
32
+ resolve: resolve,
33
+ reject: reject
34
+ }]);
35
+ });
36
+ });
37
+ }, []);
38
+ var resolveHeadItem = useCallback(function (value) {
39
+ setAsyncQueue(function (queue) {
40
+ var first = queue[0],
41
+ rest = queue.slice(1);
42
+ first == null ? void 0 : first.resolve(value);
43
+ return rest;
44
+ });
45
+ }, []);
46
+ var rejectHeadItem = useCallback(function (reason) {
47
+ setAsyncQueue(function (queue) {
48
+ var first = queue[0],
49
+ rest = queue.slice(1);
50
+ first == null ? void 0 : first.reject(reason);
51
+ return rest;
52
+ });
53
+ }, []);
54
+ return {
55
+ head: asyncQueue[0] ? {
56
+ data: (_asyncQueue$ = asyncQueue[0]) == null ? void 0 : _asyncQueue$.data,
57
+ type: (_asyncQueue$2 = asyncQueue[0]) == null ? void 0 : _asyncQueue$2.type,
58
+ resolve: resolveHeadItem,
59
+ reject: rejectHeadItem
60
+ } : undefined,
61
+ registerToQueue: registerToQueue
62
+ };
63
+ };
64
+ var syncUIFactory = function syncUIFactory() {
65
+ var mutSyncUIComponentsRenderQueue = [];
66
+ var ThrowIfMoreInstances = getSingletonCompCheck("You have to init <RegisterSyncUI /> just one time");
67
+ return {
68
+ makeSyncUI: function makeSyncUI(SyncUserComp) {
69
+ var _ref, _SyncUserComp$display;
70
+
71
+ var _debugName = (_ref = (_SyncUserComp$display = SyncUserComp.displayName) != null ? _SyncUserComp$display : SyncUserComp.name) != null ? _ref : "uniqSymbolMessageType";
72
+
73
+ var syncUIComponentType = Symbol(_debugName); // object with the registerToQueue key has to be there to change returned mutable reference object while the function is already called
74
+
75
+ var singletonSyncUIRef = {
76
+ registerToQueue: undefined
77
+ };
78
+
79
+ var SyncUISingletonComp = function SyncUISingletonComp(props) {
80
+ useComponentDidMount(function () {
81
+ singletonSyncUIRef.registerToQueue = props.registerToQueue;
82
+ return function () {
83
+ return singletonSyncUIRef.registerToQueue = undefined;
84
+ };
85
+ });
86
+ if (!props.head) return null;
87
+ if (props.head.type !== syncUIComponentType) return null;
88
+ return React.createElement(SyncUserComp, {
89
+ data: props.head.data,
90
+ resolve: props.head.resolve,
91
+ reject: props.head.reject
92
+ });
93
+ };
94
+
95
+ mutSyncUIComponentsRenderQueue.push(SyncUISingletonComp);
96
+ return function (input) {
97
+ if (!singletonSyncUIRef.registerToQueue) throw new Error("You have to initialize <RegisterSyncUI />");
98
+ return singletonSyncUIRef.registerToQueue(syncUIComponentType, input);
99
+ };
100
+ },
101
+ RegisterSyncUI: function RegisterSyncUI() {
102
+ var queue = useAsyncQueue();
103
+ return React.createElement(React.Fragment, null, React.createElement(ThrowIfMoreInstances, null), mutSyncUIComponentsRenderQueue.map(function (SyncComp, key) {
104
+ return React.createElement(React.Fragment, {
105
+ key: key
106
+ }, React.createElement(SyncComp, Object.assign({}, queue)));
107
+ }));
108
+ }
109
+ };
110
+ };
111
+
112
+ var syncUIFactory$1 = syncUIFactory;
113
+
114
+ var _syncUIFactory2 = /*#__PURE__*/syncUIFactory$1(),
115
+ makeSyncUI = _syncUIFactory2.makeSyncUI,
116
+ RegisterSyncUI = _syncUIFactory2.RegisterSyncUI;
117
+
118
+ export { RegisterSyncUI, makeSyncUI, syncUIFactory$1 as syncUIFactory };
119
+ //# sourceMappingURL=react-sync-ui.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-sync-ui.esm.js","sources":["../src/syncUI.tsx","../src/index.ts"],"sourcesContent":["import React, { useCallback, useEffect, useState } from \"react\";\n\nexport const useComponentDidMount = (fn: Parameters<typeof useEffect>[0]) => {\n useEffect(fn, []);\n};\n\nconst getSingletonCompCheck = (errorMsg: string) => {\n let globalMountCounter = 0;\n\n return () => {\n useComponentDidMount(() => {\n if (globalMountCounter > 0) throw new Error(errorMsg);\n globalMountCounter++;\n });\n return <React.Fragment />;\n };\n};\n\n// TODO: add docs + add tests\nexport const useAsyncQueue = <Data, ResolveValue = void>() => {\n const [asyncQueue, setAsyncQueue] = useState(\n [] as {\n // TODO: rename type into typeId\n type: Symbol;\n data: Data;\n resolve: (arg: ResolveValue) => void;\n reject: (arg: any) => void;\n }[]\n );\n\n const registerToQueue = useCallback((type: Symbol, data: Data) => {\n return new Promise<ResolveValue>((resolve, reject) => setAsyncQueue(p => [...p, { type, data, resolve, reject }]));\n }, []);\n\n const resolveHeadItem = useCallback((value: ResolveValue) => {\n setAsyncQueue(queue => {\n const [first, ...rest] = queue;\n first?.resolve(value);\n return rest;\n });\n }, []);\n\n const rejectHeadItem = useCallback((reason?: any) => {\n setAsyncQueue(queue => {\n const [first, ...rest] = queue;\n first?.reject(reason);\n return rest;\n });\n }, []);\n\n return {\n head: asyncQueue[0]\n ? {\n data: asyncQueue[0]?.data,\n type: asyncQueue[0]?.type,\n resolve: resolveHeadItem,\n reject: rejectHeadItem\n }\n : undefined,\n registerToQueue\n };\n};\n// https://github.com/jaredpalmer/tsdx/issues/200???\n// TODO: there is tsdx old typescript parser and new ts fancy syntax is not working...\n// type QueueItem<Data, ResolveValue> = ReturnType<typeof useAsyncQueue<any, any>>\ntype QueueItem<Data, ResolveValue> = {\n head:\n | {\n data: Data;\n type: Symbol;\n resolve: (value: ResolveValue) => void;\n reject: (reason?: any) => void;\n }\n | undefined;\n registerToQueue: (type: Symbol, data: Data) => Promise<ResolveValue>;\n};\n\nexport const syncUIFactory = () => {\n const mutSyncUIComponentsRenderQueue = [] as React.FC<QueueItem<any, any>>[];\n\n const ThrowIfMoreInstances = getSingletonCompCheck(\"You have to init <RegisterSyncUI /> just one time\");\n\n return {\n makeSyncUI: <ArgData, ResolveValue = void>(\n SyncUserComp: React.FC<{\n data: ArgData;\n resolve: (value: ResolveValue) => void;\n reject: (reason?: any) => void;\n }>\n ) => {\n const _debugName = SyncUserComp.displayName ?? SyncUserComp.name ?? \"uniqSymbolMessageType\";\n\n const syncUIComponentType = Symbol(_debugName);\n\n // object with the registerToQueue key has to be there to change returned mutable reference object while the function is already called\n const singletonSyncUIRef = {\n registerToQueue: undefined as undefined | QueueItem<ArgData, ResolveValue>[\"registerToQueue\"]\n };\n\n const SyncUISingletonComp = (props: QueueItem<ArgData, ResolveValue>) => {\n useComponentDidMount(() => {\n singletonSyncUIRef.registerToQueue = props.registerToQueue;\n return () => (singletonSyncUIRef.registerToQueue = undefined);\n });\n\n if (!props.head) return null;\n if (props.head.type !== syncUIComponentType) return null;\n\n return <SyncUserComp data={props.head.data} resolve={props.head.resolve} reject={props.head.reject} />;\n };\n\n mutSyncUIComponentsRenderQueue.push(SyncUISingletonComp);\n\n return (input: ArgData) => {\n if (!singletonSyncUIRef.registerToQueue) throw new Error(`You have to initialize <RegisterSyncUI />`);\n return singletonSyncUIRef.registerToQueue(syncUIComponentType, input);\n };\n },\n RegisterSyncUI: () => {\n const queue = useAsyncQueue();\n return (\n <>\n <ThrowIfMoreInstances />\n {mutSyncUIComponentsRenderQueue.map((SyncComp, key) => (\n <React.Fragment key={key}>\n <SyncComp {...queue} />\n </React.Fragment>\n ))}\n </>\n );\n }\n };\n};\n","import { syncUIFactory as _syncUIFactory } from \"./syncUI\";\nexport const syncUIFactory = _syncUIFactory;\nexport const { makeSyncUI, RegisterSyncUI } = syncUIFactory();\n"],"names":["useComponentDidMount","fn","useEffect","getSingletonCompCheck","errorMsg","globalMountCounter","Error","React","Fragment","useAsyncQueue","useState","asyncQueue","setAsyncQueue","registerToQueue","useCallback","type","data","Promise","resolve","reject","p","resolveHeadItem","value","queue","first","rest","rejectHeadItem","reason","head","undefined","syncUIFactory","mutSyncUIComponentsRenderQueue","ThrowIfMoreInstances","makeSyncUI","SyncUserComp","_debugName","displayName","name","syncUIComponentType","Symbol","singletonSyncUIRef","SyncUISingletonComp","props","push","input","RegisterSyncUI","map","SyncComp","key","_syncUIFactory"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import React, { useEffect } from "react";
2
+ export declare const useComponentDidMount: (fn: Parameters<typeof useEffect>[0]) => void;
3
+ export declare const useAsyncQueue: <Data, ResolveValue = void>() => {
4
+ head: {
5
+ data: Data;
6
+ type: Symbol;
7
+ resolve: (value: ResolveValue) => void;
8
+ reject: (reason?: any) => void;
9
+ } | undefined;
10
+ registerToQueue: (type: Symbol, data: Data) => Promise<ResolveValue>;
11
+ };
12
+ export declare const syncUIFactory: () => {
13
+ makeSyncUI: <ArgData, ResolveValue = void>(SyncUserComp: React.FC<{
14
+ data: ArgData;
15
+ resolve: (value: ResolveValue) => void;
16
+ reject: (reason?: any) => void;
17
+ }>) => (input: ArgData) => Promise<ResolveValue>;
18
+ RegisterSyncUI: () => JSX.Element;
19
+ };
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "react-sync-ui",
3
+ "version": "0.0.1",
4
+ "repository": "https://github.com/Svehla/react-sync-ui",
5
+ "license": "MIT",
6
+ "author": "Jakub Švehla",
7
+ "main": "dist/index.js",
8
+ "module": "dist/index.esm.js",
9
+ "typings": "dist/index.d.ts",
10
+ "files": [
11
+ "dist",
12
+ "src"
13
+ ],
14
+ "scripts": {
15
+ "analyze": "size-limit --why",
16
+ "build": "tsdx build",
17
+ "lint": "tsdx lint",
18
+ "lint:fix": "tsdx lint --fix",
19
+ "prepare": "tsdx build",
20
+ "size": "size-limit",
21
+ "start": "tsdx watch",
22
+ "test": "tsdx test --passWithNoTests",
23
+ "test:watch": "tsdx test --passWithNoTests --watchAll"
24
+ },
25
+ "husky": {
26
+ "hooks": {
27
+ "pre-commit": "tsdx lint"
28
+ }
29
+ },
30
+ "devDependencies": {
31
+ "@size-limit/preset-small-lib": "^5.0.5",
32
+ "@testing-library/react-hooks": "^7.0.2",
33
+ "@types/react": "^17.0.27",
34
+ "@types/react-dom": "^17.0.9",
35
+ "@typescript-eslint/parser": "^4.33.0",
36
+ "eslint-config-react-app": "^6.0.0",
37
+ "eslint-plugin-react": "^7.31.10",
38
+ "eslint-plugin-sort-imports-es6-autofix": "^0.6.0",
39
+ "husky": "^7.0.2",
40
+ "react": "^17.0.2",
41
+ "react-dom": "^17.0.2",
42
+ "size-limit": "^5.0.5",
43
+ "tsdx": "^0.14.1",
44
+ "tslib": "^2.3.1",
45
+ "typescript": "^4.8.3"
46
+ },
47
+ "peerDependencies": {
48
+ "react": ">=16"
49
+ },
50
+ "engines": {
51
+ "node": ">=10"
52
+ },
53
+ "size-limit": []
54
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { syncUIFactory as _syncUIFactory } from "./syncUI";
2
+ export const syncUIFactory = _syncUIFactory;
3
+ export const { makeSyncUI, RegisterSyncUI } = syncUIFactory();
package/src/syncUI.tsx ADDED
@@ -0,0 +1,133 @@
1
+ import React, { useCallback, useEffect, useState } from "react";
2
+
3
+ export const useComponentDidMount = (fn: Parameters<typeof useEffect>[0]) => {
4
+ useEffect(fn, []);
5
+ };
6
+
7
+ const getSingletonCompCheck = (errorMsg: string) => {
8
+ let globalMountCounter = 0;
9
+
10
+ return () => {
11
+ useComponentDidMount(() => {
12
+ if (globalMountCounter > 0) throw new Error(errorMsg);
13
+ globalMountCounter++;
14
+ });
15
+ return <React.Fragment />;
16
+ };
17
+ };
18
+
19
+ // TODO: add docs + add tests
20
+ export const useAsyncQueue = <Data, ResolveValue = void>() => {
21
+ const [asyncQueue, setAsyncQueue] = useState(
22
+ [] as {
23
+ // TODO: rename type into typeId
24
+ type: Symbol;
25
+ data: Data;
26
+ resolve: (arg: ResolveValue) => void;
27
+ reject: (arg: any) => void;
28
+ }[]
29
+ );
30
+
31
+ const registerToQueue = useCallback((type: Symbol, data: Data) => {
32
+ return new Promise<ResolveValue>((resolve, reject) => setAsyncQueue(p => [...p, { type, data, resolve, reject }]));
33
+ }, []);
34
+
35
+ const resolveHeadItem = useCallback((value: ResolveValue) => {
36
+ setAsyncQueue(queue => {
37
+ const [first, ...rest] = queue;
38
+ first?.resolve(value);
39
+ return rest;
40
+ });
41
+ }, []);
42
+
43
+ const rejectHeadItem = useCallback((reason?: any) => {
44
+ setAsyncQueue(queue => {
45
+ const [first, ...rest] = queue;
46
+ first?.reject(reason);
47
+ return rest;
48
+ });
49
+ }, []);
50
+
51
+ return {
52
+ head: asyncQueue[0]
53
+ ? {
54
+ data: asyncQueue[0]?.data,
55
+ type: asyncQueue[0]?.type,
56
+ resolve: resolveHeadItem,
57
+ reject: rejectHeadItem
58
+ }
59
+ : undefined,
60
+ registerToQueue
61
+ };
62
+ };
63
+ // https://github.com/jaredpalmer/tsdx/issues/200???
64
+ // TODO: there is tsdx old typescript parser and new ts fancy syntax is not working...
65
+ // type QueueItem<Data, ResolveValue> = ReturnType<typeof useAsyncQueue<any, any>>
66
+ type QueueItem<Data, ResolveValue> = {
67
+ head:
68
+ | {
69
+ data: Data;
70
+ type: Symbol;
71
+ resolve: (value: ResolveValue) => void;
72
+ reject: (reason?: any) => void;
73
+ }
74
+ | undefined;
75
+ registerToQueue: (type: Symbol, data: Data) => Promise<ResolveValue>;
76
+ };
77
+
78
+ export const syncUIFactory = () => {
79
+ const mutSyncUIComponentsRenderQueue = [] as React.FC<QueueItem<any, any>>[];
80
+
81
+ const ThrowIfMoreInstances = getSingletonCompCheck("You have to init <RegisterSyncUI /> just one time");
82
+
83
+ return {
84
+ makeSyncUI: <ArgData, ResolveValue = void>(
85
+ SyncUserComp: React.FC<{
86
+ data: ArgData;
87
+ resolve: (value: ResolveValue) => void;
88
+ reject: (reason?: any) => void;
89
+ }>
90
+ ) => {
91
+ const _debugName = SyncUserComp.displayName ?? SyncUserComp.name ?? "uniqSymbolMessageType";
92
+
93
+ const syncUIComponentType = Symbol(_debugName);
94
+
95
+ // object with the registerToQueue key has to be there to change returned mutable reference object while the function is already called
96
+ const singletonSyncUIRef = {
97
+ registerToQueue: undefined as undefined | QueueItem<ArgData, ResolveValue>["registerToQueue"]
98
+ };
99
+
100
+ const SyncUISingletonComp = (props: QueueItem<ArgData, ResolveValue>) => {
101
+ useComponentDidMount(() => {
102
+ singletonSyncUIRef.registerToQueue = props.registerToQueue;
103
+ return () => (singletonSyncUIRef.registerToQueue = undefined);
104
+ });
105
+
106
+ if (!props.head) return null;
107
+ if (props.head.type !== syncUIComponentType) return null;
108
+
109
+ return <SyncUserComp data={props.head.data} resolve={props.head.resolve} reject={props.head.reject} />;
110
+ };
111
+
112
+ mutSyncUIComponentsRenderQueue.push(SyncUISingletonComp);
113
+
114
+ return (input: ArgData) => {
115
+ if (!singletonSyncUIRef.registerToQueue) throw new Error(`You have to initialize <RegisterSyncUI />`);
116
+ return singletonSyncUIRef.registerToQueue(syncUIComponentType, input);
117
+ };
118
+ },
119
+ RegisterSyncUI: () => {
120
+ const queue = useAsyncQueue();
121
+ return (
122
+ <>
123
+ <ThrowIfMoreInstances />
124
+ {mutSyncUIComponentsRenderQueue.map((SyncComp, key) => (
125
+ <React.Fragment key={key}>
126
+ <SyncComp {...queue} />
127
+ </React.Fragment>
128
+ ))}
129
+ </>
130
+ );
131
+ }
132
+ };
133
+ };