diff options
Diffstat (limited to 'packages/exchange-backoffice-ui/src/route.ts')
-rw-r--r-- | packages/exchange-backoffice-ui/src/route.ts | 167 |
1 files changed, 0 insertions, 167 deletions
diff --git a/packages/exchange-backoffice-ui/src/route.ts b/packages/exchange-backoffice-ui/src/route.ts deleted file mode 100644 index d54f9be83..000000000 --- a/packages/exchange-backoffice-ui/src/route.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { createHashHistory } from "history"; -import { h as create, VNode } from "preact"; -import { useEffect, useState } from "preact/hooks"; -const history = createHashHistory(); - -type PageDefinition<DynamicPart extends Record<string, string>> = { - pattern: string; - (params: DynamicPart): string; -}; - -function replaceAll( - pattern: string, - vars: Record<string, string>, - values: Record<string, string>, -): string { - let result = pattern; - for (const v in vars) { - result = result.replace(vars[v], !values[v] ? "" : values[v]); - } - return result; -} - -export function pageDefinition<T extends Record<string, string>>( - pattern: string, -): PageDefinition<T> { - const patternParams = pattern.match(/(:[\w?]*)/g); - if (!patternParams) - throw Error( - `page definition pattern ${pattern} doesn't have any parameter`, - ); - - const vars = patternParams.reduce((prev, cur) => { - const pName = cur.match(/(\w+)/g); - - //skip things like :? in the path pattern - if (!pName || !pName[0]) return prev; - const name = pName[0]; - return { ...prev, [name]: cur }; - }, {} as Record<string, string>); - - const f = (values: T): string => replaceAll(pattern, vars, values); - f.pattern = pattern; - return f; -} - -export type PageEntry<T = unknown> = T extends Record<string, string> - ? { - url: PageDefinition<T>; - view: (props: T) => VNode; - } - : T extends unknown - ? { - url: string; - view: (props: {}) => VNode; - } - : never; - -export function Router({ - pageList, - onNotFound, -}: { - pageList: Array<PageEntry<any>>; - onNotFound: () => VNode; -}): VNode { - const current = useCurrentLocation(pageList); - if (current !== undefined) { - return create(current.page.view, current.values); - } - return onNotFound(); -} - -type Location = { - page: PageEntry<any>; - path: string; - values: Record<string, string>; -}; -export function useCurrentLocation(pageList: Array<PageEntry<any>>) { - const [currentLocation, setCurrentLocation] = useState<Location>(); - /** - * Search path in the pageList - * get the values from the path found - * add params from searchParams - * - * @param path - * @param params - */ - function doSync(path: string, params: URLSearchParams) { - let result: typeof currentLocation; - for (let idx = 0; idx < pageList.length; idx++) { - const page = pageList[idx]; - if (typeof page.url === "string") { - if (page.url === path) { - const values: Record<string, string> = {}; - params.forEach((v, k) => { - values[k] = v; - }); - result = { page, values, path }; - break; - } - } else { - const values = doestUrlMatchToRoute(path, page.url.pattern); - if (values !== undefined) { - params.forEach((v, k) => { - values[k] = v; - }); - result = { page, values, path }; - break; - } - } - } - setCurrentLocation(result); - } - useEffect(() => { - doSync(window.location.hash, new URLSearchParams(window.location.search)); - return history.listen(() => { - doSync(window.location.hash, new URLSearchParams(window.location.search)); - }); - }, []); - return currentLocation; -} - -function doestUrlMatchToRoute( - url: string, - route: string, -): undefined | Record<string, string> { - const paramsPattern = /(?:\?([^#]*))?$/; - // const paramsPattern = /(?:\?([^#]*))?(#.*)?$/; - const params = url.match(paramsPattern); - const urlWithoutParams = url.replace(paramsPattern, ""); - - const result: Record<string, string> = {}; - if (params && params[1]) { - const paramList = params[1].split("&"); - for (let i = 0; i < paramList.length; i++) { - const idx = paramList[i].indexOf("="); - const name = paramList[i].substring(0, idx); - const value = paramList[i].substring(idx + 1); - result[decodeURIComponent(name)] = decodeURIComponent(value); - } - } - const urlSeg = urlWithoutParams.split("/"); - const routeSeg = route.split("/"); - let max = Math.max(urlSeg.length, routeSeg.length); - for (let i = 0; i < max; i++) { - if (routeSeg[i] && routeSeg[i].charAt(0) === ":") { - const param = routeSeg[i].replace(/(^:|[+*?]+$)/g, ""); - - const flags = (routeSeg[i].match(/[+*?]+$/) || EMPTY)[0] || ""; - const plus = ~flags.indexOf("+"); - const star = ~flags.indexOf("*"); - const val = urlSeg[i] || ""; - - if (!val && !star && (flags.indexOf("?") < 0 || plus)) { - return undefined; - } - result[param] = decodeURIComponent(val); - if (plus || star) { - result[param] = urlSeg.slice(i).map(decodeURIComponent).join("/"); - break; - } - } else if (routeSeg[i] !== urlSeg[i]) { - return undefined; - } - } - return result; -} -const EMPTY: Record<string, string> = {}; |