soseki 0.0.8 → 0.0.9

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.
@@ -1,4 +1,4 @@
1
- import type { RouteDefinition } from "../core/route.types.js";
1
+ import { type RouterRouteDefinition } from "./router.jsx";
2
2
  /**
3
3
  * `BrowserRouter` コンポーネントに引き渡すプロパティーの型定義です。
4
4
  */
@@ -6,7 +6,7 @@ export type BrowserRouterProps = {
6
6
  /**
7
7
  * アプリケーション全体の画面構造を定義したルート定義の配列です。
8
8
  */
9
- routes: readonly RouteDefinition[];
9
+ routes: readonly RouterRouteDefinition[];
10
10
  };
11
11
  /**
12
12
  * ブラウザー環境における SPA ルーティングを開始するための、最上位エントリーポイントコンポーネントです。
@@ -1 +1 @@
1
- {"version":3,"file":"browser-router.d.ts","sourceRoot":"","sources":["../../../src/components/browser-router.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAK9D;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;OAEG;IACH,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;CACpC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAKnF"}
1
+ {"version":3,"file":"browser-router.d.ts","sourceRoot":"","sources":["../../../src/components/browser-router.tsx"],"names":[],"mappings":"AAEA,OAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;OAEG;IACH,MAAM,EAAE,SAAS,qBAAqB,EAAE,CAAC;CAC1C,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAKnF"}
@@ -1,6 +1,36 @@
1
1
  import * as React from "react";
2
- import type { RouteDefinition } from "../core/route.types.js";
3
2
  import type { IEngine } from "../engines/engine.types.js";
3
+ export type RouterRouteDefinitionObject = {
4
+ readonly path: string;
5
+ readonly index?: boolean | undefined;
6
+ readonly action?: {
7
+ (args: any): unknown;
8
+ } | undefined;
9
+ readonly shouldReload?: {
10
+ (args: any): boolean;
11
+ } | undefined;
12
+ readonly loader?: {
13
+ (args: any): unknown;
14
+ } | undefined;
15
+ readonly component?: React.ComponentType<{}> | undefined;
16
+ };
17
+ export type RouterRouteDefinitionModule = {
18
+ readonly path: string;
19
+ readonly index?: boolean | undefined;
20
+ readonly action?: {
21
+ (args: any): unknown;
22
+ } | undefined;
23
+ readonly shouldReload?: {
24
+ (args: any): boolean;
25
+ } | undefined;
26
+ readonly loader?: {
27
+ (args: any): unknown;
28
+ } | undefined;
29
+ readonly component?: React.ComponentType<{}> | undefined;
30
+ readonly default?: React.ComponentType<{}> | undefined;
31
+ get [Symbol.toStringTag](): string;
32
+ };
33
+ export type RouterRouteDefinition = RouterRouteDefinitionObject | RouterRouteDefinitionModule;
4
34
  /**
5
35
  * `Router` コンポーネントに渡されるルートプロパティーの型定義です。
6
36
  */
@@ -12,7 +42,7 @@ export type RouterProps = {
12
42
  /**
13
43
  * ユーザーがアプリケーションに定義したルート定義の配列です。
14
44
  */
15
- routes: readonly RouteDefinition[];
45
+ routes: readonly RouterRouteDefinition[];
16
46
  };
17
47
  /**
18
48
  * 宣言的なルート定義と、命令的なルーティング実行エンジンを仲介・統合し、アプリケーションの最上位でルーティングのライフサイクルと状態管理を司るプロバイダーコンポーネントです。
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/components/router.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,OAAO,KAAK,EAAkC,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9F,OAAO,KAAK,EAAE,OAAO,EAAe,MAAM,4BAA4B,CAAC;AAkEvE;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,KAAK,EAAE,WAAW,4BAkIhD"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/components/router.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,OAAO,KAAK,EAAE,OAAO,EAAe,MAAM,4BAA4B,CAAC;AAkEvE,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,YAAY,CAAC,EAAE;QAAE,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,YAAY,CAAC,EAAE;QAAE,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAA;KAAE,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,2BAA2B,GAAG,2BAA2B,CAAC;AAE9F;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,MAAM,EAAE,SAAS,qBAAqB,EAAE,CAAC;CAC1C,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,KAAK,EAAE,WAAW,4BAkIhD"}
@@ -1,10 +1,48 @@
1
- import type { ReadonlyURL } from "./readonly-url.types.js";
1
+ import type { ReadonlyURL, ReadonlyURLSearchParams } from "./readonly-url.types.js";
2
2
  /**
3
3
  * アプリケーション内のルーティングにおけるパスを安全に構築・解析・操作するためのクラスです。
4
4
  *
5
5
  * 内包するホストやプロトコルといった余分な情報を排除し、パス、クエリー、ハッシュのみを一貫した規則で管理します。
6
6
  */
7
- export default class RoutePath {
7
+ export interface ReadonlyRoutePath {
8
+ /**
9
+ * 正規化されたパス部分の文字列です。
10
+ */
11
+ readonly pathname: string;
12
+ /**
13
+ * 先頭に `?` を含むクエリー文字列です。
14
+ *
15
+ * 常にソートされます。
16
+ */
17
+ readonly search: string;
18
+ /**
19
+ * 内部の `URL` インスタンスが保持する、クエリーパラメーターを操作するための `URLSearchParams` オブジェクトを取得します。
20
+ */
21
+ readonly searchParams: ReadonlyURLSearchParams;
22
+ /**
23
+ * 先頭に `#` を含むハッシュ文字列を取得します。
24
+ */
25
+ readonly hash: string;
26
+ /**
27
+ * 現在保持しているすべてのコンポーネントを結合し、ルーティング用のパス文字列として出力します。
28
+ *
29
+ * @returns ソート済みのクエリーおよびハッシュを含んだ、正規化されたパス全体の文字列を返します。
30
+ */
31
+ toString(): string;
32
+ /**
33
+ * このインスタンスを複製し、上書き可能な形式で取得します。
34
+ *
35
+ * @returns 上書き可能な {@link RoutePath|`RoutePath`} インスタンスです。
36
+ */
37
+ clone(): RoutePath;
38
+ }
39
+ /**
40
+ * アプリケーション内のルーティングにおけるパスを安全に構築・解析・操作するためのクラスです。
41
+ *
42
+ * 内包するホストやプロトコルといった余分な情報を排除し、パス、クエリー、ハッシュのみを一貫した規則で管理します。
43
+ */
44
+ export default class RoutePath implements ReadonlyRoutePath {
45
+ #private;
8
46
  /**
9
47
  * 与えられた文字列または URL オブジェクトから、正規化されたパス文字列を即座に生成する静的メソッドです。
10
48
  *
@@ -12,12 +50,6 @@ export default class RoutePath {
12
50
  * @returns 冗長なスラッシュや末尾のスラッシュが取り除かれた、結合済みのパス文字列を返します。
13
51
  */
14
52
  static encode(path: string | Pick<ReadonlyURL, "pathname" | "search" | "hash">): string;
15
- /**
16
- * 内部でパスコンポーネントの解析と検証を委譲するために保持する、組み込みの `URL` インスタンスです。
17
- *
18
- * 基底となる仮想的なオリジンと結合して管理されます。
19
- */
20
- private url;
21
53
  /**
22
54
  * 新しい `RoutePath` インスタンスを初期化します。
23
55
  *
@@ -53,5 +85,11 @@ export default class RoutePath {
53
85
  * @returns ソート済みのクエリーおよびハッシュを含んだ、正規化されたパス全体の文字列を返します。
54
86
  */
55
87
  toString(): string;
88
+ /**
89
+ * このインスタンスを複製し、上書き可能な形式で取得します。
90
+ *
91
+ * @returns 上書き可能な {@link RoutePath|`RoutePath`} インスタンスです。
92
+ */
93
+ clone(): RoutePath;
56
94
  }
57
95
  //# sourceMappingURL=route-path.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"route-path.d.ts","sourceRoot":"","sources":["../../../src/core/route-path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAO3D;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,SAAS;IAC5B;;;;;OAKG;WACW,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC,GAAG,MAAM;IAI9F;;;;OAIG;IACH,OAAO,CAAC,GAAG,CAAM;IAEjB;;;;;;OAMG;gBACgB,IAAI,GAAE,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAM;IAkBxF;;OAEG;IACH,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAED,IAAW,QAAQ,CAAC,KAAK,EAAE,MAAM,EAQhC;IAED;;;;OAIG;IACH,IAAW,MAAM,IAAI,MAAM,CAG1B;IAED,IAAW,MAAM,CAAC,KAAK,EAAE,MAAM,EAE9B;IAED;;OAEG;IACH,IAAW,YAAY,IAAI,eAAe,CAEzC;IAED;;OAEG;IACH,IAAW,IAAI,IAAI,MAAM,CAExB;IAED,IAAW,IAAI,CAAC,KAAK,EAAE,MAAM,EAE5B;IAED;;;;OAIG;IACI,QAAQ,IAAI,MAAM;CAI1B"}
1
+ {"version":3,"file":"route-path.d.ts","sourceRoot":"","sources":["../../../src/core/route-path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAOpF;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,uBAAuB,CAAC;IAE/C;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,QAAQ,IAAI,MAAM,CAAC;IAEnB;;;;OAIG;IACH,KAAK,IAAI,SAAS,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,SAAU,YAAW,iBAAiB;;IACzD;;;;;OAKG;WACW,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC,GAAG,MAAM;IAW9F;;;;;;OAMG;gBACgB,IAAI,GAAE,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAM;IAkBxF;;OAEG;IACH,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAED,IAAW,QAAQ,CAAC,KAAK,EAAE,MAAM,EAQhC;IAED;;;;OAIG;IACH,IAAW,MAAM,IAAI,MAAM,CAG1B;IAED,IAAW,MAAM,CAAC,KAAK,EAAE,MAAM,EAE9B;IAED;;OAEG;IACH,IAAW,YAAY,IAAI,eAAe,CAEzC;IAED;;OAEG;IACH,IAAW,IAAI,IAAI,MAAM,CAExB;IAED,IAAW,IAAI,CAAC,KAAK,EAAE,MAAM,EAE5B;IAED;;;;OAIG;IACI,QAAQ,IAAI,MAAM;IAKzB;;;;OAIG;IACI,KAAK,IAAI,SAAS;CAG1B"}
@@ -1,3 +1,15 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _RoutePath_url;
1
13
  /**
2
14
  * 連続する複数のスラッシュを検出するための正規表現です。
3
15
  */
@@ -7,7 +19,7 @@ const MULTI_SLASH = /\/\/+/gu;
7
19
  *
8
20
  * 内包するホストやプロトコルといった余分な情報を排除し、パス、クエリー、ハッシュのみを一貫した規則で管理します。
9
21
  */
10
- export default class RoutePath {
22
+ class RoutePath {
11
23
  /**
12
24
  * 与えられた文字列または URL オブジェクトから、正規化されたパス文字列を即座に生成する静的メソッドです。
13
25
  *
@@ -25,6 +37,12 @@ export default class RoutePath {
25
37
  * @param path 初期化に使用するパス文字列、または `ReadonlyURL` の一部のプロパティーを持つオブジェクトです。既定値は空文字列です。
26
38
  */
27
39
  constructor(path = "") {
40
+ /**
41
+ * 内部でパスコンポーネントの解析と検証を委譲するために保持する、組み込みの `URL` インスタンスです。
42
+ *
43
+ * 基底となる仮想的なオリジンと結合して管理されます。
44
+ */
45
+ _RoutePath_url.set(this, void 0);
28
46
  if (typeof path === "string") {
29
47
  path = ("/" + path).replace(MULTI_SLASH, "/");
30
48
  }
@@ -33,25 +51,25 @@ export default class RoutePath {
33
51
  path = ("/" + pathname).replace(MULTI_SLASH, "/") + search + hash;
34
52
  }
35
53
  // 組み込みの URL クラスによる厳密な解析機能を利用するため、仮想のプロトコルとホストを前置きして初期化します。
36
- this.url = new URL("x://y" + path);
54
+ __classPrivateFieldSet(this, _RoutePath_url, new URL("x://y" + path), "f");
37
55
  // ルートパス(/)単体である場合を除き、末尾に存在する不要なスラッシュを削除して一貫性を保ちます。
38
- const { pathname } = this.url;
56
+ const { pathname } = __classPrivateFieldGet(this, _RoutePath_url, "f");
39
57
  if (pathname !== "/" && pathname.endsWith("/")) {
40
- this.url.pathname = pathname.substring(0, pathname.length - 1);
58
+ __classPrivateFieldGet(this, _RoutePath_url, "f").pathname = pathname.substring(0, pathname.length - 1);
41
59
  }
42
60
  }
43
61
  /**
44
62
  * 正規化されたパス部分の文字列です。
45
63
  */
46
64
  get pathname() {
47
- return this.url.pathname;
65
+ return __classPrivateFieldGet(this, _RoutePath_url, "f").pathname;
48
66
  }
49
67
  set pathname(value) {
50
- this.url.pathname = value;
68
+ __classPrivateFieldGet(this, _RoutePath_url, "f").pathname = value;
51
69
  // ルートパス(/)単体である場合を除き、末尾に存在する不要なスラッシュを削除して一貫性を保ちます。
52
- const pathname = ("/" + this.url.pathname).replace(MULTI_SLASH, "/");
70
+ const pathname = ("/" + __classPrivateFieldGet(this, _RoutePath_url, "f").pathname).replace(MULTI_SLASH, "/");
53
71
  if (pathname !== "/" && pathname.endsWith("/")) {
54
- this.url.pathname = pathname.substring(0, pathname.length - 1);
72
+ __classPrivateFieldGet(this, _RoutePath_url, "f").pathname = pathname.substring(0, pathname.length - 1);
55
73
  }
56
74
  }
57
75
  /**
@@ -60,26 +78,26 @@ export default class RoutePath {
60
78
  * 常にソートされます。
61
79
  */
62
80
  get search() {
63
- this.url.searchParams.sort();
64
- return this.url.search;
81
+ __classPrivateFieldGet(this, _RoutePath_url, "f").searchParams.sort();
82
+ return __classPrivateFieldGet(this, _RoutePath_url, "f").search;
65
83
  }
66
84
  set search(value) {
67
- this.url.search = value;
85
+ __classPrivateFieldGet(this, _RoutePath_url, "f").search = value;
68
86
  }
69
87
  /**
70
88
  * 内部の `URL` インスタンスが保持する、クエリーパラメーターを操作するための `URLSearchParams` オブジェクトを取得します。
71
89
  */
72
90
  get searchParams() {
73
- return this.url.searchParams;
91
+ return __classPrivateFieldGet(this, _RoutePath_url, "f").searchParams;
74
92
  }
75
93
  /**
76
94
  * 先頭に `#` を含むハッシュ文字列を取得します。
77
95
  */
78
96
  get hash() {
79
- return this.url.hash;
97
+ return __classPrivateFieldGet(this, _RoutePath_url, "f").hash;
80
98
  }
81
99
  set hash(value) {
82
- this.url.hash = value;
100
+ __classPrivateFieldGet(this, _RoutePath_url, "f").hash = value;
83
101
  }
84
102
  /**
85
103
  * 現在保持しているすべてのコンポーネントを結合し、ルーティング用のパス文字列として出力します。
@@ -90,4 +108,14 @@ export default class RoutePath {
90
108
  const { hash, search, pathname } = this;
91
109
  return pathname + search + hash;
92
110
  }
111
+ /**
112
+ * このインスタンスを複製し、上書き可能な形式で取得します。
113
+ *
114
+ * @returns 上書き可能な {@link RoutePath|`RoutePath`} インスタンスです。
115
+ */
116
+ clone() {
117
+ return new RoutePath(this.toString());
118
+ }
93
119
  }
120
+ _RoutePath_url = new WeakMap();
121
+ export default RoutePath;
@@ -22,4 +22,9 @@ export type * from "./core/start-action.js";
22
22
  export { default as startAction } from "./core/start-action.js";
23
23
  export type * from "./core/start-loaders.js";
24
24
  export { default as startLoaders } from "./core/start-loaders.js";
25
+ /**************************************************************************************************/
26
+ export type * from "./hooks/use-route-context.js";
27
+ export { default as useRouteContext } from "./hooks/use-route-context.js";
28
+ export type * from "./hooks/use-router-context.js";
29
+ export { default as useRouterContext } from "./hooks/use-router-context.js";
25
30
  //# sourceMappingURL=core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core.ts"],"names":[],"mappings":"AAAA,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAE5D,oGAAoG;AAEpG,mBAAmB,6BAA6B,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEtE,mBAAmB,8BAA8B,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAExE,oGAAoG;AAEpG,mBAAmB,gCAAgC,CAAC;AACpD,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAE/E,mBAAmB,mCAAmC,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEpF,mBAAmB,oCAAoC,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAEtF,mBAAmB,wBAAwB,CAAC;AAC5C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAEhE,mBAAmB,wBAAwB,CAAC;AAC5C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAEhE,mBAAmB,sBAAsB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,mBAAmB,wBAAwB,CAAC;AAC5C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAEhE,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core.ts"],"names":[],"mappings":"AAAA,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAE5D,oGAAoG;AAEpG,mBAAmB,6BAA6B,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEtE,mBAAmB,8BAA8B,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAExE,oGAAoG;AAEpG,mBAAmB,gCAAgC,CAAC;AACpD,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAE/E,mBAAmB,mCAAmC,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAEpF,mBAAmB,oCAAoC,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AAEtF,mBAAmB,wBAAwB,CAAC;AAC5C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAEhE,mBAAmB,wBAAwB,CAAC;AAC5C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAEhE,mBAAmB,sBAAsB,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAE5D,mBAAmB,wBAAwB,CAAC;AAC5C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAEhE,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAElE,oGAAoG;AAEpG,mBAAmB,8BAA8B,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE1E,mBAAmB,+BAA+B,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,+BAA+B,CAAC"}
package/dist/src/core.js CHANGED
@@ -9,3 +9,5 @@ export { default as matchRoutes } from "./core/match-routes.js";
9
9
  export { default as RoutePath } from "./core/route-path.js";
10
10
  export { default as startAction } from "./core/start-action.js";
11
11
  export { default as startLoaders } from "./core/start-loaders.js";
12
+ export { default as useRouteContext } from "./hooks/use-route-context.js";
13
+ export { default as useRouterContext } from "./hooks/use-router-context.js";
@@ -1,4 +1,5 @@
1
1
  import type { NinjaPromise } from "ninja-promise";
2
+ import type { RoutePath } from "../core.js";
2
3
  import type { HistoryEntry } from "../core/expect-history-entry.js";
3
4
  import type { HistoryEntryId } from "../core/history-entry-id-schema.js";
4
5
  import type { MatchedRoute } from "../core/match-routes.js";
@@ -151,28 +152,22 @@ export declare namespace IEngine {
151
152
  /**
152
153
  * URL パスで前方移動する形式です。
153
154
  */
154
- type: "PATH";
155
+ type: "STATIC";
155
156
  /**
156
157
  * URL パスです。
157
158
  */
158
159
  path: string;
159
160
  } | {
160
161
  /**
161
- * URL の各コンポーネントを個別に指定する形式です。
162
+ * URL の各コンポーネントを関数形式で個別に指定する形式です。
162
163
  */
163
- type: "PARTIAL";
164
+ type: "DYNAMIC";
164
165
  /**
165
- * 最初のスラッシュ `/` から始まる URL のパス部分です。
166
- */
167
- pathname?: string | undefined;
168
- /**
169
- * 先頭のクエスチョンマーク `?` を含む URL のクエリー文字列です。
170
- */
171
- search?: string | undefined;
172
- /**
173
- * URL のハッシュ(シャープ記号 `#` を含むフラグメント識別子)です。
166
+ * 動的にパッチを適用する関数です。
167
+ *
168
+ * @param path アプリケーション内のルーティングにおけるパスを安全に構築・解析・操作するためのオブジェクトです。
174
169
  */
175
- hash?: string | undefined;
170
+ patch(path: RoutePath): void;
176
171
  };
177
172
  /**
178
173
  * 履歴スタックへの追加方法を指定します。
@@ -1 +1 @@
1
- {"version":3,"file":"engine.types.d.ts","sourceRoot":"","sources":["../../../src/engines/engine.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.types.d.ts","sourceRoot":"","sources":["../../../src/engines/engine.types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"navigation-api-engine.d.ts","sourceRoot":"","sources":["../../../src/engines/navigation-api-engine.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,OAAO;IACzD;;OAEG;IACH,OAAO,CAAC,UAAU,CAAa;IAE/B;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAsB;IAEhD;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAyB;IAEnD;;;;OAIG;;IAwBH;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,UAAU;IA2BhD;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,WAAW;IAgSnD;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,GAAG,IAAI;IAkCtC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,GAAG,IAAI;CAwE3C"}
1
+ {"version":3,"file":"navigation-api-engine.d.ts","sourceRoot":"","sources":["../../../src/engines/navigation-api-engine.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,mBAAoB,YAAW,OAAO;IACzD;;OAEG;IACH,OAAO,CAAC,UAAU,CAAa;IAE/B;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAsB;IAEhD;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAyB;IAEnD;;;;OAIG;;IAwBH;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,UAAU;IA2BhD;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,GAAG,OAAO,CAAC,WAAW;IAgSnD;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,GAAG,IAAI;IAkCtC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,GAAG,IAAI;CAgE3C"}
@@ -356,28 +356,21 @@ export default class NavigationApiEngine {
356
356
  case "LINK": {
357
357
  const { to, history } = args;
358
358
  switch (to.type) {
359
- case "PATH": {
359
+ case "STATIC": {
360
360
  // 完全なパス文字列の余分なスラッシュなどをエンコードして直接遷移します。
361
361
  const path = RoutePath.encode(to.path);
362
362
  this.navigation.navigate(path, { history });
363
363
  break;
364
364
  }
365
- case "PARTIAL": {
366
- // 現在のロケーション情報をベースに、指定されたパーツ(パス名、クエリー、ハッシュのみなど)を部分的にパッチ(上書き)したマージ URL を算出します。
365
+ case "DYNAMIC": {
366
+ // 現在のロケーション情報をベースに、指定されたパーツ(パス名、クエリー、ハッシュのみなど)を部分的に上書きしたマージ URL を算出します。
367
367
  const currentPath = new RoutePath(window.location);
368
- const nextPath = new RoutePath(window.location);
369
- if (typeof to.pathname === "string") {
370
- nextPath.pathname = to.pathname;
371
- }
372
- if (typeof to.search === "string") {
373
- nextPath.search = to.search;
374
- }
375
- if (typeof to.hash === "string") {
376
- nextPath.hash = to.hash;
377
- }
368
+ const currentPathString = currentPath.toString();
369
+ const nextPath = currentPath;
370
+ to.patch(nextPath);
378
371
  const nextPathString = nextPath.toString();
379
372
  // 無駄な遷移履歴を作らないように、URL に実際の変化がある場合のみ navigate を実行します。
380
- if (nextPathString !== currentPath.toString()) {
373
+ if (nextPathString !== currentPathString) {
381
374
  this.navigation.navigate(nextPathString, { history });
382
375
  }
383
376
  break;
@@ -1,3 +1,4 @@
1
+ import type { RoutePath } from "../core.js";
1
2
  /**
2
3
  * 遷移先のアドレスを指定するための表現型です。
3
4
  *
@@ -16,6 +17,13 @@ export type NavigateTo = string | {
16
17
  * 遷移先に付与するハッシュフラグメント(例: `"#profile"`)です。
17
18
  */
18
19
  readonly hash?: string | undefined;
20
+ } | {
21
+ /**
22
+ * 動的にパッチを適用します。
23
+ *
24
+ * @param path アプリケーション内のルーティングにおけるパスを安全に構築・解析・操作するためのオブジェクトです。
25
+ */
26
+ (route: RoutePath): void;
19
27
  };
20
28
  /**
21
29
  * 画面遷移の挙動をカスタマイズするためのオプション型です。
@@ -1 +1 @@
1
- {"version":3,"file":"use-navigate.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-navigate.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAClB,MAAM,GACN;IACE;;OAEG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEvC;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAErC;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC,CAAC;AAEN;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACxC,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAElD;;;;OAIG;IACH,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,IAAI,gBAAgB,CAwCtD"}
1
+ {"version":3,"file":"use-navigate.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-navigate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG5C;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAClB,MAAM,GACN;IACE;;OAEG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEvC;;OAEG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAErC;;OAEG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC,GACD;IACE;;;;OAIG;IACH,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEN;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACxC,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAElD;;;;OAIG;IACH,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,WAAW,IAAI,gBAAgB,CA6DtD"}
@@ -23,7 +23,27 @@ export default function useNavigate() {
23
23
  return routerNavigate({
24
24
  to: {
25
25
  path: to,
26
- type: "PATH",
26
+ type: "STATIC",
27
+ },
28
+ type: "LINK",
29
+ history,
30
+ });
31
+ }
32
+ else if (typeof to === "object") {
33
+ return routerNavigate({
34
+ to: {
35
+ type: "DYNAMIC",
36
+ patch(path) {
37
+ if (typeof to.pathname === "string") {
38
+ path.pathname = to.pathname;
39
+ }
40
+ if (typeof to.search === "string") {
41
+ path.search = to.search;
42
+ }
43
+ if (typeof to.hash === "string") {
44
+ path.hash = to.hash;
45
+ }
46
+ },
27
47
  },
28
48
  type: "LINK",
29
49
  history,
@@ -32,8 +52,10 @@ export default function useNavigate() {
32
52
  else {
33
53
  return routerNavigate({
34
54
  to: {
35
- ...to,
36
- type: "PARTIAL",
55
+ type: "DYNAMIC",
56
+ patch(path) {
57
+ to(path);
58
+ },
37
59
  },
38
60
  type: "LINK",
39
61
  history,
@@ -0,0 +1,3 @@
1
+ import { type ReadonlyRoutePath } from "../core/route-path.js";
2
+ export default function useRoutePath(): ReadonlyRoutePath;
3
+ //# sourceMappingURL=use-route-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-route-path.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-route-path.ts"],"names":[],"mappings":"AAEA,OAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG1E,MAAM,CAAC,OAAO,UAAU,YAAY,IAAI,iBAAiB,CAKxD"}
@@ -0,0 +1,8 @@
1
+ import * as React from "react";
2
+ import RoutePath from "../core/route-path.js";
3
+ import useRouterContext from "./use-router-context.js";
4
+ export default function useRoutePath() {
5
+ const url = useRouterContext((router) => router.currentEntry.url);
6
+ const path = React.useMemo(() => new RoutePath(url), [url]);
7
+ return path;
8
+ }
@@ -23,6 +23,8 @@ export type * from "./hooks/use-navigate.js";
23
23
  export { default as useNavigate } from "./hooks/use-navigate.js";
24
24
  export type * from "./hooks/use-params.js";
25
25
  export { default as useParams } from "./hooks/use-params.js";
26
+ export type * from "./hooks/use-route-path.js";
27
+ export { default as useRoutePath } from "./hooks/use-route-path.js";
26
28
  export type * from "./hooks/use-submit.js";
27
29
  export { default as useSubmit } from "./hooks/use-submit.js";
28
30
  /**************************************************************************************************/
@@ -1 +1 @@
1
- {"version":3,"file":"soseki.d.ts","sourceRoot":"","sources":["../../src/soseki.ts"],"names":[],"mappings":"AAAA,mBAAmB,iCAAiC,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAE3E,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAE5D,oGAAoG;AAEpG,YAAY,EACV,KAAK,EACL,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,2BAA2B,EAC3B,2BAA2B,EAC3B,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,kBAAkB,CAAC;AAE1B,mBAAmB,oCAAoC,CAAC;AAExD,mBAAmB,8BAA8B,CAAC;AAElD,mBAAmB,6BAA6B,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE1E,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAElE,mBAAmB,uBAAuB,CAAC;AAE3C,oGAAoG;AAEpG,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEjE,mBAAmB,uBAAuB,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE7D,mBAAmB,uBAAuB,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE7D,oGAAoG;AAEpG,mBAAmB,qBAAqB,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"soseki.d.ts","sourceRoot":"","sources":["../../src/soseki.ts"],"names":[],"mappings":"AAAA,mBAAmB,iCAAiC,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAE3E,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAE5D,oGAAoG;AAEpG,YAAY,EACV,KAAK,EACL,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,2BAA2B,EAC3B,2BAA2B,EAC3B,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,kBAAkB,CAAC;AAE1B,mBAAmB,oCAAoC,CAAC;AAExD,mBAAmB,8BAA8B,CAAC;AAElD,mBAAmB,6BAA6B,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE1E,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAElE,mBAAmB,uBAAuB,CAAC;AAE3C,oGAAoG;AAEpG,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,4BAA4B,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEtE,mBAAmB,yBAAyB,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEjE,mBAAmB,uBAAuB,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE7D,mBAAmB,2BAA2B,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEpE,mBAAmB,uBAAuB,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE7D,oGAAoG;AAEpG,mBAAmB,qBAAqB,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC"}
@@ -8,5 +8,6 @@ export { default as useFormAction } from "./hooks/use-form-action.js";
8
8
  export { default as useLoaderData } from "./hooks/use-loader-data.js";
9
9
  export { default as useNavigate } from "./hooks/use-navigate.js";
10
10
  export { default as useParams } from "./hooks/use-params.js";
11
+ export { default as useRoutePath } from "./hooks/use-route-path.js";
11
12
  export { default as useSubmit } from "./hooks/use-submit.js";
12
13
  export { default as redirect } from "./utils/redirect.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "soseki",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "",
5
5
  "homepage": "https://github.com/tai-kun/soseki.js",
6
6
  "license": "MIT",
@@ -1,7 +1,6 @@
1
- import type { RouteDefinition } from "../core/route.types.js";
2
1
  import NavigationApiEngine from "../engines/navigation-api-engine.js";
3
2
  import useSingleton from "../hooks/_use-singleton.js";
4
- import Router from "./router.jsx";
3
+ import Router, { type RouterRouteDefinition } from "./router.jsx";
5
4
 
6
5
  /**
7
6
  * `BrowserRouter` コンポーネントに引き渡すプロパティーの型定義です。
@@ -10,7 +9,7 @@ export type BrowserRouterProps = {
10
9
  /**
11
10
  * アプリケーション全体の画面構造を定義したルート定義の配列です。
12
11
  */
13
- routes: readonly RouteDefinition[];
12
+ routes: readonly RouterRouteDefinition[];
14
13
  };
15
14
 
16
15
  /**
@@ -10,7 +10,7 @@ import processRoutes from "../core/_process-routes.js";
10
10
  import type { HistoryEntry } from "../core/expect-history-entry.js";
11
11
  import type { HistoryEntryId } from "../core/history-entry-id-schema.js";
12
12
  import type { MatchedRoute } from "../core/match-routes.js";
13
- import type { ActionFunction, LoaderFunction, RouteDefinition } from "../core/route.types.js";
13
+ import type { ActionFunction, LoaderFunction } from "../core/route.types.js";
14
14
  import type { IEngine, RouterState } from "../engines/engine.types.js";
15
15
 
16
16
  /**
@@ -77,6 +77,28 @@ function RouteRenderer(props: RouteRendererProps): React.ReactElement {
77
77
  return <ComponentRenderer route={route} outlet={outlet} />;
78
78
  }
79
79
 
80
+ export type RouterRouteDefinitionObject = {
81
+ readonly path: string;
82
+ readonly index?: boolean | undefined;
83
+ readonly action?: { (args: any): unknown } | undefined;
84
+ readonly shouldReload?: { (args: any): boolean } | undefined;
85
+ readonly loader?: { (args: any): unknown } | undefined;
86
+ readonly component?: React.ComponentType<{}> | undefined;
87
+ };
88
+
89
+ export type RouterRouteDefinitionModule = {
90
+ readonly path: string;
91
+ readonly index?: boolean | undefined;
92
+ readonly action?: { (args: any): unknown } | undefined;
93
+ readonly shouldReload?: { (args: any): boolean } | undefined;
94
+ readonly loader?: { (args: any): unknown } | undefined;
95
+ readonly component?: React.ComponentType<{}> | undefined;
96
+ readonly default?: React.ComponentType<{}> | undefined;
97
+ get [Symbol.toStringTag](): string;
98
+ };
99
+
100
+ export type RouterRouteDefinition = RouterRouteDefinitionObject | RouterRouteDefinitionModule;
101
+
80
102
  /**
81
103
  * `Router` コンポーネントに渡されるルートプロパティーの型定義です。
82
104
  */
@@ -89,7 +111,7 @@ export type RouterProps = {
89
111
  /**
90
112
  * ユーザーがアプリケーションに定義したルート定義の配列です。
91
113
  */
92
- routes: readonly RouteDefinition[];
114
+ routes: readonly RouterRouteDefinition[];
93
115
  };
94
116
 
95
117
  /**
@@ -1,4 +1,4 @@
1
- import type { ReadonlyURL } from "./readonly-url.types.js";
1
+ import type { ReadonlyURL, ReadonlyURLSearchParams } from "./readonly-url.types.js";
2
2
 
3
3
  /**
4
4
  * 連続する複数のスラッシュを検出するための正規表現です。
@@ -10,7 +10,50 @@ const MULTI_SLASH = /\/\/+/gu;
10
10
  *
11
11
  * 内包するホストやプロトコルといった余分な情報を排除し、パス、クエリー、ハッシュのみを一貫した規則で管理します。
12
12
  */
13
- export default class RoutePath {
13
+ export interface ReadonlyRoutePath {
14
+ /**
15
+ * 正規化されたパス部分の文字列です。
16
+ */
17
+ readonly pathname: string;
18
+
19
+ /**
20
+ * 先頭に `?` を含むクエリー文字列です。
21
+ *
22
+ * 常にソートされます。
23
+ */
24
+ readonly search: string;
25
+
26
+ /**
27
+ * 内部の `URL` インスタンスが保持する、クエリーパラメーターを操作するための `URLSearchParams` オブジェクトを取得します。
28
+ */
29
+ readonly searchParams: ReadonlyURLSearchParams;
30
+
31
+ /**
32
+ * 先頭に `#` を含むハッシュ文字列を取得します。
33
+ */
34
+ readonly hash: string;
35
+
36
+ /**
37
+ * 現在保持しているすべてのコンポーネントを結合し、ルーティング用のパス文字列として出力します。
38
+ *
39
+ * @returns ソート済みのクエリーおよびハッシュを含んだ、正規化されたパス全体の文字列を返します。
40
+ */
41
+ toString(): string;
42
+
43
+ /**
44
+ * このインスタンスを複製し、上書き可能な形式で取得します。
45
+ *
46
+ * @returns 上書き可能な {@link RoutePath|`RoutePath`} インスタンスです。
47
+ */
48
+ clone(): RoutePath;
49
+ }
50
+
51
+ /**
52
+ * アプリケーション内のルーティングにおけるパスを安全に構築・解析・操作するためのクラスです。
53
+ *
54
+ * 内包するホストやプロトコルといった余分な情報を排除し、パス、クエリー、ハッシュのみを一貫した規則で管理します。
55
+ */
56
+ export default class RoutePath implements ReadonlyRoutePath {
14
57
  /**
15
58
  * 与えられた文字列または URL オブジェクトから、正規化されたパス文字列を即座に生成する静的メソッドです。
16
59
  *
@@ -26,7 +69,7 @@ export default class RoutePath {
26
69
  *
27
70
  * 基底となる仮想的なオリジンと結合して管理されます。
28
71
  */
29
- private url: URL;
72
+ readonly #url: URL;
30
73
 
31
74
  /**
32
75
  * 新しい `RoutePath` インスタンスを初期化します。
@@ -44,12 +87,12 @@ export default class RoutePath {
44
87
  }
45
88
 
46
89
  // 組み込みの URL クラスによる厳密な解析機能を利用するため、仮想のプロトコルとホストを前置きして初期化します。
47
- this.url = new URL("x://y" + path);
90
+ this.#url = new URL("x://y" + path);
48
91
 
49
92
  // ルートパス(/)単体である場合を除き、末尾に存在する不要なスラッシュを削除して一貫性を保ちます。
50
- const { pathname } = this.url;
93
+ const { pathname } = this.#url;
51
94
  if (pathname !== "/" && pathname.endsWith("/")) {
52
- this.url.pathname = pathname.substring(0, pathname.length - 1);
95
+ this.#url.pathname = pathname.substring(0, pathname.length - 1);
53
96
  }
54
97
  }
55
98
 
@@ -57,16 +100,16 @@ export default class RoutePath {
57
100
  * 正規化されたパス部分の文字列です。
58
101
  */
59
102
  public get pathname(): string {
60
- return this.url.pathname;
103
+ return this.#url.pathname;
61
104
  }
62
105
 
63
106
  public set pathname(value: string) {
64
- this.url.pathname = value;
107
+ this.#url.pathname = value;
65
108
 
66
109
  // ルートパス(/)単体である場合を除き、末尾に存在する不要なスラッシュを削除して一貫性を保ちます。
67
- const pathname = ("/" + this.url.pathname).replace(MULTI_SLASH, "/");
110
+ const pathname = ("/" + this.#url.pathname).replace(MULTI_SLASH, "/");
68
111
  if (pathname !== "/" && pathname.endsWith("/")) {
69
- this.url.pathname = pathname.substring(0, pathname.length - 1);
112
+ this.#url.pathname = pathname.substring(0, pathname.length - 1);
70
113
  }
71
114
  }
72
115
 
@@ -76,30 +119,30 @@ export default class RoutePath {
76
119
  * 常にソートされます。
77
120
  */
78
121
  public get search(): string {
79
- this.url.searchParams.sort();
80
- return this.url.search;
122
+ this.#url.searchParams.sort();
123
+ return this.#url.search;
81
124
  }
82
125
 
83
126
  public set search(value: string) {
84
- this.url.search = value;
127
+ this.#url.search = value;
85
128
  }
86
129
 
87
130
  /**
88
131
  * 内部の `URL` インスタンスが保持する、クエリーパラメーターを操作するための `URLSearchParams` オブジェクトを取得します。
89
132
  */
90
133
  public get searchParams(): URLSearchParams {
91
- return this.url.searchParams;
134
+ return this.#url.searchParams;
92
135
  }
93
136
 
94
137
  /**
95
138
  * 先頭に `#` を含むハッシュ文字列を取得します。
96
139
  */
97
140
  public get hash(): string {
98
- return this.url.hash;
141
+ return this.#url.hash;
99
142
  }
100
143
 
101
144
  public set hash(value: string) {
102
- this.url.hash = value;
145
+ this.#url.hash = value;
103
146
  }
104
147
 
105
148
  /**
@@ -111,4 +154,13 @@ export default class RoutePath {
111
154
  const { hash, search, pathname } = this;
112
155
  return pathname + search + hash;
113
156
  }
157
+
158
+ /**
159
+ * このインスタンスを複製し、上書き可能な形式で取得します。
160
+ *
161
+ * @returns 上書き可能な {@link RoutePath|`RoutePath`} インスタンスです。
162
+ */
163
+ public clone(): RoutePath {
164
+ return new RoutePath(this.toString());
165
+ }
114
166
  }
package/src/core.ts CHANGED
@@ -34,3 +34,11 @@ export { default as startAction } from "./core/start-action.js";
34
34
 
35
35
  export type * from "./core/start-loaders.js";
36
36
  export { default as startLoaders } from "./core/start-loaders.js";
37
+
38
+ /**************************************************************************************************/
39
+
40
+ export type * from "./hooks/use-route-context.js";
41
+ export { default as useRouteContext } from "./hooks/use-route-context.js";
42
+
43
+ export type * from "./hooks/use-router-context.js";
44
+ export { default as useRouterContext } from "./hooks/use-router-context.js";
@@ -1,5 +1,6 @@
1
1
  import type { NinjaPromise } from "ninja-promise";
2
2
 
3
+ import type { RoutePath } from "../core.js";
3
4
  import type { HistoryEntry } from "../core/expect-history-entry.js";
4
5
  import type { HistoryEntryId } from "../core/history-entry-id-schema.js";
5
6
  import type { MatchedRoute } from "../core/match-routes.js";
@@ -178,7 +179,7 @@ export namespace IEngine {
178
179
  /**
179
180
  * URL パスで前方移動する形式です。
180
181
  */
181
- type: "PATH";
182
+ type: "STATIC";
182
183
 
183
184
  /**
184
185
  * URL パスです。
@@ -187,24 +188,16 @@ export namespace IEngine {
187
188
  }
188
189
  | {
189
190
  /**
190
- * URL の各コンポーネントを個別に指定する形式です。
191
+ * URL の各コンポーネントを関数形式で個別に指定する形式です。
191
192
  */
192
- type: "PARTIAL";
193
+ type: "DYNAMIC";
193
194
 
194
195
  /**
195
- * 最初のスラッシュ `/` から始まる URL のパス部分です。
196
+ * 動的にパッチを適用する関数です。
197
+ *
198
+ * @param path アプリケーション内のルーティングにおけるパスを安全に構築・解析・操作するためのオブジェクトです。
196
199
  */
197
- pathname?: string | undefined;
198
-
199
- /**
200
- * 先頭のクエスチョンマーク `?` を含む URL のクエリー文字列です。
201
- */
202
- search?: string | undefined;
203
-
204
- /**
205
- * URL のハッシュ(シャープ記号 `#` を含むフラグメント識別子)です。
206
- */
207
- hash?: string | undefined;
200
+ patch(path: RoutePath): void;
208
201
  };
209
202
 
210
203
  /**
@@ -435,7 +435,7 @@ export default class NavigationApiEngine implements IEngine {
435
435
  case "LINK": {
436
436
  const { to, history } = args;
437
437
  switch (to.type) {
438
- case "PATH": {
438
+ case "STATIC": {
439
439
  // 完全なパス文字列の余分なスラッシュなどをエンコードして直接遷移します。
440
440
 
441
441
  const path = RoutePath.encode(to.path);
@@ -444,25 +444,17 @@ export default class NavigationApiEngine implements IEngine {
444
444
  break;
445
445
  }
446
446
 
447
- case "PARTIAL": {
448
- // 現在のロケーション情報をベースに、指定されたパーツ(パス名、クエリー、ハッシュのみなど)を部分的にパッチ(上書き)したマージ URL を算出します。
447
+ case "DYNAMIC": {
448
+ // 現在のロケーション情報をベースに、指定されたパーツ(パス名、クエリー、ハッシュのみなど)を部分的に上書きしたマージ URL を算出します。
449
449
 
450
450
  const currentPath = new RoutePath(window.location);
451
- const nextPath = new RoutePath(window.location);
452
- if (typeof to.pathname === "string") {
453
- nextPath.pathname = to.pathname;
454
- }
455
- if (typeof to.search === "string") {
456
- nextPath.search = to.search;
457
- }
458
- if (typeof to.hash === "string") {
459
- nextPath.hash = to.hash;
460
- }
461
-
451
+ const currentPathString = currentPath.toString();
452
+ const nextPath = currentPath;
453
+ to.patch(nextPath);
462
454
  const nextPathString = nextPath.toString();
463
455
 
464
456
  // 無駄な遷移履歴を作らないように、URL に実際の変化がある場合のみ navigate を実行します。
465
- if (nextPathString !== currentPath.toString()) {
457
+ if (nextPathString !== currentPathString) {
466
458
  this.navigation.navigate(nextPathString, { history });
467
459
  }
468
460
 
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
 
3
- import type {} from "../engines/engine.types.js";
3
+ import type { RoutePath } from "../core.js";
4
4
  import useRouterContext from "./use-router-context.js";
5
5
 
6
6
  /**
@@ -25,6 +25,14 @@ export type NavigateTo =
25
25
  * 遷移先に付与するハッシュフラグメント(例: `"#profile"`)です。
26
26
  */
27
27
  readonly hash?: string | undefined;
28
+ }
29
+ | {
30
+ /**
31
+ * 動的にパッチを適用します。
32
+ *
33
+ * @param path アプリケーション内のルーティングにおけるパスを安全に構築・解析・操作するためのオブジェクトです。
34
+ */
35
+ (route: RoutePath): void;
28
36
  };
29
37
 
30
38
  /**
@@ -84,7 +92,26 @@ export default function useNavigate(): NavigateFunction {
84
92
  return routerNavigate({
85
93
  to: {
86
94
  path: to,
87
- type: "PATH",
95
+ type: "STATIC",
96
+ },
97
+ type: "LINK",
98
+ history,
99
+ });
100
+ } else if (typeof to === "object") {
101
+ return routerNavigate({
102
+ to: {
103
+ type: "DYNAMIC",
104
+ patch(path) {
105
+ if (typeof to.pathname === "string") {
106
+ path.pathname = to.pathname;
107
+ }
108
+ if (typeof to.search === "string") {
109
+ path.search = to.search;
110
+ }
111
+ if (typeof to.hash === "string") {
112
+ path.hash = to.hash;
113
+ }
114
+ },
88
115
  },
89
116
  type: "LINK",
90
117
  history,
@@ -92,8 +119,10 @@ export default function useNavigate(): NavigateFunction {
92
119
  } else {
93
120
  return routerNavigate({
94
121
  to: {
95
- ...to,
96
- type: "PARTIAL",
122
+ type: "DYNAMIC",
123
+ patch(path) {
124
+ to(path);
125
+ },
97
126
  },
98
127
  type: "LINK",
99
128
  history,
@@ -0,0 +1,11 @@
1
+ import * as React from "react";
2
+
3
+ import RoutePath, { type ReadonlyRoutePath } from "../core/route-path.js";
4
+ import useRouterContext from "./use-router-context.js";
5
+
6
+ export default function useRoutePath(): ReadonlyRoutePath {
7
+ const url = useRouterContext((router) => router.currentEntry.url);
8
+ const path = React.useMemo(() => new RoutePath(url), [url]);
9
+
10
+ return path;
11
+ }
package/src/soseki.ts CHANGED
@@ -59,6 +59,9 @@ export { default as useNavigate } from "./hooks/use-navigate.js";
59
59
  export type * from "./hooks/use-params.js";
60
60
  export { default as useParams } from "./hooks/use-params.js";
61
61
 
62
+ export type * from "./hooks/use-route-path.js";
63
+ export { default as useRoutePath } from "./hooks/use-route-path.js";
64
+
62
65
  export type * from "./hooks/use-submit.js";
63
66
  export { default as useSubmit } from "./hooks/use-submit.js";
64
67