@openwebf/react-router 0.24.2 → 1.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/dist/index.d.ts +40 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +510 -66
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +513 -64
- package/dist/index.js.map +1 -1
- package/dist/platform/browserHistory.d.ts +114 -0
- package/dist/platform/browserHistory.d.ts.map +1 -0
- package/dist/platform/index.d.ts +32 -0
- package/dist/platform/index.d.ts.map +1 -0
- package/dist/routes/utils.d.ts +2 -1
- package/dist/routes/utils.d.ts.map +1 -1
- package/dist/utils/RouterLink.d.ts +4 -2
- package/dist/utils/RouterLink.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -36,14 +36,347 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
39
|
+
* Platform detection and abstraction layer
|
|
40
40
|
*
|
|
41
|
-
*
|
|
41
|
+
* Detects whether running in WebF or standard browser environment
|
|
42
|
+
* and provides a unified interface for platform-specific APIs.
|
|
43
|
+
*
|
|
44
|
+
* WebF types are provided by @openwebf/webf-enterprise-typings package.
|
|
45
|
+
* In browser environments, the router works without WebF types.
|
|
42
46
|
*/
|
|
43
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Get the WebF hybridHistory object if available
|
|
49
|
+
* Types come from @openwebf/webf-enterprise-typings peer dependency
|
|
50
|
+
*/
|
|
51
|
+
function getWebFHybridHistory() {
|
|
44
52
|
var _a;
|
|
45
53
|
return (_a = globalThis === null || globalThis === void 0 ? void 0 : globalThis.webf) === null || _a === void 0 ? void 0 : _a.hybridHistory;
|
|
46
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Detect the current platform
|
|
57
|
+
*/
|
|
58
|
+
function detectPlatform() {
|
|
59
|
+
// Check for WebF's hybridHistory API
|
|
60
|
+
if (getWebFHybridHistory()) {
|
|
61
|
+
return 'webf';
|
|
62
|
+
}
|
|
63
|
+
return 'browser';
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check if running in WebF environment
|
|
67
|
+
*/
|
|
68
|
+
function isWebF() {
|
|
69
|
+
return detectPlatform() === 'webf';
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if running in browser environment
|
|
73
|
+
*/
|
|
74
|
+
function isBrowser() {
|
|
75
|
+
return detectPlatform() === 'browser';
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get the current platform type (evaluated once at module load)
|
|
79
|
+
*/
|
|
80
|
+
const platform = detectPlatform();
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Browser History Adapter
|
|
84
|
+
*
|
|
85
|
+
* Provides a unified history API that mimics WebF's hybridHistory
|
|
86
|
+
* but uses the standard browser History API under the hood.
|
|
87
|
+
*
|
|
88
|
+
* Supports SSR/Node.js environments by providing memory-based fallback.
|
|
89
|
+
*/
|
|
90
|
+
/**
|
|
91
|
+
* Check if we're in a browser environment
|
|
92
|
+
*/
|
|
93
|
+
function hasWindow() {
|
|
94
|
+
return typeof window !== 'undefined' && typeof window.history !== 'undefined';
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Generate a unique key for history entries
|
|
98
|
+
*/
|
|
99
|
+
function generateKey() {
|
|
100
|
+
return Math.random().toString(36).substring(2, 10);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Browser History implementation that provides WebF-like navigation APIs
|
|
104
|
+
*/
|
|
105
|
+
class BrowserHistoryAdapter {
|
|
106
|
+
constructor() {
|
|
107
|
+
this._stack = [];
|
|
108
|
+
this._currentIndex = -1;
|
|
109
|
+
this._listeners = new Set();
|
|
110
|
+
this._initialized = false;
|
|
111
|
+
this._initialize();
|
|
112
|
+
}
|
|
113
|
+
_initialize() {
|
|
114
|
+
if (this._initialized)
|
|
115
|
+
return;
|
|
116
|
+
this._initialized = true;
|
|
117
|
+
// SSR/Node.js fallback - use memory-based history
|
|
118
|
+
if (!hasWindow()) {
|
|
119
|
+
const key = generateKey();
|
|
120
|
+
this._stack = [{ path: '/', state: null, key }];
|
|
121
|
+
this._currentIndex = 0;
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
// Initialize with current location
|
|
125
|
+
const initialPath = window.location.pathname || '/';
|
|
126
|
+
const initialState = window.history.state;
|
|
127
|
+
if (initialState === null || initialState === void 0 ? void 0 : initialState.key) {
|
|
128
|
+
// Restore from existing state
|
|
129
|
+
this._stack = [{ path: initialState.path, state: initialState.state, key: initialState.key }];
|
|
130
|
+
this._currentIndex = 0;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// Fresh start
|
|
134
|
+
const key = generateKey();
|
|
135
|
+
const entry = { path: initialPath, state: null, key };
|
|
136
|
+
this._stack = [entry];
|
|
137
|
+
this._currentIndex = 0;
|
|
138
|
+
// Replace current state with our tracked state
|
|
139
|
+
window.history.replaceState({ path: initialPath, state: null, key, index: 0 }, '', initialPath);
|
|
140
|
+
}
|
|
141
|
+
// Listen to popstate events
|
|
142
|
+
window.addEventListener('popstate', this._handlePopState.bind(this));
|
|
143
|
+
}
|
|
144
|
+
_handlePopState(event) {
|
|
145
|
+
const state = event.state;
|
|
146
|
+
if (state === null || state === void 0 ? void 0 : state.key) {
|
|
147
|
+
// Find the entry in our stack
|
|
148
|
+
const index = this._stack.findIndex((e) => e.key === state.key);
|
|
149
|
+
if (index !== -1) {
|
|
150
|
+
this._currentIndex = index;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Dispatch custom event for Routes component
|
|
154
|
+
this._dispatchRouterChangeEvent((state === null || state === void 0 ? void 0 : state.path) || window.location.pathname, state === null || state === void 0 ? void 0 : state.state, 'didPopNext');
|
|
155
|
+
}
|
|
156
|
+
_dispatchRouterChangeEvent(path, state, kind) {
|
|
157
|
+
if (typeof document === 'undefined')
|
|
158
|
+
return;
|
|
159
|
+
const event = new CustomEvent('hybridrouterchange', {
|
|
160
|
+
bubbles: true,
|
|
161
|
+
composed: true,
|
|
162
|
+
detail: { path, state, kind },
|
|
163
|
+
});
|
|
164
|
+
event.path = path;
|
|
165
|
+
event.state = state;
|
|
166
|
+
event.kind = kind;
|
|
167
|
+
document.dispatchEvent(event);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get the current state
|
|
171
|
+
*/
|
|
172
|
+
get state() {
|
|
173
|
+
var _a, _b;
|
|
174
|
+
return (_b = (_a = this._stack[this._currentIndex]) === null || _a === void 0 ? void 0 : _a.state) !== null && _b !== void 0 ? _b : null;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get the current path
|
|
178
|
+
*/
|
|
179
|
+
get path() {
|
|
180
|
+
var _a, _b;
|
|
181
|
+
return (_b = (_a = this._stack[this._currentIndex]) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : '/';
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Get the full navigation stack
|
|
185
|
+
*/
|
|
186
|
+
get buildContextStack() {
|
|
187
|
+
// Return entries up to current index (simulating WebF's stack behavior)
|
|
188
|
+
return this._stack.slice(0, this._currentIndex + 1);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Push a new named route (WebF-style)
|
|
192
|
+
*/
|
|
193
|
+
pushNamed(path, options) {
|
|
194
|
+
var _a;
|
|
195
|
+
const key = generateKey();
|
|
196
|
+
const state = (_a = options === null || options === void 0 ? void 0 : options.arguments) !== null && _a !== void 0 ? _a : null;
|
|
197
|
+
const newIndex = this._currentIndex + 1;
|
|
198
|
+
// Truncate forward stack if we're in the middle
|
|
199
|
+
this._stack = this._stack.slice(0, newIndex);
|
|
200
|
+
const entry = { path, state, key };
|
|
201
|
+
this._stack.push(entry);
|
|
202
|
+
this._currentIndex = newIndex;
|
|
203
|
+
if (hasWindow()) {
|
|
204
|
+
window.history.pushState({ path, state, key, index: newIndex }, '', path);
|
|
205
|
+
}
|
|
206
|
+
this._dispatchRouterChangeEvent(path, state, 'didPush');
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Replace the current route (WebF-style)
|
|
210
|
+
*/
|
|
211
|
+
pushReplacementNamed(path, options) {
|
|
212
|
+
var _a;
|
|
213
|
+
const key = generateKey();
|
|
214
|
+
const state = (_a = options === null || options === void 0 ? void 0 : options.arguments) !== null && _a !== void 0 ? _a : null;
|
|
215
|
+
const entry = { path, state, key };
|
|
216
|
+
this._stack[this._currentIndex] = entry;
|
|
217
|
+
if (hasWindow()) {
|
|
218
|
+
window.history.replaceState({ path, state, key, index: this._currentIndex }, '', path);
|
|
219
|
+
}
|
|
220
|
+
this._dispatchRouterChangeEvent(path, state, 'didPush');
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Go back in history
|
|
224
|
+
*/
|
|
225
|
+
back() {
|
|
226
|
+
var _a;
|
|
227
|
+
if (hasWindow()) {
|
|
228
|
+
window.history.back();
|
|
229
|
+
}
|
|
230
|
+
else if (this._currentIndex > 0) {
|
|
231
|
+
// Memory-based fallback for SSR
|
|
232
|
+
this._currentIndex--;
|
|
233
|
+
const entry = this._stack[this._currentIndex];
|
|
234
|
+
this._dispatchRouterChangeEvent((_a = entry === null || entry === void 0 ? void 0 : entry.path) !== null && _a !== void 0 ? _a : '/', entry === null || entry === void 0 ? void 0 : entry.state, 'didPopNext');
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Pop the current route (Flutter-style)
|
|
239
|
+
*/
|
|
240
|
+
pop(result) {
|
|
241
|
+
var _a;
|
|
242
|
+
if (this._currentIndex > 0) {
|
|
243
|
+
if (hasWindow()) {
|
|
244
|
+
window.history.back();
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
// Memory-based fallback for SSR
|
|
248
|
+
this._currentIndex--;
|
|
249
|
+
const entry = this._stack[this._currentIndex];
|
|
250
|
+
this._dispatchRouterChangeEvent((_a = entry === null || entry === void 0 ? void 0 : entry.path) !== null && _a !== void 0 ? _a : '/', entry === null || entry === void 0 ? void 0 : entry.state, 'didPopNext');
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Pop routes until reaching a specific route
|
|
256
|
+
*/
|
|
257
|
+
popUntil(targetPath) {
|
|
258
|
+
var _a;
|
|
259
|
+
const targetIndex = this._stack.findIndex((e) => e.path === targetPath);
|
|
260
|
+
if (targetIndex !== -1 && targetIndex < this._currentIndex) {
|
|
261
|
+
if (hasWindow()) {
|
|
262
|
+
const delta = targetIndex - this._currentIndex;
|
|
263
|
+
window.history.go(delta);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
// Memory-based fallback for SSR
|
|
267
|
+
this._currentIndex = targetIndex;
|
|
268
|
+
const entry = this._stack[this._currentIndex];
|
|
269
|
+
this._dispatchRouterChangeEvent((_a = entry === null || entry === void 0 ? void 0 : entry.path) !== null && _a !== void 0 ? _a : '/', entry === null || entry === void 0 ? void 0 : entry.state, 'didPopNext');
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Pop the current route and push a new route
|
|
275
|
+
*/
|
|
276
|
+
popAndPushNamed(path, options) {
|
|
277
|
+
var _a;
|
|
278
|
+
const key = generateKey();
|
|
279
|
+
const state = (_a = options === null || options === void 0 ? void 0 : options.arguments) !== null && _a !== void 0 ? _a : null;
|
|
280
|
+
const entry = { path, state, key };
|
|
281
|
+
this._stack[this._currentIndex] = entry;
|
|
282
|
+
if (hasWindow()) {
|
|
283
|
+
window.history.replaceState({ path, state, key, index: this._currentIndex }, '', path);
|
|
284
|
+
}
|
|
285
|
+
this._dispatchRouterChangeEvent(path, state, 'didPush');
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Push a new route and remove routes until a specific route
|
|
289
|
+
*/
|
|
290
|
+
pushNamedAndRemoveUntil(state, path, untilPath) {
|
|
291
|
+
const targetIndex = this._stack.findIndex((e) => e.path === untilPath);
|
|
292
|
+
if (targetIndex !== -1) {
|
|
293
|
+
// Truncate stack to target and add new entry
|
|
294
|
+
this._stack = this._stack.slice(0, targetIndex + 1);
|
|
295
|
+
this._currentIndex = targetIndex;
|
|
296
|
+
}
|
|
297
|
+
this.pushNamed(path, { arguments: state });
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Push a new route and remove all routes until a specific route (Flutter-style)
|
|
301
|
+
*/
|
|
302
|
+
pushNamedAndRemoveUntilRoute(newPath, untilPath, options) {
|
|
303
|
+
this.pushNamedAndRemoveUntil(options === null || options === void 0 ? void 0 : options.arguments, newPath, untilPath);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Check if we can go back
|
|
307
|
+
*/
|
|
308
|
+
canPop() {
|
|
309
|
+
return this._currentIndex > 0;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Pop if possible, return success status
|
|
313
|
+
*/
|
|
314
|
+
maybePop(result) {
|
|
315
|
+
if (this.canPop()) {
|
|
316
|
+
this.pop(result);
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Push state (web-style)
|
|
323
|
+
*/
|
|
324
|
+
pushState(state, name) {
|
|
325
|
+
this.pushNamed(name, { arguments: state });
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Replace state (web-style)
|
|
329
|
+
*/
|
|
330
|
+
replaceState(state, name) {
|
|
331
|
+
this.pushReplacementNamed(name, { arguments: state });
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Pop and push with restoration capability
|
|
335
|
+
*/
|
|
336
|
+
restorablePopAndPushState(state, name) {
|
|
337
|
+
const key = generateKey();
|
|
338
|
+
this.popAndPushNamed(name, { arguments: state });
|
|
339
|
+
return key;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Pop and push named route with restoration capability
|
|
343
|
+
*/
|
|
344
|
+
restorablePopAndPushNamed(path, options) {
|
|
345
|
+
const key = generateKey();
|
|
346
|
+
this.popAndPushNamed(path, options);
|
|
347
|
+
return key;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Singleton instance
|
|
351
|
+
let browserHistoryInstance = null;
|
|
352
|
+
/**
|
|
353
|
+
* Get the browser history adapter instance
|
|
354
|
+
*/
|
|
355
|
+
function getBrowserHistory() {
|
|
356
|
+
if (!browserHistoryInstance) {
|
|
357
|
+
browserHistoryInstance = new BrowserHistoryAdapter();
|
|
358
|
+
}
|
|
359
|
+
return browserHistoryInstance;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Reset the browser history adapter (for testing)
|
|
363
|
+
*/
|
|
364
|
+
function resetBrowserHistory() {
|
|
365
|
+
browserHistoryInstance = null;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Get the appropriate history object based on the current platform.
|
|
370
|
+
* Returns WebF's hybridHistory in WebF environment, or BrowserHistoryAdapter in browser.
|
|
371
|
+
*/
|
|
372
|
+
function getHybridHistory() {
|
|
373
|
+
const webfHistory = getWebFHybridHistory();
|
|
374
|
+
if (webfHistory) {
|
|
375
|
+
return webfHistory;
|
|
376
|
+
}
|
|
377
|
+
// Fallback to browser history adapter
|
|
378
|
+
return getBrowserHistory();
|
|
379
|
+
}
|
|
47
380
|
let ensureRouteMountedCallback = null;
|
|
48
381
|
function __unstable_setEnsureRouteMountedCallback(callback) {
|
|
49
382
|
ensureRouteMountedCallback = callback;
|
|
@@ -57,7 +390,8 @@ function ensureRouteMounted(pathname) {
|
|
|
57
390
|
}
|
|
58
391
|
/**
|
|
59
392
|
* WebF Router object - provides comprehensive navigation APIs
|
|
60
|
-
* Combines web-like history management with Flutter-like navigation patterns
|
|
393
|
+
* Combines web-like history management with Flutter-like navigation patterns.
|
|
394
|
+
* Works in both WebF native environment and standard browser environment.
|
|
61
395
|
*/
|
|
62
396
|
const WebFRouter = {
|
|
63
397
|
/**
|
|
@@ -88,8 +422,6 @@ const WebFRouter = {
|
|
|
88
422
|
*/
|
|
89
423
|
push: (path, state) => __awaiter(void 0, void 0, void 0, function* () {
|
|
90
424
|
const hybridHistory = getHybridHistory();
|
|
91
|
-
if (!hybridHistory)
|
|
92
|
-
throw new Error('WebF hybridHistory is not available');
|
|
93
425
|
yield ensureRouteMounted(path);
|
|
94
426
|
hybridHistory.pushNamed(path, { arguments: state });
|
|
95
427
|
}),
|
|
@@ -99,8 +431,6 @@ const WebFRouter = {
|
|
|
99
431
|
*/
|
|
100
432
|
replace: (path, state) => __awaiter(void 0, void 0, void 0, function* () {
|
|
101
433
|
const hybridHistory = getHybridHistory();
|
|
102
|
-
if (!hybridHistory)
|
|
103
|
-
throw new Error('WebF hybridHistory is not available');
|
|
104
434
|
yield ensureRouteMounted(path);
|
|
105
435
|
hybridHistory.pushReplacementNamed(path, { arguments: state });
|
|
106
436
|
}),
|
|
@@ -109,8 +439,6 @@ const WebFRouter = {
|
|
|
109
439
|
*/
|
|
110
440
|
back: () => {
|
|
111
441
|
const hybridHistory = getHybridHistory();
|
|
112
|
-
if (!hybridHistory)
|
|
113
|
-
throw new Error('WebF hybridHistory is not available');
|
|
114
442
|
hybridHistory.back();
|
|
115
443
|
},
|
|
116
444
|
/**
|
|
@@ -119,8 +447,6 @@ const WebFRouter = {
|
|
|
119
447
|
*/
|
|
120
448
|
pop: (result) => {
|
|
121
449
|
const hybridHistory = getHybridHistory();
|
|
122
|
-
if (!hybridHistory)
|
|
123
|
-
throw new Error('WebF hybridHistory is not available');
|
|
124
450
|
hybridHistory.pop(result);
|
|
125
451
|
},
|
|
126
452
|
/**
|
|
@@ -128,8 +454,6 @@ const WebFRouter = {
|
|
|
128
454
|
*/
|
|
129
455
|
popUntil: (path) => {
|
|
130
456
|
const hybridHistory = getHybridHistory();
|
|
131
|
-
if (!hybridHistory)
|
|
132
|
-
throw new Error('WebF hybridHistory is not available');
|
|
133
457
|
hybridHistory.popUntil(path);
|
|
134
458
|
},
|
|
135
459
|
/**
|
|
@@ -137,8 +461,6 @@ const WebFRouter = {
|
|
|
137
461
|
*/
|
|
138
462
|
popAndPushNamed: (path, state) => __awaiter(void 0, void 0, void 0, function* () {
|
|
139
463
|
const hybridHistory = getHybridHistory();
|
|
140
|
-
if (!hybridHistory)
|
|
141
|
-
throw new Error('WebF hybridHistory is not available');
|
|
142
464
|
yield ensureRouteMounted(path);
|
|
143
465
|
hybridHistory.popAndPushNamed(path, { arguments: state });
|
|
144
466
|
}),
|
|
@@ -147,8 +469,6 @@ const WebFRouter = {
|
|
|
147
469
|
*/
|
|
148
470
|
pushNamedAndRemoveUntil: (path, state, untilPath) => __awaiter(void 0, void 0, void 0, function* () {
|
|
149
471
|
const hybridHistory = getHybridHistory();
|
|
150
|
-
if (!hybridHistory)
|
|
151
|
-
throw new Error('WebF hybridHistory is not available');
|
|
152
472
|
yield ensureRouteMounted(path);
|
|
153
473
|
hybridHistory.pushNamedAndRemoveUntil(state, path, untilPath);
|
|
154
474
|
}),
|
|
@@ -157,8 +477,6 @@ const WebFRouter = {
|
|
|
157
477
|
*/
|
|
158
478
|
pushNamedAndRemoveUntilRoute: (newPath, untilPath, state) => __awaiter(void 0, void 0, void 0, function* () {
|
|
159
479
|
const hybridHistory = getHybridHistory();
|
|
160
|
-
if (!hybridHistory)
|
|
161
|
-
throw new Error('WebF hybridHistory is not available');
|
|
162
480
|
yield ensureRouteMounted(newPath);
|
|
163
481
|
hybridHistory.pushNamedAndRemoveUntilRoute(newPath, untilPath, { arguments: state });
|
|
164
482
|
}),
|
|
@@ -167,8 +485,6 @@ const WebFRouter = {
|
|
|
167
485
|
*/
|
|
168
486
|
canPop: () => {
|
|
169
487
|
const hybridHistory = getHybridHistory();
|
|
170
|
-
if (!hybridHistory)
|
|
171
|
-
return false;
|
|
172
488
|
return hybridHistory.canPop();
|
|
173
489
|
},
|
|
174
490
|
/**
|
|
@@ -177,8 +493,6 @@ const WebFRouter = {
|
|
|
177
493
|
*/
|
|
178
494
|
maybePop: (result) => {
|
|
179
495
|
const hybridHistory = getHybridHistory();
|
|
180
|
-
if (!hybridHistory)
|
|
181
|
-
return false;
|
|
182
496
|
return hybridHistory.maybePop(result);
|
|
183
497
|
},
|
|
184
498
|
/**
|
|
@@ -186,8 +500,6 @@ const WebFRouter = {
|
|
|
186
500
|
*/
|
|
187
501
|
pushState: (state, name) => {
|
|
188
502
|
const hybridHistory = getHybridHistory();
|
|
189
|
-
if (!hybridHistory)
|
|
190
|
-
throw new Error('WebF hybridHistory is not available');
|
|
191
503
|
hybridHistory.pushState(state, name);
|
|
192
504
|
},
|
|
193
505
|
/**
|
|
@@ -195,8 +507,6 @@ const WebFRouter = {
|
|
|
195
507
|
*/
|
|
196
508
|
replaceState: (state, name) => {
|
|
197
509
|
const hybridHistory = getHybridHistory();
|
|
198
|
-
if (!hybridHistory)
|
|
199
|
-
throw new Error('WebF hybridHistory is not available');
|
|
200
510
|
hybridHistory.replaceState(state, name);
|
|
201
511
|
},
|
|
202
512
|
/**
|
|
@@ -205,8 +515,6 @@ const WebFRouter = {
|
|
|
205
515
|
*/
|
|
206
516
|
restorablePopAndPushState: (state, name) => {
|
|
207
517
|
const hybridHistory = getHybridHistory();
|
|
208
|
-
if (!hybridHistory)
|
|
209
|
-
throw new Error('WebF hybridHistory is not available');
|
|
210
518
|
return hybridHistory.restorablePopAndPushState(state, name);
|
|
211
519
|
},
|
|
212
520
|
/**
|
|
@@ -215,8 +523,6 @@ const WebFRouter = {
|
|
|
215
523
|
*/
|
|
216
524
|
restorablePopAndPushNamed: (path, state) => __awaiter(void 0, void 0, void 0, function* () {
|
|
217
525
|
const hybridHistory = getHybridHistory();
|
|
218
|
-
if (!hybridHistory)
|
|
219
|
-
throw new Error('WebF hybridHistory is not available');
|
|
220
526
|
yield ensureRouteMounted(path);
|
|
221
527
|
return hybridHistory.restorablePopAndPushNamed(path, { arguments: state });
|
|
222
528
|
})
|
|
@@ -319,41 +625,168 @@ var useMemoizedFn = function (fn) {
|
|
|
319
625
|
return memoizedFn.current;
|
|
320
626
|
};
|
|
321
627
|
|
|
322
|
-
//
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
628
|
+
// Lazily create the WebF component only when needed
|
|
629
|
+
let RawWebFRouterLink = null;
|
|
630
|
+
function getRawWebFRouterLink() {
|
|
631
|
+
if (RawWebFRouterLink)
|
|
632
|
+
return RawWebFRouterLink;
|
|
633
|
+
RawWebFRouterLink = reactCoreUi.createWebFComponent({
|
|
634
|
+
tagName: 'webf-router-link',
|
|
635
|
+
displayName: 'WebFRouterLink',
|
|
636
|
+
// Map props to attributes
|
|
637
|
+
attributeProps: ['path', 'title', 'theme'],
|
|
638
|
+
// Event handlers
|
|
639
|
+
events: [
|
|
640
|
+
{
|
|
641
|
+
propName: 'onScreen',
|
|
642
|
+
eventName: 'onscreen',
|
|
643
|
+
handler: (callback) => (event) => {
|
|
644
|
+
callback(event);
|
|
645
|
+
},
|
|
336
646
|
},
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
callback(event);
|
|
647
|
+
{
|
|
648
|
+
propName: 'offScreen',
|
|
649
|
+
eventName: 'offscreen',
|
|
650
|
+
handler: (callback) => (event) => {
|
|
651
|
+
callback(event);
|
|
652
|
+
},
|
|
344
653
|
},
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
654
|
+
{
|
|
655
|
+
propName: 'onPrerendering',
|
|
656
|
+
eventName: 'prerendering',
|
|
657
|
+
handler: (callback) => (event) => {
|
|
658
|
+
callback(event);
|
|
659
|
+
},
|
|
351
660
|
},
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
661
|
+
],
|
|
662
|
+
});
|
|
663
|
+
return RawWebFRouterLink;
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Browser-based RouterLink implementation
|
|
667
|
+
* Used when running in standard browser environment instead of WebF
|
|
668
|
+
*/
|
|
669
|
+
const BrowserRouterLink = function (props) {
|
|
670
|
+
const [isActive, setIsActive] = React.useState(false);
|
|
671
|
+
const [isRender, setIsRender] = React.useState(false);
|
|
672
|
+
const hasTriggeredOnScreen = React.useRef(false);
|
|
673
|
+
React.useEffect(() => {
|
|
674
|
+
const browserHistory = getBrowserHistory();
|
|
675
|
+
const currentPath = browserHistory.path;
|
|
676
|
+
// Check if this route matches the current path
|
|
677
|
+
const isCurrentlyActive = currentPath === props.path;
|
|
678
|
+
setIsActive(isCurrentlyActive);
|
|
679
|
+
if (isCurrentlyActive && !hasTriggeredOnScreen.current) {
|
|
680
|
+
hasTriggeredOnScreen.current = true;
|
|
681
|
+
setIsRender(true);
|
|
682
|
+
// Create a synthetic event for onScreen callback
|
|
683
|
+
if (props.onScreen) {
|
|
684
|
+
const syntheticEvent = {
|
|
685
|
+
state: browserHistory.state,
|
|
686
|
+
kind: 'didPush',
|
|
687
|
+
path: props.path,
|
|
688
|
+
nativeEvent: new Event('onscreen'),
|
|
689
|
+
currentTarget: null,
|
|
690
|
+
target: null,
|
|
691
|
+
bubbles: true,
|
|
692
|
+
cancelable: false,
|
|
693
|
+
defaultPrevented: false,
|
|
694
|
+
eventPhase: 0,
|
|
695
|
+
isTrusted: true,
|
|
696
|
+
preventDefault: () => { },
|
|
697
|
+
isDefaultPrevented: () => false,
|
|
698
|
+
stopPropagation: () => { },
|
|
699
|
+
isPropagationStopped: () => false,
|
|
700
|
+
persist: () => { },
|
|
701
|
+
timeStamp: Date.now(),
|
|
702
|
+
type: 'onscreen',
|
|
703
|
+
};
|
|
704
|
+
props.onScreen(syntheticEvent);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
// Listen for route changes
|
|
708
|
+
const handleRouteChange = (event) => {
|
|
709
|
+
var _a, _b, _c, _d, _e;
|
|
710
|
+
const customEvent = event;
|
|
711
|
+
const newPath = ((_a = customEvent.detail) === null || _a === void 0 ? void 0 : _a.path) || event.path;
|
|
712
|
+
const newIsActive = newPath === props.path;
|
|
713
|
+
if (newIsActive && !isActive) {
|
|
714
|
+
// Route became active
|
|
715
|
+
hasTriggeredOnScreen.current = true;
|
|
716
|
+
setIsRender(true);
|
|
717
|
+
setIsActive(true);
|
|
718
|
+
if (props.onScreen) {
|
|
719
|
+
const syntheticEvent = {
|
|
720
|
+
state: ((_b = customEvent.detail) === null || _b === void 0 ? void 0 : _b.state) || event.state,
|
|
721
|
+
kind: (((_c = customEvent.detail) === null || _c === void 0 ? void 0 : _c.kind) || event.kind),
|
|
722
|
+
path: newPath,
|
|
723
|
+
nativeEvent: event,
|
|
724
|
+
currentTarget: event.currentTarget,
|
|
725
|
+
target: event.target,
|
|
726
|
+
bubbles: true,
|
|
727
|
+
cancelable: false,
|
|
728
|
+
defaultPrevented: false,
|
|
729
|
+
eventPhase: 0,
|
|
730
|
+
isTrusted: true,
|
|
731
|
+
preventDefault: () => { },
|
|
732
|
+
isDefaultPrevented: () => false,
|
|
733
|
+
stopPropagation: () => { },
|
|
734
|
+
isPropagationStopped: () => false,
|
|
735
|
+
persist: () => { },
|
|
736
|
+
timeStamp: Date.now(),
|
|
737
|
+
type: 'onscreen',
|
|
738
|
+
};
|
|
739
|
+
props.onScreen(syntheticEvent);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
else if (!newIsActive && isActive) {
|
|
743
|
+
// Route became inactive
|
|
744
|
+
setIsActive(false);
|
|
745
|
+
if (props.offScreen) {
|
|
746
|
+
const syntheticEvent = {
|
|
747
|
+
state: ((_d = customEvent.detail) === null || _d === void 0 ? void 0 : _d.state) || event.state,
|
|
748
|
+
kind: (((_e = customEvent.detail) === null || _e === void 0 ? void 0 : _e.kind) || event.kind),
|
|
749
|
+
path: newPath,
|
|
750
|
+
nativeEvent: event,
|
|
751
|
+
currentTarget: event.currentTarget,
|
|
752
|
+
target: event.target,
|
|
753
|
+
bubbles: true,
|
|
754
|
+
cancelable: false,
|
|
755
|
+
defaultPrevented: false,
|
|
756
|
+
eventPhase: 0,
|
|
757
|
+
isTrusted: true,
|
|
758
|
+
preventDefault: () => { },
|
|
759
|
+
isDefaultPrevented: () => false,
|
|
760
|
+
stopPropagation: () => { },
|
|
761
|
+
isPropagationStopped: () => false,
|
|
762
|
+
persist: () => { },
|
|
763
|
+
timeStamp: Date.now(),
|
|
764
|
+
type: 'offscreen',
|
|
765
|
+
};
|
|
766
|
+
props.offScreen(syntheticEvent);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
};
|
|
770
|
+
document.addEventListener('hybridrouterchange', handleRouteChange);
|
|
771
|
+
return () => {
|
|
772
|
+
document.removeEventListener('hybridrouterchange', handleRouteChange);
|
|
773
|
+
};
|
|
774
|
+
}, [props.path, props.onScreen, props.offScreen, isActive]);
|
|
775
|
+
// In browser mode, we render a div that acts as a route container
|
|
776
|
+
// Only show content when route is rendered (similar to WebF behavior)
|
|
777
|
+
return (React.createElement("div", { "data-path": props.path, "data-title": props.title, style: {
|
|
778
|
+
display: isActive ? 'block' : 'none',
|
|
779
|
+
width: '100%',
|
|
780
|
+
height: '100%',
|
|
781
|
+
} }, isRender ? props.children : null));
|
|
782
|
+
};
|
|
783
|
+
/**
|
|
784
|
+
* WebF RouterLink implementation
|
|
785
|
+
* Used in WebF native environment
|
|
786
|
+
*/
|
|
787
|
+
const WebFNativeRouterLink = function (props) {
|
|
356
788
|
const [isRender, enableRender] = React.useState(false);
|
|
789
|
+
const RawComponent = getRawWebFRouterLink();
|
|
357
790
|
const handleOnScreen = (event) => {
|
|
358
791
|
enableRender(true);
|
|
359
792
|
if (props.onScreen) {
|
|
@@ -365,7 +798,18 @@ const WebFRouterLink = function (props) {
|
|
|
365
798
|
enableRender(true);
|
|
366
799
|
(_a = props.onPrerendering) === null || _a === void 0 ? void 0 : _a.call(props, event);
|
|
367
800
|
};
|
|
368
|
-
return (React.createElement(
|
|
801
|
+
return (React.createElement(RawComponent, { title: props.title, path: props.path, theme: props.theme, onScreen: handleOnScreen, offScreen: props.offScreen, onPrerendering: handlePrerendering }, isRender ? props.children : null));
|
|
802
|
+
};
|
|
803
|
+
/**
|
|
804
|
+
* Unified RouterLink component that works in both WebF and browser environments
|
|
805
|
+
*/
|
|
806
|
+
const WebFRouterLink = function (props) {
|
|
807
|
+
// Use WebF native implementation if in WebF environment
|
|
808
|
+
if (isWebF()) {
|
|
809
|
+
return React.createElement(WebFNativeRouterLink, Object.assign({}, props));
|
|
810
|
+
}
|
|
811
|
+
// Use browser-based implementation
|
|
812
|
+
return React.createElement(BrowserRouterLink, Object.assign({}, props));
|
|
369
813
|
};
|
|
370
814
|
|
|
371
815
|
/**
|
|
@@ -832,9 +1276,14 @@ exports.Routes = Routes;
|
|
|
832
1276
|
exports.WebFRouter = WebFRouter;
|
|
833
1277
|
exports.WebFRouterLink = WebFRouterLink;
|
|
834
1278
|
exports.__unstable_setEnsureRouteMountedCallback = __unstable_setEnsureRouteMountedCallback;
|
|
1279
|
+
exports.detectPlatform = detectPlatform;
|
|
1280
|
+
exports.isBrowser = isBrowser;
|
|
1281
|
+
exports.isWebF = isWebF;
|
|
835
1282
|
exports.matchPath = matchPath;
|
|
836
1283
|
exports.matchRoutes = matchRoutes;
|
|
837
1284
|
exports.pathToRegex = pathToRegex;
|
|
1285
|
+
exports.platform = platform;
|
|
1286
|
+
exports.resetBrowserHistory = resetBrowserHistory;
|
|
838
1287
|
exports.useLocation = useLocation;
|
|
839
1288
|
exports.useNavigate = useNavigate;
|
|
840
1289
|
exports.useParams = useParams;
|