@ulu/frontend-vue 0.1.0-beta.25 → 0.1.0-beta.26
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/{breakpoints-BvNFc-QA.js → breakpoints-aTCoPjuD.js} +1 -1
- package/dist/frontend-vue.js +15 -16
- package/dist/{index-BoP_DGKp.js → index-BmSq65FA.js} +937 -941
- package/lib/composables/index.js +1 -2
- package/lib/composables/useDocumentTitle.js +39 -25
- package/lib/utils/router.js +32 -43
- package/package.json +1 -1
- package/types/composables/index.d.ts +0 -1
- package/types/composables/useDocumentTitle.d.ts +11 -7
- package/types/composables/useDocumentTitle.d.ts.map +1 -1
- package/types/utils/router.d.ts +11 -8
- package/types/utils/router.d.ts.map +1 -1
- package/lib/composables/usePageTitle.js +0 -37
package/lib/composables/index.js
CHANGED
|
@@ -10,5 +10,4 @@ export { useWindowResize } from './useWindowResize.js';
|
|
|
10
10
|
export { useRequiredInject } from './useRequiredInject.js';
|
|
11
11
|
export { useBreakpointManager } from './useBreakpointManager.js';
|
|
12
12
|
export { usePagination } from './usePagination.js';
|
|
13
|
-
export { useDocumentTitle } from './useDocumentTitle.js';
|
|
14
|
-
export { usePageTitle } from './usePageTitle.js';
|
|
13
|
+
export { useDocumentTitle } from './useDocumentTitle.js';
|
|
@@ -1,46 +1,60 @@
|
|
|
1
|
-
import { computed } from
|
|
2
|
-
import { useHead as defaultUseHead } from
|
|
3
|
-
import { useRoute as defaultUseRoute } from
|
|
4
|
-
import {
|
|
1
|
+
import { reactive, watchEffect, onUnmounted, unref, computed } from "vue";
|
|
2
|
+
import { useHead as defaultUseHead } from "@unhead/vue";
|
|
3
|
+
import { useRoute as defaultUseRoute } from "vue-router";
|
|
4
|
+
import { getRouteTitle } from "../utils/router.js";
|
|
5
|
+
|
|
6
|
+
// A reactive map to store component-defined titles.
|
|
7
|
+
const componentTitles = reactive({});
|
|
5
8
|
|
|
6
9
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
+
* A composable to manage the document title.
|
|
11
|
+
*
|
|
12
|
+
* When called with a `title` option, it sets a dynamic title for the current page.
|
|
13
|
+
* This is for use within specific components.
|
|
10
14
|
*
|
|
11
|
-
*
|
|
15
|
+
* When called without a `title` option (typically in App.vue), it manages the
|
|
16
|
+
* document title for the whole app, using titles from components or route meta.
|
|
12
17
|
*
|
|
13
18
|
* @param {object} options
|
|
14
|
-
* @param {string} [options.
|
|
15
|
-
* @param {
|
|
16
|
-
* @param {Function} [options.
|
|
19
|
+
* @param {import('vue').Ref<string> | string} [options.title] - The dynamic title to set for the current page.
|
|
20
|
+
* @param {string} [options.titleTemplate='%s'] - The template for the document title, e.g., '%s | My Site'.
|
|
21
|
+
* @param {Function} [options.useRoute=defaultUseRoute] - Injectable `useRoute` for testing.
|
|
22
|
+
* @param {Function} [options.useHead=defaultUseHead] - Injectable `useHead` for testing.
|
|
17
23
|
*/
|
|
18
24
|
export function useDocumentTitle(options = {}) {
|
|
19
25
|
const {
|
|
20
|
-
|
|
26
|
+
title,
|
|
27
|
+
titleTemplate = "%s",
|
|
21
28
|
useRoute = defaultUseRoute,
|
|
22
|
-
useHead = defaultUseHead
|
|
29
|
+
useHead = defaultUseHead,
|
|
23
30
|
} = options;
|
|
24
31
|
|
|
25
32
|
const route = useRoute();
|
|
33
|
+
const path = route.path;
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
// --- Setter Mode ---
|
|
36
|
+
// If a title is provided, we're in "setter" mode, used within a component.
|
|
37
|
+
if (title !== undefined) {
|
|
38
|
+
watchEffect(() => {
|
|
39
|
+
componentTitles[path] = unref(title);
|
|
40
|
+
});
|
|
31
41
|
|
|
32
|
-
|
|
42
|
+
onUnmounted(() => {
|
|
43
|
+
delete componentTitles[path];
|
|
44
|
+
});
|
|
45
|
+
return; // End execution for setter mode.
|
|
46
|
+
}
|
|
33
47
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
48
|
+
// --- Manager Mode ---
|
|
49
|
+
// If no title is provided, we're in "manager" mode, used in App.vue.
|
|
50
|
+
const documentTitle = computed(() => {
|
|
51
|
+
const titleFromComponent = componentTitles[route.path];
|
|
52
|
+
const titleFromMeta = getRouteTitle(route, route);
|
|
53
|
+
const resolvedTitle = titleFromComponent || titleFromMeta;
|
|
38
54
|
|
|
39
|
-
|
|
40
|
-
return title ? titleTemplate.replace('%s', title) : 'App';
|
|
55
|
+
return resolvedTitle ? titleTemplate.replace("%s", resolvedTitle) : "App";
|
|
41
56
|
});
|
|
42
57
|
|
|
43
|
-
// useHead is reactive, so it will automatically update when documentTitle changes.
|
|
44
58
|
useHead({
|
|
45
59
|
title: documentTitle,
|
|
46
60
|
});
|
package/lib/utils/router.js
CHANGED
|
@@ -1,10 +1,29 @@
|
|
|
1
|
-
import { getPageTitle } from "../composables/usePageTitle.js";
|
|
2
1
|
/**
|
|
3
2
|
* This Module Creates Menus from route or router config
|
|
4
3
|
* - Note: Functions prefixed with "$" work with $route objects (running application, provided by vue-router ie $router, useRoute, etc),
|
|
5
4
|
* @module router-utils
|
|
6
5
|
*/
|
|
7
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Resolves a route's title from its meta.
|
|
9
|
+
* - If `meta.title` is a function, it's called with the `currentRoute` (or the route itself).
|
|
10
|
+
* - Otherwise, `meta.title` is returned.
|
|
11
|
+
* This function is the single source of truth for resolving titles from route configuration.
|
|
12
|
+
* @param {object} route The route or route match object.
|
|
13
|
+
* @param {object} [currentRoute] The current route from `useRoute()`, passed to functional titles.
|
|
14
|
+
* @returns {string|undefined} The resolved title, or undefined if not found.
|
|
15
|
+
*/
|
|
16
|
+
export function getRouteTitle(route, currentRoute) {
|
|
17
|
+
const meta = route?.meta || {};
|
|
18
|
+
let title = meta.title;
|
|
19
|
+
|
|
20
|
+
if (typeof title === "function") {
|
|
21
|
+
title = title(currentRoute || route);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return title;
|
|
25
|
+
}
|
|
26
|
+
|
|
8
27
|
/**
|
|
9
28
|
* Route Menu Item
|
|
10
29
|
* @typedef {Object} RouteMenuItem
|
|
@@ -39,7 +58,6 @@ export function createBaseMenu(routes, options) {
|
|
|
39
58
|
return currentRoutes
|
|
40
59
|
.filter(r => opts.qualifier(r, parentPath))
|
|
41
60
|
.map(r => {
|
|
42
|
-
// Need to grab meta from child but use the parent path
|
|
43
61
|
const menuRoute = r.children ? getChildIndexRoute(r.children) : r;
|
|
44
62
|
const children = r.children ? r.children.filter(child => child.path !== "") : false;
|
|
45
63
|
const item = createMenuItem(menuRoute, getItemPath(r, parentPath), opts.item);
|
|
@@ -89,7 +107,6 @@ export function createSectionMenu(routes, sectionPath, options) {
|
|
|
89
107
|
};
|
|
90
108
|
const opts = Object.assign({}, defaults, options);
|
|
91
109
|
const base = routes.find(r => r.path !== "/" && sectionPath.includes(r.path));
|
|
92
|
-
// Go through each item and
|
|
93
110
|
const getSection = (current, previous, path) => {
|
|
94
111
|
if (current.children) {
|
|
95
112
|
const child = current.children.find(c => c.path.includes(sectionPath));
|
|
@@ -110,20 +127,6 @@ export function createSectionMenu(routes, sectionPath, options) {
|
|
|
110
127
|
.sort(opts.sort);
|
|
111
128
|
}
|
|
112
129
|
|
|
113
|
-
/**
|
|
114
|
-
* For a given route this will return the route that renders. For routes without
|
|
115
|
-
* children this is the route itself for those with children (first child with empty path)
|
|
116
|
-
* @param {Object} route Route object to resolve
|
|
117
|
-
* @returns {Object} Resolved route
|
|
118
|
-
*/
|
|
119
|
-
// export function resolveRouteIndex(route) {
|
|
120
|
-
// if (route.children) {
|
|
121
|
-
// return getChildIndexRoute(route.children);
|
|
122
|
-
// } else {
|
|
123
|
-
// return route;
|
|
124
|
-
// }
|
|
125
|
-
// }
|
|
126
|
-
|
|
127
130
|
/**
|
|
128
131
|
* For a given array of child routes return the index
|
|
129
132
|
* @param {Array} children Children array of routes
|
|
@@ -132,6 +135,7 @@ export function createSectionMenu(routes, sectionPath, options) {
|
|
|
132
135
|
export function getChildIndexRoute(children) {
|
|
133
136
|
return children.find(r => r.path === "");
|
|
134
137
|
}
|
|
138
|
+
|
|
135
139
|
/**
|
|
136
140
|
* Creates common menu item structure from route, pulls title and weight from meta (on route or index child)
|
|
137
141
|
* @param {Object} route Route
|
|
@@ -151,9 +155,10 @@ export function createMenuItem(route, routePath = route.path, options) {
|
|
|
151
155
|
if (opts.indexMeta && route.children) {
|
|
152
156
|
meta = Object.assign({}, meta, getChildIndexRoute(route.children)?.meta);
|
|
153
157
|
}
|
|
158
|
+
const routeWithMergedMeta = { ...route, meta };
|
|
154
159
|
const item = {
|
|
155
160
|
path: routePath,
|
|
156
|
-
title:
|
|
161
|
+
title: getRouteTitle(routeWithMergedMeta, route) || "Missing Title",
|
|
157
162
|
weight: meta?.weight || 0,
|
|
158
163
|
meta
|
|
159
164
|
};
|
|
@@ -162,23 +167,26 @@ export function createMenuItem(route, routePath = route.path, options) {
|
|
|
162
167
|
}
|
|
163
168
|
return item;
|
|
164
169
|
}
|
|
170
|
+
|
|
165
171
|
/**
|
|
166
|
-
* Test if route is static (doesn't
|
|
172
|
+
* Test if route is static (doesn't include parameters)
|
|
167
173
|
* @param {Object} route Route object to test
|
|
168
174
|
* @returns {Boolean} Whether or not this route is static (not dynamic)
|
|
169
175
|
*/
|
|
170
176
|
export function isStaticRoute(route) {
|
|
171
177
|
return !route.path.includes("/:");
|
|
172
178
|
}
|
|
179
|
+
|
|
173
180
|
/**
|
|
174
181
|
*
|
|
175
182
|
* @param {Object} route Route object to test
|
|
176
183
|
* @returns {Boolean} Whether or not this route is a static base route
|
|
177
184
|
*/
|
|
178
185
|
export function isStaticBaseRoute(route) {
|
|
179
|
-
const matches = route.path.match(/\//) || [];
|
|
186
|
+
const matches = route.path.match(/\//g) || [];
|
|
180
187
|
return isStaticRoute(route) && matches.length === 1;
|
|
181
188
|
}
|
|
189
|
+
|
|
182
190
|
/**
|
|
183
191
|
* Function to make normal <a> behave as router links instread of page reload
|
|
184
192
|
* @param {Object} router Router instance (ie src/router) to push routes to
|
|
@@ -195,6 +203,7 @@ export function nativeLinkRouter(router, event) {
|
|
|
195
203
|
}
|
|
196
204
|
}
|
|
197
205
|
}
|
|
206
|
+
|
|
198
207
|
/**
|
|
199
208
|
* Returns the child routes for base route
|
|
200
209
|
* @param {Object} route Route Object
|
|
@@ -203,6 +212,7 @@ export function nativeLinkRouter(router, event) {
|
|
|
203
212
|
export function $getRouteChildren(route, parent = $getParentRoute(route)) {
|
|
204
213
|
return parent?.children;
|
|
205
214
|
}
|
|
215
|
+
|
|
206
216
|
/**
|
|
207
217
|
* Returns the route's parent
|
|
208
218
|
* @param {Object} route Route Object
|
|
@@ -257,7 +267,6 @@ export function $createSectionMenu(route, options) {
|
|
|
257
267
|
/**
|
|
258
268
|
* For a given $route, this will generate a breadcrumb trail.
|
|
259
269
|
* It iterates through `route.matched` to build the trail.
|
|
260
|
-
* - Prioritizes titles set via the `usePageTitle` composable for the current page.
|
|
261
270
|
* - Falls back to `meta.title` (string or function).
|
|
262
271
|
* - Skips routes where `meta.breadcrumb` is set to `false`.
|
|
263
272
|
* - Avoids duplicate crumbs for nested routes with empty paths.
|
|
@@ -269,36 +278,16 @@ export function $createBreadcrumb(route) {
|
|
|
269
278
|
let prevPath;
|
|
270
279
|
|
|
271
280
|
const crumbs = matched.reduce((arr, match, index) => {
|
|
272
|
-
// Skip routes configured to be hidden from breadcrumbs
|
|
273
281
|
if (match.meta?.breadcrumb === false) {
|
|
274
282
|
return arr;
|
|
275
283
|
}
|
|
276
284
|
|
|
277
|
-
// Avoid duplicates from child routes with empty paths
|
|
278
285
|
if (match.path === prevPath) {
|
|
279
286
|
return arr;
|
|
280
287
|
}
|
|
281
288
|
|
|
282
289
|
const isLast = index === matched.length - 1;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
// 1. Prioritize component-defined title for the current page
|
|
286
|
-
if (isLast) {
|
|
287
|
-
title = getPageTitle(currentPath);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// 2. Fallback to meta.title (function or string)
|
|
291
|
-
if (!title) {
|
|
292
|
-
const metaTitle = match.meta?.title;
|
|
293
|
-
if (typeof metaTitle === 'function') {
|
|
294
|
-
title = metaTitle(route);
|
|
295
|
-
} else {
|
|
296
|
-
title = metaTitle;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// 3. Final fallback
|
|
301
|
-
title = title || 'Missing Title';
|
|
290
|
+
const title = getRouteTitle(match, route) || "Missing Title";
|
|
302
291
|
|
|
303
292
|
arr.push({
|
|
304
293
|
title,
|
|
@@ -311,4 +300,4 @@ export function $createBreadcrumb(route) {
|
|
|
311
300
|
}, []);
|
|
312
301
|
|
|
313
302
|
return crumbs;
|
|
314
|
-
}
|
|
303
|
+
}
|
package/package.json
CHANGED
|
@@ -5,5 +5,4 @@ export { useRequiredInject } from "./useRequiredInject.js";
|
|
|
5
5
|
export { useBreakpointManager } from "./useBreakpointManager.js";
|
|
6
6
|
export { usePagination } from "./usePagination.js";
|
|
7
7
|
export { useDocumentTitle } from "./useDocumentTitle.js";
|
|
8
|
-
export { usePageTitle } from "./usePageTitle.js";
|
|
9
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* It pulls titles from the `usePageTitle` system, falling back to `meta.title`,
|
|
4
|
-
* and formats it with a template.
|
|
2
|
+
* A composable to manage the document title.
|
|
5
3
|
*
|
|
6
|
-
*
|
|
4
|
+
* When called with a `title` option, it sets a dynamic title for the current page.
|
|
5
|
+
* This is for use within specific components.
|
|
6
|
+
*
|
|
7
|
+
* When called without a `title` option (typically in App.vue), it manages the
|
|
8
|
+
* document title for the whole app, using titles from components or route meta.
|
|
7
9
|
*
|
|
8
10
|
* @param {object} options
|
|
9
|
-
* @param {string} [options.
|
|
10
|
-
* @param {
|
|
11
|
-
* @param {Function} [options.
|
|
11
|
+
* @param {import('vue').Ref<string> | string} [options.title] - The dynamic title to set for the current page.
|
|
12
|
+
* @param {string} [options.titleTemplate='%s'] - The template for the document title, e.g., '%s | My Site'.
|
|
13
|
+
* @param {Function} [options.useRoute=defaultUseRoute] - Injectable `useRoute` for testing.
|
|
14
|
+
* @param {Function} [options.useHead=defaultUseHead] - Injectable `useHead` for testing.
|
|
12
15
|
*/
|
|
13
16
|
export function useDocumentTitle(options?: {
|
|
17
|
+
title?: import("vue").Ref<string> | string;
|
|
14
18
|
titleTemplate?: string;
|
|
15
19
|
useRoute?: Function;
|
|
16
20
|
useHead?: Function;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDocumentTitle.d.ts","sourceRoot":"","sources":["../../lib/composables/useDocumentTitle.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useDocumentTitle.d.ts","sourceRoot":"","sources":["../../lib/composables/useDocumentTitle.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;GAcG;AACH,2CALG;IAAqD,KAAK,GAAlD,OAAO,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM;IACjB,aAAa,GAA9B,MAAM;IACa,QAAQ;IACR,OAAO;CACpC,QAsCA"}
|
package/types/utils/router.d.ts
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
* - Note: Functions prefixed with "$" work with $route objects (running application, provided by vue-router ie $router, useRoute, etc),
|
|
4
4
|
* @module router-utils
|
|
5
5
|
*/
|
|
6
|
+
/**
|
|
7
|
+
* Resolves a route's title from its meta.
|
|
8
|
+
* - If `meta.title` is a function, it's called with the `currentRoute` (or the route itself).
|
|
9
|
+
* - Otherwise, `meta.title` is returned.
|
|
10
|
+
* This function is the single source of truth for resolving titles from route configuration.
|
|
11
|
+
* @param {object} route The route or route match object.
|
|
12
|
+
* @param {object} [currentRoute] The current route from `useRoute()`, passed to functional titles.
|
|
13
|
+
* @returns {string|undefined} The resolved title, or undefined if not found.
|
|
14
|
+
*/
|
|
15
|
+
export function getRouteTitle(route: object, currentRoute?: object): string | undefined;
|
|
6
16
|
/**
|
|
7
17
|
* Route Menu Item
|
|
8
18
|
* @typedef {Object} RouteMenuItem
|
|
@@ -38,12 +48,6 @@ export function createSectionMenu(routes: any, sectionPath: any, options: {
|
|
|
38
48
|
includeIndex: boolean;
|
|
39
49
|
item: any;
|
|
40
50
|
}): Array<RouteMenuItem>;
|
|
41
|
-
/**
|
|
42
|
-
* For a given route this will return the route that renders. For routes without
|
|
43
|
-
* children this is the route itself for those with children (first child with empty path)
|
|
44
|
-
* @param {Object} route Route object to resolve
|
|
45
|
-
* @returns {Object} Resolved route
|
|
46
|
-
*/
|
|
47
51
|
/**
|
|
48
52
|
* For a given array of child routes return the index
|
|
49
53
|
* @param {Array} children Children array of routes
|
|
@@ -64,7 +68,7 @@ export function createMenuItem(route: any, routePath: any, options: {
|
|
|
64
68
|
indexMeta: Function;
|
|
65
69
|
}): RouteMenuItem;
|
|
66
70
|
/**
|
|
67
|
-
* Test if route is static (doesn't
|
|
71
|
+
* Test if route is static (doesn't include parameters)
|
|
68
72
|
* @param {Object} route Route object to test
|
|
69
73
|
* @returns {Boolean} Whether or not this route is static (not dynamic)
|
|
70
74
|
*/
|
|
@@ -113,7 +117,6 @@ export function $createSectionMenu(route: any, options: {
|
|
|
113
117
|
/**
|
|
114
118
|
* For a given $route, this will generate a breadcrumb trail.
|
|
115
119
|
* It iterates through `route.matched` to build the trail.
|
|
116
|
-
* - Prioritizes titles set via the `usePageTitle` composable for the current page.
|
|
117
120
|
* - Falls back to `meta.title` (string or function).
|
|
118
121
|
* - Skips routes where `meta.breadcrumb` is set to `false`.
|
|
119
122
|
* - Avoids duplicate crumbs for nested routes with empty paths.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../lib/utils/router.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../lib/utils/router.js"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;GAQG;AACH,qCAJW,MAAM,iBACN,MAAM,GACJ,MAAM,GAAC,SAAS,CAW5B;AAED;;;;;GAKG;AAEH;;;;;;;GAOG;AACH,uCANW,GAAC,WAET;IAAwB,SAAS;IACT,IAAI;CAC5B,GAAU,KAAK,CAAE,aAAa,CAAC,CAgCjC;AAED;;GAEG;AACH,4CAcC;AAED;;;;;;;;GAQG;AACH,0CAPW,GAAC,eACD,GAAC,WAET;IAAyB,YAAY;IACb,IAAI;CAC5B,GAAU,KAAK,CAAE,aAAa,CAAC,CA4BjC;AAED;;;;GAIG;AACH,yDAEC;AAED;;;;;;;;GAQG;AACH,oEAJG;IAA0B,MAAM;IACN,SAAS;CACnC,GAAU,aAAa,CAuBzB;AAED;;;;GAIG;AACH,mDAEC;AAED;;;;GAIG;AACH,uDAGC;AAED;;;;GAIG;AACH,gEAUC;AAED;;;;GAIG;AACH,iEAEC;AAED;;;;;GAKG;AACH,2DAFY,UAAW,CAUtB;AAUD;;;;;;;;;;GAUG;AACH,wDALG;IAAwB,MAAM;IACL,YAAY;IACb,IAAI;CAC5B,GAAU,KAAK,CAAE,aAAa,CAAC,CAgBjC;AAED;;;;;;;;GAQG;AACH,+CAFa,KAAK,CAAE;IAAC,KAAK,SAAS;IAAC,EAAE,MAAS;IAAC,OAAO,UAAS;CAAC,CAAC,CA6BjE"}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { reactive, watchEffect, onUnmounted, unref } from "vue";
|
|
2
|
-
import { useRoute as defaultUseRoute } from "vue-router";
|
|
3
|
-
|
|
4
|
-
// A reactive map to store component-defined titles for the current route.
|
|
5
|
-
// Key: route.path, Value: title string
|
|
6
|
-
export const pageTitles = reactive({});
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* A composable to set the title for the current page/route from within its component.
|
|
10
|
-
* This provides a single source of truth for a page's title, which can be
|
|
11
|
-
* consumed by various parts of the application (e.g., breadcrumbs, document title).
|
|
12
|
-
* @param {import('vue').Ref<string> | string} title The title to set for the current page. Can be a ref, computed, or a plain string.
|
|
13
|
-
* @param {{ useRoute: Function }} options For dependency injection in tests/stories.
|
|
14
|
-
*/
|
|
15
|
-
export function usePageTitle(title, { useRoute = defaultUseRoute } = {}) {
|
|
16
|
-
const route = useRoute();
|
|
17
|
-
const path = route.path;
|
|
18
|
-
|
|
19
|
-
watchEffect(() => {
|
|
20
|
-
pageTitles[path] = unref(title);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
// Clean up when the component is unmounted to prevent memory leaks
|
|
24
|
-
onUnmounted(() => {
|
|
25
|
-
delete pageTitles[path];
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Gets the dynamically set page title for a given path.
|
|
31
|
-
* For internal use by consumers like breadcrumb or document title utilities.
|
|
32
|
-
* @param {string} path The route path to look up.
|
|
33
|
-
* @returns {string | undefined}
|
|
34
|
-
*/
|
|
35
|
-
export function getPageTitle(path) {
|
|
36
|
-
return pageTitles[path];
|
|
37
|
-
}
|