From 70da0b193406f8d3b1586ad0ab05e5e7c90965cd Mon Sep 17 00:00:00 2001 From: Kirill Date: Sat, 1 Oct 2022 20:16:12 +0300 Subject: [PATCH] fix: create route/routes view --- demo/app/index.tsx | 16 +++++--- demo/app/routing.tsx | 6 --- src/create-is-opened.ts | 16 ++++++++ src/create-route-view.tsx | 56 +++++++++++++++++---------- src/create-routes-view.tsx | 77 +++++++++++++++++++++----------------- src/link.tsx | 2 +- src/route.tsx | 16 ++------ 7 files changed, 111 insertions(+), 78 deletions(-) create mode 100644 src/create-is-opened.ts diff --git a/demo/app/index.tsx b/demo/app/index.tsx index d2f8c1e..6148b11 100644 --- a/demo/app/index.tsx +++ b/demo/app/index.tsx @@ -1,4 +1,4 @@ -import { Route, RouterProvider } from 'atomic-router-solid'; +import { createRoutesView, Route, RouterProvider } from 'atomic-router-solid'; import { HomePage } from '../pages/home'; import { NotFound } from '../pages/not-found'; @@ -7,13 +7,19 @@ import { PostsSingle } from '../pages/posts-single'; import { router } from './routing'; +const RoutesView = createRoutesView({ + routes: [ + { route: HomePage.route, view: HomePage.Page }, + { route: PostsList.route, view: PostsList.Page }, + { route: PostsSingle.route, view: PostsSingle.Page }, + ], + otherwise: NotFound.Page, +}); + export const App = () => { return ( - - - - + ); }; diff --git a/demo/app/routing.tsx b/demo/app/routing.tsx index 28e75e6..039c16d 100644 --- a/demo/app/routing.tsx +++ b/demo/app/routing.tsx @@ -22,9 +22,3 @@ export const router = createHistoryRouter({ }); router.setHistory(history); - -sample({ - clock: router.routeNotFound, - fn: () => ({}), - target: NotFound.route.open, -}); diff --git a/src/create-is-opened.ts b/src/create-is-opened.ts new file mode 100644 index 0000000..e25172c --- /dev/null +++ b/src/create-is-opened.ts @@ -0,0 +1,16 @@ +import type { RouteInstance } from 'atomic-router'; +import { useUnit } from 'effector-solid'; +import { createMemo } from 'solid-js'; + +export function createIsOpened( + route: RouteInstance | RouteInstance[] +) { + return createMemo(() => { + if (Array.isArray(route)) { + const allRoutes = useUnit(route.map((route) => route.$isOpened)); + return allRoutes.some((r) => r()); + } + + return useUnit(route.$isOpened)(); + }); +} diff --git a/src/create-route-view.tsx b/src/create-route-view.tsx index 81a9ac5..cb07f62 100644 --- a/src/create-route-view.tsx +++ b/src/create-route-view.tsx @@ -1,27 +1,45 @@ -import type { RouteInstance } from 'atomic-router'; -import { combine } from 'effector'; -import { useUnit } from 'effector-solid'; +import type { RouteInstance, RouteParams } from 'atomic-router'; import type { Component } from 'solid-js'; -import { Show } from 'solid-js'; +import { Match, mergeProps, Switch } from 'solid-js'; import { Dynamic } from 'solid-js/web'; -export const createRouteView = ( - route: RouteInstance | RouteInstance[], - View: Component -) => { - const $isOpened = Array.isArray(route) - ? combine(combine(route.map((r) => r.$isOpened)), (isOpened) => - isOpened.includes(true) - ) - : route.$isOpened; +import { createIsOpened } from './create-is-opened'; - return (props: Props) => { - const isOpened = useUnit($isOpened); +export interface RouteViewConfig { + route: RouteInstance | RouteInstance[]; + view: Component; + otherwise?: Component; +} + +export function createRouteView< + Props, + Params extends RouteParams, + Config extends { + [key in keyof RouteViewConfig]?: RouteViewConfig< + Props, + Params + >[key]; + } +>(config: Config) { + return ( + props: Props & Omit, keyof Config> + ) => { + const mergedConfig = mergeProps(config, props) as RouteViewConfig< + Props, + Params + >; + const isOpened = createIsOpened(mergedConfig.route); return ( - - - + + + + + + + + + ); }; -}; +} diff --git a/src/create-routes-view.tsx b/src/create-routes-view.tsx index 68bc2ac..afdc64b 100644 --- a/src/create-routes-view.tsx +++ b/src/create-routes-view.tsx @@ -1,43 +1,50 @@ -import type { RouteInstance } from 'atomic-router'; -import { combine } from 'effector'; -import { useUnit } from 'effector-solid'; -import type { Component } from 'solid-js'; -import { For, Show } from 'solid-js'; -import { Dynamic } from 'solid-js/web'; +import type { RouteInstance, RouteParams } from 'atomic-router'; +import { Component, createMemo, Match, mergeProps, Switch } from 'solid-js'; +import { Dynamic, For } from 'solid-js/web'; -import { createRouteView } from './create-route-view'; +import { createIsOpened } from './create-is-opened'; -export const createRoutesView = (config: { - routes: { - route: RouteInstance | RouteInstance[]; - view: Component; - }[]; - notFound?: Component; -}) => { - const views = config.routes.map(({ route, view }) => - createRouteView(route, view) - ); - const $isSomeOpened = combine( - ...config.routes - .map(({ route }) => route) - .flat() - .map((route) => route.$isOpened), - // @ts-expect-error - (...isOpened) => isOpened.some(Boolean) - ); +interface RouteRecord { + route: RouteInstance | RouteInstance[]; + view: Component; +} - const NotFound = config.notFound; +export interface RoutesViewConfig { + routes: RouteRecord[]; + otherwise?: Component; +} - return () => { - const isSomeOpened = useUnit($isSomeOpened); +export function createRoutesView( + config: Config +) { + return (props: Omit) => { + const mergedConfig = mergeProps(config, props) as Config; + const routes = createMemo(() => + mergedConfig.routes.map((routeRecord) => { + const isOpened = createIsOpened(routeRecord.route); + return { + ...routeRecord, + get isOpened() { + return isOpened(); + }, + }; + }) + ); return ( - } - keyed={false}> - {(View) => } - + + + {(route) => ( + + + + )} + + + + + + ); }; -}; +} diff --git a/src/link.tsx b/src/link.tsx index 97f70ac..9ce40c3 100644 --- a/src/link.tsx +++ b/src/link.tsx @@ -19,7 +19,7 @@ type Props = { } & Exclude, 'href'>; export function Link(props: Props) { - props = mergeProps({activeClass: 'active'}, props); + props = mergeProps({ activeClass: 'active' }, props); const toIsString = createMemo(() => typeof props.to === 'string'); diff --git a/src/route.tsx b/src/route.tsx index 5d41a72..39ff4dd 100644 --- a/src/route.tsx +++ b/src/route.tsx @@ -1,25 +1,17 @@ import type { RouteInstance, RouteParams } from 'atomic-router'; -import { useUnit } from 'effector-solid'; import type { Component } from 'solid-js'; -import { createMemo, Show } from 'solid-js'; +import { Show } from 'solid-js'; import { Dynamic } from 'solid-js/web'; +import { createIsOpened } from './create-is-opened'; + type RouteProps = { route: RouteInstance | RouteInstance[]; view: Component; }; export function Route(props: RouteProps) { - const isOpened = createMemo(() => { - const route = props.route; - - if (Array.isArray(route)) { - const allRoutes = useUnit(route.map((route) => route.$isOpened)); - return allRoutes.some((r) => r()); - } - - return useUnit(route.$isOpened)(); - }); + const isOpened = createIsOpened(props.route); return (