Files
2020-10-22 11:37:17 -04:00

134 lines
3.5 KiB
TypeScript

import { generateId } from './utils';
import { pathToRegexp } from './regexp';
import { RouteInfo,
ViewItem,
ViewStacks,
} from './types';
import { RouteLocationMatched } from 'vue-router';
import { shallowRef } from 'vue';
export const createViewStacks = () => {
let viewStacks: ViewStacks = {};
const clear = (outletId: number) => {
delete viewStacks[outletId];
}
const getViewStack = (outletId: number) => {
return viewStacks[outletId];
}
const registerIonPage = (viewItem: ViewItem, ionPage: HTMLElement) => {
viewItem.ionPageElement = ionPage;
}
const findViewItemByRouteInfo = (routeInfo: RouteInfo, outletId?: number) => {
return findViewItemByPath(routeInfo.pathname, outletId);
}
const findLeavingViewItemByRouteInfo = (routeInfo: RouteInfo, outletId?: number) => {
return findViewItemByPath(routeInfo.lastPathname, outletId, false);
}
const findViewItemInStack = (path: string, stack: ViewItem[]): ViewItem | undefined => {
return stack.find((viewItem: ViewItem) => {
if (viewItem.pathname === path) {
return viewItem;
}
return undefined;
})
}
const findViewItemByPath = (path: string, outletId?: number, strict: boolean = true): ViewItem | undefined => {
const matchView = (viewItem: ViewItem) => {
const pathname = path;
const viewItemPath = viewItem.matchedRoute.path;
const regexp = pathToRegexp(viewItemPath, [], {
end: viewItem.exact,
strict: viewItem.exact,
sensitive: false
});
return (regexp.exec(pathname)) ? viewItem : undefined;
}
if (outletId) {
const stack = viewStacks[outletId];
if (!stack) return undefined;
const quickMatch = findViewItemInStack(path, stack);
if (quickMatch) return quickMatch;
if (!strict) {
const match = stack.find(matchView);
if (match) return match;
}
} else {
for (let outletId in viewStacks) {
const stack = viewStacks[outletId];
const viewItem = findViewItemInStack(path, stack);
if (viewItem) {
return viewItem;
}
}
}
return undefined;
}
const createViewItem = (outletId: number, vueComponent: any, matchedRoute: RouteLocationMatched, routeInfo: RouteInfo, ionPage?: HTMLElement): ViewItem => {
return {
id: generateId('viewItem'),
pathname: routeInfo.pathname,
outletId,
matchedRoute,
ionPageElement: ionPage,
vueComponent,
vueComponentRef: shallowRef(),
ionRoute: false,
mount: false,
exact: routeInfo.pathname === matchedRoute.path
};
}
const add = (viewItem: ViewItem): void => {
const { outletId } = viewItem;
if (!viewStacks[outletId]) {
viewStacks[outletId] = [viewItem];
} else {
viewStacks[outletId].push(viewItem);
}
}
const remove = (viewItem: ViewItem, outletId?: number): void => {
if (!outletId) { throw Error('outletId required') }
const viewStack = viewStacks[outletId];
if (viewStack) {
viewStacks[outletId] = viewStack.filter(item => item.id !== viewItem.id);
}
}
const getChildrenToRender = (outletId: number): ViewItem[] => {
const viewStack = viewStacks[outletId];
if (viewStack) {
const components = viewStacks[outletId].filter(v => v.mount);
return components;
}
return [];
}
return {
clear,
findViewItemByRouteInfo,
findLeavingViewItemByRouteInfo,
createViewItem,
getChildrenToRender,
add,
remove,
registerIonPage,
getViewStack
}
}