Skip to content

Commit 1e23738

Browse files
committed
clean up the project
1 parent c430a7e commit 1e23738

File tree

11 files changed

+80
-59
lines changed

11 files changed

+80
-59
lines changed

src/examples/basic/components/AdminLayout/AdminLayout.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Tabs } from "../../components/Tabs/Tabs.tsx";
33

44
import { TabStoreKey } from "../../constants/tabs.constants.ts";
55
import { validateTabPaths } from "src/lib/tabs/validateTabPaths.ts";
6-
import { usePersistTabs } from "src/lib/tabs/persist.tsx";
6+
import { usePersistTabs } from "src/lib/tabs/usePersistTabs.tsx";
77

88
import { useEffect, useMemo, useRef, useState } from "react";
99

src/examples/basic/routes/CategoriesRoute.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Tabs } from "src/examples/basic/components/Tabs/Tabs.tsx";
44
import { RouterTabPath, useRouterTabs } from "src/lib/tabs/useRouterTabs.tsx";
55

66
import { TabModel } from "src/lib/tabs-ui/tabs-ui.types.ts";
7-
import { usePersistTabs } from "src/lib/tabs/persist.tsx";
7+
import { usePersistTabs } from "src/lib/tabs/usePersistTabs.tsx";
88
import { localStorageDriver } from "src/lib/storage/local-storage.ts";
99
import { validateTabPaths } from "src/lib/tabs/validateTabPaths.ts";
1010
import { useDataRouterContext } from "src/hooks/useDataRouterContext.tsx";

src/examples/basic/routes/ProductsRoute.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { TabModel } from "src/lib/tabs-ui/tabs-ui.types.ts";
55
import { Link, useParams } from "react-router-dom";
66
import { useEffect, useMemo, useState } from "react";
77

8-
import { usePersistTabs } from "src/lib/tabs/persist.tsx";
8+
import { usePersistTabs } from "src/lib/tabs/usePersistTabs.tsx";
99
import { localStorageDriver } from "src/lib/storage/local-storage.ts";
1010
import { validateTabPaths } from "src/lib/tabs/validateTabPaths.ts";
1111
import { useDataRouterContext } from "src/hooks/useDataRouterContext.tsx";

src/examples/basic/utils/convertRouteTreeToRouterTabsConfig.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Outlet, RouteObject } from "react-router-dom";
22
import { flattenRoutes } from "src/lib/tabs/flattenRoutes.ts";
33
import { Handle } from "src/examples/basic/types.ts";
4-
import { TabConfig } from "src/lib/tabs/useRouterTabs.tsx";
4+
import { TabDefinition } from "src/lib/tabs/useRouterTabs.tsx";
55
import { theBeginning } from "src/lib/tabs/theBeginning.ts";
66
import { TabModel } from "src/lib/tabs-ui/tabs-ui.types.ts";
77
import { whenRoutePathIs } from "src/lib/tabs/whenRoutePathIs.ts";
@@ -16,7 +16,7 @@ export const convertRouteTreeToRouterTabsConfig = (
1616
return (route.handle as Handle)?.tabs.find((tab) => tab.key === key);
1717
});
1818

19-
const config: TabConfig<TabModel>[] = matchedRoutes.map((route) => {
19+
const config: TabDefinition<TabModel>[] = matchedRoutes.map((route) => {
2020
const handle = route.handle as Handle;
2121
const tabMeta = handle.tabs.find((tab) => (tab.key = key));
2222

src/examples/clip-one/components/AdminLayout/AdminLayout.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ import {
1212
} from "../../constants/routes.constants.ts";
1313
import {
1414
RouterTabPath,
15-
TabConfig,
15+
TabDefinition,
1616
useRouterTabs,
1717
} from "src/lib/tabs/useRouterTabs.tsx";
1818
import { css } from "@emotion/react";
1919
import { Outlet } from "react-router-dom";
2020
import { TabModel } from "src/lib/tabs-ui/tabs-ui.types.ts";
2121
import { theBeginning } from "src/lib/tabs/theBeginning.ts";
2222
import { validateTabPaths } from "src/lib/tabs/validateTabPaths.ts";
23-
import { usePersistTabs } from "src/lib/tabs/persist.tsx";
23+
import { usePersistTabs } from "src/lib/tabs/usePersistTabs.tsx";
2424
import { localStorageDriver } from "src/lib/storage/local-storage.ts";
2525
import { whenRoutePathIs } from "src/lib/tabs/whenRoutePathIs.ts";
2626

@@ -47,7 +47,7 @@ export function AdminLayout() {
4747
validateTabPaths(getTabsFromStorage() || [], router),
4848
);
4949

50-
const [config] = useState<TabConfig<Properties>[]>(() => [
50+
const [config] = useState<TabDefinition<Properties>[]>(() => [
5151
{
5252
mapToUiState: (_, path) => ({
5353
id: path,

src/examples/clip-one/routes/CategoriesRoute.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import { useEffect, useMemo, useState } from "react";
44
import { Tabs } from "../components/Tabs/Tabs.tsx";
55
import {
66
RouterTabPath,
7-
TabConfig,
7+
TabDefinition,
88
useRouterTabs,
99
} from "src/lib/tabs/useRouterTabs.tsx";
1010
import { data as categories } from "../data/categories.json";
1111

1212
import { TabModel } from "src/lib/tabs-ui/tabs-ui.types.ts";
13-
import { usePersistTabs } from "src/lib/tabs/persist.tsx";
13+
import { usePersistTabs } from "src/lib/tabs/usePersistTabs.tsx";
1414
import { localStorageDriver } from "src/lib/storage/local-storage.ts";
1515
import { validateTabPaths } from "src/lib/tabs/validateTabPaths.ts";
1616
import { useDataRouterContext } from "src/hooks/useDataRouterContext.tsx";
@@ -43,7 +43,7 @@ export function CategoriesRoute() {
4343
validateTabPaths(getTabsFromStorage() || defaultTabs, router),
4444
);
4545

46-
const config = useMemo<TabConfig<TabModel>[]>(
46+
const config = useMemo<TabDefinition<TabModel>[]>(
4747
() => [
4848
{
4949
mapToUiState: (_, path) => ({

src/examples/clip-one/routes/ProductsRoute.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Outlet, useNavigate, useParams } from "react-router-dom";
55
import { useEffect, useMemo, useState } from "react";
66
import { data as products } from "../data/products.json";
77

8-
import { usePersistTabs } from "src/lib/tabs/persist.tsx";
8+
import { usePersistTabs } from "src/lib/tabs/usePersistTabs.tsx";
99
import { localStorageDriver } from "src/lib/storage/local-storage.ts";
1010
import { validateTabPaths } from "src/lib/tabs/validateTabPaths.ts";
1111
import { useDataRouterContext } from "src/hooks/useDataRouterContext.tsx";
@@ -18,7 +18,7 @@ import {
1818
} from "../constants/routes.constants.ts";
1919
import {
2020
RouterTabPath,
21-
TabConfig,
21+
TabDefinition,
2222
useRouterTabs,
2323
} from "src/lib/tabs/useRouterTabs.tsx";
2424
import { css } from "@emotion/react";
@@ -185,7 +185,7 @@ export function ProductDetailRoute() {
185185
productDetailSettingTabsRoute.replace(":id", params.id),
186186
]);
187187

188-
const config = useMemo<TabConfig<TabModel>[]>(
188+
const config = useMemo<TabDefinition<TabModel>[]>(
189189
() => [
190190
{
191191
mapToUiState: (_, tab) => ({

src/lib/tabs/getUrl.ts

-8
This file was deleted.
File renamed without changes.

src/lib/tabs/useRouterTabs.tsx

+59-34
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
import { DataRouteMatch, matchRoutes } from "react-router-dom";
1+
import { DataRouteMatch, Location, matchRoutes } from "react-router-dom";
22
import { useCallback, useEffect } from "react";
33
import { RouterState } from "@remix-run/router";
4-
import { last, replaceAt, insertAt } from "src/utils/array-utils.ts";
4+
import { replaceAt, insertAt } from "src/utils/array-utils.ts";
55
import { Router } from "@remix-run/router";
6-
import { getUrl } from "src/lib/tabs/getUrl.ts";
76
import { normalizePathname } from "src/lib/tabs/normalizePathname.ts";
87

98
type ValidUiState = Record<string, any>;
109

11-
export type TabConfig<UiState extends ValidUiState = ValidUiState> = {
10+
export type TabDefinition<UiState extends ValidUiState = ValidUiState> = {
1211
shouldOpen: (match: DataRouteMatch) => boolean;
1312
insertAt: (tabs: RouterTabPath[]) => number;
1413
mapToUiState: (match: DataRouteMatch, path: RouterTabPath) => UiState;
@@ -20,10 +19,15 @@ type PathsChangeCallback = (
2019
paths: RouterTabPath[] | { (prevPaths: RouterTabPath[]): RouterTabPath[] },
2120
) => void;
2221

22+
type MatchRouterTabResult = {
23+
definition: TabDefinition;
24+
match: DataRouteMatch;
25+
};
26+
2327
export const matchRouterTab = (
2428
matches: DataRouteMatch[],
25-
config: TabConfig[],
26-
) => {
29+
config: TabDefinition[],
30+
): MatchRouterTabResult | undefined => {
2731
for (let i = matches.length - 1; i > -1; i--) {
2832
const match = matches[i];
2933
const definition = config.find((def) => def.shouldOpen(match));
@@ -41,12 +45,29 @@ export const useRouterTabs = <
4145
UiState extends ValidUiState = ValidUiState,
4246
>(options: {
4347
router: Router;
44-
config: TabConfig<UiState>[];
48+
config: TabDefinition<UiState>[];
4549
onPathsChange?: PathsChangeCallback;
4650
paths: RouterTabPath[];
4751
}) => {
4852
const { onPathsChange, paths, config, router } = options;
4953

54+
const isOpenFor = useCallback(
55+
(match: DataRouteMatch) => (path: string) => {
56+
const matches = matchRoutes(router.routes, path) || [];
57+
const result = matchRouterTab(matches, config);
58+
59+
if (!result) {
60+
return false;
61+
}
62+
63+
return (
64+
normalizePathname(result.match.pathname) ===
65+
normalizePathname(match.pathname)
66+
);
67+
},
68+
[router.routes, config],
69+
);
70+
5071
const updateTabs = useCallback(
5172
(state: RouterState) => {
5273
const { matches, location, navigation } = state;
@@ -55,39 +76,33 @@ export const useRouterTabs = <
5576
return;
5677
}
5778

58-
const result = matchRouterTab(matches, config);
79+
const matchResult = matchRouterTab(matches, config);
5980

60-
if (!result) {
81+
if (!matchResult) {
6182
return;
6283
}
63-
const { definition, match } = result;
84+
6485
const getNextPaths = (prevPaths: RouterTabPath[]) => {
65-
const tab = prevPaths.find((path) => {
66-
const matches = matchRoutes(router.routes, path) || [];
67-
const result = matchRouterTab(matches, config);
68-
return (
69-
result &&
70-
normalizePathname(result.match.pathname) ===
71-
normalizePathname(match.pathname)
72-
);
73-
});
86+
const tab = prevPaths.find(isOpenFor(matchResult.match));
7487

75-
const { pathname } = last(matches);
76-
const { search } = location;
77-
const path = normalizePathname(pathname) + search;
88+
const path = getUrl(location);
7889

7990
if (tab) {
8091
// update the tab path
8192
const index = prevPaths.indexOf(tab);
8293

8394
return replaceAt(prevPaths, index, path);
8495
} else {
85-
return insertAt(prevPaths, definition.insertAt(prevPaths), path);
96+
return insertAt(
97+
prevPaths,
98+
matchResult.definition.insertAt(prevPaths),
99+
path,
100+
);
86101
}
87102
};
88103
onPathsChange?.(getNextPaths);
89104
},
90-
[config, onPathsChange, router.routes],
105+
[config, onPathsChange, isOpenFor],
91106
);
92107

93108
useEffect(() => {
@@ -96,23 +111,33 @@ export const useRouterTabs = <
96111
return router.subscribe(updateTabs);
97112
}, [router, updateTabs]);
98113

99-
const tabs = paths.map((path) => {
114+
const toUiState = (path: string) => {
100115
const matches = matchRoutes(router.routes, path) || [];
101-
const result = matchRouterTab(matches, config)!;
116+
const result = matchRouterTab(matches, config);
102117

103-
return result.definition.mapToUiState(result.match, path) as UiState;
104-
});
118+
if (!result) {
119+
return undefined;
120+
}
121+
const { definition, match } = result;
122+
return definition.mapToUiState(match, path);
123+
};
105124

106-
const matches = matchRoutes(router.routes, router.state.location) || [];
107-
const result = matchRouterTab(matches, config);
125+
const tabs = paths
126+
.map(toUiState)
127+
.filter((tab): tab is UiState => Boolean(tab));
108128

109-
const activeTab = result?.definition.mapToUiState(
110-
result.match,
111-
getUrl(router.state.location),
112-
) as UiState | undefined;
129+
const activeTab = toUiState(getUrl(router.state.location)) as
130+
| UiState
131+
| undefined;
113132

114133
return {
115134
tabs,
116135
activeTab,
117136
};
118137
};
138+
139+
const getUrl = (location: Location) => {
140+
const { pathname, search } = location;
141+
142+
return normalizePathname(pathname) + search;
143+
};

src/routes/HomeRoute.tsx

+7-3
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ export function HomeRoute() {
99
<div css={innerStyles}>
1010
<h1 css={titleStyles}>Examples:</h1>
1111
<ul>
12-
<li>
12+
<li css={listItemStyles}>
1313
<Link to={basicHomeRoute}>Basic</Link>
1414
</li>
15-
<li>
16-
<Link to={clipOneHomeRoute}>Clip one</Link>
15+
<li css={listItemStyles}>
16+
<Link to={clipOneHomeRoute}>Clip one admin</Link>
1717
</li>
1818
</ul>
1919
</div>
@@ -31,6 +31,10 @@ const containerStyles = css`
3131
flex-direction: column;
3232
`;
3333

34+
const listItemStyles = css`
35+
white-space: nowrap;
36+
`;
37+
3438
const innerStyles = css`
3539
width: 100px;
3640
`;

0 commit comments

Comments
 (0)