@simonbackx/vue-app-navigation 2.18.0 → 2.19.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.js CHANGED
@@ -244,6 +244,9 @@ class HistoryManagerStatic {
244
244
  this.isQueueRunning = true;
245
245
  const action = this.historyQueue.shift();
246
246
  if (action) {
247
+ if (this.debug) {
248
+ console.log("Running history queue action");
249
+ }
247
250
  const p = action();
248
251
  if (p) {
249
252
  p.finally(() => this.runQueue()).catch(console.error);
@@ -251,6 +254,9 @@ class HistoryManagerStatic {
251
254
  this.runQueue();
252
255
  }
253
256
  } else {
257
+ if (this.debug) {
258
+ console.log("History queue done");
259
+ }
254
260
  this.isQueueRunning = false;
255
261
  this.callListeners();
256
262
  }
@@ -262,11 +268,17 @@ class HistoryManagerStatic {
262
268
  history.go(delta);
263
269
  let timer = void 0;
264
270
  let called = false;
271
+ const startTime = /* @__PURE__ */ new Date();
265
272
  const listener = () => {
266
273
  if (called) return;
267
274
  called = true;
268
275
  clearTimeout(timer);
269
276
  window.removeEventListener("popstate", listener);
277
+ const end = /* @__PURE__ */ new Date();
278
+ if (this.debug) {
279
+ const ms = end.getTime() - startTime.getTime();
280
+ console.log("Waiting for popstate event took " + ms + "ms");
281
+ }
270
282
  setTimeout(() => {
271
283
  this.manualStateAction = false;
272
284
  resolve();
@@ -276,7 +288,7 @@ class HistoryManagerStatic {
276
288
  timer = setTimeout(() => {
277
289
  console.warn("Timeout while waiting for history.go");
278
290
  listener();
279
- }, 200);
291
+ }, 400);
280
292
  });
281
293
  });
282
294
  }
@@ -523,9 +535,9 @@ class HistoryManagerStatic {
523
535
  activate() {
524
536
  history.scrollRestoration = "manual";
525
537
  async function onPopState(event) {
526
- var _a;
538
+ var _a, _b;
527
539
  if (this.debug) {
528
- console.log("HistoryManager popstate");
540
+ console.log("HistoryManager popstate", (_a = event.state) == null ? void 0 : _a.counter);
529
541
  }
530
542
  if (this.isAdjustingState) {
531
543
  console.warn("Duplicate popstate");
@@ -534,8 +546,8 @@ class HistoryManagerStatic {
534
546
  if (this.manualStateAction) {
535
547
  return;
536
548
  }
549
+ const newCounter = (_b = event.state) == null ? void 0 : _b.counter;
537
550
  this.isAdjustingState = true;
538
- const newCounter = (_a = event.state) == null ? void 0 : _a.counter;
539
551
  if (newCounter !== void 0) {
540
552
  if (newCounter > this.counter) {
541
553
  if (this.debug) {
@@ -761,6 +773,7 @@ const _ComponentWithProperties = class _ComponentWithProperties {
761
773
  }
762
774
  const state = HistoryManager.getCurrentState();
763
775
  this.historyIndex = state.index;
776
+ if (_ComponentWithProperties.debug) console.warn("Assigned index to component", this.component.name ?? this, state.index);
764
777
  _ComponentWithProperties.historyIndexOwners.set(state.index, this);
765
778
  }
766
779
  inheritHistoryIndex(index) {
@@ -820,6 +833,7 @@ const _ComponentWithProperties = class _ComponentWithProperties {
820
833
  if (_ComponentWithProperties.debug) console.warn("Returning to a component that has no history index assigned. Has this component been pushed to a navigation controller properly before returning to it?", this.component.name);
821
834
  return false;
822
835
  }
836
+ if (_ComponentWithProperties.debug) console.warn("Returned to component", this.component.name ?? this);
823
837
  HistoryManager.returnToHistoryIndex(this.historyIndex);
824
838
  return true;
825
839
  }
@@ -1151,7 +1165,7 @@ const ComponentWithPropertiesInstance = defineComponent({
1151
1165
  };
1152
1166
  }
1153
1167
  });
1154
- const _sfc_main$5 = {
1168
+ const _sfc_main$4 = {
1155
1169
  name: "FramedComponent",
1156
1170
  components: {
1157
1171
  ComponentWithPropertiesInstance
@@ -1188,8 +1202,8 @@ function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
1188
1202
  ])
1189
1203
  ]);
1190
1204
  }
1191
- const FramedComponent = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$2]]);
1192
- const _sfc_main$4 = defineComponent({
1205
+ const FramedComponent = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$2]]);
1206
+ const NavigationController$1 = defineComponent({
1193
1207
  name: "NavigationController",
1194
1208
  components: {
1195
1209
  FramedComponent
@@ -1203,6 +1217,9 @@ const _sfc_main$4 = defineComponent({
1203
1217
  },
1204
1218
  reactive_navigation_can_dismiss: {
1205
1219
  default: false
1220
+ },
1221
+ reactive_navigationController: {
1222
+ default: null
1206
1223
  }
1207
1224
  },
1208
1225
  provide() {
@@ -1261,6 +1278,11 @@ const _sfc_main$4 = defineComponent({
1261
1278
  cachedProvides: /* @__PURE__ */ new Map()
1262
1279
  };
1263
1280
  },
1281
+ computed: {
1282
+ navigationController() {
1283
+ return unref(this.reactive_navigationController);
1284
+ }
1285
+ },
1264
1286
  watch: {
1265
1287
  // whenever question changes, this function will run
1266
1288
  mainComponent(newComponent) {
@@ -1756,7 +1778,14 @@ function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
1756
1778
  }, 8, ["onBeforeEnter", "onBeforeLeave", "onEnter", "onLeave", "onAfterLeave", "onAfterEnter", "onEnterCancelled"])
1757
1779
  ])) : createCommentVNode("", true);
1758
1780
  }
1759
- const NavigationController = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["render", _sfc_render$1]]);
1781
+ const NavigationController = /* @__PURE__ */ _export_sfc(NavigationController$1, [["render", _sfc_render$1]]);
1782
+ function typeRoute(route) {
1783
+ return route;
1784
+ }
1785
+ const defineRoute = (route) => {
1786
+ defineRoutes([route]);
1787
+ return route;
1788
+ };
1760
1789
  function usePop() {
1761
1790
  const rawPop = inject("reactive_navigation_pop", null);
1762
1791
  return (options) => {
@@ -1774,12 +1803,18 @@ function useNavigate() {
1774
1803
  const show = useShow();
1775
1804
  const showDetail = useShowDetail();
1776
1805
  const toRoute = async function(route, options) {
1777
- let componentProperties = (options == null ? void 0 : options.properties) ?? (options == null ? void 0 : options.params) ?? {};
1806
+ let componentProperties = (options == null ? void 0 : options.properties) ?? {};
1778
1807
  let params = (options == null ? void 0 : options.params) ?? {};
1779
- if (!(options == null ? void 0 : options.properties) && route.paramsToProps) {
1780
- componentProperties = route.paramsToProps(params, options == null ? void 0 : options.query);
1808
+ if (!(options == null ? void 0 : options.properties)) {
1809
+ if ("paramsToProps" in route) {
1810
+ componentProperties = route.paramsToProps((options == null ? void 0 : options.params) ?? {}, options == null ? void 0 : options.query);
1811
+ } else {
1812
+ if (options == null ? void 0 : options.params) {
1813
+ throw new Error("Using route to a route that only has properties, no parameters. Use properties instead of params in navigate() for this route: " + route.url);
1814
+ }
1815
+ }
1781
1816
  }
1782
- if (!(options == null ? void 0 : options.params) && route.propsToParams && componentProperties) {
1817
+ if (!(options == null ? void 0 : options.params) && "propsToParams" in route) {
1783
1818
  const { params: p } = route.propsToParams(await componentProperties);
1784
1819
  params = p;
1785
1820
  }
@@ -1789,7 +1824,8 @@ function useNavigate() {
1789
1824
  url,
1790
1825
  adjustHistory: (options == null ? void 0 : options.adjustHistory) ?? true,
1791
1826
  animated: (options == null ? void 0 : options.animated) ?? true,
1792
- modalDisplayStyle: route.present && typeof route.present === "string" ? route.present : void 0,
1827
+ modalDisplayStyle: void 0,
1828
+ // modalDisplayStyle: route.present && typeof route.present === 'string' ? route.present : undefined,
1793
1829
  checkRoutes: (options == null ? void 0 : options.checkRoutes) ?? false,
1794
1830
  componentProperties: await componentProperties
1795
1831
  });
@@ -1798,7 +1834,7 @@ function useNavigate() {
1798
1834
  let component;
1799
1835
  const isComponentFunction = typeof route.component === "function" && !(!!route.component.prototype && route.component.prototype.constructor === route.component);
1800
1836
  if (isComponentFunction || componentProperties.then) {
1801
- const method = isComponentFunction ? route.component : () => route.component;
1837
+ const method = isComponentFunction ? route.component : (_) => route.component;
1802
1838
  const originalProperties = componentProperties;
1803
1839
  if (!("PromiseComponent" in window)) {
1804
1840
  throw new Error("Required PromiseComponent window variable to make async components work in routes");
@@ -1806,8 +1842,12 @@ function useNavigate() {
1806
1842
  component = window.PromiseComponent;
1807
1843
  componentProperties = {
1808
1844
  promise: async () => {
1809
- const realComponent = await method();
1810
- return new ComponentWithProperties(realComponent === "self" ? instance == null ? void 0 : instance.type : realComponent, await originalProperties);
1845
+ const properties = await originalProperties;
1846
+ const realComponent = await method(properties);
1847
+ if (realComponent instanceof ComponentWithProperties) {
1848
+ return realComponent;
1849
+ }
1850
+ return new ComponentWithProperties(realComponent === "self" ? instance == null ? void 0 : instance.type : realComponent, properties);
1811
1851
  }
1812
1852
  };
1813
1853
  } else {
@@ -1850,7 +1890,7 @@ function useNavigate() {
1850
1890
  new ComponentWithProperties(component, componentProperties)
1851
1891
  ],
1852
1892
  checkRoutes: (options == null ? void 0 : options.checkRoutes) ?? false
1853
- });
1893
+ }, typeof route.show === "object" && route.show !== null && "getCustomShow" in route.show ? route.show.getCustomShow() : void 0);
1854
1894
  }
1855
1895
  };
1856
1896
  const currentRoutes = getCurrentRoutes();
@@ -1938,13 +1978,18 @@ function defineRoutes(routes) {
1938
1978
  const navigate = useNavigate();
1939
1979
  const currentRoutes = getCurrentRoutes();
1940
1980
  const provideDefaultHandler = inject("reactive_provide_default_handler", null);
1981
+ let hadRoutes = false;
1941
1982
  if (currentRoutes.value.length) {
1942
- console.error("Multiple calls to defineRoutes: routes will get overwritten");
1983
+ hadRoutes = true;
1984
+ routes = [...currentRoutes.value, ...Array.isArray(routes) ? routes : []];
1943
1985
  }
1944
1986
  currentRoutes.value = Array.isArray(routes) ? routes : [];
1987
+ if (hadRoutes) {
1988
+ return;
1989
+ }
1945
1990
  async function handleRoutes(routes2) {
1946
1991
  for (const route of routes2) {
1947
- const result = urlhelpers.match(route.url, route.params);
1992
+ const result = urlhelpers.match(route.url, "params" in route ? route.params : {});
1948
1993
  if (result) {
1949
1994
  try {
1950
1995
  await navigate(route, {
@@ -2001,24 +2046,12 @@ function defineRoutes(routes) {
2001
2046
  }
2002
2047
  };
2003
2048
  onCheckRoutes(async () => {
2004
- if (Array.isArray(routes)) {
2005
- if (await handleRoutes(routes)) {
2049
+ const routes2 = currentRoutes.value;
2050
+ if (Array.isArray(routes2)) {
2051
+ if (await handleRoutes(routes2)) {
2006
2052
  setDefaultHandler();
2007
2053
  return;
2008
2054
  }
2009
- } else {
2010
- const extraRoutes = await routes();
2011
- if (Array.isArray(extraRoutes)) {
2012
- if (await handleRoutes(extraRoutes)) {
2013
- setDefaultHandler();
2014
- return;
2015
- }
2016
- } else {
2017
- if (extraRoutes) {
2018
- setDefaultHandler();
2019
- return;
2020
- }
2021
- }
2022
2055
  }
2023
2056
  setDefaultHandler();
2024
2057
  });
@@ -2027,10 +2060,6 @@ function defineRoutes(routes) {
2027
2060
  setDefaultHandler();
2028
2061
  });
2029
2062
  }
2030
- const checkRouteCache = {
2031
- lastUrl: null,
2032
- results: /* @__PURE__ */ new Map()
2033
- };
2034
2063
  function useCurrentHref() {
2035
2064
  const state = ref(window.location.href);
2036
2065
  const owner = {};
@@ -2047,6 +2076,10 @@ function useCheckRoute() {
2047
2076
  const currentRoutes = getCurrentRoutes();
2048
2077
  const instance = getCurrentInstance();
2049
2078
  const currentPath = useCurrentHref();
2079
+ const checkRouteCache = {
2080
+ lastUrl: null,
2081
+ results: /* @__PURE__ */ new Map()
2082
+ };
2050
2083
  const checkMatchResult = function(route, result, options) {
2051
2084
  if (!result) {
2052
2085
  return false;
@@ -2062,7 +2095,7 @@ function useCheckRoute() {
2062
2095
  return false;
2063
2096
  }
2064
2097
  }
2065
- if (!(options == null ? void 0 : options.params) && route.propsToParams && options.properties) {
2098
+ if (!(options == null ? void 0 : options.params) && "propsToParams" in route && options.properties) {
2066
2099
  const { params } = route.propsToParams(options.properties);
2067
2100
  for (const key in params) {
2068
2101
  if (result.params[key] !== params[key]) {
@@ -2085,7 +2118,7 @@ function useCheckRoute() {
2085
2118
  }
2086
2119
  };
2087
2120
  const checkRoute = function(route, options) {
2088
- const result = urlhelpers.matchCurrent(route.url, route.params);
2121
+ const result = urlhelpers.matchCurrent(route.url, "params" in route ? route.params : {});
2089
2122
  checkRouteCache.results.set(route.url, { result, route });
2090
2123
  if (route.name) {
2091
2124
  checkRouteCache.results.set(route.name, { result, route });
@@ -2150,8 +2183,8 @@ function useShow() {
2150
2183
  const currentComponent = useCurrentComponent();
2151
2184
  const rawShow = inject("reactive_navigation_show", null);
2152
2185
  const urlHelpers = useUrl();
2153
- return (options) => {
2154
- const show = unref(rawShow);
2186
+ return (options, customShow) => {
2187
+ const show = customShow ?? unref(rawShow);
2155
2188
  if (!show) {
2156
2189
  console.warn("Failed to perform show");
2157
2190
  return Promise.resolve();
@@ -2761,6 +2794,13 @@ const _sfc_main = defineComponent({
2761
2794
  }
2762
2795
  };
2763
2796
  },
2797
+ detailProvide() {
2798
+ return {
2799
+ // Detail can not alter the navigation of the parent of split view controller.
2800
+ reactive_navigation_can_pop: false,
2801
+ reactive_navigation_can_dismiss: false
2802
+ };
2803
+ },
2764
2804
  lastIsDetail() {
2765
2805
  var _a, _b;
2766
2806
  return this.detailKey != null && ((_b = (_a = this.navigationController) == null ? void 0 : _a.mainComponent) == null ? void 0 : _b.key) == this.detailKey;
@@ -2799,6 +2839,7 @@ const _sfc_main = defineComponent({
2799
2839
  return this.navigationController.returnToHistoryIndex();
2800
2840
  },
2801
2841
  onResize() {
2842
+ if (this.$el.isConnected === false) return false;
2802
2843
  if (this.shouldCollapse()) {
2803
2844
  if (this.detail) {
2804
2845
  this.collapse().catch(console.error);
@@ -3005,8 +3046,9 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
3005
3046
  _ctx.detail ? (openBlock(), createElementBlock("div", _hoisted_3, [
3006
3047
  (openBlock(), createBlock(_component_FramedComponent, {
3007
3048
  key: _ctx.detail.key,
3008
- root: _ctx.detail
3009
- }, null, 8, ["root"]))
3049
+ root: _ctx.detail,
3050
+ "custom-provide": _ctx.detailProvide
3051
+ }, null, 8, ["root", "custom-provide"]))
3010
3052
  ])) : createCommentVNode("", true)
3011
3053
  ], 8, _hoisted_1);
3012
3054
  }
@@ -3024,6 +3066,7 @@ export {
3024
3066
  SplitViewController,
3025
3067
  _sfc_main$3 as StackComponent,
3026
3068
  UrlHelper,
3069
+ defineRoute,
3027
3070
  defineRoutes,
3028
3071
  extendUrl,
3029
3072
  forAllRoots,
@@ -3038,6 +3081,7 @@ export {
3038
3081
  setTitleSuffix,
3039
3082
  setUrl,
3040
3083
  templateToUrl,
3084
+ typeRoute,
3041
3085
  useCanDismiss,
3042
3086
  useCanPop,
3043
3087
  useCheckRoute,
@@ -3,7 +3,7 @@ import { ComponentWithProperties, ComponentWithPropertiesType } from './Componen
3
3
  import { PopOptions } from './PopOptions';
4
4
  import { PushOptions } from './PushOptions';
5
5
 
6
- declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
6
+ declare const NavigationController: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
7
7
  root: {
8
8
  default: null;
9
9
  type: PropType<ComponentWithProperties | null>;
@@ -29,7 +29,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
29
29
  asyncQueue: (() => Promise<void>)[];
30
30
  asyncQueueRunning: boolean;
31
31
  cachedProvides: Map<number, any>;
32
- }, {}, {
32
+ }, {
33
+ navigationController(): InstanceType<typeof NavigationController> | null;
34
+ }, {
33
35
  cacheComponentProvides(newComponent: ComponentWithPropertiesType): void;
34
36
  provideForComponent(key: number): any;
35
37
  runQueue<T>(run: () => Promise<T>): Promise<T>;
@@ -135,7 +137,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
135
137
  asyncQueue: (() => Promise<void>)[];
136
138
  asyncQueueRunning: boolean;
137
139
  cachedProvides: Map<number, any>;
138
- }, {}, {
140
+ }, {
141
+ navigationController(): InstanceType<typeof NavigationController> | null;
142
+ }, {
139
143
  cacheComponentProvides(newComponent: ComponentWithPropertiesType): void;
140
144
  provideForComponent(key: number): any;
141
145
  runQueue<T>(run: () => Promise<T>): Promise<T>;
@@ -172,6 +176,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
172
176
  reactive_navigation_can_dismiss: {
173
177
  default: boolean;
174
178
  };
179
+ reactive_navigationController: {
180
+ default: null;
181
+ };
175
182
  }, {}, {
176
183
  FramedComponent: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
177
184
  root: {
@@ -235,7 +242,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
235
242
  asyncQueue: (() => Promise<void>)[];
236
243
  asyncQueueRunning: boolean;
237
244
  cachedProvides: Map<number, any>;
238
- }, {}, {
245
+ }, {
246
+ navigationController(): InstanceType<typeof NavigationController> | null;
247
+ }, {
239
248
  cacheComponentProvides(newComponent: ComponentWithPropertiesType): void;
240
249
  provideForComponent(key: number): any;
241
250
  runQueue<T>(run: () => Promise<T>): Promise<T>;
@@ -266,4 +275,4 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
266
275
  reactive_navigation_show: (options: PushOptions) => Promise<void>;
267
276
  reactive_navigation_pop: import('vue').ComputedRef<unknown>;
268
277
  }, true, {}, any>;
269
- export default _default;
278
+ export default NavigationController;
@@ -23,12 +23,16 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
23
23
  reactive_navigation_disable_url: import('vue').ComputedRef<boolean>;
24
24
  reactive_provide_default_handler: (defaultHandler: DefaultRouteHandler) => void;
25
25
  };
26
+ detailProvide(): {
27
+ reactive_navigation_can_pop: boolean;
28
+ reactive_navigation_can_dismiss: boolean;
29
+ };
26
30
  lastIsDetail(): boolean;
27
31
  navigationController(): InstanceType<typeof NavigationController>;
28
32
  masterElement(): HTMLElement;
29
33
  }, {
30
34
  returnToHistoryIndex(): boolean;
31
- onResize(): void;
35
+ onResize(): false | undefined;
32
36
  getScrollElement(element?: HTMLElement | null): HTMLElement;
33
37
  shouldNavigateAway(): Promise<boolean>;
34
38
  showDetail(options: PushOptions): Promise<boolean>;
@@ -74,7 +78,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
74
78
  asyncQueue: (() => Promise<void>)[];
75
79
  asyncQueueRunning: boolean;
76
80
  cachedProvides: Map<number, any>;
77
- }, {}, {
81
+ }, {
82
+ navigationController(): InstanceType<typeof NavigationController> | null;
83
+ }, {
78
84
  cacheComponentProvides(newComponent: ComponentWithPropertiesType): void;
79
85
  provideForComponent(key: number): any;
80
86
  runQueue<T>(run: () => Promise<T>): Promise<T>;
@@ -180,7 +186,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
180
186
  asyncQueue: (() => Promise<void>)[];
181
187
  asyncQueueRunning: boolean;
182
188
  cachedProvides: Map<number, any>;
183
- }, {}, {
189
+ }, {
190
+ navigationController(): InstanceType<typeof NavigationController> | null;
191
+ }, {
184
192
  cacheComponentProvides(newComponent: ComponentWithPropertiesType): void;
185
193
  provideForComponent(key: number): any;
186
194
  runQueue<T>(run: () => Promise<T>): Promise<T>;
@@ -217,6 +225,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
217
225
  reactive_navigation_can_dismiss: {
218
226
  default: boolean;
219
227
  };
228
+ reactive_navigationController: {
229
+ default: null;
230
+ };
220
231
  }, {}, {
221
232
  FramedComponent: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
222
233
  root: {
@@ -280,7 +291,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
280
291
  asyncQueue: (() => Promise<void>)[];
281
292
  asyncQueueRunning: boolean;
282
293
  cachedProvides: Map<number, any>;
283
- }, {}, {
294
+ }, {
295
+ navigationController(): InstanceType<typeof NavigationController> | null;
296
+ }, {
284
297
  cacheComponentProvides(newComponent: ComponentWithPropertiesType): void;
285
298
  provideForComponent(key: number): any;
286
299
  runQueue<T>(run: () => Promise<T>): Promise<T>;
@@ -360,12 +373,16 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
360
373
  reactive_navigation_disable_url: import('vue').ComputedRef<boolean>;
361
374
  reactive_provide_default_handler: (defaultHandler: DefaultRouteHandler) => void;
362
375
  };
376
+ detailProvide(): {
377
+ reactive_navigation_can_pop: boolean;
378
+ reactive_navigation_can_dismiss: boolean;
379
+ };
363
380
  lastIsDetail(): boolean;
364
381
  navigationController(): InstanceType<typeof NavigationController>;
365
382
  masterElement(): HTMLElement;
366
383
  }, {
367
384
  returnToHistoryIndex(): boolean;
368
- onResize(): void;
385
+ onResize(): false | undefined;
369
386
  getScrollElement(element?: HTMLElement | null): HTMLElement;
370
387
  shouldNavigateAway(): Promise<boolean>;
371
388
  showDetail(options: PushOptions): Promise<boolean>;
@@ -400,7 +417,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
400
417
  asyncQueue: (() => Promise<void>)[];
401
418
  asyncQueueRunning: boolean;
402
419
  cachedProvides: Map<number, any>;
403
- }, {}, {
420
+ }, {
421
+ navigationController(): InstanceType<typeof NavigationController> | null;
422
+ }, {
404
423
  cacheComponentProvides(newComponent: ComponentWithPropertiesType): void;
405
424
  provideForComponent(key: number): any;
406
425
  runQueue<T>(run: () => Promise<T>): Promise<T>;
@@ -506,7 +525,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
506
525
  asyncQueue: (() => Promise<void>)[];
507
526
  asyncQueueRunning: boolean;
508
527
  cachedProvides: Map<number, any>;
509
- }, {}, {
528
+ }, {
529
+ navigationController(): InstanceType<typeof NavigationController> | null;
530
+ }, {
510
531
  cacheComponentProvides(newComponent: ComponentWithPropertiesType): void;
511
532
  provideForComponent(key: number): any;
512
533
  runQueue<T>(run: () => Promise<T>): Promise<T>;
@@ -543,6 +564,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
543
564
  reactive_navigation_can_dismiss: {
544
565
  default: boolean;
545
566
  };
567
+ reactive_navigationController: {
568
+ default: null;
569
+ };
546
570
  }, {}, {
547
571
  FramedComponent: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
548
572
  root: {
@@ -606,7 +630,9 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
606
630
  asyncQueue: (() => Promise<void>)[];
607
631
  asyncQueueRunning: boolean;
608
632
  cachedProvides: Map<number, any>;
609
- }, {}, {
633
+ }, {
634
+ navigationController(): InstanceType<typeof NavigationController> | null;
635
+ }, {
610
636
  cacheComponentProvides(newComponent: ComponentWithPropertiesType): void;
611
637
  provideForComponent(key: number): any;
612
638
  runQueue<T>(run: () => Promise<T>): Promise<T>;
@@ -692,12 +718,16 @@ declare const _default: import('vue').DefineComponent<import('vue').ExtractPropT
692
718
  reactive_navigation_disable_url: import('vue').ComputedRef<boolean>;
693
719
  reactive_provide_default_handler: (defaultHandler: DefaultRouteHandler) => void;
694
720
  };
721
+ detailProvide(): {
722
+ reactive_navigation_can_pop: boolean;
723
+ reactive_navigation_can_dismiss: boolean;
724
+ };
695
725
  lastIsDetail(): boolean;
696
726
  navigationController(): InstanceType<typeof NavigationController>;
697
727
  masterElement(): HTMLElement;
698
728
  }, {
699
729
  returnToHistoryIndex(): boolean;
700
- onResize(): void;
730
+ onResize(): false | undefined;
701
731
  getScrollElement(element?: HTMLElement | null): HTMLElement;
702
732
  shouldNavigateAway(): Promise<boolean>;
703
733
  showDetail(options: PushOptions): Promise<boolean>;
@@ -66,6 +66,10 @@ export declare class UrlHelper {
66
66
  static trim(url: string): string;
67
67
  match<Params>(template: string, params?: UrlParamsConstructors<Params>): UrlMatchResult<Params> | undefined;
68
68
  }
69
+ type ConstructorToType<C> = C extends NumberConstructor ? number : C extends StringConstructor ? string : C extends BooleanConstructor ? boolean : never;
70
+ export type ParamsFromConstructors<C> = {
71
+ [K in keyof C]: ConstructorToType<C[K]>;
72
+ };
69
73
  export type UrlParamsConstructors<Params> = {
70
74
  [Key in keyof Params]: Params[Key] extends number ? NumberConstructor : StringConstructor;
71
75
  };
@@ -80,3 +84,4 @@ export type UrlMatchResult<Params> = {
80
84
  export declare function matchPath<Params>(path: string | string[], query: URLSearchParams, template: string, params?: UrlParamsConstructors<Params>): UrlMatchResult<Params> | undefined;
81
85
  export declare function matchQuery(): void;
82
86
  export declare function templateToUrl<Params>(template: string, params: Params): string;
87
+ export {};
@@ -3,70 +3,67 @@ import { ComponentWithProperties, ModalDisplayStyle } from '../ComponentWithProp
3
3
  import { HistoryUrl } from '../HistoryManager';
4
4
  import { PopOptions } from '../PopOptions';
5
5
  import { PushOptions } from '../PushOptions';
6
- import { UrlMatchResult, UrlParamsConstructors } from './UrlHelper';
6
+ import { ParamsFromConstructors, UrlMatchResult, UrlParamsConstructors } from './UrlHelper';
7
7
 
8
- export type Route<Params> = {
9
- name?: string;
10
- url: string;
11
- params?: UrlParamsConstructors<Params>;
12
- query?: UrlParamsConstructors<unknown>;
13
- component: Component | (() => Promise<Component>) | 'self';
8
+ type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
9
+ export declare function typeRoute<const C extends Record<string, StringConstructor | NumberConstructor>, Props = unknown>(route: DistributiveOmit<RouteWithParams<Props, ParamsFromConstructors<C>>, 'params'> & {
10
+ params: C;
11
+ }): RouteWithParams<Props, ParamsFromConstructors<C>>;
12
+ export declare function typeRoute<Props = unknown>(route: RouteWithoutParams<Props>): RouteWithoutParams<Props>;
13
+ export declare const defineRoute: typeof typeRoute;
14
+ type NotFunction<T> = T extends Function ? never : T;
15
+ type RouteComponent<Props> = {
14
16
  present?: ModalDisplayStyle | true;
15
- show?: true | 'detail';
16
- isDefault?: RouteNavigationOptions<Params>;
17
- paramsToProps?: (params: Params, query?: URLSearchParams) => Promise<Record<string, unknown>> | Record<string, unknown>;
18
- /**
19
- * Used for building back the URL if only properties are provided
20
- */
21
- propsToParams?: (props: Record<string, unknown>) => {
22
- params: Params;
23
- query?: URLSearchParams;
17
+ show?: true | 'detail' | {
18
+ getCustomShow: () => (options: PushOptions) => Promise<void>;
24
19
  };
20
+ component: NotFunction<Component> | 'self' | ((props: Record<string, unknown>) => Promise<Component | ComponentWithProperties> | Component | ComponentWithProperties);
25
21
  } | {
26
- name?: string;
27
- url: string;
28
- params?: UrlParamsConstructors<Params>;
29
- query?: UrlParamsConstructors<unknown>;
30
- present?: ModalDisplayStyle | true;
31
22
  handler: (options: {
32
23
  url: string;
33
24
  adjustHistory: boolean;
34
25
  animated: boolean;
35
26
  modalDisplayStyle: ModalDisplayStyle | undefined;
36
27
  checkRoutes: boolean;
37
- componentProperties: Record<string, unknown>;
28
+ componentProperties: Props;
38
29
  }) => Promise<void>;
39
- isDefault?: RouteNavigationOptions<Params>;
40
- paramsToProps?: (params: Params, query?: URLSearchParams) => Promise<Record<string, unknown>> | Record<string, unknown>;
41
- /**
42
- * Used for building back the URL if only properties are provided
43
- */
44
- propsToParams?: (props: Record<string, unknown>) => {
30
+ };
31
+ export type RouteWithParams<Props, Params> = {
32
+ name?: string;
33
+ url: string;
34
+ params: UrlParamsConstructors<Params>;
35
+ isDefault?: RouteNavigationOptions<Props, Params> & ({
36
+ params: Params;
37
+ } | {
38
+ properties: Props;
39
+ });
40
+ paramsToProps: (params: Params, query?: URLSearchParams) => Promise<Props> | Props;
41
+ propsToParams: (props: Props) => {
45
42
  params: Params;
46
43
  query?: URLSearchParams;
47
44
  };
48
- };
49
- export type RouteNavigationOptions<Params> = {
45
+ } & RouteComponent<Props>;
46
+ export type RouteWithoutParams<Props> = {
47
+ name?: string;
48
+ url: string;
49
+ isDefault?: RouteNavigationOptions<Props>;
50
+ defaultProperties?: (query?: URLSearchParams) => Promise<Props> | Props;
51
+ } & RouteComponent<Props>;
52
+ export type Route<Props = Record<string, unknown>, Params = Record<string, unknown>> = RouteWithParams<Props, Params> | RouteWithoutParams<Props>;
53
+ export type RouteNavigationOptions<Props = Record<string, unknown>, Params = Record<string, never>> = {
50
54
  params?: Params;
51
- properties?: Record<string, unknown>;
55
+ properties?: Props;
52
56
  query?: URLSearchParams;
53
57
  animated?: boolean;
54
58
  adjustHistory?: boolean;
55
59
  checkRoutes?: boolean;
56
60
  };
57
- export type RouteIdentification<Params> = {
58
- name: string;
59
- } | {
60
- url: string;
61
- } | {
62
- route: Route<Params>;
63
- };
64
61
  export type NavigationOptions<T> = {
65
62
  title: string | ((this: T) => string);
66
63
  routes?: Route<any>[];
67
64
  };
68
65
  export declare function usePop(): (options?: PopOptions) => Promise<void> | undefined;
69
- export declare function useNavigate(): <Params extends Record<string, unknown>>(prop1: string | Route<Params>, prop2?: RouteNavigationOptions<Params>) => Promise<void>;
66
+ export declare function useNavigate(): <Props extends Record<string, unknown>, Params extends Record<string, unknown>>(prop1: string | Route<Props, Params>, prop2?: RouteNavigationOptions<Props, Params>) => Promise<void>;
70
67
  export type DefaultRouteHandler = () => Promise<boolean>;
71
68
  /**
72
69
  * Return true when the route has been handled and other route checks should not be executed.
@@ -74,12 +71,12 @@ export type DefaultRouteHandler = () => Promise<boolean>;
74
71
  export type OnCheckRoutesHandler = () => Promise<void | boolean> | void | boolean;
75
72
  export declare function onCheckRoutes(handler: OnCheckRoutesHandler): void;
76
73
  export declare function onNotCheckRoutes(handler: OnCheckRoutesHandler): void;
77
- export declare function defineRoutes(routes: (Route<any>[]) | (() => Promise<boolean | (Route<any>[])>)): void;
74
+ export declare function defineRoutes(routes: Route<any, any>[]): void;
78
75
  export declare function useCurrentHref(): Ref<string, string>;
79
76
  export declare function useCheckRoute(): <Params extends Record<string, unknown>>(prop1: string | Route<Params>, prop2?: RouteNavigationOptions<Params>) => boolean;
80
77
  export declare function normalizePushOptions(o: PushOptions | ComponentWithProperties, currentComponent: ComponentWithProperties | null, urlHelpers: ReturnType<typeof useUrl>): PushOptions;
81
78
  export declare function useManualPresent(): (present: (options: PushOptions) => Promise<void> | void, options: PushOptions | ComponentWithProperties) => void | Promise<void>;
82
- export declare function useShow(): (options: PushOptions | ComponentWithProperties) => Promise<void>;
79
+ export declare function useShow(): (options: PushOptions | ComponentWithProperties, customShow?: (options: PushOptions) => Promise<void>) => Promise<void>;
83
80
  export declare function useShowDetail(): (options: PushOptions | ComponentWithProperties) => Promise<void>;
84
81
  export declare function usePresent(): (options: PushOptions | ComponentWithProperties) => Promise<void>;
85
82
  export declare function useDismiss(): (options?: PopOptions) => Promise<void>;
@@ -106,3 +103,4 @@ export declare function useUrl(): {
106
103
  matchCurrent<Params>(template: string, params?: UrlParamsConstructors<Params>): UrlMatchResult<Params> | undefined;
107
104
  overrideUrl(url: HistoryUrl, title?: string): void;
108
105
  };
106
+ export {};
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@simonbackx/vue-app-navigation",
3
3
  "main": "./dist/index.js",
4
4
  "types": "./dist/index.d.ts",
5
- "version": "2.18.0",
5
+ "version": "2.19.0",
6
6
  "exports": {
7
7
  ".": {
8
8
  "import": "./dist/index.js",
@@ -31,15 +31,15 @@
31
31
  "eslint-plugin-stamhoofd": "^2.74.0",
32
32
  "sass": "^1.32.4",
33
33
  "tslib": "^2.8.1",
34
- "typescript": "^5.6.2",
34
+ "typescript": "^6.0.3",
35
35
  "vite": "^5.2.10",
36
36
  "vite-plugin-dts": "^3.9.0",
37
37
  "vue": "^3.5.12",
38
38
  "vue-tsc": "^3.2.6"
39
39
  },
40
40
  "peerDependencies": {
41
- "vue": "^3.5.12",
42
- "tslib": "^2.8.1"
41
+ "tslib": "^2.8.1",
42
+ "vue": "^3.5.12"
43
43
  },
44
44
  "dependencies": {
45
45
  "@vue/shared": "^3.5.12"