soseki 0.0.5 → 0.0.6
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/LICENSE +21 -0
- package/dist/src/components/browser-router.d.ts +19 -0
- package/dist/src/components/browser-router.d.ts.map +1 -0
- package/dist/src/components/browser-router.jsx +15 -0
- package/dist/src/components/outlet.d.ts +8 -0
- package/dist/src/components/outlet.d.ts.map +1 -0
- package/dist/src/components/outlet.jsx +15 -0
- package/dist/src/components/router.d.ts +21 -0
- package/dist/src/components/router.d.ts.map +1 -0
- package/dist/src/components/router.jsx +138 -0
- package/dist/src/contexts/route-context.d.ts +19 -0
- package/dist/src/contexts/route-context.d.ts.map +1 -0
- package/dist/src/contexts/route-context.js +6 -0
- package/dist/src/contexts/router-context.d.ts +55 -0
- package/dist/src/contexts/router-context.d.ts.map +1 -0
- package/dist/src/contexts/router-context.js +8 -0
- package/dist/src/core/_compare-route-paths.d.ts +11 -0
- package/dist/src/core/_compare-route-paths.d.ts.map +1 -0
- package/dist/src/core/_compare-route-paths.js +92 -0
- package/dist/src/core/_match-route-path.d.ts +22 -0
- package/dist/src/core/_match-route-path.d.ts.map +1 -0
- package/dist/src/core/_match-route-path.js +26 -0
- package/dist/src/core/_process-routes.d.ts +14 -0
- package/dist/src/core/_process-routes.d.ts.map +1 -0
- package/dist/src/core/_process-routes.js +45 -0
- package/dist/src/core/_singleton.d.ts +12 -0
- package/dist/src/core/_singleton.d.ts.map +1 -0
- package/dist/src/core/_singleton.js +18 -0
- package/dist/src/core/_unreachable.d.ts +16 -0
- package/dist/src/core/_unreachable.d.ts.map +1 -0
- package/dist/src/core/_unreachable.js +8 -0
- package/dist/src/core/_valibot.d.ts +25 -0
- package/dist/src/core/_valibot.d.ts.map +1 -0
- package/dist/src/core/_valibot.js +30 -0
- package/dist/src/core/errors.d.ts +182 -0
- package/dist/src/core/errors.d.ts.map +1 -0
- package/dist/src/core/errors.js +166 -0
- package/dist/src/core/expect-history-entry.d.ts +59 -0
- package/dist/src/core/expect-history-entry.d.ts.map +1 -0
- package/dist/src/core/expect-history-entry.js +42 -0
- package/dist/src/core/form-data-to-html-form-element.d.ts +11 -0
- package/dist/src/core/form-data-to-html-form-element.d.ts.map +1 -0
- package/dist/src/core/form-data-to-html-form-element.js +31 -0
- package/dist/src/core/history-entry-id-schema.d.ts +17 -0
- package/dist/src/core/history-entry-id-schema.d.ts.map +1 -0
- package/dist/src/core/history-entry-id-schema.js +9 -0
- package/dist/src/core/history-entry-url-schema.d.ts +18 -0
- package/dist/src/core/history-entry-url-schema.d.ts.map +1 -0
- package/dist/src/core/history-entry-url-schema.js +20 -0
- package/dist/src/core/init-loaders.d.ts +28 -0
- package/dist/src/core/init-loaders.d.ts.map +1 -0
- package/dist/src/core/init-loaders.js +30 -0
- package/dist/src/core/match-routes.d.ts +28 -0
- package/dist/src/core/match-routes.d.ts.map +1 -0
- package/dist/src/core/match-routes.js +31 -0
- package/dist/src/core/readonly-form-data.types.d.ts +74 -0
- package/dist/src/core/readonly-form-data.types.d.ts.map +1 -0
- package/dist/src/core/readonly-url.types.d.ts +164 -0
- package/dist/src/core/readonly-url.types.d.ts.map +1 -0
- package/dist/src/core/redirect-response.d.ts +37 -0
- package/dist/src/core/redirect-response.d.ts.map +1 -0
- package/dist/src/core/redirect-response.js +19 -0
- package/dist/src/core/route-path.d.ts +57 -0
- package/dist/src/core/route-path.d.ts.map +1 -0
- package/dist/src/core/route-path.js +93 -0
- package/dist/src/core/route-request.d.ts +149 -0
- package/dist/src/core/route-request.d.ts.map +1 -0
- package/dist/src/core/route-request.js +41 -0
- package/dist/src/core/route.types.d.ts +296 -0
- package/dist/src/core/route.types.d.ts.map +1 -0
- package/dist/src/core/start-action.d.ts +53 -0
- package/dist/src/core/start-action.d.ts.map +1 -0
- package/dist/src/core/start-action.js +95 -0
- package/dist/src/core/start-loaders.d.ts +63 -0
- package/dist/src/core/start-loaders.d.ts.map +1 -0
- package/dist/src/core/start-loaders.js +138 -0
- package/dist/{core.d.ts → src/core.d.ts} +7 -11
- package/dist/src/core.d.ts.map +1 -0
- package/dist/{core.js → src/core.js} +2 -4
- package/dist/src/engines/engine.types.d.ts +216 -0
- package/dist/src/engines/engine.types.d.ts.map +1 -0
- package/dist/src/engines/navigation-api-engine.d.ts +50 -0
- package/dist/src/engines/navigation-api-engine.d.ts.map +1 -0
- package/dist/src/engines/navigation-api-engine.js +411 -0
- package/dist/src/engines.d.ts +4 -0
- package/dist/src/engines.d.ts.map +1 -0
- package/dist/src/engines.js +1 -0
- package/dist/src/hooks/_use-singleton.d.ts +11 -0
- package/dist/src/hooks/_use-singleton.d.ts.map +1 -0
- package/dist/src/hooks/_use-singleton.js +26 -0
- package/dist/src/hooks/use-action-data.d.ts +17 -0
- package/dist/src/hooks/use-action-data.d.ts.map +1 -0
- package/dist/src/hooks/use-action-data.js +16 -0
- package/dist/src/hooks/use-form-action.d.ts +7 -0
- package/dist/src/hooks/use-form-action.d.ts.map +1 -0
- package/dist/src/hooks/use-form-action.js +9 -0
- package/dist/src/hooks/use-loader-data.d.ts +9 -0
- package/dist/src/hooks/use-loader-data.d.ts.map +1 -0
- package/dist/src/hooks/use-loader-data.js +20 -0
- package/dist/src/hooks/use-navigate.d.ts +53 -0
- package/dist/src/hooks/use-navigate.d.ts.map +1 -0
- package/dist/src/hooks/use-navigate.js +43 -0
- package/dist/{hooks → src/hooks}/use-params.d.ts +2 -2
- package/dist/src/hooks/use-params.d.ts.map +1 -0
- package/dist/{hooks → src/hooks}/use-params.js +1 -1
- package/dist/src/hooks/use-route-context.d.ts +10 -0
- package/dist/src/hooks/use-route-context.d.ts.map +1 -0
- package/dist/src/hooks/use-route-context.js +17 -0
- package/dist/src/hooks/use-router-context.d.ts +12 -0
- package/dist/src/hooks/use-router-context.d.ts.map +1 -0
- package/dist/src/hooks/use-router-context.js +20 -0
- package/dist/src/hooks/use-submit.d.ts +59 -0
- package/dist/src/hooks/use-submit.d.ts.map +1 -0
- package/dist/src/hooks/use-submit.js +38 -0
- package/dist/src/soseki.d.ts +31 -0
- package/dist/src/soseki.d.ts.map +1 -0
- package/dist/src/soseki.js +12 -0
- package/dist/src/utils/redirect.d.ts +11 -0
- package/dist/src/utils/redirect.d.ts.map +1 -0
- package/dist/src/utils/redirect.js +12 -0
- package/package.json +47 -40
- package/src/components/browser-router.tsx +8 -11
- package/src/components/outlet.tsx +3 -2
- package/src/components/router.tsx +139 -145
- package/src/contexts/route-context.ts +6 -5
- package/src/contexts/router-context.ts +36 -19
- package/src/core/_compare-route-paths.ts +48 -34
- package/src/core/_match-route-path.ts +21 -15
- package/src/core/_process-routes.ts +44 -46
- package/src/core/_singleton.ts +13 -38
- package/src/core/_unreachable.ts +12 -7
- package/src/core/_valibot.ts +19 -116
- package/src/core/errors.ts +150 -495
- package/src/core/expect-history-entry.ts +40 -41
- package/src/core/form-data-to-html-form-element.ts +37 -0
- package/src/core/history-entry-id-schema.ts +6 -11
- package/src/core/history-entry-url-schema.ts +25 -18
- package/src/core/init-loaders.ts +35 -57
- package/src/core/match-routes.ts +33 -65
- package/src/core/readonly-form-data.types.ts +48 -28
- package/src/core/readonly-url.types.ts +57 -28
- package/src/core/redirect-response.ts +26 -15
- package/src/core/route-path.ts +114 -0
- package/src/core/route-request.ts +144 -32
- package/src/core/route.types.ts +250 -226
- package/src/core/start-action.ts +164 -0
- package/src/core/start-loaders.ts +190 -212
- package/src/core.ts +8 -15
- package/src/engines/engine.types.ts +204 -166
- package/src/engines/navigation-api-engine.ts +332 -233
- package/src/engines.ts +4 -0
- package/src/hooks/_use-singleton.ts +30 -0
- package/src/hooks/use-action-data.ts +21 -26
- package/src/hooks/use-form-action.ts +4 -5
- package/src/hooks/use-loader-data.ts +16 -18
- package/src/hooks/use-navigate.ts +69 -28
- package/src/hooks/use-params.ts +4 -4
- package/src/hooks/use-route-context.ts +20 -0
- package/src/hooks/use-router-context.ts +25 -0
- package/src/hooks/use-submit.ts +48 -53
- package/src/soseki.ts +27 -34
- package/src/utils/redirect.ts +5 -5
- package/dist/components/action-id.d.ts +0 -19
- package/dist/components/action-id.d.ts.map +0 -1
- package/dist/components/action-id.jsx +0 -14
- package/dist/components/browser-router.d.ts +0 -17
- package/dist/components/browser-router.d.ts.map +0 -1
- package/dist/components/browser-router.jsx +0 -13
- package/dist/components/hidden-input.d.ts +0 -20
- package/dist/components/hidden-input.d.ts.map +0 -1
- package/dist/components/hidden-input.jsx +0 -8
- package/dist/components/outlet.d.ts +0 -8
- package/dist/components/outlet.d.ts.map +0 -1
- package/dist/components/outlet.jsx +0 -15
- package/dist/components/router.d.ts +0 -23
- package/dist/components/router.d.ts.map +0 -1
- package/dist/components/router.jsx +0 -128
- package/dist/contexts/route-context.d.ts +0 -19
- package/dist/contexts/route-context.d.ts.map +0 -1
- package/dist/contexts/route-context.js +0 -6
- package/dist/contexts/router-context.d.ts +0 -46
- package/dist/contexts/router-context.d.ts.map +0 -1
- package/dist/contexts/router-context.js +0 -8
- package/dist/core/_action-id-registry.d.ts +0 -10
- package/dist/core/_action-id-registry.d.ts.map +0 -1
- package/dist/core/_action-id-registry.js +0 -8
- package/dist/core/_capture-stack-trace.d.ts +0 -8
- package/dist/core/_capture-stack-trace.d.ts.map +0 -1
- package/dist/core/_capture-stack-trace.js +0 -12
- package/dist/core/_compare-route-paths.d.ts +0 -11
- package/dist/core/_compare-route-paths.d.ts.map +0 -1
- package/dist/core/_compare-route-paths.js +0 -80
- package/dist/core/_create-html-form-element-form-form-data.d.ts +0 -9
- package/dist/core/_create-html-form-element-form-form-data.d.ts.map +0 -1
- package/dist/core/_create-html-form-element-form-form-data.js +0 -27
- package/dist/core/_encode-pathname.d.ts +0 -10
- package/dist/core/_encode-pathname.d.ts.map +0 -1
- package/dist/core/_encode-pathname.js +0 -16
- package/dist/core/_is-error.d.ts +0 -3
- package/dist/core/_is-error.d.ts.map +0 -1
- package/dist/core/_is-error.js +0 -13
- package/dist/core/_is-promise-like.d.ts +0 -8
- package/dist/core/_is-promise-like.d.ts.map +0 -1
- package/dist/core/_is-promise-like.js +0 -12
- package/dist/core/_match-route-path.d.ts +0 -19
- package/dist/core/_match-route-path.d.ts.map +0 -1
- package/dist/core/_match-route-path.js +0 -22
- package/dist/core/_process-routes.d.ts +0 -9
- package/dist/core/_process-routes.d.ts.map +0 -1
- package/dist/core/_process-routes.js +0 -47
- package/dist/core/_singleton.d.ts +0 -18
- package/dist/core/_singleton.d.ts.map +0 -1
- package/dist/core/_singleton.js +0 -37
- package/dist/core/_unreachable.d.ts +0 -12
- package/dist/core/_unreachable.d.ts.map +0 -1
- package/dist/core/_unreachable.js +0 -8
- package/dist/core/_use-singleton.d.ts +0 -11
- package/dist/core/_use-singleton.d.ts.map +0 -1
- package/dist/core/_use-singleton.js +0 -21
- package/dist/core/_valibot.d.ts +0 -52
- package/dist/core/_valibot.d.ts.map +0 -1
- package/dist/core/_valibot.js +0 -107
- package/dist/core/_weak-id-registry.d.ts +0 -76
- package/dist/core/_weak-id-registry.d.ts.map +0 -1
- package/dist/core/_weak-id-registry.js +0 -67
- package/dist/core/constants.d.ts +0 -5
- package/dist/core/constants.d.ts.map +0 -1
- package/dist/core/constants.js +0 -4
- package/dist/core/data-map.types.d.ts +0 -23
- package/dist/core/data-map.types.d.ts.map +0 -1
- package/dist/core/data-map.types.js +0 -1
- package/dist/core/data-store.types.d.ts +0 -22
- package/dist/core/data-store.types.d.ts.map +0 -1
- package/dist/core/data-store.types.js +0 -1
- package/dist/core/deferred-promise.d.ts +0 -203
- package/dist/core/deferred-promise.d.ts.map +0 -1
- package/dist/core/deferred-promise.js +0 -200
- package/dist/core/errors.d.ts +0 -303
- package/dist/core/errors.d.ts.map +0 -1
- package/dist/core/errors.js +0 -400
- package/dist/core/expect-history-entry.d.ts +0 -52
- package/dist/core/expect-history-entry.d.ts.map +0 -1
- package/dist/core/expect-history-entry.js +0 -38
- package/dist/core/history-entry-id-schema.d.ts +0 -17
- package/dist/core/history-entry-id-schema.d.ts.map +0 -1
- package/dist/core/history-entry-id-schema.js +0 -9
- package/dist/core/history-entry-url-schema.d.ts +0 -20
- package/dist/core/history-entry-url-schema.d.ts.map +0 -1
- package/dist/core/history-entry-url-schema.js +0 -16
- package/dist/core/init-loaders.d.ts +0 -37
- package/dist/core/init-loaders.d.ts.map +0 -1
- package/dist/core/init-loaders.js +0 -38
- package/dist/core/match-routes.d.ts +0 -31
- package/dist/core/match-routes.d.ts.map +0 -1
- package/dist/core/match-routes.js +0 -54
- package/dist/core/readonly-form-data.types.d.ts +0 -32
- package/dist/core/readonly-form-data.types.d.ts.map +0 -1
- package/dist/core/readonly-url.types.d.ts +0 -135
- package/dist/core/readonly-url.types.d.ts.map +0 -1
- package/dist/core/redirect-response.d.ts +0 -29
- package/dist/core/redirect-response.d.ts.map +0 -1
- package/dist/core/redirect-response.js +0 -17
- package/dist/core/route-request.d.ts +0 -52
- package/dist/core/route-request.d.ts.map +0 -1
- package/dist/core/route-request.js +0 -26
- package/dist/core/route.types.d.ts +0 -309
- package/dist/core/route.types.d.ts.map +0 -1
- package/dist/core/start-actions.d.ts +0 -60
- package/dist/core/start-actions.d.ts.map +0 -1
- package/dist/core/start-actions.js +0 -186
- package/dist/core/start-loaders.d.ts +0 -69
- package/dist/core/start-loaders.d.ts.map +0 -1
- package/dist/core/start-loaders.js +0 -154
- package/dist/core.d.ts.map +0 -1
- package/dist/engines/engine.types.d.ts +0 -190
- package/dist/engines/engine.types.d.ts.map +0 -1
- package/dist/engines/navigation-api-engine.d.ts +0 -48
- package/dist/engines/navigation-api-engine.d.ts.map +0 -1
- package/dist/engines/navigation-api-engine.js +0 -332
- package/dist/hooks/_use-route-context.d.ts +0 -10
- package/dist/hooks/_use-route-context.d.ts.map +0 -1
- package/dist/hooks/_use-route-context.js +0 -17
- package/dist/hooks/_use-router-context.d.ts +0 -10
- package/dist/hooks/_use-router-context.d.ts.map +0 -1
- package/dist/hooks/_use-router-context.js +0 -18
- package/dist/hooks/use-action-data.d.ts +0 -23
- package/dist/hooks/use-action-data.d.ts.map +0 -1
- package/dist/hooks/use-action-data.js +0 -16
- package/dist/hooks/use-form-action.d.ts +0 -7
- package/dist/hooks/use-form-action.d.ts.map +0 -1
- package/dist/hooks/use-form-action.js +0 -10
- package/dist/hooks/use-loader-data.d.ts +0 -11
- package/dist/hooks/use-loader-data.d.ts.map +0 -1
- package/dist/hooks/use-loader-data.js +0 -19
- package/dist/hooks/use-navigate.d.ts +0 -39
- package/dist/hooks/use-navigate.d.ts.map +0 -1
- package/dist/hooks/use-navigate.js +0 -26
- package/dist/hooks/use-params.d.ts.map +0 -1
- package/dist/hooks/use-pathname.d.ts +0 -7
- package/dist/hooks/use-pathname.d.ts.map +0 -1
- package/dist/hooks/use-pathname.js +0 -9
- package/dist/hooks/use-submit.d.ts +0 -66
- package/dist/hooks/use-submit.d.ts.map +0 -1
- package/dist/hooks/use-submit.js +0 -35
- package/dist/soseki.d.ts +0 -42
- package/dist/soseki.d.ts.map +0 -1
- package/dist/soseki.js +0 -19
- package/dist/utils/get-action-id.d.ts +0 -8
- package/dist/utils/get-action-id.d.ts.map +0 -1
- package/dist/utils/get-action-id.js +0 -11
- package/dist/utils/href.d.ts +0 -11
- package/dist/utils/href.d.ts.map +0 -1
- package/dist/utils/href.js +0 -12
- package/dist/utils/redirect.d.ts +0 -11
- package/dist/utils/redirect.d.ts.map +0 -1
- package/dist/utils/redirect.js +0 -12
- package/dist/utils/route-index.d.ts +0 -41
- package/dist/utils/route-index.d.ts.map +0 -1
- package/dist/utils/route-index.js +0 -12
- package/dist/utils/route-route.d.ts +0 -62
- package/dist/utils/route-route.d.ts.map +0 -1
- package/dist/utils/route-route.js +0 -25
- package/dist/utils/set-action-id.d.ts +0 -9
- package/dist/utils/set-action-id.d.ts.map +0 -1
- package/dist/utils/set-action-id.js +0 -12
- package/src/components/action-id.tsx +0 -35
- package/src/components/hidden-input.tsx +0 -39
- package/src/core/_action-id-registry.ts +0 -11
- package/src/core/_capture-stack-trace.ts +0 -12
- package/src/core/_create-html-form-element-form-form-data.ts +0 -32
- package/src/core/_encode-pathname.ts +0 -17
- package/src/core/_is-error.ts +0 -16
- package/src/core/_is-promise-like.ts +0 -14
- package/src/core/_use-singleton.ts +0 -24
- package/src/core/_weak-id-registry.ts +0 -125
- package/src/core/constants.ts +0 -4
- package/src/core/data-map.types.ts +0 -28
- package/src/core/data-store.types.ts +0 -25
- package/src/core/deferred-promise.ts +0 -408
- package/src/core/start-actions.ts +0 -274
- package/src/hooks/_use-route-context.ts +0 -19
- package/src/hooks/_use-router-context.ts +0 -25
- package/src/hooks/use-pathname.ts +0 -10
- package/src/utils/get-action-id.ts +0 -12
- package/src/utils/href.ts +0 -17
- package/src/utils/route-index.ts +0 -70
- package/src/utils/route-route.ts +0 -111
- package/src/utils/set-action-id.ts +0 -14
- /package/dist/{core → src/core}/readonly-form-data.types.js +0 -0
- /package/dist/{core → src/core}/readonly-url.types.js +0 -0
- /package/dist/{core → src/core}/route.types.js +0 -0
- /package/dist/{engines → src/engines}/engine.types.js +0 -0
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import unreachable from "../core/_unreachable.js";
|
|
2
|
+
import * as v from "../core/_valibot.js";
|
|
3
|
+
import { NavigationApiNotSupportedError } from "../core/errors.js";
|
|
4
|
+
import expectHistoryEntry from "../core/expect-history-entry.js";
|
|
5
|
+
import createHtmlFormElementFormFormData from "../core/form-data-to-html-form-element.js";
|
|
6
|
+
import HistoryEntryIdSchema from "../core/history-entry-id-schema.js";
|
|
7
|
+
import HistoryEntryUrlSchema from "../core/history-entry-url-schema.js";
|
|
8
|
+
import initLoaders from "../core/init-loaders.js";
|
|
9
|
+
import matchRoutes from "../core/match-routes.js";
|
|
10
|
+
import RoutePath from "../core/route-path.js";
|
|
11
|
+
import startAction from "../core/start-action.js";
|
|
12
|
+
import startLoaders from "../core/start-loaders.js";
|
|
13
|
+
/**
|
|
14
|
+
* モダンブラウザーに搭載されている標準の `Navigation API` を活用し、クライアントサイドにおける高度な SPA ルーティングを制御するエンジンクラスです。
|
|
15
|
+
*/
|
|
16
|
+
export default class NavigationApiEngine {
|
|
17
|
+
/**
|
|
18
|
+
* `NavigationApiEngine` クラスのインスタンスを初期化します。
|
|
19
|
+
*
|
|
20
|
+
* 実行環境が `Navigation API` をサポートしていない場合はエラーを投げます。
|
|
21
|
+
*/
|
|
22
|
+
constructor() {
|
|
23
|
+
let navigation_;
|
|
24
|
+
// グローバル環境または window オブジェクトから navigation インスタンスの回収を試みます。
|
|
25
|
+
for (const getNav of [() => navigation, () => window.navigation]) {
|
|
26
|
+
try {
|
|
27
|
+
navigation_ = getNav();
|
|
28
|
+
if (typeof navigation_ !== "undefined") {
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch { }
|
|
33
|
+
}
|
|
34
|
+
// オブジェクトとして存在しない場合はサポート外の環境とみなします。
|
|
35
|
+
if (typeof navigation_ !== "object") {
|
|
36
|
+
throw new NavigationApiNotSupportedError();
|
|
37
|
+
}
|
|
38
|
+
this.navigation = navigation_;
|
|
39
|
+
this.subscribedEntryIds = new Set();
|
|
40
|
+
this.navAbortController = null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 現在のページ URL に基づき、ルーターの初期状態を構築・登録します。
|
|
44
|
+
*
|
|
45
|
+
* @param args ルート定義配列、共通データストア、初期化用のアボートシグナルを含むオブジェクトです。
|
|
46
|
+
* @returns 構築された初期の `RouterState`。適合するルートがないか、履歴が無い場合は `null` を返します。
|
|
47
|
+
*/
|
|
48
|
+
init(args) {
|
|
49
|
+
const currentEntry = expectHistoryEntry(this.navigation.currentEntry);
|
|
50
|
+
if (!currentEntry) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const { routes, getSignal, loaderDataStore } = args;
|
|
54
|
+
const currentRoutes = matchRoutes(routes, currentEntry.url);
|
|
55
|
+
if (!currentRoutes) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
// 初期表示に必要なすべてのローダーを一斉に並行起動します。
|
|
59
|
+
const dataMap = initLoaders(currentRoutes, {
|
|
60
|
+
url: currentEntry.url,
|
|
61
|
+
signal: getSignal(),
|
|
62
|
+
});
|
|
63
|
+
// 起動したローダーの結果(NinjaPromise)のマップを、現在の履歴 ID をキーとしてキャッシュします。
|
|
64
|
+
loaderDataStore.set(currentEntry.id, dataMap);
|
|
65
|
+
return {
|
|
66
|
+
entry: currentEntry,
|
|
67
|
+
routes: currentRoutes,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* ブラウザーの継続的なナビゲーションイベント(リンククリック、フォーム送信、履歴移動)の監視を開始します。
|
|
72
|
+
*
|
|
73
|
+
* @param args ルート配列、UI側への状態反映関数、各種ストア、シグナル取得関数を含むオブジェクトです。
|
|
74
|
+
*/
|
|
75
|
+
start(args) {
|
|
76
|
+
const { routes, update, getSignal, actionDataStore, loaderDataStore } = args;
|
|
77
|
+
/**
|
|
78
|
+
* ユーザーのアクションによって発生したすべての遷移要求をインターセプトして処理する、ルーティングの中枢ハンドラーです。
|
|
79
|
+
*/
|
|
80
|
+
const handleNavigate = (event) => {
|
|
81
|
+
// 処理すべきでない通常のブラウザー固有のナビゲーション(ハッシュ変更、ファイルのダウンロードなど)は、
|
|
82
|
+
// 標準の挙動を妨げないようにインターセプトせず即座にスルーします。
|
|
83
|
+
// 参照: https://developer.mozilla.org/docs/Web/API/Navigation_API#handling_a_navigation_using_intercept
|
|
84
|
+
if (!event.isTrusted ||
|
|
85
|
+
!event.canIntercept ||
|
|
86
|
+
event.hashChange ||
|
|
87
|
+
event.downloadRequest !== null) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const currentEntry = expectHistoryEntry(this.navigation.currentEntry);
|
|
91
|
+
if (!currentEntry) {
|
|
92
|
+
// 現在のエントリーが存在しない場合は、ルーターを未マッチ状態(null)にリセットして制御をブラウザーに返します。
|
|
93
|
+
event.intercept({
|
|
94
|
+
async handler() {
|
|
95
|
+
update(null);
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// 移動先の URL を検証し、適合するルート定義があるかを探索します。
|
|
101
|
+
const destUrl = v.expect(HistoryEntryUrlSchema(), event.destination.url);
|
|
102
|
+
const destRoutes = matchRoutes(routes, destUrl);
|
|
103
|
+
if (!destRoutes) {
|
|
104
|
+
// 移動先のルート定義が見つからない場合は、ルーターを未マッチ状態(null)にリセットして制御をブラウザーに返します。
|
|
105
|
+
event.intercept({
|
|
106
|
+
async handler() {
|
|
107
|
+
update(null);
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
// 前回の遷移から短時間で遷移する場合を考慮し、進行中だった以前の古い非同期処理をすべて安全に中断します。
|
|
113
|
+
this.navAbortController?.abort();
|
|
114
|
+
this.navAbortController = new AbortController();
|
|
115
|
+
const { signal } = this.navAbortController;
|
|
116
|
+
const { formData } = event;
|
|
117
|
+
const prevEntryInHandler = currentEntry;
|
|
118
|
+
// 分岐 A: フォームデータが伴う場合 = データ変更要求(HTTP POST / Action 契機)
|
|
119
|
+
if (formData) {
|
|
120
|
+
const { sourceElement } = event;
|
|
121
|
+
// submit メソッドによってプログラムから動的生成されたフォーム要素であれば、用済みのため DOM から削除します。
|
|
122
|
+
if (sourceElement?.hasAttribute("data-sosekisubmit")) {
|
|
123
|
+
document.body.removeChild(sourceElement);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* A-1: URL が書き換わる直前の段階で割り込んでアクション関数を実行するハンドラーです。
|
|
127
|
+
*/
|
|
128
|
+
const precommitHandler = async (controller) => {
|
|
129
|
+
const action = startAction(destRoutes, {
|
|
130
|
+
url: destUrl,
|
|
131
|
+
signal,
|
|
132
|
+
formData,
|
|
133
|
+
});
|
|
134
|
+
if (!action) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
// アクションの実行状態を現在の履歴 ID に紐づけてストアへ保存します。
|
|
138
|
+
actionDataStore
|
|
139
|
+
.getOrInsertComputed(currentEntry.id, () => new Map())
|
|
140
|
+
.set(action.func, action.data);
|
|
141
|
+
// アクションの開始に伴い、UI 層へローディング状態などの再描画を伝播します。
|
|
142
|
+
update();
|
|
143
|
+
// 全アクションの処理が完了するまで待機します。
|
|
144
|
+
const actionResponse = await action.idle();
|
|
145
|
+
const redirectUrl = new URL(currentEntry.url.href);
|
|
146
|
+
switch (action.data.status) {
|
|
147
|
+
case "rejected": {
|
|
148
|
+
// アクションがエラーで失敗した場合は、URL を変更せず現在の元のページに強制リダイレクトさせます。
|
|
149
|
+
const { pathname, search, hash } = currentEntry.url;
|
|
150
|
+
controller.redirect(pathname + search + hash);
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
case "fulfilled": {
|
|
154
|
+
// アクションが正常終了した場合、返り値にリダイレクト指示が含まれていればその目的地へ遷移させます。
|
|
155
|
+
// リダイレクトがなければそのまま本来の目的地へとブラウザーのコミット先を書き換えます。
|
|
156
|
+
const { redirectTo = currentEntry.url } = actionResponse;
|
|
157
|
+
const { pathname, search, hash } = redirectTo;
|
|
158
|
+
controller.redirect(pathname + search + hash);
|
|
159
|
+
redirectUrl.pathname = pathname;
|
|
160
|
+
redirectUrl.search = search;
|
|
161
|
+
redirectUrl.hash = hash;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
default:
|
|
165
|
+
unreachable(action.data.status);
|
|
166
|
+
}
|
|
167
|
+
// 次の描画確定フェーズへコンテキスト情報を引き継ぎます。
|
|
168
|
+
return {
|
|
169
|
+
action: action.func,
|
|
170
|
+
actionData: action.data,
|
|
171
|
+
redirectUrl,
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* A-2: アクションが完了し、ブラウザーの URL コミットが確定した後に画面表示を同期させるハンドラーです。
|
|
176
|
+
*/
|
|
177
|
+
const handler = async (args) => {
|
|
178
|
+
if (!args) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const { action, actionData, redirectUrl } = args;
|
|
182
|
+
// 履歴エントリーを再度取得します。
|
|
183
|
+
const currentEntry = expectHistoryEntry(this.navigation.currentEntry);
|
|
184
|
+
if (!currentEntry) {
|
|
185
|
+
// 現在のエントリーが存在しない場合は、ルーターを未マッチ状態(null)にリセットして制御をブラウザーに返します。
|
|
186
|
+
update(null);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
// コミットされた実際のブラウザー URL が、想定しているリダイレクト先と一致しない場合は処理を中断します。
|
|
190
|
+
if (currentEntry.url.href !== redirectUrl.href) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
// 確定した新しい履歴 ID に改めてアクション結果をキャッシュします。
|
|
194
|
+
actionDataStore
|
|
195
|
+
.getOrInsertComputed(currentEntry.id, () => new Map())
|
|
196
|
+
.set(action, actionData);
|
|
197
|
+
const currentRoutes = matchRoutes(routes, currentEntry.url);
|
|
198
|
+
if (!currentRoutes) {
|
|
199
|
+
// 現在のルート定義が見つからない場合は、ルーターを未マッチ状態(null)にリセットして制御をブラウザーに返します。
|
|
200
|
+
update(null);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
// アクションの処理結果を反映させるために、該当するルートのローダーを実行します。
|
|
204
|
+
const prevEntry = prevEntryInHandler;
|
|
205
|
+
const prevRoutes = matchRoutes(routes, prevEntry.url);
|
|
206
|
+
const startedLoaders = startLoaders({
|
|
207
|
+
signal,
|
|
208
|
+
prevEntry,
|
|
209
|
+
prevRoutes,
|
|
210
|
+
currentEntry,
|
|
211
|
+
currentRoutes,
|
|
212
|
+
loaderDataStore,
|
|
213
|
+
}, {
|
|
214
|
+
formData,
|
|
215
|
+
actionData,
|
|
216
|
+
});
|
|
217
|
+
// 最新の確定状態を UI に通知して画面を再描画します。ローダーの結果の中には実行中のものもありますが、それらの待機処理(描画)は各コンポーネントに任せます。
|
|
218
|
+
update({
|
|
219
|
+
entry: currentEntry,
|
|
220
|
+
routes: currentRoutes,
|
|
221
|
+
});
|
|
222
|
+
// 全ローダーの完了を待機します。ここで待機することで、全ローダーの実行が完了するまでブラウザーのタブにはローディングスピーナーが表示されます。
|
|
223
|
+
await startedLoaders?.idle();
|
|
224
|
+
};
|
|
225
|
+
// Navigation API のインターセプト機構に、二段階の処理をバインドします。
|
|
226
|
+
let precommitResult;
|
|
227
|
+
event.intercept({
|
|
228
|
+
async precommitHandler(controller) {
|
|
229
|
+
precommitResult = await precommitHandler(controller);
|
|
230
|
+
},
|
|
231
|
+
async handler() {
|
|
232
|
+
await handler(precommitResult);
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
// 分岐 B: フォームデータがない場合 = 通常の画面遷移(HTTP GET / リンククリック・戻る進む契機)
|
|
238
|
+
const handler = async () => {
|
|
239
|
+
const currentEntry = expectHistoryEntry(this.navigation.currentEntry);
|
|
240
|
+
if (!currentEntry) {
|
|
241
|
+
update(null);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
// 同期がズレている場合はガードします。
|
|
245
|
+
if (currentEntry.url.href !== destUrl.href) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const prevEntry = prevEntryInHandler;
|
|
249
|
+
const prevRoutes = matchRoutes(routes, prevEntry.url);
|
|
250
|
+
const currentRoutes = destRoutes;
|
|
251
|
+
// キャッシュの再利用判定を含めて、移動先のローダー関数群を精査・起動します。
|
|
252
|
+
const startedLoaders = startLoaders({
|
|
253
|
+
signal,
|
|
254
|
+
prevEntry,
|
|
255
|
+
prevRoutes,
|
|
256
|
+
currentEntry,
|
|
257
|
+
currentRoutes,
|
|
258
|
+
loaderDataStore,
|
|
259
|
+
});
|
|
260
|
+
// 最新の確定状態を UI に通知して画面を再描画します。ローダーの結果の中には実行中のものもありますが、それらの待機処理(描画)は各コンポーネントに任せます。
|
|
261
|
+
update({
|
|
262
|
+
entry: currentEntry,
|
|
263
|
+
routes: currentRoutes,
|
|
264
|
+
});
|
|
265
|
+
// 全ローダーの完了を待機します。ここで待機することで、全ローダーの実行が完了するまでブラウザーのタブにはローディングスピーナーが表示されます。
|
|
266
|
+
await startedLoaders?.idle();
|
|
267
|
+
};
|
|
268
|
+
event.intercept({
|
|
269
|
+
async handler() {
|
|
270
|
+
await handler();
|
|
271
|
+
},
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
const signal = getSignal();
|
|
276
|
+
// 外部からルーター全体の監視終了シグナルを受け取った際、中断処理を連動させます。
|
|
277
|
+
const handleAbort = () => {
|
|
278
|
+
this.navAbortController?.abort();
|
|
279
|
+
this.navAbortController = null;
|
|
280
|
+
};
|
|
281
|
+
signal.addEventListener("abort", handleAbort, { once: true });
|
|
282
|
+
// Navigation API の navigate イベントの購読を開始します。
|
|
283
|
+
this.navigation.addEventListener("navigate", handleNavigate, { signal });
|
|
284
|
+
// セッション履歴から溢れて破棄された古い履歴エントリーのデータ(アクション・ローダーのキャッシュ)を自動削除します。
|
|
285
|
+
for (const entry of this.navigation.entries()) {
|
|
286
|
+
const entryId = v.expect(HistoryEntryIdSchema(), entry.id);
|
|
287
|
+
if (this.subscribedEntryIds.has(entryId)) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const handleDispose = () => {
|
|
291
|
+
this.subscribedEntryIds.delete(entryId);
|
|
292
|
+
actionDataStore.delete(entryId);
|
|
293
|
+
loaderDataStore.delete(entryId);
|
|
294
|
+
};
|
|
295
|
+
entry.addEventListener("dispose", handleDispose, { signal });
|
|
296
|
+
this.subscribedEntryIds.add(entryId);
|
|
297
|
+
}
|
|
298
|
+
// ナビゲーションの進行に伴い、新しく生成される履歴エントリーに対しても、動的に破棄イベントの監視網を広げます。
|
|
299
|
+
const handleCurrentEntryChange = () => {
|
|
300
|
+
const currentEntry = expectHistoryEntry(this.navigation.currentEntry);
|
|
301
|
+
if (!currentEntry) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (this.subscribedEntryIds.has(currentEntry.id)) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const handleDispose = () => {
|
|
308
|
+
this.subscribedEntryIds.delete(currentEntry.id);
|
|
309
|
+
actionDataStore.delete(currentEntry.id);
|
|
310
|
+
loaderDataStore.delete(currentEntry.id);
|
|
311
|
+
};
|
|
312
|
+
this.navigation.currentEntry.addEventListener("dispose", handleDispose, { signal });
|
|
313
|
+
this.subscribedEntryIds.add(currentEntry.id);
|
|
314
|
+
};
|
|
315
|
+
this.navigation.addEventListener("currententrychange", handleCurrentEntryChange, { signal });
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* フォームデータまたはクエリーパラメータを、ブラウザーの Navigation API のライフサイクルに載せて命令的に送信します。
|
|
319
|
+
*
|
|
320
|
+
* @param args 送信データの種類に応じたサブミット引数です。
|
|
321
|
+
*/
|
|
322
|
+
submit(args) {
|
|
323
|
+
switch (args.type) {
|
|
324
|
+
case "FORM_DATA": {
|
|
325
|
+
const { action, target } = args;
|
|
326
|
+
const form = createHtmlFormElementFormFormData(target);
|
|
327
|
+
form.method = "POST";
|
|
328
|
+
form.action = action;
|
|
329
|
+
form.enctype = "multipart/form-data";
|
|
330
|
+
form.dataset["sosekisubmit"] = ""; // 後で削除できるように目印を付与します。
|
|
331
|
+
// 実際のフォーム送信を行うために DOM へ一時配置して実行します。
|
|
332
|
+
// ハンドラーがこの要素を使用した後に DOM から削除します。
|
|
333
|
+
document.body.appendChild(form);
|
|
334
|
+
form.submit();
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
case "URL_SEARCH_PARAMS": {
|
|
338
|
+
const { action, target, history } = args;
|
|
339
|
+
const path = new RoutePath(action);
|
|
340
|
+
path.search = target.toString();
|
|
341
|
+
// Navigation API を用いて、クエリーが上書きされた新しいアドレスへ遷移させます。
|
|
342
|
+
this.navigation.navigate(path.toString(), { history });
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
default:
|
|
346
|
+
unreachable(args);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* 命令的なページ遷移を処理します。
|
|
351
|
+
*
|
|
352
|
+
* @param args 遷移タイプに応じたナビゲーション引数です。
|
|
353
|
+
*/
|
|
354
|
+
navigate(args) {
|
|
355
|
+
switch (args.type) {
|
|
356
|
+
case "LINK": {
|
|
357
|
+
const { to, history } = args;
|
|
358
|
+
switch (to.type) {
|
|
359
|
+
case "PATH": {
|
|
360
|
+
// 完全なパス文字列の余分なスラッシュなどをエンコードして直接遷移します。
|
|
361
|
+
const path = RoutePath.encode(to.path);
|
|
362
|
+
this.navigation.navigate(path, { history });
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
case "PARTIAL": {
|
|
366
|
+
// 現在のロケーション情報をベースに、指定されたパーツ(パス名、クエリー、ハッシュのみなど)を部分的にパッチ(上書き)したマージ URL を算出します。
|
|
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
|
+
}
|
|
378
|
+
const nextPathString = nextPath.toString();
|
|
379
|
+
// 無駄な遷移履歴を作らないように、URL に実際の変化がある場合のみ navigate を実行します。
|
|
380
|
+
if (nextPathString !== currentPath.toString()) {
|
|
381
|
+
this.navigation.navigate(nextPathString, { history });
|
|
382
|
+
}
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
default:
|
|
386
|
+
unreachable(to);
|
|
387
|
+
}
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
case "MOVE": {
|
|
391
|
+
const currentEntry = expectHistoryEntry(this.navigation.currentEntry);
|
|
392
|
+
if (!currentEntry) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
const { delta } = args;
|
|
396
|
+
// 現在のインデックスから相対位置(例: -1 なら 1 つ戻る)を計算し、履歴スタックに該当するインデックスが存在するか探索します。
|
|
397
|
+
const index = currentEntry.index + delta;
|
|
398
|
+
const entry = this.navigation.entries().find((e) => e.index === index);
|
|
399
|
+
if (!entry) {
|
|
400
|
+
// スタックの限界を超える移動要求の場合は何もしません。
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
// Navigation API の traverseTo メソッドを使用し、一意の識別キーを指定して目的地へジャンプします。
|
|
404
|
+
this.navigation.traverseTo(entry.key);
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
default:
|
|
408
|
+
unreachable(args);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engines.d.ts","sourceRoot":"","sources":["../../src/engines.ts"],"names":[],"mappings":"AAAA,mBAAmB,2BAA2B,CAAC;AAE/C,mBAAmB,oCAAoC,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,oCAAoC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as NavigationApiEngine } from "./engines/navigation-api-engine.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* コンポーネントのライフサイクルにおいて、渡されたファクトリー関数を最初のレンダリング時に一度だけ実行し、その結果を以降の再レンダリング間で永続的に共有・保持するためのカスタムフックです。
|
|
3
|
+
*
|
|
4
|
+
* `React.useMemo` と異なり、React の内部都合によるキャッシュの不意な破棄・再計算が発生しないことが保証されます。
|
|
5
|
+
*
|
|
6
|
+
* @template T ファクトリー関数が生成するオブジェクトの型定義です。
|
|
7
|
+
* @param fn 初回レンダリング時にのみ呼び出される、オブジェクト生成用の初期化関数です。
|
|
8
|
+
* @returns 初回実行時に生成され、保持され続けている型 `T` のシングルトンインスタンスを返します。
|
|
9
|
+
*/
|
|
10
|
+
export default function useSingleton<T>(fn: () => T): T;
|
|
11
|
+
//# sourceMappingURL=_use-singleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_use-singleton.d.ts","sourceRoot":"","sources":["../../../src/hooks/_use-singleton.ts"],"names":[],"mappings":"AAOA;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAatD"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* 初期化前(未初期化状態)であることを安全に判定するための、値が空の内部専用ユニークオブジェクトです。
|
|
4
|
+
*/
|
|
5
|
+
const nil = {};
|
|
6
|
+
/**
|
|
7
|
+
* コンポーネントのライフサイクルにおいて、渡されたファクトリー関数を最初のレンダリング時に一度だけ実行し、その結果を以降の再レンダリング間で永続的に共有・保持するためのカスタムフックです。
|
|
8
|
+
*
|
|
9
|
+
* `React.useMemo` と異なり、React の内部都合によるキャッシュの不意な破棄・再計算が発生しないことが保証されます。
|
|
10
|
+
*
|
|
11
|
+
* @template T ファクトリー関数が生成するオブジェクトの型定義です。
|
|
12
|
+
* @param fn 初回レンダリング時にのみ呼び出される、オブジェクト生成用の初期化関数です。
|
|
13
|
+
* @returns 初回実行時に生成され、保持され続けている型 `T` のシングルトンインスタンスを返します。
|
|
14
|
+
*/
|
|
15
|
+
export default function useSingleton(fn) {
|
|
16
|
+
// 生成されたオブジェクトをコンポーネントの生存期間中保持するために useRef を使用します。
|
|
17
|
+
// 初期値として、未初期化の目印である nil オブジェクトを型アサーションして流し込みます。
|
|
18
|
+
const ref = React.useRef(nil);
|
|
19
|
+
// 参照している中身がマッピングされたオブジェクト(nil)のままであれば、まだ一度も初期化されていないと判定します。
|
|
20
|
+
if (ref.current === nil) {
|
|
21
|
+
// 初期化関数を実行し、生成された実体を現在の参照へと上書きします。
|
|
22
|
+
// この処理は初回のレンダリングパスの中で完全に同期的に実行されます。
|
|
23
|
+
ref.current = fn();
|
|
24
|
+
}
|
|
25
|
+
return ref.current;
|
|
26
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { NinjaPromise } from "ninja-promise";
|
|
2
|
+
import type RedirectResponse from "../core/redirect-response.js";
|
|
3
|
+
/**
|
|
4
|
+
* アクション関数の戻り値の型から、リダイレクト応答を除外して正規化するユーティリティー型です。
|
|
5
|
+
*
|
|
6
|
+
* アクションがリダイレクトを返した場合、フレームワークの内部仕様によって実際の値は `undefined` に置換されるため、型定義においてもその挙動を忠実に表現します。
|
|
7
|
+
*/
|
|
8
|
+
type ActionResult<TResult> = TResult extends RedirectResponse ? undefined : TResult;
|
|
9
|
+
/**
|
|
10
|
+
* 現在の階層のルートに紐づくアクション関数の最新の実行結果を購読・取得するためのカスタムフックです。
|
|
11
|
+
*
|
|
12
|
+
* @template TData アクション関数そのものの型、またはアクションが返すことが期待されるデータ構造の型定義です。関数型が渡された場合は、自動的にその戻り値の型(推論結果)が解凍されます。
|
|
13
|
+
* @returns アクションが実行済み、または実行中であれば結果を内包した `NinjaPromise` を返し、一度も実行されていないか対象のアクションが存在しない場合は `undefined` を返します。
|
|
14
|
+
*/
|
|
15
|
+
export default function useActionData<TData = unknown>(): NinjaPromise<ActionResult<Awaited<TData extends (...args: any) => infer TReturn ? TReturn : TData>>> | undefined;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=use-action-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-action-data.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-action-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,KAAK,gBAAgB,MAAM,8BAA8B,CAAC;AAIjE;;;;GAIG;AACH,KAAK,YAAY,CAAC,OAAO,IAAI,OAAO,SAAS,gBAAgB,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpF;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,KAAK,GAAG,OAAO,KACjD,YAAY,CACV,YAAY,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,MAAM,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC,CAAC,CACvF,GACD,SAAS,CAQZ"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import useRouteContext from "./use-route-context.js";
|
|
2
|
+
import useRouterContext from "./use-router-context.js";
|
|
3
|
+
/**
|
|
4
|
+
* 現在の階層のルートに紐づくアクション関数の最新の実行結果を購読・取得するためのカスタムフックです。
|
|
5
|
+
*
|
|
6
|
+
* @template TData アクション関数そのものの型、またはアクションが返すことが期待されるデータ構造の型定義です。関数型が渡された場合は、自動的にその戻り値の型(推論結果)が解凍されます。
|
|
7
|
+
* @returns アクションが実行済み、または実行中であれば結果を内包した `NinjaPromise` を返し、一度も実行されていないか対象のアクションが存在しない場合は `undefined` を返します。
|
|
8
|
+
*/
|
|
9
|
+
export default function useActionData() {
|
|
10
|
+
const { action } = useRouteContext();
|
|
11
|
+
const actionData = useRouterContext((router) => {
|
|
12
|
+
const { currentEntry, actionDataStore } = router;
|
|
13
|
+
return actionDataStore.get(currentEntry.id)?.get(action);
|
|
14
|
+
});
|
|
15
|
+
return actionData;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-form-action.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-form-action.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,IAAI,MAAM,CAE9C"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import useRouteContext from "./use-route-context.js";
|
|
2
|
+
/**
|
|
3
|
+
* 現在の階層のルートに紐づく、動的パラメーターが具現化された実際の URL パス文字列を取得するカスタムフックです。
|
|
4
|
+
*
|
|
5
|
+
* @returns 現在のルートに対応する具現化済みの URL パス文字列(例: `"/items/123"`)を返します。
|
|
6
|
+
*/
|
|
7
|
+
export default function useFormAction() {
|
|
8
|
+
return useRouteContext().urlPath;
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NinjaPromise } from "ninja-promise";
|
|
2
|
+
/**
|
|
3
|
+
* 現在の階層のルートに紐づくローダー関数の実行結果を購読・取得するためのカスタムフックです。
|
|
4
|
+
*
|
|
5
|
+
* @template TData ローダー関数そのものの型、またはローダーが返すことが期待されるデータ構造の型定義です。関数型が渡された場合は、自動的にその非同期戻り値の型(非同期の解凍結果)が推論されます。
|
|
6
|
+
* @returns ローダーの実行状態を管理している `NinjaPromise` を返します。
|
|
7
|
+
*/
|
|
8
|
+
export default function useLoaderData<TData = unknown>(): NinjaPromise<Awaited<TData extends (...args: any) => infer TReturn ? TReturn : TData>>;
|
|
9
|
+
//# sourceMappingURL=use-loader-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-loader-data.d.ts","sourceRoot":"","sources":["../../../src/hooks/use-loader-data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAMlD;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,KAAK,GAAG,OAAO,KAAK,YAAY,CACpE,OAAO,CAAC,KAAK,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,MAAM,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC,CACzE,CAWA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { LoaderDataNotFoundError } from "../core/errors.js";
|
|
2
|
+
import useRouteContext from "./use-route-context.js";
|
|
3
|
+
import useRouterContext from "./use-router-context.js";
|
|
4
|
+
/**
|
|
5
|
+
* 現在の階層のルートに紐づくローダー関数の実行結果を購読・取得するためのカスタムフックです。
|
|
6
|
+
*
|
|
7
|
+
* @template TData ローダー関数そのものの型、またはローダーが返すことが期待されるデータ構造の型定義です。関数型が渡された場合は、自動的にその非同期戻り値の型(非同期の解凍結果)が推論されます。
|
|
8
|
+
* @returns ローダーの実行状態を管理している `NinjaPromise` を返します。
|
|
9
|
+
*/
|
|
10
|
+
export default function useLoaderData() {
|
|
11
|
+
const { loader } = useRouteContext();
|
|
12
|
+
const loaderData = useRouterContext((router) => {
|
|
13
|
+
const { currentEntry, loaderDataStore } = router;
|
|
14
|
+
return loaderDataStore.get(currentEntry.id)?.get(loader);
|
|
15
|
+
});
|
|
16
|
+
if (!loaderData) {
|
|
17
|
+
throw new LoaderDataNotFoundError({ loader });
|
|
18
|
+
}
|
|
19
|
+
return loaderData;
|
|
20
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 遷移先のアドレスを指定するための表現型です。
|
|
3
|
+
*
|
|
4
|
+
* 完全な URL パス文字列か、またはパスの各コンポーネントを部分的にパッチするためのオブジェクトのいずれかを受け入れます。
|
|
5
|
+
*/
|
|
6
|
+
export type NavigateTo = string | {
|
|
7
|
+
/**
|
|
8
|
+
* 遷移先のドメイン以下のリクエストパス(例: `"/dashboard"`)です。
|
|
9
|
+
*/
|
|
10
|
+
readonly pathname?: string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* 遷移先に付与する検索クエリー文字列(例: `"?id=foo"`)です。
|
|
13
|
+
*/
|
|
14
|
+
readonly search?: string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* 遷移先に付与するハッシュフラグメント(例: `"#profile"`)です。
|
|
17
|
+
*/
|
|
18
|
+
readonly hash?: string | undefined;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* 画面遷移の挙動をカスタマイズするためのオプション型です。
|
|
22
|
+
*/
|
|
23
|
+
export type NavigateOptions = {
|
|
24
|
+
/**
|
|
25
|
+
* 履歴スタックへの追加方法を制御します。`true` の場合は現在の履歴を上書きし、`false` または省略時は新規追加します。
|
|
26
|
+
*/
|
|
27
|
+
readonly replace?: boolean | undefined;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* プログラムから命令的に画面遷移を実行する、`NavigateFunction` 関数のオーバーロードインターフェース定義です。
|
|
31
|
+
*/
|
|
32
|
+
export interface NavigateFunction {
|
|
33
|
+
/**
|
|
34
|
+
* 指定されたアドレスへ画面を遷移させます。
|
|
35
|
+
*
|
|
36
|
+
* @param to 遷移先の対象となるデータ表現です。
|
|
37
|
+
* @param options 履歴のスタック方法などを制御するオプションです。
|
|
38
|
+
*/
|
|
39
|
+
(to: NavigateTo, options?: NavigateOptions): void;
|
|
40
|
+
/**
|
|
41
|
+
* ブラウザーのセッション履歴スタック内を、現在地を基準に相対移動させます。
|
|
42
|
+
*
|
|
43
|
+
* @param delta 移動する履歴のステップ数(例: `-1` で1つ戻る、`1` で1つ進む)です。
|
|
44
|
+
*/
|
|
45
|
+
(delta: number): void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* リンクなどを介さない、ボタンのクリックハンドラーや非同期処理の完了時などから、プログラムによって命令的に画面遷移や履歴移動をトリガーするための関数を取得するカスタムフックです。
|
|
49
|
+
*
|
|
50
|
+
* @returns `NavigateFunction` 関数です。
|
|
51
|
+
*/
|
|
52
|
+
export default function useNavigate(): NavigateFunction;
|
|
53
|
+
//# sourceMappingURL=use-navigate.d.ts.map
|
|
@@ -0,0 +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"}
|