@cripty2001/utils 0.0.259 → 0.0.261
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/dist/Appserver/client/react.d.ts +52 -0
- package/dist/Appserver/client/react.js +143 -0
- package/dist/Appserver/server.d.ts +4 -2
- package/dist/Appserver/server.js +40 -40
- package/dist/Appstorage.d.ts +1 -1
- package/dist/Appstorage.js +6 -10
- package/dist/Dispatcher.js +9 -13
- package/dist/Logger/Logger.js +5 -7
- package/dist/Searcher/index.js +1 -5
- package/dist/index.js +38 -70
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +1 -5
- package/dist/react/logger-display.js +12 -18
- package/dist/react-ui/button.js +9 -12
- package/dist/react-ui/copiable.js +11 -14
- package/dist/react-ui/form.d.ts +2 -2
- package/dist/react-ui/form.js +13 -19
- package/dist/react-ui/index.d.ts +8 -8
- package/dist/react-ui/index.js +9 -22
- package/dist/react-ui/input.js +11 -14
- package/dist/react-ui/loader.d.ts +1 -1
- package/dist/react-ui/loader.js +9 -12
- package/dist/react-ui/modal.js +9 -12
- package/dist/react-ui/table.js +6 -9
- package/dist/react-ui/textButton.d.ts +1 -1
- package/dist/react-ui/textButton.js +4 -10
- package/dist/react-whispr.d.ts +3 -3
- package/dist/react-whispr.js +60 -76
- package/package.json +9 -2
- package/dist/Appserver/client.d.ts +0 -1
- package/dist/Appserver/client.js +0 -147
- package/dist/Appserver/common.d.ts +0 -3
- package/dist/Appserver/common.js +0 -2
- package/dist/MailTemplate/image.d.ts +0 -10
- package/dist/MailTemplate/image.js +0 -37
- package/dist/MailTemplate/index.d.ts +0 -31
- package/dist/MailTemplate/index.js +0 -90
- package/dist/MailTemplate/raw.d.ts +0 -7
- package/dist/MailTemplate/raw.js +0 -12
- package/dist/MailTemplate/text.d.ts +0 -13
- package/dist/MailTemplate/text.js +0 -28
package/dist/react-ui/loader.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const react_whispr_1 = require("../react-whispr");
|
|
6
|
-
const react_1 = require("react");
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useWhisprValue } from "../react-whispr.js";
|
|
3
|
+
import { useRef } from "react";
|
|
7
4
|
const spinKeyframes = `
|
|
8
5
|
@keyframes spin {
|
|
9
6
|
from { transform: rotate(0deg); }
|
|
@@ -18,23 +15,23 @@ if (typeof document !== 'undefined') {
|
|
|
18
15
|
document.head.appendChild(style);
|
|
19
16
|
}
|
|
20
17
|
}
|
|
21
|
-
function Loader(props) {
|
|
18
|
+
export default function Loader(props) {
|
|
22
19
|
const ck = props.computeRefreshKey ?? ((input) => JSON.stringify(input));
|
|
23
|
-
const active =
|
|
20
|
+
const active = useRef({
|
|
24
21
|
input: undefined,
|
|
25
22
|
output: { loading: true, progress: 0 }
|
|
26
23
|
});
|
|
27
|
-
const incoming =
|
|
24
|
+
const incoming = useWhisprValue(props.data.data);
|
|
28
25
|
if (ck(active.current.input) !== ck(incoming.input) ||
|
|
29
26
|
!incoming.output.loading) {
|
|
30
27
|
active.current = incoming;
|
|
31
28
|
}
|
|
32
|
-
return ((
|
|
29
|
+
return (_jsx("div", { children: _jsx(Content, { data: active.current, children: props.children, loader: props.loader }) }));
|
|
33
30
|
}
|
|
34
31
|
function Content({ data, children, loader }) {
|
|
35
32
|
const result = data.output;
|
|
36
33
|
if (result.loading)
|
|
37
|
-
return loader ?? ((
|
|
34
|
+
return loader ?? (_jsx("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh' }, children: _jsx("div", { style: {
|
|
38
35
|
animation: 'spin 1s linear infinite',
|
|
39
36
|
borderRadius: '9999px',
|
|
40
37
|
height: '3rem',
|
|
@@ -43,6 +40,6 @@ function Content({ data, children, loader }) {
|
|
|
43
40
|
borderBottom: '2px solid #111827'
|
|
44
41
|
} }) }));
|
|
45
42
|
if (!result.ok)
|
|
46
|
-
return (
|
|
43
|
+
return _jsx("div", { style: { color: '#ef4444' }, children: result.error.message });
|
|
47
44
|
return children({ data: result.data });
|
|
48
45
|
}
|
package/dist/react-ui/modal.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.default = ModalComponent;
|
|
4
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const react_1 = require("react");
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
6
3
|
const slideUpKeyframes = `
|
|
7
4
|
@keyframes slide-up {
|
|
8
5
|
from {
|
|
@@ -24,11 +21,11 @@ if (typeof document !== 'undefined') {
|
|
|
24
21
|
}
|
|
25
22
|
}
|
|
26
23
|
let modalCount = 0;
|
|
27
|
-
function ModalComponent({ children, open, setOpen, animate = false, panelClassName = "", }) {
|
|
28
|
-
const zIndex =
|
|
29
|
-
const id =
|
|
30
|
-
const dismiss =
|
|
31
|
-
|
|
24
|
+
export default function ModalComponent({ children, open, setOpen, animate = false, panelClassName = "", }) {
|
|
25
|
+
const zIndex = useRef(1000 + modalCount++).current;
|
|
26
|
+
const id = useRef(`modal-${zIndex}`).current;
|
|
27
|
+
const dismiss = useCallback(() => setOpen(false), [setOpen]);
|
|
28
|
+
useEffect(() => {
|
|
32
29
|
if (!open)
|
|
33
30
|
return;
|
|
34
31
|
const onKey = (event) => {
|
|
@@ -41,7 +38,7 @@ function ModalComponent({ children, open, setOpen, animate = false, panelClassNa
|
|
|
41
38
|
if (!open)
|
|
42
39
|
return null;
|
|
43
40
|
const content = typeof children === "function" ? children({ dismiss }) : children;
|
|
44
|
-
return ((
|
|
41
|
+
return (_jsx("div", { id: id, style: {
|
|
45
42
|
position: 'fixed',
|
|
46
43
|
top: 0,
|
|
47
44
|
left: 0,
|
|
@@ -55,5 +52,5 @@ function ModalComponent({ children, open, setOpen, animate = false, panelClassNa
|
|
|
55
52
|
height: '100vh',
|
|
56
53
|
width: '100vw',
|
|
57
54
|
zIndex: zIndex,
|
|
58
|
-
}, onClick: dismiss, children: (
|
|
55
|
+
}, onClick: dismiss, children: _jsx("div", { role: "dialog", "aria-modal": "true", className: panelClassName, style: { maxWidth: '100%', animation: animate ? 'slide-up 0.3s ease-out' : undefined }, onClick: (e) => e.stopPropagation(), children: content }) }));
|
|
59
56
|
}
|
package/dist/react-ui/table.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.default = Table;
|
|
4
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
function Table({ value, headers }) {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export default function Table({ value, headers }) {
|
|
6
3
|
if (value.length === 0) {
|
|
7
|
-
return ((
|
|
4
|
+
return (_jsx("div", { style: { textAlign: 'center', paddingTop: '2rem', paddingBottom: '2rem', color: '#4b5563' }, children: "No data found" }));
|
|
8
5
|
}
|
|
9
|
-
return ((
|
|
6
|
+
return (_jsx("div", { style: { backgroundColor: 'white', borderRadius: '0.5rem', boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)', overflow: 'hidden' }, children: _jsx("div", { style: { overflowX: 'auto' }, children: _jsxs("table", { style: { width: '100%' }, children: [_jsx("thead", { style: { backgroundColor: '#f3f4f6' }, children: _jsx("tr", { children: headers.map((header, index) => (_jsx("th", { style: {
|
|
10
7
|
paddingLeft: '1.5rem',
|
|
11
8
|
paddingRight: '1.5rem',
|
|
12
9
|
paddingTop: '0.75rem',
|
|
@@ -17,10 +14,10 @@ function Table({ value, headers }) {
|
|
|
17
14
|
color: '#6b7280',
|
|
18
15
|
textTransform: 'uppercase',
|
|
19
16
|
letterSpacing: '0.05em'
|
|
20
|
-
}, children: header }, index))) }) }), (
|
|
17
|
+
}, children: header }, index))) }) }), _jsx("tbody", { style: { backgroundColor: 'white' }, children: value.map((row, rowIndex) => (_jsx("tr", { style: {
|
|
21
18
|
borderTop: rowIndex > 0 ? '1px solid #e5e7eb' : 'none',
|
|
22
19
|
transition: 'background-color 0.15s ease-in-out'
|
|
23
|
-
}, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = '#f9fafb'; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = 'white'; }, children: row.map((cell, cellIndex) => ((
|
|
20
|
+
}, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = '#f9fafb'; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = 'white'; }, children: row.map((cell, cellIndex) => (_jsx("td", { style: {
|
|
24
21
|
paddingLeft: '1.5rem',
|
|
25
22
|
paddingRight: '1.5rem',
|
|
26
23
|
paddingTop: '1rem',
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.default = TextButton;
|
|
7
|
-
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
-
const button_1 = __importDefault(require("./button"));
|
|
9
|
-
function TextButton({ title, onClick, className, icon }) {
|
|
10
|
-
return ((0, jsx_runtime_1.jsx)(button_1.default, { onClick: onClick, className: className, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-row gap-4 items-center justify-center", children: [icon, title] }) }));
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Button from "./button.js";
|
|
3
|
+
export default function TextButton({ title, onClick, className, icon }) {
|
|
4
|
+
return (_jsx(Button, { onClick: onClick, className: className, children: _jsxs("div", { className: "flex flex-row gap-4 items-center justify-center", children: [icon, title] }) }));
|
|
11
5
|
}
|
package/dist/react-whispr.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Whispr } from "@cripty2001/whispr";
|
|
2
|
-
import { JSONEncodable } from ".";
|
|
3
|
-
import { Dispatcher } from "./Dispatcher";
|
|
4
|
-
import { SearcherData } from "./Searcher";
|
|
2
|
+
import { JSONEncodable } from "./index.js";
|
|
3
|
+
import { Dispatcher } from "./Dispatcher.js";
|
|
4
|
+
import { SearcherData } from "./Searcher/index.js";
|
|
5
5
|
/**
|
|
6
6
|
* Convert a Whispr value into a reactive react value, usable in function components with the standard react reactive system.
|
|
7
7
|
* If the value is not a Whispr, it is returned as is, thus allowing for progressive migration and adoption
|
package/dist/react-whispr.js
CHANGED
|
@@ -1,25 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
exports.useClock = useClock;
|
|
8
|
-
exports.useDebounced = useDebounced;
|
|
9
|
-
exports.useSynced = useSynced;
|
|
10
|
-
exports.useAsync = useAsync;
|
|
11
|
-
exports.useAsyncEffect = useAsyncEffect;
|
|
12
|
-
exports.useRelTime = useRelTime;
|
|
13
|
-
exports.useSearcher = useSearcher;
|
|
14
|
-
exports.useSafeRef = useSafeRef;
|
|
15
|
-
exports.useAsyncInput = useAsyncInput;
|
|
16
|
-
exports.whisprFromExternal = whisprFromExternal;
|
|
17
|
-
const whispr_1 = require("@cripty2001/whispr");
|
|
18
|
-
const react_1 = require("react");
|
|
19
|
-
const lodash_1 = require("lodash");
|
|
20
|
-
const _1 = require(".");
|
|
21
|
-
const Dispatcher_1 = require("./Dispatcher");
|
|
22
|
-
const Searcher_1 = require("./Searcher");
|
|
1
|
+
import { Whispr } from "@cripty2001/whispr";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { isEqual } from "lodash";
|
|
4
|
+
import { CURRENT_TS_MS, getClock, getRandomId } from "./index.js";
|
|
5
|
+
import { Dispatcher } from "./Dispatcher.js";
|
|
6
|
+
import { Searcher } from "./Searcher/index.js";
|
|
23
7
|
/**
|
|
24
8
|
* Convert a Whispr value into a reactive react value, usable in function components with the standard react reactive system.
|
|
25
9
|
* If the value is not a Whispr, it is returned as is, thus allowing for progressive migration and adoption
|
|
@@ -34,16 +18,16 @@ const Searcher_1 = require("./Searcher");
|
|
|
34
18
|
* return <div>{value}</div>;
|
|
35
19
|
* }
|
|
36
20
|
*/
|
|
37
|
-
function useWhisprValue(w, computer = (d) => d) {
|
|
38
|
-
const value_w =
|
|
39
|
-
const unsubscribe =
|
|
40
|
-
const [value, setValue] =
|
|
41
|
-
const valueref =
|
|
42
|
-
|
|
21
|
+
export function useWhisprValue(w, computer = (d) => d) {
|
|
22
|
+
const value_w = useRef(Whispr.create(computer(w.value))[0]);
|
|
23
|
+
const unsubscribe = useRef(() => { });
|
|
24
|
+
const [value, setValue] = useState(value_w.current.value);
|
|
25
|
+
const valueref = useRef(value); // Yep, react and his strange stale closures...
|
|
26
|
+
useEffect(() => {
|
|
43
27
|
unsubscribe.current();
|
|
44
|
-
value_w.current =
|
|
28
|
+
value_w.current = Whispr.from({ w }, ({ w }) => computer(w));
|
|
45
29
|
unsubscribe.current = value_w.current.subscribe((newValue) => {
|
|
46
|
-
if (
|
|
30
|
+
if (isEqual(newValue, valueref.current))
|
|
47
31
|
return;
|
|
48
32
|
setValue(newValue);
|
|
49
33
|
valueref.current = newValue;
|
|
@@ -59,15 +43,15 @@ function useWhisprValue(w, computer = (d) => d) {
|
|
|
59
43
|
*
|
|
60
44
|
* @remarks The returned whispr has already been ref-fed, so it can be directly used without worrying about react recreating it or similar bad things
|
|
61
45
|
*/
|
|
62
|
-
function useWhispr(data) {
|
|
63
|
-
const [w, setW] =
|
|
46
|
+
export function useWhispr(data) {
|
|
47
|
+
const [w, setW] = useRef(Whispr.create(data instanceof Whispr ?
|
|
64
48
|
data.value :
|
|
65
49
|
data)).current;
|
|
66
|
-
|
|
67
|
-
setW(data instanceof
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
setW(data instanceof Whispr ? data.value : data);
|
|
68
52
|
}, [data, setW]);
|
|
69
53
|
// Hooks can't be called conditionally, so we need to do this check at the end
|
|
70
|
-
if (data instanceof
|
|
54
|
+
if (data instanceof Whispr)
|
|
71
55
|
return data;
|
|
72
56
|
return w;
|
|
73
57
|
}
|
|
@@ -77,8 +61,8 @@ function useWhispr(data) {
|
|
|
77
61
|
* @param cb The callback to call on value change
|
|
78
62
|
* @param unsafe If true, the callback will be allowed to throw errors, that will then bubble up
|
|
79
63
|
*/
|
|
80
|
-
function useOnWhispr(w, cb, unsafe = false) {
|
|
81
|
-
|
|
64
|
+
export function useOnWhispr(w, cb, unsafe = false) {
|
|
65
|
+
useEffect(() => {
|
|
82
66
|
const unsub = w.subscribe(cb, undefined, unsafe);
|
|
83
67
|
return () => unsub();
|
|
84
68
|
}, [w, cb]);
|
|
@@ -87,27 +71,27 @@ function useOnWhispr(w, cb, unsafe = false) {
|
|
|
87
71
|
* Return a reactive current timestamp (ms)
|
|
88
72
|
* @returns The current timestamp
|
|
89
73
|
*/
|
|
90
|
-
function useCurrentTimestamp() {
|
|
91
|
-
return useWhisprValue(
|
|
74
|
+
export function useCurrentTimestamp() {
|
|
75
|
+
return useWhisprValue(CURRENT_TS_MS());
|
|
92
76
|
}
|
|
93
77
|
/**
|
|
94
78
|
* Return a reactive clock value, based on the current timestamp and a given rate.
|
|
95
79
|
* @param rate The rate to use for the clock
|
|
96
80
|
* @returns The clock value
|
|
97
81
|
*/
|
|
98
|
-
function useClock(rate) {
|
|
99
|
-
return useWhisprValue(
|
|
82
|
+
export function useClock(rate) {
|
|
83
|
+
return useWhisprValue(getClock(rate));
|
|
100
84
|
}
|
|
101
85
|
/**
|
|
102
86
|
* Debounce a reactive value, deep checking for equality, and stopping updates until the value changes.
|
|
103
87
|
* @param value The value to debounce
|
|
104
88
|
* @returns The debounced value
|
|
105
89
|
*/
|
|
106
|
-
function useDebounced(value) {
|
|
107
|
-
const lastEmitted =
|
|
108
|
-
const [debounced, setDebounced] =
|
|
109
|
-
|
|
110
|
-
if (
|
|
90
|
+
export function useDebounced(value) {
|
|
91
|
+
const lastEmitted = useRef(value);
|
|
92
|
+
const [debounced, setDebounced] = useState(value);
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
if (isEqual(lastEmitted.current, value))
|
|
111
95
|
return;
|
|
112
96
|
lastEmitted.current = value;
|
|
113
97
|
setDebounced(value);
|
|
@@ -121,25 +105,25 @@ function useDebounced(value) {
|
|
|
121
105
|
* @param setValue The function to set the value
|
|
122
106
|
* @returns The synced value and the function to set it
|
|
123
107
|
*/
|
|
124
|
-
function useSynced(def, value, setValue) {
|
|
125
|
-
const [v, setV] =
|
|
108
|
+
export function useSynced(def, value, setValue) {
|
|
109
|
+
const [v, setV] = useState(def);
|
|
126
110
|
if ((value !== undefined && setValue === undefined) ||
|
|
127
111
|
(value === undefined && setValue !== undefined))
|
|
128
112
|
throw new Error('Either both value and setValue must be provided, or both must be undefined');
|
|
129
|
-
const setValueRef =
|
|
130
|
-
|
|
113
|
+
const setValueRef = useRef(setValue);
|
|
114
|
+
useEffect(() => {
|
|
131
115
|
setValueRef.current = setValue;
|
|
132
116
|
}, [setValue]);
|
|
133
117
|
// Only sync downstream (external -> local)
|
|
134
|
-
|
|
118
|
+
useEffect(() => {
|
|
135
119
|
if (value === undefined)
|
|
136
120
|
return;
|
|
137
|
-
if (
|
|
121
|
+
if (isEqual(v, value))
|
|
138
122
|
return;
|
|
139
123
|
setV(value);
|
|
140
124
|
}, [value]);
|
|
141
125
|
// Return a setter that updates both
|
|
142
|
-
const syncedSetter =
|
|
126
|
+
const syncedSetter = useCallback((newValue) => {
|
|
143
127
|
setV(prev => {
|
|
144
128
|
const resolved = typeof newValue === 'function'
|
|
145
129
|
? newValue(prev)
|
|
@@ -236,21 +220,21 @@ function useSynced(def, value, setValue) {
|
|
|
236
220
|
* console.error('Error:', state.error);
|
|
237
221
|
* }
|
|
238
222
|
*/
|
|
239
|
-
function useAsync(data, debouce, interval, f) {
|
|
223
|
+
export function useAsync(data, debouce, interval, f) {
|
|
240
224
|
// Initing reactive input
|
|
241
|
-
const [input, setInput] = useSafeRef(() =>
|
|
242
|
-
|
|
225
|
+
const [input, setInput] = useSafeRef(() => Whispr.create(data ?? getRandomId()));
|
|
226
|
+
useEffect(() => {
|
|
243
227
|
if (data !== null) {
|
|
244
228
|
setInput(data); // Debouncing already handled by dispatcher
|
|
245
229
|
}
|
|
246
230
|
}, [data, setInput]);
|
|
247
231
|
// Initing dispatcher
|
|
248
|
-
const dispatcher = useSafeRef(() => new
|
|
232
|
+
const dispatcher = useSafeRef(() => new Dispatcher(input, (i, p, s) => f(i, p, s), debouce));
|
|
249
233
|
// Starting refresher
|
|
250
234
|
const clock = useClock(interval ?
|
|
251
235
|
interval :
|
|
252
236
|
Number.MAX_SAFE_INTEGER);
|
|
253
|
-
|
|
237
|
+
useEffect(() => {
|
|
254
238
|
dispatcher.refresh();
|
|
255
239
|
}, [clock, dispatcher]);
|
|
256
240
|
// Returning dispatcher and refresh function
|
|
@@ -285,7 +269,7 @@ function useAsync(data, debouce, interval, f) {
|
|
|
285
269
|
* // Do something with data
|
|
286
270
|
* }, userId, 300);
|
|
287
271
|
*/
|
|
288
|
-
function useAsyncEffect(f, data, debounce = 200) {
|
|
272
|
+
export function useAsyncEffect(f, data, debounce = 200) {
|
|
289
273
|
const [dispatcher] = useAsync(data, debounce, null, f);
|
|
290
274
|
useOnWhispr(dispatcher.data, (data) => {
|
|
291
275
|
if (!data.output.loading && !data.output.ok) {
|
|
@@ -299,10 +283,10 @@ function useAsyncEffect(f, data, debounce = 200) {
|
|
|
299
283
|
* @param data The data to format. Reactive
|
|
300
284
|
* @returns The formatted timestamp
|
|
301
285
|
*/
|
|
302
|
-
function useRelTime(_data) {
|
|
286
|
+
export function useRelTime(_data) {
|
|
303
287
|
const rtf = new Intl.RelativeTimeFormat(navigator.language, { numeric: "auto" });
|
|
304
288
|
const data = useWhispr(_data);
|
|
305
|
-
const toReturn = useSafeRef(() =>
|
|
289
|
+
const toReturn = useSafeRef(() => Whispr.from({ data, curr: CURRENT_TS_MS() }, ({ data, curr }) => {
|
|
306
290
|
const then = data instanceof Date ? data.getTime() : data;
|
|
307
291
|
const seconds = Math.round(then - curr) / 1000;
|
|
308
292
|
const { base, unit } = getRelTimeFormat(seconds);
|
|
@@ -358,10 +342,10 @@ function getRelTimeFormat(_diff) {
|
|
|
358
342
|
* - The filtered data
|
|
359
343
|
* - A boolean indicating if the search is pending
|
|
360
344
|
*/
|
|
361
|
-
function useSearcher(data, limit) {
|
|
362
|
-
const searcher =
|
|
363
|
-
const [pending, setPending] =
|
|
364
|
-
const [results, setResults] =
|
|
345
|
+
export function useSearcher(data, limit) {
|
|
346
|
+
const searcher = useRef(new Searcher(data));
|
|
347
|
+
const [pending, setPending] = useState(false);
|
|
348
|
+
const [results, setResults] = useState({
|
|
365
349
|
results: [],
|
|
366
350
|
_meta: {
|
|
367
351
|
ts: 0,
|
|
@@ -373,7 +357,7 @@ function useSearcher(data, limit) {
|
|
|
373
357
|
results: searcher.current.search(q, limit)
|
|
374
358
|
};
|
|
375
359
|
}, setPending);
|
|
376
|
-
|
|
360
|
+
useEffect(() => {
|
|
377
361
|
searcher.current.updateData(data);
|
|
378
362
|
setResults(draft => {
|
|
379
363
|
draft.results = searcher.current.search(q.q, limit);
|
|
@@ -393,8 +377,8 @@ function useSearcher(data, limit) {
|
|
|
393
377
|
* @param value The value to initialize the ref with. If a function is provided, it will be called to initialize the ref.
|
|
394
378
|
* @returns
|
|
395
379
|
*/
|
|
396
|
-
function useSafeRef(value) {
|
|
397
|
-
const ref =
|
|
380
|
+
export function useSafeRef(value) {
|
|
381
|
+
const ref = useRef(null);
|
|
398
382
|
if (ref.current === null) {
|
|
399
383
|
ref.current = value();
|
|
400
384
|
}
|
|
@@ -457,15 +441,15 @@ function useSafeRef(value) {
|
|
|
457
441
|
* The returned `result` will lag behind `value` during async processing. Consider showing a loader or some other similar indication
|
|
458
442
|
* Handler is NOT reactive. Conceptually it is a pure function that derives an async status from the value input, so there is no reason for it to be reactive, and this saves a lot heachaches with react reactivity loops.
|
|
459
443
|
*/
|
|
460
|
-
function useAsyncInput(value, setValue, handler, setPending = () => { }) {
|
|
461
|
-
const [meta, setMeta] =
|
|
444
|
+
export function useAsyncInput(value, setValue, handler, setPending = () => { }) {
|
|
445
|
+
const [meta, setMeta] = useState({
|
|
462
446
|
config: value._meta.config,
|
|
463
447
|
ts: value._meta.ts
|
|
464
448
|
});
|
|
465
|
-
|
|
449
|
+
useEffect(() => {
|
|
466
450
|
setPending(true);
|
|
467
451
|
}, [meta, setPending]);
|
|
468
|
-
|
|
452
|
+
useEffect(() => {
|
|
469
453
|
if (value._meta.ts > meta.ts) {
|
|
470
454
|
setMeta(value._meta);
|
|
471
455
|
}
|
|
@@ -481,7 +465,7 @@ function useAsyncInput(value, setValue, handler, setPending = () => { }) {
|
|
|
481
465
|
};
|
|
482
466
|
});
|
|
483
467
|
const result = useWhisprValue(result_d.filtered);
|
|
484
|
-
|
|
468
|
+
useEffect(() => {
|
|
485
469
|
if (result === null)
|
|
486
470
|
return;
|
|
487
471
|
if (result._meta.ts <= value._meta.ts)
|
|
@@ -489,7 +473,7 @@ function useAsyncInput(value, setValue, handler, setPending = () => { }) {
|
|
|
489
473
|
setValue(result);
|
|
490
474
|
setPending(false);
|
|
491
475
|
}, [result, value, setValue, setPending]);
|
|
492
|
-
const returnedSetValue =
|
|
476
|
+
const returnedSetValue = useCallback((updater) => {
|
|
493
477
|
const cloned = structuredClone(meta.config);
|
|
494
478
|
const new_data = updater(cloned);
|
|
495
479
|
const chosen = new_data ?? cloned;
|
|
@@ -504,13 +488,13 @@ function useAsyncInput(value, setValue, handler, setPending = () => { }) {
|
|
|
504
488
|
result,
|
|
505
489
|
];
|
|
506
490
|
}
|
|
507
|
-
function whisprFromExternal(getData, interval) {
|
|
491
|
+
export function whisprFromExternal(getData, interval) {
|
|
508
492
|
const cleanup = () => {
|
|
509
493
|
if (intervalRef !== null) {
|
|
510
494
|
clearInterval(intervalRef);
|
|
511
495
|
}
|
|
512
496
|
};
|
|
513
|
-
const [value, setValue] =
|
|
497
|
+
const [value, setValue] = Whispr.create(getData(), cleanup);
|
|
514
498
|
const intervalRef = (() => {
|
|
515
499
|
return interval !== null ?
|
|
516
500
|
setInterval(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cripty2001/utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.261",
|
|
4
4
|
"description": "Internal Set of utils. If you need them use them, otherwise go to the next package ;)",
|
|
5
5
|
"homepage": "https://github.com/cripty2001/utils#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@cripty2001/whispr": "^0.4.1",
|
|
33
33
|
"@sinclair/typebox": "^0.34.41",
|
|
34
|
-
"lodash": "^4.17.21"
|
|
34
|
+
"lodash": "^4.17.21",
|
|
35
|
+
"react-oidc-context": "^3.3.1"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"@types/lodash": "^4.17.21",
|
|
@@ -53,6 +54,7 @@
|
|
|
53
54
|
"optional": true
|
|
54
55
|
}
|
|
55
56
|
},
|
|
57
|
+
"type": "module",
|
|
56
58
|
"exports": {
|
|
57
59
|
".": {
|
|
58
60
|
"import": "./dist/index.js",
|
|
@@ -94,6 +96,11 @@
|
|
|
94
96
|
"types": "./dist/Appserver/server.d.ts",
|
|
95
97
|
"require": "./dist/Appserver/server.js"
|
|
96
98
|
},
|
|
99
|
+
"./appserver/client/react": {
|
|
100
|
+
"import": "./dist/Appserver/client/react.js",
|
|
101
|
+
"types": "./dist/Appserver/client/react.d.ts",
|
|
102
|
+
"require": "./dist/Appserver/client/react.js"
|
|
103
|
+
},
|
|
97
104
|
"./react": {
|
|
98
105
|
"import": "./dist/react/index.js",
|
|
99
106
|
"types": "./dist/react/index.d.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/Appserver/client.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// import { Whispr, WhisprSetter } from "@cripty2001/whispr";
|
|
3
|
-
// import { decode, encode } from "@msgpack/msgpack";
|
|
4
|
-
// import { AppserverData } from "./common";
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
// export type { AppserverData };
|
|
7
|
-
// export type ClientCreateOptions = {
|
|
8
|
-
// rpcMount: string;
|
|
9
|
-
// };
|
|
10
|
-
// export class ClientError extends Error {
|
|
11
|
-
// constructor(message: string) {
|
|
12
|
-
// super(message);
|
|
13
|
-
// }
|
|
14
|
-
// }
|
|
15
|
-
// export class ClientAuthError extends ClientError {
|
|
16
|
-
// constructor(
|
|
17
|
-
// public readonly code: string = "PERMISSION_DENIED",
|
|
18
|
-
// message: string = "Permission denied",
|
|
19
|
-
// public readonly payload: AppserverData = {},
|
|
20
|
-
// ) {
|
|
21
|
-
// super(message);
|
|
22
|
-
// }
|
|
23
|
-
// }
|
|
24
|
-
// export class ClientServerError extends ClientError {
|
|
25
|
-
// constructor(public code: string, message: string, public payload: AppserverData = {}) {
|
|
26
|
-
// super(message);
|
|
27
|
-
// }
|
|
28
|
-
// }
|
|
29
|
-
// type ClientValidationErrorError = {
|
|
30
|
-
// path: string;
|
|
31
|
-
// message: string;
|
|
32
|
-
// value: unknown;
|
|
33
|
-
// }
|
|
34
|
-
// export class ClientValidationError extends ClientError {
|
|
35
|
-
// public readonly errors: ClientValidationErrorError[];
|
|
36
|
-
// constructor(errors: ClientValidationErrorError[]) {
|
|
37
|
-
// const first = errors[0] ?? {
|
|
38
|
-
// path: "Internal Error",
|
|
39
|
-
// message: "",
|
|
40
|
-
// value: undefined,
|
|
41
|
-
// };
|
|
42
|
-
// super(`[Validation Error] ${first.path}: ${first.message}`);
|
|
43
|
-
// this.errors = errors;
|
|
44
|
-
// }
|
|
45
|
-
// }
|
|
46
|
-
// export class Client {
|
|
47
|
-
// private readonly token: Whispr<string | null>;
|
|
48
|
-
// private readonly setToken: WhisprSetter<string | null>;
|
|
49
|
-
// public readonly loggedIn: Whispr<boolean>;
|
|
50
|
-
// private constructor(
|
|
51
|
-
// private url: string,
|
|
52
|
-
// private readonly rpcMount: string,
|
|
53
|
-
// ) {
|
|
54
|
-
// const [token, setToken] = Whispr.create<string | null>(''); // This will make sure the loggedin only flips to false when there is really an auth rejected. Server will ignore invalid tokens on public apis anyway
|
|
55
|
-
// this.token = token;
|
|
56
|
-
// this.setToken = setToken;
|
|
57
|
-
// this.loggedIn = token.transform((t) => t !== null);
|
|
58
|
-
// }
|
|
59
|
-
// public static create(url: string, options: ClientCreateOptions): Client {
|
|
60
|
-
// const m = options.rpcMount.startsWith("/") ?
|
|
61
|
-
// options.rpcMount :
|
|
62
|
-
// `/${options.rpcMount}`;
|
|
63
|
-
// return new Client(url, m);
|
|
64
|
-
// }
|
|
65
|
-
// public async login(token: string): Promise<boolean> {
|
|
66
|
-
// this.setToken(token);
|
|
67
|
-
// return true;
|
|
68
|
-
// }
|
|
69
|
-
// public logout(): void {
|
|
70
|
-
// this.setToken(null);
|
|
71
|
-
// }
|
|
72
|
-
// public async exec<I extends AppserverData, O extends AppserverData>(
|
|
73
|
-
// action: string,
|
|
74
|
-
// input: I,
|
|
75
|
-
// onError: Record<string, (payload: AppserverData) => Promise<void>> = {},
|
|
76
|
-
// ): Promise<O> {
|
|
77
|
-
// while (true) {
|
|
78
|
-
// try {
|
|
79
|
-
// return await this.unsafeExec(action, input);
|
|
80
|
-
// } catch (e) {
|
|
81
|
-
// if (e instanceof ClientAuthError) {
|
|
82
|
-
// this.logout();
|
|
83
|
-
// await this.token.load();
|
|
84
|
-
// continue;
|
|
85
|
-
// }
|
|
86
|
-
// if (e instanceof ClientServerError) {
|
|
87
|
-
// const handler = onError[e.code];
|
|
88
|
-
// if (handler) {
|
|
89
|
-
// await handler(e.payload);
|
|
90
|
-
// }
|
|
91
|
-
// }
|
|
92
|
-
// throw e;
|
|
93
|
-
// }
|
|
94
|
-
// }
|
|
95
|
-
// }
|
|
96
|
-
// private async unsafeExec<I extends AppserverData, O extends AppserverData>(
|
|
97
|
-
// action: string,
|
|
98
|
-
// input: I,
|
|
99
|
-
// ): Promise<O> {
|
|
100
|
-
// const testedToken = this.token.value;
|
|
101
|
-
// const actionKey = action;
|
|
102
|
-
// const wireBody = {
|
|
103
|
-
// action: actionKey,
|
|
104
|
-
// payload: input as AppserverData,
|
|
105
|
-
// };
|
|
106
|
-
// const res = await fetch(`${this.url}${this.rpcMount}`, {
|
|
107
|
-
// method: "POST",
|
|
108
|
-
// headers: {
|
|
109
|
-
// "Content-Type": "application/vnd.msgpack",
|
|
110
|
-
// ...(testedToken !== null ? { Authorization: `Bearer ${testedToken}` } : {}),
|
|
111
|
-
// },
|
|
112
|
-
// body: new Uint8Array(encode(wireBody)),
|
|
113
|
-
// });
|
|
114
|
-
// const buf = await res.arrayBuffer();
|
|
115
|
-
// const decoded = decode(buf);
|
|
116
|
-
// if (res.status === 200)
|
|
117
|
-
// return decoded as O;
|
|
118
|
-
// if (res.status === 422) {
|
|
119
|
-
// const data = decoded as {
|
|
120
|
-
// errors: ClientValidationErrorError[];
|
|
121
|
-
// received: AppserverData;
|
|
122
|
-
// }
|
|
123
|
-
// throw new ClientValidationError(data.errors);
|
|
124
|
-
// }
|
|
125
|
-
// const genericError = decoded as {
|
|
126
|
-
// error: string;
|
|
127
|
-
// code: string;
|
|
128
|
-
// payload: AppserverData;
|
|
129
|
-
// }
|
|
130
|
-
// if (res.status === 400 || res.status === 404 || res.status === 500) {
|
|
131
|
-
// throw new ClientServerError(
|
|
132
|
-
// genericError.code,
|
|
133
|
-
// genericError.error,
|
|
134
|
-
// genericError.payload ?? {},
|
|
135
|
-
// );
|
|
136
|
-
// }
|
|
137
|
-
// if (res.status === 401 || res.status === 403) {
|
|
138
|
-
// this.setToken(null);
|
|
139
|
-
// throw new ClientAuthError(
|
|
140
|
-
// genericError.code,
|
|
141
|
-
// genericError.error,
|
|
142
|
-
// genericError.payload,
|
|
143
|
-
// )
|
|
144
|
-
// }
|
|
145
|
-
// throw new ClientError(`Unexpected server response: ${res.status}`);
|
|
146
|
-
// }
|
|
147
|
-
// }
|
package/dist/Appserver/common.js
DELETED