chayns-api 3.0.1 → 3.1.0-beta.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/dist/cjs/calls/index.js +4 -1
- package/dist/cjs/calls/visibilityChangeListener.js +4 -4
- package/dist/cjs/components/ChaynsProvider.js +34 -6
- package/dist/cjs/components/withHydrationBoundary.js +2 -2
- package/dist/cjs/constants/index.js +0 -22
- package/dist/cjs/contexts/HistoryLayerContext.js +89 -0
- package/dist/cjs/contexts/index.js +38 -0
- package/dist/cjs/handler/history/FrameHistoryLayer.js +100 -0
- package/dist/cjs/handler/history/HistoryLayer.js +321 -0
- package/dist/cjs/handler/history/index.js +19 -0
- package/dist/cjs/hooks/history.js +454 -0
- package/dist/cjs/hooks/index.js +62 -1
- package/dist/cjs/host/ChaynsHost.js +113 -54
- package/dist/cjs/host/iframe/HostIframe.js +70 -5
- package/dist/cjs/host/module/ModuleHost.js +50 -44
- package/dist/cjs/index.js +139 -6
- package/dist/cjs/types/history.js +1 -0
- package/dist/cjs/umd.index.js +2 -2
- package/dist/cjs/utils/EventBus.js +33 -0
- package/dist/cjs/{util → utils}/appStorage.js +2 -2
- package/dist/cjs/utils/equality.js +19 -0
- package/dist/cjs/utils/history/BlockRegistry.js +153 -0
- package/dist/cjs/utils/history/NavigationQueue.js +389 -0
- package/dist/cjs/utils/history/layerTree.js +32 -0
- package/dist/cjs/utils/history/nativeBackHandling.js +61 -0
- package/dist/cjs/utils/history/navigationIndex.js +74 -0
- package/dist/cjs/utils/history/rootLayer.js +213 -0
- package/dist/cjs/utils/history/segments.js +15 -0
- package/dist/cjs/utils/history/stateProjector.js +156 -0
- package/dist/cjs/utils/history/url.js +47 -0
- package/dist/cjs/utils/history/window.js +9 -0
- package/dist/cjs/wrapper/AppWrapper.js +24 -24
- package/dist/cjs/wrapper/FrameWrapper.js +35 -2
- package/dist/cjs/wrapper/ModuleFederationWrapper.js +2 -0
- package/dist/cjs/wrapper/StaticChaynsApi.js +1 -1
- package/dist/esm/calls/index.js +2 -0
- package/dist/esm/calls/visibilityChangeListener.js +1 -1
- package/dist/esm/components/ChaynsProvider.js +34 -6
- package/dist/esm/components/withHydrationBoundary.js +1 -1
- package/dist/esm/constants/index.js +1 -3
- package/dist/esm/contexts/HistoryLayerContext.js +76 -0
- package/dist/esm/contexts/index.js +3 -0
- package/dist/esm/handler/history/FrameHistoryLayer.js +105 -0
- package/dist/esm/handler/history/HistoryLayer.js +321 -0
- package/dist/esm/handler/history/index.js +2 -0
- package/dist/esm/hooks/history.js +428 -0
- package/dist/esm/hooks/index.js +2 -1
- package/dist/esm/host/ChaynsHost.js +113 -54
- package/dist/esm/host/iframe/HostIframe.js +70 -5
- package/dist/esm/host/module/ModuleHost.js +50 -44
- package/dist/esm/index.js +15 -6
- package/dist/esm/types/history.js +1 -0
- package/dist/esm/umd.index.js +2 -2
- package/dist/esm/utils/EventBus.js +31 -0
- package/dist/esm/{util → utils}/appStorage.js +1 -1
- package/dist/esm/utils/equality.js +12 -0
- package/dist/esm/utils/history/BlockRegistry.js +151 -0
- package/dist/esm/utils/history/NavigationQueue.js +386 -0
- package/dist/esm/utils/history/layerTree.js +24 -0
- package/dist/esm/utils/history/nativeBackHandling.js +59 -0
- package/dist/esm/utils/history/navigationIndex.js +62 -0
- package/dist/esm/utils/history/rootLayer.js +205 -0
- package/dist/esm/utils/history/segments.js +7 -0
- package/dist/esm/utils/history/stateProjector.js +147 -0
- package/dist/esm/utils/history/url.js +40 -0
- package/dist/esm/utils/history/window.js +3 -0
- package/dist/esm/wrapper/AppWrapper.js +6 -6
- package/dist/esm/wrapper/FrameWrapper.js +35 -2
- package/dist/esm/wrapper/ModuleFederationWrapper.js +2 -0
- package/dist/esm/wrapper/StaticChaynsApi.js +2 -1
- package/dist/types/calls/index.d.ts +5 -0
- package/dist/types/components/ChaynsProvider.d.ts +21 -0
- package/dist/types/constants/index.d.ts +0 -2
- package/dist/types/contexts/HistoryLayerContext.d.ts +33 -0
- package/dist/types/contexts/index.d.ts +3 -0
- package/dist/types/handler/history/FrameHistoryLayer.d.ts +99 -0
- package/dist/types/handler/history/HistoryLayer.d.ts +117 -0
- package/dist/types/handler/history/index.d.ts +2 -0
- package/dist/types/hooks/history.d.ts +89 -0
- package/dist/types/hooks/index.d.ts +1 -0
- package/dist/types/host/ChaynsHost.d.ts +12 -0
- package/dist/types/host/iframe/HostIframe.d.ts +4 -0
- package/dist/types/host/module/ModuleHost.d.ts +4 -0
- package/dist/types/index.d.ts +15 -6
- package/dist/types/types/IChaynsReact.d.ts +3 -0
- package/dist/types/types/history.d.ts +74 -0
- package/dist/types/umd.index.d.ts +2 -2
- package/dist/types/utils/EventBus.d.ts +10 -0
- package/dist/types/{util → utils}/collectCssChunks.d.ts +1 -1
- package/dist/types/utils/equality.d.ts +2 -0
- package/dist/types/utils/history/BlockRegistry.d.ts +45 -0
- package/dist/types/utils/history/NavigationQueue.d.ts +118 -0
- package/dist/types/utils/history/layerTree.d.ts +10 -0
- package/dist/types/utils/history/nativeBackHandling.d.ts +47 -0
- package/dist/types/utils/history/navigationIndex.d.ts +17 -0
- package/dist/types/utils/history/rootLayer.d.ts +42 -0
- package/dist/types/utils/history/segments.d.ts +2 -0
- package/dist/types/utils/history/stateProjector.d.ts +24 -0
- package/dist/types/utils/history/url.d.ts +17 -0
- package/dist/types/utils/history/window.d.ts +1 -0
- package/dist/types/wrapper/FrameWrapper.d.ts +1 -0
- package/dist/types/wrapper/StaticChaynsApi.d.ts +1 -0
- package/package.json +2 -1
- /package/dist/cjs/{constants → contexts}/hydrationContext.js +0 -0
- /package/dist/cjs/{constants → contexts}/moduleContext.js +0 -0
- /package/dist/cjs/{helper/apiListenerHelper.js → utils/apiListener.js} +0 -0
- /package/dist/cjs/{util → utils}/appCall.js +0 -0
- /package/dist/cjs/{util → utils}/bindChaynsApi.js +0 -0
- /package/dist/cjs/{util → utils}/collectCssChunks.js +0 -0
- /package/dist/cjs/{util → utils}/deviceHelper.js +0 -0
- /package/dist/cjs/{util → utils}/heightHelper.js +0 -0
- /package/dist/cjs/{util → utils}/initModuleFederationSharing.js +0 -0
- /package/dist/cjs/{util → utils}/is.js +0 -0
- /package/dist/cjs/{util → utils}/postIframeForm.js +0 -0
- /package/dist/cjs/{util → utils}/transferNestedFunctions.js +0 -0
- /package/dist/cjs/{util → utils}/url.js +0 -0
- /package/dist/esm/{constants → contexts}/hydrationContext.js +0 -0
- /package/dist/esm/{constants → contexts}/moduleContext.js +0 -0
- /package/dist/esm/{helper/apiListenerHelper.js → utils/apiListener.js} +0 -0
- /package/dist/esm/{util → utils}/appCall.js +0 -0
- /package/dist/esm/{util → utils}/bindChaynsApi.js +0 -0
- /package/dist/esm/{util → utils}/collectCssChunks.js +0 -0
- /package/dist/esm/{util → utils}/deviceHelper.js +0 -0
- /package/dist/esm/{util → utils}/heightHelper.js +0 -0
- /package/dist/esm/{util → utils}/initModuleFederationSharing.js +0 -0
- /package/dist/esm/{util → utils}/is.js +0 -0
- /package/dist/esm/{util → utils}/postIframeForm.js +0 -0
- /package/dist/esm/{util → utils}/transferNestedFunctions.js +0 -0
- /package/dist/esm/{util → utils}/url.js +0 -0
- /package/dist/types/{constants → contexts}/hydrationContext.d.ts +0 -0
- /package/dist/types/{constants → contexts}/moduleContext.d.ts +0 -0
- /package/dist/types/{helper/apiListenerHelper.d.ts → utils/apiListener.d.ts} +0 -0
- /package/dist/types/{util → utils}/appCall.d.ts +0 -0
- /package/dist/types/{util → utils}/appStorage.d.ts +0 -0
- /package/dist/types/{util → utils}/bindChaynsApi.d.ts +0 -0
- /package/dist/types/{util → utils}/deviceHelper.d.ts +0 -0
- /package/dist/types/{util → utils}/heightHelper.d.ts +0 -0
- /package/dist/types/{util → utils}/initModuleFederationSharing.d.ts +0 -0
- /package/dist/types/{util → utils}/is.d.ts +0 -0
- /package/dist/types/{util → utils}/postIframeForm.d.ts +0 -0
- /package/dist/types/{util → utils}/transferNestedFunctions.d.ts +0 -0
- /package/dist/types/{util → utils}/url.d.ts +0 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { ChaynsHistoryLayer } from '../../handler/history/HistoryLayer';
|
|
2
|
+
import { NavigationQueue } from './NavigationQueue';
|
|
3
|
+
import { BlockRegistry } from './BlockRegistry';
|
|
4
|
+
import { findChaynsHistoryLayerById } from './layerTree';
|
|
5
|
+
import { projectToUrl, parseFromUrl } from './url';
|
|
6
|
+
import { projectToState, applyStateToTree, diffIncomingState, hasChaynsHistoryState } from './stateProjector';
|
|
7
|
+
import { silentGo, consumeSilent, incrementIdx, getCurrentIdx, syncCurrentIdxFromState } from './navigationIndex';
|
|
8
|
+
import { hasWindowHistory } from './window';
|
|
9
|
+
import { shallowEqualArr } from '../equality';
|
|
10
|
+
import { getSite } from '../../calls';
|
|
11
|
+
import { normalizeHistorySegments } from './segments';
|
|
12
|
+
import { NativeBackHandler } from './nativeBackHandling';
|
|
13
|
+
function getInitialPathname(overrideUrl) {
|
|
14
|
+
if (overrideUrl) {
|
|
15
|
+
try {
|
|
16
|
+
return new URL(overrideUrl).pathname;
|
|
17
|
+
} catch {}
|
|
18
|
+
return overrideUrl.startsWith('/') ? overrideUrl : `/${overrideUrl}`;
|
|
19
|
+
}
|
|
20
|
+
if (hasWindowHistory()) {
|
|
21
|
+
return window.location.pathname;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const siteUrl = getSite().url;
|
|
25
|
+
if (siteUrl) return new URL(siteUrl).pathname;
|
|
26
|
+
} catch {}
|
|
27
|
+
return '/';
|
|
28
|
+
}
|
|
29
|
+
function resolveInitialSegments(overrideUrl, n) {
|
|
30
|
+
const pathname = getInitialPathname(overrideUrl);
|
|
31
|
+
const all = pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
32
|
+
const taken = all.slice(0, n);
|
|
33
|
+
while (taken.length < n) taken.push('');
|
|
34
|
+
return taken;
|
|
35
|
+
}
|
|
36
|
+
export function resolveSegmentsFrom(overrideUrl, startIndex) {
|
|
37
|
+
const pathname = getInitialPathname(overrideUrl);
|
|
38
|
+
const all = pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
39
|
+
return all.slice(startIndex);
|
|
40
|
+
}
|
|
41
|
+
export function initRootChaynsHistoryLayer(opts = {}) {
|
|
42
|
+
var _opts$segmentCount;
|
|
43
|
+
const blockRegistry = new BlockRegistry();
|
|
44
|
+
let queueRef = null;
|
|
45
|
+
const deps = {
|
|
46
|
+
getRoot: () => rootLayer,
|
|
47
|
+
getQueue: () => {
|
|
48
|
+
if (!queueRef) {
|
|
49
|
+
throw new Error('[chaynsHistory] NavigationQueue not initialized yet.');
|
|
50
|
+
}
|
|
51
|
+
return queueRef;
|
|
52
|
+
},
|
|
53
|
+
getBlockRegistry: () => blockRegistry
|
|
54
|
+
};
|
|
55
|
+
const rootLayer = new ChaynsHistoryLayer({
|
|
56
|
+
id: 'root',
|
|
57
|
+
parent: null,
|
|
58
|
+
deps,
|
|
59
|
+
segmentCount: (_opts$segmentCount = opts.segmentCount) !== null && _opts$segmentCount !== void 0 ? _opts$segmentCount : 0,
|
|
60
|
+
segments: opts.segmentCount ? resolveInitialSegments(opts.url, opts.segmentCount) : []
|
|
61
|
+
});
|
|
62
|
+
const nativeBackHandler = new NativeBackHandler({
|
|
63
|
+
rootLayer,
|
|
64
|
+
blockRegistry
|
|
65
|
+
});
|
|
66
|
+
const syncNativeHandling = nativeBackHandler.sync;
|
|
67
|
+
const queue = new NavigationQueue({
|
|
68
|
+
getRoot: () => rootLayer,
|
|
69
|
+
findLayer: id => findChaynsHistoryLayerById(rootLayer, id),
|
|
70
|
+
checkBlocks: target => blockRegistry.checkBlocks(target),
|
|
71
|
+
projectUrl: () => projectToUrl(rootLayer),
|
|
72
|
+
projectState: () => {
|
|
73
|
+
var _ref;
|
|
74
|
+
const existing = hasWindowHistory() ? {
|
|
75
|
+
...((_ref = window.history.state) !== null && _ref !== void 0 ? _ref : {})
|
|
76
|
+
} : {};
|
|
77
|
+
delete existing.__chaynsHistory;
|
|
78
|
+
return projectToState(rootLayer, existing);
|
|
79
|
+
},
|
|
80
|
+
diffIncomingState: raw => diffIncomingState(rootLayer, raw),
|
|
81
|
+
applyIncomingState: raw => applyStateToTree(rootLayer, raw),
|
|
82
|
+
silentGo: delta => silentGo(delta),
|
|
83
|
+
getCurrentIdx: () => getCurrentIdx(),
|
|
84
|
+
incrementIdx: () => incrementIdx(),
|
|
85
|
+
onCommit: syncNativeHandling,
|
|
86
|
+
applyUrlSegments: () => {
|
|
87
|
+
if (!hasWindowHistory()) return {
|
|
88
|
+
changedLayerIds: new Set()
|
|
89
|
+
};
|
|
90
|
+
const {
|
|
91
|
+
perLayerSegments
|
|
92
|
+
} = parseFromUrl(window.location.pathname, rootLayer);
|
|
93
|
+
const changed = new Set();
|
|
94
|
+
for (const [id, segs] of perLayerSegments) {
|
|
95
|
+
const layer = findChaynsHistoryLayerById(rootLayer, id);
|
|
96
|
+
if (!layer) continue;
|
|
97
|
+
const normalizedSegs = normalizeHistorySegments(segs);
|
|
98
|
+
const prev = layer._getOwnSegments();
|
|
99
|
+
if (!shallowEqualArr(prev, normalizedSegs)) {
|
|
100
|
+
layer._setOwnSegmentsSilent(normalizedSegs);
|
|
101
|
+
changed.add(id);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
changedLayerIds: changed
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
queueRef = queue;
|
|
110
|
+
const existingState = hasWindowHistory() ? window.history.state : null;
|
|
111
|
+
syncCurrentIdxFromState(existingState);
|
|
112
|
+
if (!hasChaynsHistoryState(existingState)) {
|
|
113
|
+
var _opts$segmentCount2, _opts$url;
|
|
114
|
+
const segmentCount = (_opts$segmentCount2 = opts.segmentCount) !== null && _opts$segmentCount2 !== void 0 ? _opts$segmentCount2 : 0;
|
|
115
|
+
if (segmentCount > 0) {
|
|
116
|
+
const pathname = getInitialPathname(opts.url);
|
|
117
|
+
const all = pathname.replace(/^\//, '').split('/').filter(Boolean);
|
|
118
|
+
rootLayer._setBootstrapPool(all.slice(segmentCount));
|
|
119
|
+
} else {
|
|
120
|
+
rootLayer._setBootstrapUrlResolver(() => getInitialPathname(opts.url));
|
|
121
|
+
}
|
|
122
|
+
const rawUrl = (_opts$url = opts.url) !== null && _opts$url !== void 0 ? _opts$url : hasWindowHistory() ? window.location.href : null;
|
|
123
|
+
if (rawUrl) {
|
|
124
|
+
try {
|
|
125
|
+
const base = rawUrl.startsWith('http') ? rawUrl : `http://x${rawUrl.startsWith('/') ? rawUrl : '/' + rawUrl}`;
|
|
126
|
+
const parsed = new URL(base);
|
|
127
|
+
const params = {};
|
|
128
|
+
parsed.searchParams.forEach((v, k) => {
|
|
129
|
+
params[k] = v;
|
|
130
|
+
});
|
|
131
|
+
if (Object.keys(params).length > 0) rootLayer._setOwnParamsSilent(params);
|
|
132
|
+
const hash = parsed.hash.replace(/^#/, '');
|
|
133
|
+
if (hash) rootLayer._setOwnHashSilent(hash);
|
|
134
|
+
} catch {}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (hasWindowHistory()) {
|
|
138
|
+
const existing = existingState;
|
|
139
|
+
if (!hasChaynsHistoryState(existing)) {
|
|
140
|
+
const foreign = {
|
|
141
|
+
...(existing !== null && existing !== void 0 ? existing : {})
|
|
142
|
+
};
|
|
143
|
+
delete foreign.__chaynsHistory;
|
|
144
|
+
const initialState = projectToState(rootLayer, foreign);
|
|
145
|
+
const idx = getCurrentIdx();
|
|
146
|
+
window.history.replaceState({
|
|
147
|
+
...initialState,
|
|
148
|
+
__chaynsHistory: {
|
|
149
|
+
...initialState.__chaynsHistory,
|
|
150
|
+
__idx: idx
|
|
151
|
+
}
|
|
152
|
+
}, '', window.location.href);
|
|
153
|
+
} else {
|
|
154
|
+
applyStateToTree(rootLayer, existing);
|
|
155
|
+
if (syncCurrentIdxFromState(existing) === null) {
|
|
156
|
+
const foreign = {
|
|
157
|
+
...(existing !== null && existing !== void 0 ? existing : {})
|
|
158
|
+
};
|
|
159
|
+
delete foreign.__chaynsHistory;
|
|
160
|
+
const currentState = projectToState(rootLayer, foreign);
|
|
161
|
+
const idx = getCurrentIdx();
|
|
162
|
+
window.history.replaceState({
|
|
163
|
+
...currentState,
|
|
164
|
+
__chaynsHistory: {
|
|
165
|
+
...currentState.__chaynsHistory,
|
|
166
|
+
__idx: idx
|
|
167
|
+
}
|
|
168
|
+
}, '', window.location.href);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
blockRegistry.subscribeToChanges(syncNativeHandling);
|
|
172
|
+
window.addEventListener('popstate', event => {
|
|
173
|
+
syncCurrentIdxFromState(event.state);
|
|
174
|
+
if (consumeSilent()) {
|
|
175
|
+
syncNativeHandling();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const raw = event.state;
|
|
179
|
+
if (!hasChaynsHistoryState(raw)) {
|
|
180
|
+
syncNativeHandling();
|
|
181
|
+
} else {
|
|
182
|
+
const skipBlockCheck = nativeBackHandler.consumeBypassFlag();
|
|
183
|
+
void queue.enqueue({
|
|
184
|
+
kind: 'popstate',
|
|
185
|
+
rawState: raw,
|
|
186
|
+
skipBlockCheck
|
|
187
|
+
}).finally(syncNativeHandling);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
syncNativeHandling();
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
rootLayer
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
let _rootLayerResult = null;
|
|
197
|
+
export function getOrInitRootChaynsHistoryLayer(url, segmentCount) {
|
|
198
|
+
if (!_rootLayerResult) {
|
|
199
|
+
_rootLayerResult = initRootChaynsHistoryLayer({
|
|
200
|
+
url,
|
|
201
|
+
segmentCount
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return _rootLayerResult;
|
|
205
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const normalizeHistorySegments = segments => segments.filter(segment => segment.length > 0);
|
|
2
|
+
export const normalizeHistoryRouteInput = route => {
|
|
3
|
+
if (Array.isArray(route)) {
|
|
4
|
+
return normalizeHistorySegments([...route]);
|
|
5
|
+
}
|
|
6
|
+
return route.split('/').filter(Boolean);
|
|
7
|
+
};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { shallowEqualObj } from '../equality';
|
|
2
|
+
const ROOT_KEY = '__chaynsHistory';
|
|
3
|
+
const SCHEMA_VERSION = 1;
|
|
4
|
+
function buildNode(layer) {
|
|
5
|
+
const node = {
|
|
6
|
+
...layer._getOwnState()
|
|
7
|
+
};
|
|
8
|
+
const params = layer._getOwnParams();
|
|
9
|
+
if (Object.keys(params).length > 0) node.__params = {
|
|
10
|
+
...params
|
|
11
|
+
};
|
|
12
|
+
const hash = layer._getOwnHash();
|
|
13
|
+
if (hash !== undefined) node.__hash = hash;
|
|
14
|
+
const activeChildId = layer.getActiveChildId();
|
|
15
|
+
if (activeChildId) {
|
|
16
|
+
node.activeChild = activeChildId;
|
|
17
|
+
const child = layer.getChildLayer(activeChildId);
|
|
18
|
+
if (child) {
|
|
19
|
+
node.childState = buildNode(child);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return node;
|
|
23
|
+
}
|
|
24
|
+
export function projectToState(root, existing = {}) {
|
|
25
|
+
const tree = buildNode(root);
|
|
26
|
+
return {
|
|
27
|
+
...existing,
|
|
28
|
+
[ROOT_KEY]: {
|
|
29
|
+
v: SCHEMA_VERSION,
|
|
30
|
+
tree
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function applyNode(layer, node) {
|
|
35
|
+
const {
|
|
36
|
+
activeChild,
|
|
37
|
+
childState,
|
|
38
|
+
__params,
|
|
39
|
+
__hash,
|
|
40
|
+
...ownProps
|
|
41
|
+
} = node;
|
|
42
|
+
layer._setOwnStateSilent(ownProps);
|
|
43
|
+
layer._setOwnParamsSilent(__params !== null && __params !== void 0 ? __params : {});
|
|
44
|
+
layer._setOwnHashSilent('__hash' in node ? __hash : undefined);
|
|
45
|
+
if (activeChild !== undefined) {
|
|
46
|
+
layer._setActiveChildSilent(activeChild);
|
|
47
|
+
if (childState) {
|
|
48
|
+
const child = layer.getChildLayer(activeChild);
|
|
49
|
+
if (child) applyNode(child, childState);
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
layer._setActiveChildSilent(null);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function applyStateToTree(root, raw) {
|
|
56
|
+
const node = extractNode(raw);
|
|
57
|
+
if (!node) return {
|
|
58
|
+
changedLayerIds: new Set()
|
|
59
|
+
};
|
|
60
|
+
const changedLayerIds = new Set();
|
|
61
|
+
applyNodeTracked(root, node, changedLayerIds);
|
|
62
|
+
return {
|
|
63
|
+
changedLayerIds
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function diffIncomingState(root, raw) {
|
|
67
|
+
const node = extractNode(raw);
|
|
68
|
+
if (!node) return {
|
|
69
|
+
changedLayerIds: new Set()
|
|
70
|
+
};
|
|
71
|
+
const changedLayerIds = new Set();
|
|
72
|
+
diffNodeTracked(root, node, changedLayerIds);
|
|
73
|
+
return {
|
|
74
|
+
changedLayerIds
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function extractNode(raw) {
|
|
78
|
+
if (!raw || typeof raw !== 'object') return null;
|
|
79
|
+
const entry = raw[ROOT_KEY];
|
|
80
|
+
if (!entry || typeof entry !== 'object') return null;
|
|
81
|
+
const {
|
|
82
|
+
tree
|
|
83
|
+
} = entry;
|
|
84
|
+
return tree !== null && tree !== void 0 ? tree : null;
|
|
85
|
+
}
|
|
86
|
+
function applyNodeTracked(layer, node, changed) {
|
|
87
|
+
const {
|
|
88
|
+
activeChild,
|
|
89
|
+
childState,
|
|
90
|
+
__params,
|
|
91
|
+
__hash,
|
|
92
|
+
...ownProps
|
|
93
|
+
} = node;
|
|
94
|
+
const prevState = layer._getOwnState();
|
|
95
|
+
const prevActiveChild = layer.getActiveChildId();
|
|
96
|
+
const prevParams = layer._getOwnParams();
|
|
97
|
+
const prevHash = layer._getOwnHash();
|
|
98
|
+
const incomingParams = __params !== null && __params !== void 0 ? __params : {};
|
|
99
|
+
const incomingHash = '__hash' in node ? __hash : undefined;
|
|
100
|
+
const ownPropsClean = ownProps;
|
|
101
|
+
const stateChanged = !shallowEqualObj(prevState, ownPropsClean);
|
|
102
|
+
const activeChildChanged = prevActiveChild !== (activeChild !== null && activeChild !== void 0 ? activeChild : null);
|
|
103
|
+
const paramsChanged = !shallowEqualObj(prevParams, incomingParams);
|
|
104
|
+
const hashChanged = prevHash !== incomingHash;
|
|
105
|
+
const child = activeChild ? layer.getChildLayer(activeChild) : undefined;
|
|
106
|
+
layer._setOwnStateSilent(ownPropsClean);
|
|
107
|
+
layer._setActiveChildSilent(activeChild !== null && activeChild !== void 0 ? activeChild : null);
|
|
108
|
+
layer._setOwnParamsSilent(incomingParams);
|
|
109
|
+
layer._setOwnHashSilent(incomingHash);
|
|
110
|
+
if (stateChanged || activeChildChanged || paramsChanged || hashChanged) {
|
|
111
|
+
changed.add(layer.id);
|
|
112
|
+
}
|
|
113
|
+
if (activeChild && childState) {
|
|
114
|
+
if (child) applyNodeTracked(child, childState, changed);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function diffNodeTracked(layer, node, changed) {
|
|
118
|
+
const {
|
|
119
|
+
activeChild,
|
|
120
|
+
childState,
|
|
121
|
+
__params,
|
|
122
|
+
__hash,
|
|
123
|
+
...ownProps
|
|
124
|
+
} = node;
|
|
125
|
+
const prevState = layer._getOwnState();
|
|
126
|
+
const prevActiveChild = layer.getActiveChildId();
|
|
127
|
+
const prevParams = layer._getOwnParams();
|
|
128
|
+
const prevHash = layer._getOwnHash();
|
|
129
|
+
const incomingParams = __params !== null && __params !== void 0 ? __params : {};
|
|
130
|
+
const incomingHash = '__hash' in node ? __hash : undefined;
|
|
131
|
+
const ownPropsClean = ownProps;
|
|
132
|
+
const stateChanged = !shallowEqualObj(prevState, ownPropsClean);
|
|
133
|
+
const activeChildChanged = prevActiveChild !== (activeChild !== null && activeChild !== void 0 ? activeChild : null);
|
|
134
|
+
const paramsChanged = !shallowEqualObj(prevParams, incomingParams);
|
|
135
|
+
const hashChanged = prevHash !== incomingHash;
|
|
136
|
+
const child = activeChild ? layer.getChildLayer(activeChild) : undefined;
|
|
137
|
+
if (stateChanged || activeChildChanged || paramsChanged || hashChanged) {
|
|
138
|
+
changed.add(layer.id);
|
|
139
|
+
}
|
|
140
|
+
if (activeChild && childState) {
|
|
141
|
+
if (child) diffNodeTracked(child, childState, changed);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export { extractNode as _extractNode };
|
|
145
|
+
export function hasChaynsHistoryState(raw) {
|
|
146
|
+
return extractNode(raw) !== null;
|
|
147
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { getChaynsHistoryActiveChain } from './layerTree';
|
|
2
|
+
import { normalizeHistorySegments } from './segments';
|
|
3
|
+
export function projectToUrl(root) {
|
|
4
|
+
const chain = getChaynsHistoryActiveChain(root);
|
|
5
|
+
const parts = [];
|
|
6
|
+
const mergedParams = {};
|
|
7
|
+
let hash;
|
|
8
|
+
for (const layer of chain) {
|
|
9
|
+
for (const seg of normalizeHistorySegments(layer._getOwnSegments())) {
|
|
10
|
+
parts.push(seg);
|
|
11
|
+
}
|
|
12
|
+
Object.assign(mergedParams, layer._getOwnParams());
|
|
13
|
+
const layerHash = layer._getOwnHash();
|
|
14
|
+
if (layerHash !== undefined) hash = layerHash;
|
|
15
|
+
}
|
|
16
|
+
let url = '/' + parts.join('/');
|
|
17
|
+
const search = new URLSearchParams(mergedParams).toString();
|
|
18
|
+
if (search) url += '?' + search;
|
|
19
|
+
if (hash) url += '#' + hash;
|
|
20
|
+
return url;
|
|
21
|
+
}
|
|
22
|
+
export function parseFromUrl(url, root) {
|
|
23
|
+
const perLayerSegments = new Map();
|
|
24
|
+
const pathname = url.startsWith('/') ? url.slice(1) : url;
|
|
25
|
+
const all = pathname ? pathname.split('/') : [];
|
|
26
|
+
let offset = 0;
|
|
27
|
+
const chain = getChaynsHistoryActiveChain(root);
|
|
28
|
+
for (const layer of chain) {
|
|
29
|
+
const count = layer.getSegmentCount();
|
|
30
|
+
const slice = all.slice(offset, offset + count);
|
|
31
|
+
while (slice.length < count) slice.push('');
|
|
32
|
+
perLayerSegments.set(layer.id, slice);
|
|
33
|
+
offset += count;
|
|
34
|
+
}
|
|
35
|
+
const pendingSegments = offset < all.length ? all.slice(offset) : [];
|
|
36
|
+
return {
|
|
37
|
+
perLayerSegments,
|
|
38
|
+
pendingSegments
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -7,12 +7,12 @@ import { sendMessageToGroup, sendMessageToPage, sendMessageToUser } from '../cal
|
|
|
7
7
|
import { DefaultLoginDialogOptions } from '../constants';
|
|
8
8
|
import { DeviceLanguage } from '../constants/languages';
|
|
9
9
|
import DialogHandler from '../handler/DialogHandler';
|
|
10
|
-
import { addApiListener, dispatchApiEvent, removeApiListener } from '../
|
|
10
|
+
import { addApiListener, dispatchApiEvent, removeApiListener } from '../utils/apiListener';
|
|
11
11
|
import { AppName, DialogButtonType, DialogType, Environment, Font, Gender, IconType, LoginState, RuntimeEnviroment, TappEvent } from '../types/IChaynsReact';
|
|
12
|
-
import invokeAppCall from '../
|
|
13
|
-
import { addAppStorageListener, clearAppStorage, isAppStorageAvailable, setAppStorageItem } from '../
|
|
14
|
-
import getDeviceInfo, { getScreenSize } from '../
|
|
15
|
-
import { isAppCallSupported } from '../
|
|
12
|
+
import invokeAppCall from '../utils/appCall';
|
|
13
|
+
import { addAppStorageListener, clearAppStorage, isAppStorageAvailable, setAppStorageItem } from '../utils/appStorage';
|
|
14
|
+
import getDeviceInfo, { getScreenSize } from '../utils/deviceHelper';
|
|
15
|
+
import { isAppCallSupported } from '../utils/is';
|
|
16
16
|
export class AppWrapper {
|
|
17
17
|
async loadStyleSettings(siteId) {
|
|
18
18
|
try {
|
|
@@ -83,7 +83,7 @@ export class AppWrapper {
|
|
|
83
83
|
runtimeEnvironment: RuntimeEnviroment.App
|
|
84
84
|
},
|
|
85
85
|
language: {
|
|
86
|
-
site:
|
|
86
|
+
site: language,
|
|
87
87
|
translation: null,
|
|
88
88
|
device: language,
|
|
89
89
|
active: language
|
|
@@ -6,8 +6,9 @@ import getUserInfo from '../calls/getUserInfo';
|
|
|
6
6
|
import { sendMessageToGroup, sendMessageToPage, sendMessageToUser } from '../calls/sendMessage';
|
|
7
7
|
import { addVisibilityChangeListener, removeVisibilityChangeListener } from '../calls/visibilityChangeListener';
|
|
8
8
|
import DialogHandler from '../handler/DialogHandler';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { FrameHistoryLayer } from '../handler/history/FrameHistoryLayer';
|
|
10
|
+
import { setTappHeight } from '../utils/heightHelper';
|
|
11
|
+
import { initTransferNestedFunctions } from '../utils/transferNestedFunctions';
|
|
11
12
|
export class FrameWrapper {
|
|
12
13
|
constructor() {
|
|
13
14
|
_defineProperty(this, "resolve", null);
|
|
@@ -15,6 +16,7 @@ export class FrameWrapper {
|
|
|
15
16
|
_defineProperty(this, "exposedCustomFunctions", {});
|
|
16
17
|
_defineProperty(this, "exposedCustomFunctionNames", []);
|
|
17
18
|
_defineProperty(this, "resizeListener", null);
|
|
19
|
+
_defineProperty(this, "_historyLayer", null);
|
|
18
20
|
_defineProperty(this, "ready", new Promise(res => {
|
|
19
21
|
this.resolve = res;
|
|
20
22
|
}));
|
|
@@ -297,6 +299,12 @@ export class FrameWrapper {
|
|
|
297
299
|
redirect: async options => {
|
|
298
300
|
if (!this.initialized) await this.ready;
|
|
299
301
|
return this.exposedFunctions.redirect(options);
|
|
302
|
+
},
|
|
303
|
+
getHistoryLayer: () => {
|
|
304
|
+
if (!this._historyLayer) {
|
|
305
|
+
throw new Error('[chaynsHistory] No history layer available. Ensure historyLayer prop is set on the parent HostIframe.');
|
|
306
|
+
}
|
|
307
|
+
return this._historyLayer;
|
|
300
308
|
}
|
|
301
309
|
});
|
|
302
310
|
_defineProperty(this, "customFunctions", new Proxy({}, {
|
|
@@ -365,6 +373,31 @@ export class FrameWrapper {
|
|
|
365
373
|
p[e] = (...args) => this.exposedCustomFunctions[e](...args.map(a => typeof a === 'function' ? comlink.proxy(a) : a));
|
|
366
374
|
return p;
|
|
367
375
|
}, {});
|
|
376
|
+
const exposedHistory = exposed.history;
|
|
377
|
+
if (exposedHistory) {
|
|
378
|
+
const initialState = await exposedHistory.getInitialState();
|
|
379
|
+
if (initialState) {
|
|
380
|
+
this._historyLayer = new FrameHistoryLayer({
|
|
381
|
+
setRoute: (route, opts) => exposedHistory.setRoute(route, opts),
|
|
382
|
+
setParams: (params, opts) => exposedHistory.setParams(params, opts),
|
|
383
|
+
setHash: (hash, opts) => exposedHistory.setHash(hash, opts),
|
|
384
|
+
setState: (state, opts) => exposedHistory.setState(state, opts),
|
|
385
|
+
navigate: opts => exposedHistory.navigate(opts),
|
|
386
|
+
setActiveChild: (id, init) => exposedHistory.setActiveChild(id, init),
|
|
387
|
+
setSegmentCount: n => exposedHistory.setSegmentCount(n),
|
|
388
|
+
addBlock: async (callback, opts) => {
|
|
389
|
+
const remoteUnsub = await exposedHistory.addBlock(comlink.proxy(callback), opts);
|
|
390
|
+
return () => void remoteUnsub();
|
|
391
|
+
}
|
|
392
|
+
}, initialState);
|
|
393
|
+
await exposedHistory.addChangeListener(comlink.proxy(e => {
|
|
394
|
+
this._historyLayer._applyAndEmit(e);
|
|
395
|
+
}));
|
|
396
|
+
await exposedHistory.addPopstateListener(comlink.proxy(e => {
|
|
397
|
+
this._historyLayer._applyAndEmit(e);
|
|
398
|
+
}));
|
|
399
|
+
}
|
|
400
|
+
}
|
|
368
401
|
this.initialized = true;
|
|
369
402
|
this.resolve(null);
|
|
370
403
|
setTappHeight(this.functions.setHeight);
|
|
@@ -2,6 +2,7 @@ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object
|
|
|
2
2
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
3
3
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4
4
|
import DialogHandler from '../handler/DialogHandler';
|
|
5
|
+
import { getOrInitRootChaynsHistoryLayer } from '../utils/history/rootLayer';
|
|
5
6
|
import { addVisibilityChangeListener, removeVisibilityChangeListener } from '../calls/visibilityChangeListener';
|
|
6
7
|
import getUserInfo from '../calls/getUserInfo';
|
|
7
8
|
import { sendMessageToGroup, sendMessageToPage, sendMessageToUser } from '../calls/sendMessage';
|
|
@@ -38,6 +39,7 @@ export class ModuleFederationWrapper {
|
|
|
38
39
|
this.functions.createDialog = config => {
|
|
39
40
|
return new DialogHandler(config, functions.openDialog, functions.closeDialog, functions.dispatchEventToDialogClient, functions.addDialogClientEventListener);
|
|
40
41
|
};
|
|
42
|
+
this.functions.getHistoryLayer = () => getOrInitRootChaynsHistoryLayer().rootLayer;
|
|
41
43
|
}
|
|
42
44
|
async init() {
|
|
43
45
|
return undefined;
|
|
@@ -3,7 +3,7 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
|
|
|
3
3
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4
4
|
import { moduleWrapper } from '../components/moduleWrapper';
|
|
5
5
|
import { AppFlavor } from '../types/IChaynsReact';
|
|
6
|
-
import getDeviceInfo from '../
|
|
6
|
+
import getDeviceInfo from '../utils/deviceHelper';
|
|
7
7
|
import { AppWrapper } from './AppWrapper';
|
|
8
8
|
import { FrameWrapper } from './FrameWrapper';
|
|
9
9
|
import { ModuleFederationWrapper } from './ModuleFederationWrapper';
|
|
@@ -74,6 +74,7 @@ class StaticChaynsApi {
|
|
|
74
74
|
_defineProperty(this, "addAccessTokenChangeListener", void 0);
|
|
75
75
|
_defineProperty(this, "removeAccessTokenChangeListener", void 0);
|
|
76
76
|
_defineProperty(this, "redirect", void 0);
|
|
77
|
+
_defineProperty(this, "getHistoryLayer", void 0);
|
|
77
78
|
_defineProperty(this, "ready", void 0);
|
|
78
79
|
_defineProperty(this, "addDataListener", void 0);
|
|
79
80
|
_defineProperty(this, "_wrapper", void 0);
|
|
@@ -227,6 +227,11 @@ export declare const addAnonymousAccount: () => Promise<import("../types/IChayns
|
|
|
227
227
|
* @category User functions
|
|
228
228
|
*/
|
|
229
229
|
export declare const getUser: () => import("../types/IChaynsReact").ChaynsApiUser | undefined;
|
|
230
|
+
/**
|
|
231
|
+
* Returns the innermost currently mounted HistoryLayer. Falls back to the
|
|
232
|
+
* root layer when called outside any HistoryLayerProvider.
|
|
233
|
+
*/
|
|
234
|
+
export declare const getChaynsHistoryLayer: () => import("..").ChaynsHistoryLayer | null;
|
|
230
235
|
export declare const getSite: () => ChaynsApiSite;
|
|
231
236
|
export declare const getCurrentPage: () => {
|
|
232
237
|
id: number;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
2
|
import { ChaynsReactFunctions, ChaynsReactValues, IChaynsReact } from '../types/IChaynsReact';
|
|
3
|
+
import type { ChaynsHistoryLayer } from '../types/history';
|
|
3
4
|
export type ChaynsProviderProps = {
|
|
4
5
|
data?: ChaynsReactValues;
|
|
5
6
|
functions?: ChaynsReactFunctions;
|
|
@@ -8,6 +9,26 @@ export type ChaynsProviderProps = {
|
|
|
8
9
|
isModule?: boolean;
|
|
9
10
|
children?: ReactNode;
|
|
10
11
|
chaynsApiId?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Explicit history layer to provide to the React subtree.
|
|
14
|
+
* When set this layer is used directly and no root layer is auto-initialised.
|
|
15
|
+
* Use this when the parent already owns a layer and wants to scope children to it.
|
|
16
|
+
*/
|
|
17
|
+
historyLayer?: ChaynsHistoryLayer;
|
|
18
|
+
/**
|
|
19
|
+
* Initial history configuration for the root layer.
|
|
20
|
+
* Ignored when `layer` is provided explicitly.
|
|
21
|
+
* - `url`: Current page URL — browser defaults to `window.location.pathname`;
|
|
22
|
+
* for SSR pass the request URL (e.g. `req.url` or `router.asPath`).
|
|
23
|
+
* - `segmentCount`: Number of URL path segments this application claims.
|
|
24
|
+
* E.g. `segmentCount: 2` on `/shop/products/detail` → `getLayer().getRoute()` → `['shop', 'products']`.
|
|
25
|
+
*/
|
|
26
|
+
history?: {
|
|
27
|
+
url?: string;
|
|
28
|
+
segmentCount?: number;
|
|
29
|
+
};
|
|
30
|
+
segmentCount?: number;
|
|
31
|
+
isHistoryDisabled?: boolean;
|
|
11
32
|
};
|
|
12
33
|
declare const ChaynsProvider: React.FC<ChaynsProviderProps>;
|
|
13
34
|
export default ChaynsProvider;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React, { type FC, type ReactNode } from 'react';
|
|
2
|
+
import type { ChaynsHistoryLayer } from '../types/history';
|
|
3
|
+
export declare function pushChaynsHistoryLayer(layer: ChaynsHistoryLayer): void;
|
|
4
|
+
export declare function popChaynsHistoryLayer(layer: ChaynsHistoryLayer): void;
|
|
5
|
+
/** Returns the innermost currently mounted ChaynsHistoryLayer, or the root layer as fallback. */
|
|
6
|
+
export declare function getCurrentChaynsHistoryLayer(): ChaynsHistoryLayer | null;
|
|
7
|
+
declare const ChaynsHistoryLayerContext: React.Context<ChaynsHistoryLayer | null>;
|
|
8
|
+
export interface ChaynsHistoryLayerProviderProps {
|
|
9
|
+
layer: ChaynsHistoryLayer;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Provides a ChaynsHistoryLayer to the React subtree **and** registers it on the
|
|
14
|
+
* module-level layer stack so that `getCurrentChaynsHistoryLayer()` (static / non-React
|
|
15
|
+
* call sites) also sees this layer as the current one.
|
|
16
|
+
*
|
|
17
|
+
* Use `ChaynsHistoryLayerOverrideProvider` instead if you only want to override the
|
|
18
|
+
* React context without affecting static call sites.
|
|
19
|
+
*/
|
|
20
|
+
export declare const ChaynsHistoryLayerProvider: FC<ChaynsHistoryLayerProviderProps>;
|
|
21
|
+
/**
|
|
22
|
+
* Overrides the ChaynsHistoryLayer for the React subtree **only** — hooks such as
|
|
23
|
+
* `useChaynsHistoryLayer`, `useChaynsHistoryRoute`, `useChaynsHistoryNavigate`, etc. will resolve to the
|
|
24
|
+
* provided `layer`, but `getCurrentChaynsHistoryLayer()` (the static / non-React accessor
|
|
25
|
+
* that reads from the module-level layer stack) is left unchanged.
|
|
26
|
+
*
|
|
27
|
+
* This is useful when you need to scope history to a specific layer inside a
|
|
28
|
+
* React tree without affecting imperative call sites outside that tree.
|
|
29
|
+
*/
|
|
30
|
+
export declare const ChaynsHistoryLayerOverrideProvider: FC<ChaynsHistoryLayerProviderProps>;
|
|
31
|
+
/** Returns the nearest ChaynsHistoryLayer from context, or null if none. */
|
|
32
|
+
export declare function useChaynsHistoryLayerContext(): ChaynsHistoryLayer | null;
|
|
33
|
+
export default ChaynsHistoryLayerContext;
|