@tanstack/react-router 0.0.1-beta.194 → 0.0.1-beta.196

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.
@@ -134,36 +134,8 @@
134
134
  return true;
135
135
  }
136
136
 
137
- var prefix = 'Invariant failed';
138
- function invariant(condition, message) {
139
- if (condition) {
140
- return;
141
- }
142
- var provided = typeof message === 'function' ? message() : message;
143
- var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
144
- throw new Error(value);
145
- }
146
-
147
- function warning(condition, message) {
148
- {
149
- if (condition) {
150
- return;
151
- }
152
-
153
- var text = "Warning: " + message;
154
-
155
- if (typeof console !== 'undefined') {
156
- console.warn(text);
157
- }
158
-
159
- try {
160
- throw Error(text);
161
- } catch (x) {}
162
- }
163
- }
164
-
165
137
  /**
166
- * @tanstack/router-core/src/index.ts
138
+ * @tanstack/history/src/index.ts
167
139
  *
168
140
  * Copyright (c) TanStack
169
141
  *
@@ -172,7 +144,6 @@
172
144
  *
173
145
  * @license MIT
174
146
  */
175
-
176
147
  // While the public API was clearly inspired by the "history" npm package,
177
148
  // This implementation attempts to be more lightweight by
178
149
  // making assumptions about the way TanStack Router works
@@ -236,15 +207,15 @@
236
207
  };
237
208
  },
238
209
  push: (path, state) => {
239
- assignKey(state);
210
+ state = assignKey(state);
240
211
  queueTask(() => {
241
- opts.pushState(path, state);
212
+ opts.pushState(path, state, onUpdate);
242
213
  });
243
214
  },
244
215
  replace: (path, state) => {
245
- assignKey(state);
216
+ state = assignKey(state);
246
217
  queueTask(() => {
247
- opts.replaceState(path, state);
218
+ opts.replaceState(path, state, onUpdate);
248
219
  });
249
220
  },
250
221
  go: index => {
@@ -276,38 +247,112 @@
276
247
  stopBlocking();
277
248
  }
278
249
  };
279
- }
250
+ },
251
+ flush: () => opts.flush?.()
280
252
  };
281
253
  }
282
254
  function assignKey(state) {
255
+ if (!state) {
256
+ state = {};
257
+ }
283
258
  state.key = createRandomKey();
284
- // if (state.__actualLocation) {
285
- // state.__actualLocation.state = {
286
- // ...state.__actualLocation.state,
287
- // key,
288
- // }
289
- // }
259
+ return state;
290
260
  }
291
261
 
262
+ /**
263
+ * Creates a history object that can be used to interact with the browser's
264
+ * navigation. This is a lightweight API wrapping the browser's native methods.
265
+ * It is designed to work with TanStack Router, but could be used as a standalone API as well.
266
+ * IMPORTANT: This API implements history throttling via a microtask to prevent
267
+ * excessive calls to the history API. In some browsers, calling history.pushState or
268
+ * history.replaceState in quick succession can cause the browser to ignore subsequent
269
+ * calls. This API smooths out those differences and ensures that your application
270
+ * state will *eventually* match the browser state. In most cases, this is not a problem,
271
+ * but if you need to ensure that the browser state is up to date, you can use the
272
+ * `history.flush` method to immediately flush all pending state changes to the browser URL.
273
+ * @param opts
274
+ * @param opts.getHref A function that returns the current href (path + search + hash)
275
+ * @param opts.createHref A function that takes a path and returns a href (path + search + hash)
276
+ * @returns A history instance
277
+ */
292
278
  function createBrowserHistory(opts) {
293
279
  const getHref = opts?.getHref ?? (() => `${window.location.pathname}${window.location.search}${window.location.hash}`);
294
280
  const createHref = opts?.createHref ?? (path => path);
295
- const getLocation = () => parseLocation(getHref(), window.history.state);
281
+ let currentLocation = parseLocation(getHref(), window.history.state);
282
+ const getLocation = () => currentLocation;
283
+ let next;
284
+
285
+ // Because we are proactively updating the location
286
+ // in memory before actually updating the browser history,
287
+ // we need to track when we are doing this so we don't
288
+ // notify subscribers twice on the last update.
289
+ let tracking = true;
290
+
291
+ // We need to track the current scheduled update to prevent
292
+ // multiple updates from being scheduled at the same time.
293
+ let scheduled;
294
+
295
+ // This function is a wrapper to prevent any of the callback's
296
+ // side effects from causing a subscriber notification
297
+ const untrack = fn => {
298
+ tracking = false;
299
+ fn();
300
+ tracking = true;
301
+ };
302
+
303
+ // This function flushes the next update to the browser history
304
+ const flush = () => {
305
+ // Do not notify subscribers about this push/replace call
306
+ untrack(() => {
307
+ if (!next) return;
308
+ window.history[next.isPush ? 'pushState' : 'replaceState'](next.state, '', next.href);
309
+ // Reset the nextIsPush flag and clear the scheduled update
310
+ next = undefined;
311
+ scheduled = undefined;
312
+ });
313
+ };
314
+
315
+ // This function queues up a call to update the browser history
316
+ const queueHistoryAction = (type, path, state, onUpdate) => {
317
+ const href = createHref(path);
318
+
319
+ // Update the location in memory
320
+ currentLocation = parseLocation(href, state);
321
+
322
+ // Keep track of the next location we need to flush to the URL
323
+ next = {
324
+ href,
325
+ state,
326
+ isPush: next?.isPush || type === 'push'
327
+ };
328
+ // Notify subscribers
329
+ onUpdate();
330
+ if (!scheduled) {
331
+ // Schedule an update to the browser history
332
+ scheduled = Promise.resolve().then(() => flush());
333
+ }
334
+ };
296
335
  return createHistory({
297
336
  getLocation,
298
337
  subscriber: onUpdate => {
299
- window.addEventListener(pushStateEvent, onUpdate);
300
- window.addEventListener(popStateEvent, onUpdate);
338
+ window.addEventListener(pushStateEvent, () => {
339
+ currentLocation = parseLocation(getHref(), window.history.state);
340
+ onUpdate();
341
+ });
342
+ window.addEventListener(popStateEvent, () => {
343
+ currentLocation = parseLocation(getHref(), window.history.state);
344
+ onUpdate();
345
+ });
301
346
  var pushState = window.history.pushState;
302
347
  window.history.pushState = function () {
303
348
  let res = pushState.apply(history, arguments);
304
- onUpdate();
349
+ if (tracking) onUpdate();
305
350
  return res;
306
351
  };
307
352
  var replaceState = window.history.replaceState;
308
353
  window.history.replaceState = function () {
309
354
  let res = replaceState.apply(history, arguments);
310
- onUpdate();
355
+ if (tracking) onUpdate();
311
356
  return res;
312
357
  };
313
358
  return () => {
@@ -317,16 +362,13 @@
317
362
  window.removeEventListener(popStateEvent, onUpdate);
318
363
  };
319
364
  },
320
- pushState: (path, state) => {
321
- window.history.pushState(state, '', createHref(path));
322
- },
323
- replaceState: (path, state) => {
324
- window.history.replaceState(state, '', createHref(path));
325
- },
365
+ pushState: (path, state, onUpdate) => queueHistoryAction('push', path, state, onUpdate),
366
+ replaceState: (path, state, onUpdate) => queueHistoryAction('replace', path, state, onUpdate),
326
367
  back: () => window.history.back(),
327
368
  forward: () => window.history.forward(),
328
369
  go: n => window.history.go(n),
329
- createHref: path => createHref(path)
370
+ createHref: path => createHref(path),
371
+ flush
330
372
  });
331
373
  }
332
374
  function createHashHistory() {
@@ -383,6 +425,47 @@
383
425
  return (Math.random() + 1).toString(36).substring(7);
384
426
  }
385
427
 
428
+ var prefix = 'Invariant failed';
429
+ function invariant(condition, message) {
430
+ if (condition) {
431
+ return;
432
+ }
433
+ var provided = typeof message === 'function' ? message() : message;
434
+ var value = provided ? "".concat(prefix, ": ").concat(provided) : prefix;
435
+ throw new Error(value);
436
+ }
437
+
438
+ function warning(condition, message) {
439
+ {
440
+ if (condition) {
441
+ return;
442
+ }
443
+
444
+ var text = "Warning: " + message;
445
+
446
+ if (typeof console !== 'undefined') {
447
+ console.warn(text);
448
+ }
449
+
450
+ try {
451
+ throw Error(text);
452
+ } catch (x) {}
453
+ }
454
+ }
455
+
456
+ /**
457
+ * @tanstack/router-core/src/index.ts
458
+ *
459
+ * Copyright (c) TanStack
460
+ *
461
+ * This source code is licensed under the MIT license found in the
462
+ * LICENSE.md file in the root directory of this source tree.
463
+ *
464
+ * @license MIT
465
+ */
466
+
467
+ // export type Expand<T> = T
468
+
386
469
  // type Compute<T> = { [K in keyof T]: T[K] } | never
387
470
 
388
471
  // type AllKeys<T> = T extends any ? keyof T : never
@@ -2287,6 +2370,7 @@
2287
2370
  return _extends.apply(this, arguments);
2288
2371
  }
2289
2372
 
2373
+ const useLayoutEffect$1 = typeof window !== 'undefined' ? React__namespace.useLayoutEffect : React__namespace.useEffect;
2290
2374
  Route.__onInit = route => {
2291
2375
  Object.assign(route, {
2292
2376
  useMatch: (opts = {}) => {
@@ -2452,7 +2536,7 @@
2452
2536
  });
2453
2537
  function Navigate(props) {
2454
2538
  const router = useRouter();
2455
- React__namespace.useLayoutEffect(() => {
2539
+ useLayoutEffect$1(() => {
2456
2540
  router.navigate(props);
2457
2541
  }, []);
2458
2542
  return null;