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