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