solid-navigator 0.2.3 → 0.3.0

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/dev.js CHANGED
@@ -96,15 +96,31 @@ var isValidPath = (routes, pathname) => {
96
96
  });
97
97
  };
98
98
  var getHashAndSearch = () => location.hash + location.search;
99
+ function expandOptionals(pattern) {
100
+ let match = /(\/?\:[^\/]+)\?/.exec(pattern);
101
+ if (!match)
102
+ return [pattern];
103
+ let prefix = pattern.slice(0, match.index);
104
+ let suffix = pattern.slice(match.index + match[0].length);
105
+ const prefixes = [prefix, prefix += match[1]];
106
+ while (match = /^(\/\:[^\/]+)\?/.exec(suffix)) {
107
+ prefixes.push(prefix += match[1]);
108
+ suffix = suffix.slice(match[0].length);
109
+ }
110
+ return expandOptionals(suffix).reduce(
111
+ (results, expansion) => [...results, ...prefixes.map((p) => p + expansion)],
112
+ []
113
+ );
114
+ }
99
115
 
100
116
  // src/Router.tsx
101
117
  var RouterContext = createContext();
102
118
  function Router(props) {
103
- const childRoutes = children(() => props.children).toArray;
104
- const routes = createMemo(() => flattenedRoutes(childRoutes()));
105
119
  if (!props.children) {
106
120
  throw new Error("Router: No children provided.");
107
121
  }
122
+ const childRoutes = children(() => props.children).toArray;
123
+ const routes = createMemo(() => expandOptionalRoutes(flattenedRoutes(childRoutes())));
108
124
  const [pathname, setPathname] = createSignal(location.pathname);
109
125
  const [hashAndSearch, setHashAndSearch] = createSignal(getHashAndSearch());
110
126
  const [params, setParams] = createStore({});
@@ -140,6 +156,8 @@ function Router(props) {
140
156
  setHashAndSearch(getHashAndSearch());
141
157
  };
142
158
  const onClick = (event) => {
159
+ if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey)
160
+ return;
143
161
  const target = event.composedPath().find((el) => el instanceof Node && el.nodeName.toUpperCase() === "A");
144
162
  if (target?.tagName !== "A")
145
163
  return;
@@ -236,6 +254,18 @@ var flattenedRoute = (route) => {
236
254
  }
237
255
  return routes;
238
256
  };
257
+ var expandOptionalRoutes = (routes) => {
258
+ const newRoutes = [];
259
+ routes.forEach((route) => {
260
+ expandOptionals(route.path).forEach((path) => {
261
+ newRoutes.push({
262
+ ...route,
263
+ path
264
+ });
265
+ });
266
+ });
267
+ return newRoutes;
268
+ };
239
269
  var createNavigate = (routes, pathname, setPathname, setHashAndSearch) => {
240
270
  return (path, options) => {
241
271
  let newPath = path;
@@ -252,8 +282,7 @@ var createNavigate = (routes, pathname, setPathname, setHashAndSearch) => {
252
282
  history.pushState({}, "", newPath);
253
283
  }
254
284
  if (!isValidPath(routes, location.pathname)) {
255
- console.error("Invalid path: " + path);
256
- return;
285
+ console.warn("Invalid path: " + path);
257
286
  }
258
287
  setPathname(location.pathname);
259
288
  setHashAndSearch(getHashAndSearch());
@@ -303,10 +332,10 @@ var Outlet = (props) => {
303
332
  }
304
333
  return component2;
305
334
  });
306
- const MemodComponent = createMemo(() => {
335
+ const MemoComponent = createMemo(() => {
307
336
  return component()();
308
337
  });
309
- return MemodComponent;
338
+ return MemoComponent;
310
339
  };
311
340
  var Route = (props) => {
312
341
  const childRoutes = children(() => props.children).toArray;
@@ -316,6 +345,16 @@ var Route = (props) => {
316
345
  }
317
346
  });
318
347
  };
348
+ var matchComponent = (name) => {
349
+ const context = useRouterContext();
350
+ const component = createMemo(() => {
351
+ const components = context.matched()?.route.components || context.matched()?.route.mergedComponents || {};
352
+ return components[name()];
353
+ });
354
+ return createMemo(() => {
355
+ return component()();
356
+ });
357
+ };
319
358
  var _tmpl$ = /* @__PURE__ */ template(`<a sn-link>`);
320
359
  var A = (props) => {
321
360
  return (() => {
@@ -325,9 +364,19 @@ var A = (props) => {
325
364
  })();
326
365
  };
327
366
  var useMatch = (path) => {
328
- const context = useRouterContext();
329
- const matcher = createMemo(() => createMatcher(path()));
330
- return createMemo(() => matcher()(context.location.pathname));
367
+ const location2 = useLocation();
368
+ const matchers = createMemo(() => {
369
+ return expandOptionals(path()).map((path2) => createMatcher(path2));
370
+ });
371
+ return createMemo(() => {
372
+ for (let i = 0; i < matchers().length; i++) {
373
+ const matcher = matchers()[i];
374
+ const match = matcher(location2.pathname);
375
+ if (match) {
376
+ return match;
377
+ }
378
+ }
379
+ });
331
380
  };
332
381
 
333
- export { A, Navigate, Outlet, Route, Router, useLocation, useMatch, useNavigate, useParams, useSearchParams };
382
+ export { A, Navigate, Outlet, Route, Router, matchComponent, useLocation, useMatch, useNavigate, useParams, useSearchParams };
package/dist/dev.jsx CHANGED
@@ -106,15 +106,31 @@ var isValidPath = (routes, pathname) => {
106
106
  });
107
107
  };
108
108
  var getHashAndSearch = () => location.hash + location.search;
109
+ function expandOptionals(pattern) {
110
+ let match = /(\/?\:[^\/]+)\?/.exec(pattern);
111
+ if (!match)
112
+ return [pattern];
113
+ let prefix = pattern.slice(0, match.index);
114
+ let suffix = pattern.slice(match.index + match[0].length);
115
+ const prefixes = [prefix, prefix += match[1]];
116
+ while (match = /^(\/\:[^\/]+)\?/.exec(suffix)) {
117
+ prefixes.push(prefix += match[1]);
118
+ suffix = suffix.slice(match[0].length);
119
+ }
120
+ return expandOptionals(suffix).reduce(
121
+ (results, expansion) => [...results, ...prefixes.map((p) => p + expansion)],
122
+ []
123
+ );
124
+ }
109
125
 
110
126
  // src/Router.tsx
111
127
  var RouterContext = createContext();
112
128
  function Router(props) {
113
- const childRoutes = children(() => props.children).toArray;
114
- const routes = createMemo2(() => flattenedRoutes(childRoutes()));
115
129
  if (!props.children) {
116
130
  throw new Error("Router: No children provided.");
117
131
  }
132
+ const childRoutes = children(() => props.children).toArray;
133
+ const routes = createMemo2(() => expandOptionalRoutes(flattenedRoutes(childRoutes())));
118
134
  const [pathname, setPathname] = createSignal(location.pathname);
119
135
  const [hashAndSearch, setHashAndSearch] = createSignal(getHashAndSearch());
120
136
  const [params, setParams] = createStore2({});
@@ -147,6 +163,8 @@ function Router(props) {
147
163
  setHashAndSearch(getHashAndSearch());
148
164
  };
149
165
  const onClick = (event) => {
166
+ if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey)
167
+ return;
150
168
  const target = event.composedPath().find((el) => el instanceof Node && el.nodeName.toUpperCase() === "A");
151
169
  if (target?.tagName !== "A")
152
170
  return;
@@ -238,6 +256,15 @@ var flattenedRoute = (route) => {
238
256
  }
239
257
  return routes;
240
258
  };
259
+ var expandOptionalRoutes = (routes) => {
260
+ const newRoutes = [];
261
+ routes.forEach((route) => {
262
+ expandOptionals(route.path).forEach((path) => {
263
+ newRoutes.push({ ...route, path });
264
+ });
265
+ });
266
+ return newRoutes;
267
+ };
241
268
 
242
269
  // src/navigator.ts
243
270
  import { reconcile as reconcile3 } from "solid-js/store";
@@ -257,8 +284,7 @@ var createNavigate = (routes, pathname, setPathname, setHashAndSearch) => {
257
284
  history.pushState({}, "", newPath);
258
285
  }
259
286
  if (!isValidPath(routes, location.pathname)) {
260
- console.error("Invalid path: " + path);
261
- return;
287
+ console.warn("Invalid path: " + path);
262
288
  }
263
289
  setPathname(location.pathname);
264
290
  setHashAndSearch(getHashAndSearch());
@@ -311,14 +337,14 @@ var Outlet = (props) => {
311
337
  }
312
338
  return component2;
313
339
  });
314
- const MemodComponent = createMemo3(() => {
340
+ const MemoComponent = createMemo3(() => {
315
341
  return component()();
316
342
  });
317
- return <>{MemodComponent}</>;
343
+ return <>{MemoComponent}</>;
318
344
  };
319
345
 
320
346
  // src/Route.ts
321
- import { children as children2, mergeProps } from "solid-js";
347
+ import { children as children2, createMemo as createMemo4, mergeProps } from "solid-js";
322
348
  var Route = (props) => {
323
349
  const childRoutes = children2(() => props.children).toArray;
324
350
  return mergeProps(props, {
@@ -327,16 +353,37 @@ var Route = (props) => {
327
353
  }
328
354
  });
329
355
  };
356
+ var matchComponent = (name) => {
357
+ const context = useRouterContext();
358
+ const matched = () => context.matched();
359
+ const component = createMemo4(() => {
360
+ const components = context.matched()?.route.components || context.matched()?.route.mergedComponents || {};
361
+ return components[name()];
362
+ });
363
+ return createMemo4(() => {
364
+ return component()();
365
+ });
366
+ };
330
367
 
331
368
  // src/Link.tsx
332
- import { createMemo as createMemo4 } from "solid-js";
369
+ import { createMemo as createMemo5 } from "solid-js";
333
370
  var A = (props) => {
334
371
  return <a sn-link {...props} />;
335
372
  };
336
373
  var useMatch = (path) => {
337
- const context = useRouterContext();
338
- const matcher = createMemo4(() => createMatcher(path()));
339
- return createMemo4(() => matcher()(context.location.pathname));
374
+ const location2 = useLocation();
375
+ const matchers = createMemo5(() => {
376
+ return expandOptionals(path()).map((path2) => createMatcher(path2));
377
+ });
378
+ return createMemo5(() => {
379
+ for (let i = 0; i < matchers().length; i++) {
380
+ const matcher = matchers()[i];
381
+ const match = matcher(location2.pathname);
382
+ if (match) {
383
+ return match;
384
+ }
385
+ }
386
+ });
340
387
  };
341
388
  export {
342
389
  A,
@@ -344,6 +391,7 @@ export {
344
391
  Outlet,
345
392
  Route,
346
393
  Router,
394
+ matchComponent,
347
395
  useLocation,
348
396
  useMatch,
349
397
  useNavigate,
package/dist/index.d.ts CHANGED
@@ -1,15 +1,16 @@
1
1
  import * as solid_js from 'solid-js';
2
- import { JSX } from 'solid-js';
2
+ import { JSX, Component } from 'solid-js';
3
3
 
4
4
  interface RouteObject {
5
5
  path: string;
6
6
  children?: RouteObject[];
7
7
  component?: () => JSX.Element;
8
- components?: Record<string, () => JSX.Element>;
8
+ components?: Record<string, () => JSX.Element | undefined>;
9
9
  }
10
10
  declare const Route: (props: Omit<RouteObject, 'children'> & {
11
11
  children?: JSX.Element;
12
12
  }) => JSX.Element;
13
+ declare const matchComponent: (name: () => string) => Component;
13
14
 
14
15
  interface NavigateOptions {
15
16
  replace?: boolean;
@@ -48,6 +49,6 @@ type LinkProps = {
48
49
  replace?: boolean;
49
50
  } & JSX.AnchorHTMLAttributes<HTMLAnchorElement>;
50
51
  declare const A: (props: LinkProps) => JSX.Element;
51
- declare const useMatch: (path: () => string) => solid_js.Accessor<PathMatch | null>;
52
+ declare const useMatch: (path: () => string) => solid_js.Accessor<PathMatch | undefined>;
52
53
 
53
- export { A, Navigate, type NavigateOptions, Outlet, Route, type RouteObject, Router, type RouterProps, useLocation, useMatch, useNavigate, useParams, useSearchParams };
54
+ export { A, Navigate, type NavigateOptions, Outlet, Route, type RouteObject, Router, type RouterProps, matchComponent, useLocation, useMatch, useNavigate, useParams, useSearchParams };
package/dist/index.js CHANGED
@@ -96,15 +96,31 @@ var isValidPath = (routes, pathname) => {
96
96
  });
97
97
  };
98
98
  var getHashAndSearch = () => location.hash + location.search;
99
+ function expandOptionals(pattern) {
100
+ let match = /(\/?\:[^\/]+)\?/.exec(pattern);
101
+ if (!match)
102
+ return [pattern];
103
+ let prefix = pattern.slice(0, match.index);
104
+ let suffix = pattern.slice(match.index + match[0].length);
105
+ const prefixes = [prefix, prefix += match[1]];
106
+ while (match = /^(\/\:[^\/]+)\?/.exec(suffix)) {
107
+ prefixes.push(prefix += match[1]);
108
+ suffix = suffix.slice(match[0].length);
109
+ }
110
+ return expandOptionals(suffix).reduce(
111
+ (results, expansion) => [...results, ...prefixes.map((p) => p + expansion)],
112
+ []
113
+ );
114
+ }
99
115
 
100
116
  // src/Router.tsx
101
117
  var RouterContext = createContext();
102
118
  function Router(props) {
103
- const childRoutes = children(() => props.children).toArray;
104
- const routes = createMemo(() => flattenedRoutes(childRoutes()));
105
119
  if (!props.children) {
106
120
  throw new Error("Router: No children provided.");
107
121
  }
122
+ const childRoutes = children(() => props.children).toArray;
123
+ const routes = createMemo(() => expandOptionalRoutes(flattenedRoutes(childRoutes())));
108
124
  const [pathname, setPathname] = createSignal(location.pathname);
109
125
  const [hashAndSearch, setHashAndSearch] = createSignal(getHashAndSearch());
110
126
  const [params, setParams] = createStore({});
@@ -140,6 +156,8 @@ function Router(props) {
140
156
  setHashAndSearch(getHashAndSearch());
141
157
  };
142
158
  const onClick = (event) => {
159
+ if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey)
160
+ return;
143
161
  const target = event.composedPath().find((el) => el instanceof Node && el.nodeName.toUpperCase() === "A");
144
162
  if (target?.tagName !== "A")
145
163
  return;
@@ -236,6 +254,18 @@ var flattenedRoute = (route) => {
236
254
  }
237
255
  return routes;
238
256
  };
257
+ var expandOptionalRoutes = (routes) => {
258
+ const newRoutes = [];
259
+ routes.forEach((route) => {
260
+ expandOptionals(route.path).forEach((path) => {
261
+ newRoutes.push({
262
+ ...route,
263
+ path
264
+ });
265
+ });
266
+ });
267
+ return newRoutes;
268
+ };
239
269
  var createNavigate = (routes, pathname, setPathname, setHashAndSearch) => {
240
270
  return (path, options) => {
241
271
  let newPath = path;
@@ -251,9 +281,7 @@ var createNavigate = (routes, pathname, setPathname, setHashAndSearch) => {
251
281
  } else {
252
282
  history.pushState({}, "", newPath);
253
283
  }
254
- if (!isValidPath(routes, location.pathname)) {
255
- return;
256
- }
284
+ if (!isValidPath(routes, location.pathname)) ;
257
285
  setPathname(location.pathname);
258
286
  setHashAndSearch(getHashAndSearch());
259
287
  };
@@ -300,10 +328,10 @@ var Outlet = (props) => {
300
328
  }
301
329
  return component2;
302
330
  });
303
- const MemodComponent = createMemo(() => {
331
+ const MemoComponent = createMemo(() => {
304
332
  return component()();
305
333
  });
306
- return MemodComponent;
334
+ return MemoComponent;
307
335
  };
308
336
  var Route = (props) => {
309
337
  const childRoutes = children(() => props.children).toArray;
@@ -313,6 +341,16 @@ var Route = (props) => {
313
341
  }
314
342
  });
315
343
  };
344
+ var matchComponent = (name) => {
345
+ const context = useRouterContext();
346
+ const component = createMemo(() => {
347
+ const components = context.matched()?.route.components || context.matched()?.route.mergedComponents || {};
348
+ return components[name()];
349
+ });
350
+ return createMemo(() => {
351
+ return component()();
352
+ });
353
+ };
316
354
  var _tmpl$ = /* @__PURE__ */ template(`<a sn-link>`);
317
355
  var A = (props) => {
318
356
  return (() => {
@@ -322,9 +360,19 @@ var A = (props) => {
322
360
  })();
323
361
  };
324
362
  var useMatch = (path) => {
325
- const context = useRouterContext();
326
- const matcher = createMemo(() => createMatcher(path()));
327
- return createMemo(() => matcher()(context.location.pathname));
363
+ const location2 = useLocation();
364
+ const matchers = createMemo(() => {
365
+ return expandOptionals(path()).map((path2) => createMatcher(path2));
366
+ });
367
+ return createMemo(() => {
368
+ for (let i = 0; i < matchers().length; i++) {
369
+ const matcher = matchers()[i];
370
+ const match = matcher(location2.pathname);
371
+ if (match) {
372
+ return match;
373
+ }
374
+ }
375
+ });
328
376
  };
329
377
 
330
- export { A, Navigate, Outlet, Route, Router, useLocation, useMatch, useNavigate, useParams, useSearchParams };
378
+ export { A, Navigate, Outlet, Route, Router, matchComponent, useLocation, useMatch, useNavigate, useParams, useSearchParams };
package/dist/index.jsx CHANGED
@@ -106,15 +106,31 @@ var isValidPath = (routes, pathname) => {
106
106
  });
107
107
  };
108
108
  var getHashAndSearch = () => location.hash + location.search;
109
+ function expandOptionals(pattern) {
110
+ let match = /(\/?\:[^\/]+)\?/.exec(pattern);
111
+ if (!match)
112
+ return [pattern];
113
+ let prefix = pattern.slice(0, match.index);
114
+ let suffix = pattern.slice(match.index + match[0].length);
115
+ const prefixes = [prefix, prefix += match[1]];
116
+ while (match = /^(\/\:[^\/]+)\?/.exec(suffix)) {
117
+ prefixes.push(prefix += match[1]);
118
+ suffix = suffix.slice(match[0].length);
119
+ }
120
+ return expandOptionals(suffix).reduce(
121
+ (results, expansion) => [...results, ...prefixes.map((p) => p + expansion)],
122
+ []
123
+ );
124
+ }
109
125
 
110
126
  // src/Router.tsx
111
127
  var RouterContext = createContext();
112
128
  function Router(props) {
113
- const childRoutes = children(() => props.children).toArray;
114
- const routes = createMemo2(() => flattenedRoutes(childRoutes()));
115
129
  if (!props.children) {
116
130
  throw new Error("Router: No children provided.");
117
131
  }
132
+ const childRoutes = children(() => props.children).toArray;
133
+ const routes = createMemo2(() => expandOptionalRoutes(flattenedRoutes(childRoutes())));
118
134
  const [pathname, setPathname] = createSignal(location.pathname);
119
135
  const [hashAndSearch, setHashAndSearch] = createSignal(getHashAndSearch());
120
136
  const [params, setParams] = createStore2({});
@@ -147,6 +163,8 @@ function Router(props) {
147
163
  setHashAndSearch(getHashAndSearch());
148
164
  };
149
165
  const onClick = (event) => {
166
+ if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.altKey || event.ctrlKey || event.shiftKey)
167
+ return;
150
168
  const target = event.composedPath().find((el) => el instanceof Node && el.nodeName.toUpperCase() === "A");
151
169
  if (target?.tagName !== "A")
152
170
  return;
@@ -238,6 +256,15 @@ var flattenedRoute = (route) => {
238
256
  }
239
257
  return routes;
240
258
  };
259
+ var expandOptionalRoutes = (routes) => {
260
+ const newRoutes = [];
261
+ routes.forEach((route) => {
262
+ expandOptionals(route.path).forEach((path) => {
263
+ newRoutes.push({ ...route, path });
264
+ });
265
+ });
266
+ return newRoutes;
267
+ };
241
268
 
242
269
  // src/navigator.ts
243
270
  import { reconcile as reconcile3 } from "solid-js/store";
@@ -257,7 +284,6 @@ var createNavigate = (routes, pathname, setPathname, setHashAndSearch) => {
257
284
  history.pushState({}, "", newPath);
258
285
  }
259
286
  if (!isValidPath(routes, location.pathname)) {
260
- return;
261
287
  }
262
288
  setPathname(location.pathname);
263
289
  setHashAndSearch(getHashAndSearch());
@@ -308,14 +334,14 @@ var Outlet = (props) => {
308
334
  }
309
335
  return component2;
310
336
  });
311
- const MemodComponent = createMemo3(() => {
337
+ const MemoComponent = createMemo3(() => {
312
338
  return component()();
313
339
  });
314
- return <>{MemodComponent}</>;
340
+ return <>{MemoComponent}</>;
315
341
  };
316
342
 
317
343
  // src/Route.ts
318
- import { children as children2, mergeProps } from "solid-js";
344
+ import { children as children2, createMemo as createMemo4, mergeProps } from "solid-js";
319
345
  var Route = (props) => {
320
346
  const childRoutes = children2(() => props.children).toArray;
321
347
  return mergeProps(props, {
@@ -324,16 +350,37 @@ var Route = (props) => {
324
350
  }
325
351
  });
326
352
  };
353
+ var matchComponent = (name) => {
354
+ const context = useRouterContext();
355
+ const matched = () => context.matched();
356
+ const component = createMemo4(() => {
357
+ const components = context.matched()?.route.components || context.matched()?.route.mergedComponents || {};
358
+ return components[name()];
359
+ });
360
+ return createMemo4(() => {
361
+ return component()();
362
+ });
363
+ };
327
364
 
328
365
  // src/Link.tsx
329
- import { createMemo as createMemo4 } from "solid-js";
366
+ import { createMemo as createMemo5 } from "solid-js";
330
367
  var A = (props) => {
331
368
  return <a sn-link {...props} />;
332
369
  };
333
370
  var useMatch = (path) => {
334
- const context = useRouterContext();
335
- const matcher = createMemo4(() => createMatcher(path()));
336
- return createMemo4(() => matcher()(context.location.pathname));
371
+ const location2 = useLocation();
372
+ const matchers = createMemo5(() => {
373
+ return expandOptionals(path()).map((path2) => createMatcher(path2));
374
+ });
375
+ return createMemo5(() => {
376
+ for (let i = 0; i < matchers().length; i++) {
377
+ const matcher = matchers()[i];
378
+ const match = matcher(location2.pathname);
379
+ if (match) {
380
+ return match;
381
+ }
382
+ }
383
+ });
337
384
  };
338
385
  export {
339
386
  A,
@@ -341,6 +388,7 @@ export {
341
388
  Outlet,
342
389
  Route,
343
390
  Router,
391
+ matchComponent,
344
392
  useLocation,
345
393
  useMatch,
346
394
  useNavigate,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-navigator",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "description": "Solid Navigator is a library that is inspired by vue router and solid router.",
5
5
  "license": "MIT",
6
6
  "author": "SupertigerDev",