@json-render/react-native 0.8.0 → 0.9.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/README.md +21 -0
- package/dist/index.d.mts +49 -14
- package/dist/index.d.ts +49 -14
- package/dist/index.js +134 -70
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +160 -94
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -4
package/dist/index.mjs
CHANGED
|
@@ -7,76 +7,115 @@ import {
|
|
|
7
7
|
schema
|
|
8
8
|
} from "./chunk-T27PQA6P.mjs";
|
|
9
9
|
|
|
10
|
-
//
|
|
10
|
+
// ../react-state/dist/index.mjs
|
|
11
11
|
import {
|
|
12
12
|
createContext,
|
|
13
13
|
useContext,
|
|
14
|
-
useState,
|
|
15
14
|
useCallback,
|
|
16
|
-
useMemo,
|
|
17
15
|
useEffect,
|
|
18
|
-
|
|
16
|
+
useMemo,
|
|
17
|
+
useRef,
|
|
18
|
+
useSyncExternalStore
|
|
19
19
|
} from "react";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
getByPath,
|
|
22
|
+
createStateStore
|
|
23
|
+
} from "@json-render/core";
|
|
24
|
+
import { flattenToPointers } from "@json-render/core/store-utils";
|
|
21
25
|
import { jsx } from "react/jsx-runtime";
|
|
22
26
|
var StateContext = createContext(null);
|
|
27
|
+
function computeInitialFlat(isControlled, initialState) {
|
|
28
|
+
if (isControlled) return null;
|
|
29
|
+
if (Object.keys(initialState).length === 0) return {};
|
|
30
|
+
return flattenToPointers(initialState);
|
|
31
|
+
}
|
|
23
32
|
function StateProvider({
|
|
33
|
+
store: externalStore,
|
|
24
34
|
initialState = {},
|
|
25
35
|
onStateChange,
|
|
26
36
|
children
|
|
27
37
|
}) {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
const internalStoreRef = useRef(void 0);
|
|
39
|
+
if (!externalStore && !internalStoreRef.current) {
|
|
40
|
+
internalStoreRef.current = createStateStore(initialState);
|
|
41
|
+
}
|
|
42
|
+
const store = externalStore ?? internalStoreRef.current;
|
|
43
|
+
const storeRef = useRef(store);
|
|
44
|
+
storeRef.current = store;
|
|
45
|
+
const isControlledRef = useRef(!!externalStore);
|
|
46
|
+
isControlledRef.current = !!externalStore;
|
|
47
|
+
const initialModeRef = useRef(externalStore ? "controlled" : "uncontrolled");
|
|
48
|
+
const modeWarnedRef = useRef(false);
|
|
49
|
+
if (process.env.NODE_ENV !== "production") {
|
|
50
|
+
const currentMode = externalStore ? "controlled" : "uncontrolled";
|
|
51
|
+
if (currentMode !== initialModeRef.current && !modeWarnedRef.current) {
|
|
52
|
+
modeWarnedRef.current = true;
|
|
53
|
+
console.warn(
|
|
54
|
+
`StateProvider: switching from ${initialModeRef.current} to ${currentMode} mode is not supported.`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const prevInitialStateRef = useRef(initialState);
|
|
59
|
+
const prevFlatRef = useRef(
|
|
60
|
+
computeInitialFlat(!!externalStore, initialState)
|
|
61
|
+
);
|
|
32
62
|
useEffect(() => {
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
63
|
+
if (externalStore) return;
|
|
64
|
+
if (initialState === prevInitialStateRef.current) return;
|
|
65
|
+
prevInitialStateRef.current = initialState;
|
|
66
|
+
const nextFlat = initialState && Object.keys(initialState).length > 0 ? flattenToPointers(initialState) : {};
|
|
67
|
+
const prevFlat = prevFlatRef.current ?? {};
|
|
68
|
+
const allKeys = /* @__PURE__ */ new Set([
|
|
69
|
+
...Object.keys(prevFlat),
|
|
70
|
+
...Object.keys(nextFlat)
|
|
71
|
+
]);
|
|
72
|
+
const updates = {};
|
|
73
|
+
for (const key of allKeys) {
|
|
74
|
+
if (prevFlat[key] !== nextFlat[key]) {
|
|
75
|
+
updates[key] = key in nextFlat ? nextFlat[key] : void 0;
|
|
38
76
|
}
|
|
39
77
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
);
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
setByPath(next, path, value2);
|
|
50
|
-
return next;
|
|
51
|
-
});
|
|
52
|
-
onStateChange?.(path, value2);
|
|
53
|
-
},
|
|
54
|
-
[onStateChange]
|
|
78
|
+
prevFlatRef.current = nextFlat;
|
|
79
|
+
if (Object.keys(updates).length > 0) {
|
|
80
|
+
store.update(updates);
|
|
81
|
+
}
|
|
82
|
+
}, [externalStore, initialState, store]);
|
|
83
|
+
const state = useSyncExternalStore(
|
|
84
|
+
store.subscribe,
|
|
85
|
+
store.getSnapshot,
|
|
86
|
+
store.getServerSnapshot ?? store.getSnapshot
|
|
55
87
|
);
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
88
|
+
const onStateChangeRef = useRef(onStateChange);
|
|
89
|
+
onStateChangeRef.current = onStateChange;
|
|
90
|
+
const set = useCallback((path, value2) => {
|
|
91
|
+
const s = storeRef.current;
|
|
92
|
+
const prev = s.getSnapshot();
|
|
93
|
+
s.set(path, value2);
|
|
94
|
+
if (!isControlledRef.current && s.getSnapshot() !== prev) {
|
|
95
|
+
onStateChangeRef.current?.([{ path, value: value2 }]);
|
|
96
|
+
}
|
|
97
|
+
}, []);
|
|
98
|
+
const update = useCallback((updates) => {
|
|
99
|
+
const s = storeRef.current;
|
|
100
|
+
const prev = s.getSnapshot();
|
|
101
|
+
s.update(updates);
|
|
102
|
+
if (!isControlledRef.current && s.getSnapshot() !== prev) {
|
|
103
|
+
const changes = [];
|
|
104
|
+
for (const [path, value2] of Object.entries(updates)) {
|
|
105
|
+
if (getByPath(prev, path) !== value2) {
|
|
106
|
+
changes.push({ path, value: value2 });
|
|
63
107
|
}
|
|
64
|
-
return next;
|
|
65
|
-
});
|
|
66
|
-
for (const [path, value2] of entries) {
|
|
67
|
-
onStateChange?.(path, value2);
|
|
68
108
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
109
|
+
if (changes.length > 0) {
|
|
110
|
+
onStateChangeRef.current?.(changes);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}, []);
|
|
114
|
+
const get = useCallback((path) => storeRef.current.get(path), []);
|
|
115
|
+
const getSnapshot = useCallback(() => storeRef.current.getSnapshot(), []);
|
|
72
116
|
const value = useMemo(
|
|
73
|
-
() => ({
|
|
74
|
-
|
|
75
|
-
get,
|
|
76
|
-
set,
|
|
77
|
-
update
|
|
78
|
-
}),
|
|
79
|
-
[state, get, set, update]
|
|
117
|
+
() => ({ state, get, set, update, getSnapshot }),
|
|
118
|
+
[state, get, set, update, getSnapshot]
|
|
80
119
|
);
|
|
81
120
|
return /* @__PURE__ */ jsx(StateContext.Provider, { value, children });
|
|
82
121
|
}
|
|
@@ -146,7 +185,7 @@ function useIsVisible(condition) {
|
|
|
146
185
|
import {
|
|
147
186
|
createContext as createContext3,
|
|
148
187
|
useContext as useContext3,
|
|
149
|
-
useState
|
|
188
|
+
useState,
|
|
150
189
|
useCallback as useCallback2,
|
|
151
190
|
useMemo as useMemo3
|
|
152
191
|
} from "react";
|
|
@@ -194,10 +233,10 @@ function ActionProvider({
|
|
|
194
233
|
navigate,
|
|
195
234
|
children
|
|
196
235
|
}) {
|
|
197
|
-
const {
|
|
198
|
-
const [handlers, setHandlers] =
|
|
199
|
-
const [loadingActions, setLoadingActions] =
|
|
200
|
-
const [pendingConfirmation, setPendingConfirmation] =
|
|
236
|
+
const { get, set, getSnapshot } = useStateStore();
|
|
237
|
+
const [handlers, setHandlers] = useState(initialHandlers);
|
|
238
|
+
const [loadingActions, setLoadingActions] = useState(/* @__PURE__ */ new Set());
|
|
239
|
+
const [pendingConfirmation, setPendingConfirmation] = useState(null);
|
|
201
240
|
const registerHandler = useCallback2(
|
|
202
241
|
(name, handler) => {
|
|
203
242
|
setHandlers((prev) => ({ ...prev, [name]: handler }));
|
|
@@ -206,7 +245,7 @@ function ActionProvider({
|
|
|
206
245
|
);
|
|
207
246
|
const execute = useCallback2(
|
|
208
247
|
async (binding) => {
|
|
209
|
-
const resolved = resolveAction(binding,
|
|
248
|
+
const resolved = resolveAction(binding, getSnapshot());
|
|
210
249
|
if (resolved.action === "setState" && resolved.params) {
|
|
211
250
|
const statePath = resolved.params.statePath;
|
|
212
251
|
const value2 = resolved.params.value;
|
|
@@ -329,7 +368,7 @@ function ActionProvider({
|
|
|
329
368
|
});
|
|
330
369
|
}
|
|
331
370
|
},
|
|
332
|
-
[
|
|
371
|
+
[handlers, get, set, getSnapshot, navigate]
|
|
333
372
|
);
|
|
334
373
|
const confirm = useCallback2(() => {
|
|
335
374
|
pendingConfirmation?.resolve();
|
|
@@ -460,10 +499,10 @@ var styles = StyleSheet.create({
|
|
|
460
499
|
});
|
|
461
500
|
|
|
462
501
|
// src/contexts/validation.tsx
|
|
463
|
-
import
|
|
502
|
+
import React3, {
|
|
464
503
|
createContext as createContext4,
|
|
465
504
|
useContext as useContext4,
|
|
466
|
-
useState as
|
|
505
|
+
useState as useState2,
|
|
467
506
|
useCallback as useCallback3,
|
|
468
507
|
useMemo as useMemo4
|
|
469
508
|
} from "react";
|
|
@@ -511,8 +550,8 @@ function ValidationProvider({
|
|
|
511
550
|
children
|
|
512
551
|
}) {
|
|
513
552
|
const { state } = useStateStore();
|
|
514
|
-
const [fieldStates, setFieldStates] =
|
|
515
|
-
const [fieldConfigs, setFieldConfigs] =
|
|
553
|
+
const [fieldStates, setFieldStates] = useState2({});
|
|
554
|
+
const [fieldConfigs, setFieldConfigs] = useState2({});
|
|
516
555
|
const registerField = useCallback3(
|
|
517
556
|
(path, config) => {
|
|
518
557
|
setFieldConfigs((prev) => {
|
|
@@ -618,7 +657,7 @@ function useFieldValidation(path, config) {
|
|
|
618
657
|
clear: clearField,
|
|
619
658
|
registerField
|
|
620
659
|
} = useValidation();
|
|
621
|
-
|
|
660
|
+
React3.useEffect(() => {
|
|
622
661
|
if (config) {
|
|
623
662
|
registerField(path, config);
|
|
624
663
|
}
|
|
@@ -660,8 +699,11 @@ function useRepeatScope() {
|
|
|
660
699
|
return useContext5(RepeatScopeContext);
|
|
661
700
|
}
|
|
662
701
|
|
|
702
|
+
// src/index.ts
|
|
703
|
+
import { createStateStore as createStateStore2 } from "@json-render/core";
|
|
704
|
+
|
|
663
705
|
// src/renderer.tsx
|
|
664
|
-
import
|
|
706
|
+
import React5, {
|
|
665
707
|
useCallback as useCallback5,
|
|
666
708
|
useMemo as useMemo5
|
|
667
709
|
} from "react";
|
|
@@ -692,9 +734,9 @@ import {
|
|
|
692
734
|
} from "react-native";
|
|
693
735
|
|
|
694
736
|
// src/hooks.ts
|
|
695
|
-
import { useState as
|
|
737
|
+
import { useState as useState3, useCallback as useCallback4, useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
696
738
|
import {
|
|
697
|
-
setByPath
|
|
739
|
+
setByPath,
|
|
698
740
|
getByPath as getByPath2,
|
|
699
741
|
removeByPath,
|
|
700
742
|
validateSpec,
|
|
@@ -757,7 +799,7 @@ function setSpecValue(newSpec, path, value) {
|
|
|
757
799
|
if (path.startsWith("/state/")) {
|
|
758
800
|
if (!newSpec.state) newSpec.state = {};
|
|
759
801
|
const statePath = path.slice("/state".length);
|
|
760
|
-
|
|
802
|
+
setByPath(newSpec.state, statePath, value);
|
|
761
803
|
return;
|
|
762
804
|
}
|
|
763
805
|
if (path.startsWith("/elements/")) {
|
|
@@ -771,7 +813,7 @@ function setSpecValue(newSpec, path, value) {
|
|
|
771
813
|
if (element) {
|
|
772
814
|
const propPath = "/" + pathParts.slice(1).join("/");
|
|
773
815
|
const newElement = { ...element };
|
|
774
|
-
|
|
816
|
+
setByPath(
|
|
775
817
|
newElement,
|
|
776
818
|
propPath,
|
|
777
819
|
value
|
|
@@ -855,10 +897,10 @@ function useUIStream({
|
|
|
855
897
|
validate: enableValidation = false,
|
|
856
898
|
maxRetries = 5
|
|
857
899
|
}) {
|
|
858
|
-
const [spec, setSpec] =
|
|
859
|
-
const [isStreaming, setIsStreaming] =
|
|
860
|
-
const [error, setError] =
|
|
861
|
-
const [rawLines, setRawLines] =
|
|
900
|
+
const [spec, setSpec] = useState3(null);
|
|
901
|
+
const [isStreaming, setIsStreaming] = useState3(false);
|
|
902
|
+
const [error, setError] = useState3(null);
|
|
903
|
+
const [rawLines, setRawLines] = useState3([]);
|
|
862
904
|
const abortControllerRef = useRef2(null);
|
|
863
905
|
const stop = useCallback4(() => {
|
|
864
906
|
abortControllerRef.current?.abort();
|
|
@@ -1891,7 +1933,7 @@ var modalStyles = StyleSheet2.create({
|
|
|
1891
1933
|
|
|
1892
1934
|
// src/renderer.tsx
|
|
1893
1935
|
import { Fragment, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1894
|
-
var ElementErrorBoundary = class extends
|
|
1936
|
+
var ElementErrorBoundary = class extends React5.Component {
|
|
1895
1937
|
constructor(props) {
|
|
1896
1938
|
super(props);
|
|
1897
1939
|
this.state = { hasError: false };
|
|
@@ -1913,7 +1955,7 @@ var ElementErrorBoundary = class extends React6.Component {
|
|
|
1913
1955
|
return this.props.children;
|
|
1914
1956
|
}
|
|
1915
1957
|
};
|
|
1916
|
-
var ElementRenderer =
|
|
1958
|
+
var ElementRenderer = React5.memo(function ElementRenderer2({
|
|
1917
1959
|
element,
|
|
1918
1960
|
spec,
|
|
1919
1961
|
registry,
|
|
@@ -1923,6 +1965,7 @@ var ElementRenderer = React6.memo(function ElementRenderer2({
|
|
|
1923
1965
|
const repeatScope = useRepeatScope();
|
|
1924
1966
|
const { ctx } = useVisibility();
|
|
1925
1967
|
const { execute } = useActions();
|
|
1968
|
+
const { getSnapshot } = useStateStore();
|
|
1926
1969
|
const fullCtx = useMemo5(
|
|
1927
1970
|
() => repeatScope ? {
|
|
1928
1971
|
...ctx,
|
|
@@ -1935,23 +1978,27 @@ var ElementRenderer = React6.memo(function ElementRenderer2({
|
|
|
1935
1978
|
const isVisible = element.visible === void 0 ? true : evaluateVisibility2(element.visible, fullCtx);
|
|
1936
1979
|
const onBindings = element.on;
|
|
1937
1980
|
const emit = useCallback5(
|
|
1938
|
-
(eventName) => {
|
|
1981
|
+
async (eventName) => {
|
|
1939
1982
|
const binding = onBindings?.[eventName];
|
|
1940
1983
|
if (!binding) return;
|
|
1941
1984
|
const actionBindings = Array.isArray(binding) ? binding : [binding];
|
|
1942
1985
|
for (const b of actionBindings) {
|
|
1943
1986
|
if (!b.params) {
|
|
1944
|
-
execute(b);
|
|
1987
|
+
await execute(b);
|
|
1945
1988
|
continue;
|
|
1946
1989
|
}
|
|
1990
|
+
const liveCtx = {
|
|
1991
|
+
...fullCtx,
|
|
1992
|
+
stateModel: getSnapshot()
|
|
1993
|
+
};
|
|
1947
1994
|
const resolved = {};
|
|
1948
1995
|
for (const [key, val] of Object.entries(b.params)) {
|
|
1949
|
-
resolved[key] = resolveActionParam(val,
|
|
1996
|
+
resolved[key] = resolveActionParam(val, liveCtx);
|
|
1950
1997
|
}
|
|
1951
|
-
execute({ ...b, params: resolved });
|
|
1998
|
+
await execute({ ...b, params: resolved });
|
|
1952
1999
|
}
|
|
1953
2000
|
},
|
|
1954
|
-
[onBindings, execute, fullCtx]
|
|
2001
|
+
[onBindings, execute, fullCtx, getSnapshot]
|
|
1955
2002
|
);
|
|
1956
2003
|
if (!isVisible) {
|
|
1957
2004
|
return null;
|
|
@@ -2089,6 +2136,7 @@ function Renderer({
|
|
|
2089
2136
|
}
|
|
2090
2137
|
function JSONUIProvider({
|
|
2091
2138
|
registry,
|
|
2139
|
+
store,
|
|
2092
2140
|
initialState,
|
|
2093
2141
|
handlers,
|
|
2094
2142
|
navigate,
|
|
@@ -2096,10 +2144,18 @@ function JSONUIProvider({
|
|
|
2096
2144
|
onStateChange,
|
|
2097
2145
|
children
|
|
2098
2146
|
}) {
|
|
2099
|
-
return /* @__PURE__ */ jsx7(
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2147
|
+
return /* @__PURE__ */ jsx7(
|
|
2148
|
+
StateProvider,
|
|
2149
|
+
{
|
|
2150
|
+
store,
|
|
2151
|
+
initialState,
|
|
2152
|
+
onStateChange,
|
|
2153
|
+
children: /* @__PURE__ */ jsx7(VisibilityProvider, { children: /* @__PURE__ */ jsx7(ActionProvider, { handlers, navigate, children: /* @__PURE__ */ jsxs3(ValidationProvider, { customFunctions: validationFunctions, children: [
|
|
2154
|
+
children,
|
|
2155
|
+
/* @__PURE__ */ jsx7(ConfirmationDialogManager, {})
|
|
2156
|
+
] }) }) })
|
|
2157
|
+
}
|
|
2158
|
+
);
|
|
2103
2159
|
}
|
|
2104
2160
|
function ConfirmationDialogManager() {
|
|
2105
2161
|
const { pendingConfirmation, confirm, cancel } = useActions();
|
|
@@ -2164,6 +2220,7 @@ function createRenderer(catalog, components) {
|
|
|
2164
2220
|
const registry = components;
|
|
2165
2221
|
return function CatalogRenderer({
|
|
2166
2222
|
spec,
|
|
2223
|
+
store,
|
|
2167
2224
|
state,
|
|
2168
2225
|
onAction,
|
|
2169
2226
|
onStateChange,
|
|
@@ -2179,18 +2236,26 @@ function createRenderer(catalog, components) {
|
|
|
2179
2236
|
has: () => true
|
|
2180
2237
|
}
|
|
2181
2238
|
) : void 0;
|
|
2182
|
-
return /* @__PURE__ */ jsx7(
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2239
|
+
return /* @__PURE__ */ jsx7(
|
|
2240
|
+
StateProvider,
|
|
2241
|
+
{
|
|
2242
|
+
store,
|
|
2243
|
+
initialState: state,
|
|
2244
|
+
onStateChange,
|
|
2245
|
+
children: /* @__PURE__ */ jsx7(VisibilityProvider, { children: /* @__PURE__ */ jsx7(ActionProvider, { handlers: actionHandlers, children: /* @__PURE__ */ jsxs3(ValidationProvider, { children: [
|
|
2246
|
+
/* @__PURE__ */ jsx7(
|
|
2247
|
+
Renderer,
|
|
2248
|
+
{
|
|
2249
|
+
spec,
|
|
2250
|
+
registry,
|
|
2251
|
+
loading,
|
|
2252
|
+
fallback
|
|
2253
|
+
}
|
|
2254
|
+
),
|
|
2255
|
+
/* @__PURE__ */ jsx7(ConfirmationDialogManager, {})
|
|
2256
|
+
] }) }) })
|
|
2257
|
+
}
|
|
2258
|
+
);
|
|
2194
2259
|
};
|
|
2195
2260
|
}
|
|
2196
2261
|
export {
|
|
@@ -2204,6 +2269,7 @@ export {
|
|
|
2204
2269
|
VisibilityProvider,
|
|
2205
2270
|
createRenderer,
|
|
2206
2271
|
createStandardActionHandlers,
|
|
2272
|
+
createStateStore2 as createStateStore,
|
|
2207
2273
|
defineRegistry,
|
|
2208
2274
|
elementTreeSchema,
|
|
2209
2275
|
flatToTree,
|