@cratis/scene.react 4.13.0 → 4.15.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/cjs/core/coreComponents.js +1 -1
- package/dist/cjs/index.js +16 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/navigation/SceneNavigationContext.js.map +1 -1
- package/dist/cjs/navigation/SceneNavigationHost.js +19 -44
- package/dist/cjs/navigation/SceneNavigationHost.js.map +1 -1
- package/dist/cjs/navigation/createBrowserSceneHistory.js +39 -0
- package/dist/cjs/navigation/createBrowserSceneHistory.js.map +1 -0
- package/dist/cjs/navigation/createMemorySceneHistory.js +53 -0
- package/dist/cjs/navigation/createMemorySceneHistory.js.map +1 -0
- package/dist/cjs/navigation/matchSceneRoute.js +43 -0
- package/dist/cjs/navigation/matchSceneRoute.js.map +1 -0
- package/dist/cjs/navigation/resolveDestination.js +1 -0
- package/dist/cjs/navigation/resolveDestination.js.map +1 -1
- package/dist/cjs/navigation/sceneRoutesFrom.js +37 -0
- package/dist/cjs/navigation/sceneRoutesFrom.js.map +1 -0
- package/dist/cjs/navigation/useSceneHistoryNavigation.js +112 -0
- package/dist/cjs/navigation/useSceneHistoryNavigation.js.map +1 -0
- package/dist/cjs/packages/PackageHostConfiguration.js +18 -2
- package/dist/cjs/packages/PackageHostConfiguration.js.map +1 -1
- package/dist/cjs/packages/isNetworkAsset.js +18 -0
- package/dist/cjs/packages/isNetworkAsset.js.map +1 -0
- package/dist/cjs/renderer/RenderBindingScopeContext.js +15 -5
- package/dist/cjs/renderer/RenderBindingScopeContext.js.map +1 -1
- package/dist/cjs/renderer/useBoundQuery.js +50 -0
- package/dist/cjs/renderer/useBoundQuery.js.map +1 -0
- package/dist/esm/core/coreComponents.js +1 -1
- package/dist/esm/index.js +8 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/navigation/DestinationResolution.d.ts +1 -0
- package/dist/esm/navigation/DestinationResolution.d.ts.map +1 -1
- package/dist/esm/navigation/DialogResult.d.ts +5 -0
- package/dist/esm/navigation/DialogResult.d.ts.map +1 -0
- package/dist/esm/navigation/DialogResult.js +2 -0
- package/dist/esm/navigation/DialogResult.js.map +1 -0
- package/dist/esm/navigation/SceneHistory.d.ts +10 -0
- package/dist/esm/navigation/SceneHistory.d.ts.map +1 -0
- package/dist/esm/navigation/SceneHistory.js +2 -0
- package/dist/esm/navigation/SceneHistory.js.map +1 -0
- package/dist/esm/navigation/SceneNavigationContext.d.ts +6 -1
- package/dist/esm/navigation/SceneNavigationContext.d.ts.map +1 -1
- package/dist/esm/navigation/SceneNavigationContext.js.map +1 -1
- package/dist/esm/navigation/SceneNavigationHost.d.ts +7 -2
- package/dist/esm/navigation/SceneNavigationHost.d.ts.map +1 -1
- package/dist/esm/navigation/SceneNavigationHost.js +20 -45
- package/dist/esm/navigation/SceneNavigationHost.js.map +1 -1
- package/dist/esm/navigation/SceneNavigationState.d.ts +8 -0
- package/dist/esm/navigation/SceneNavigationState.d.ts.map +1 -0
- package/dist/esm/navigation/SceneNavigationState.js +2 -0
- package/dist/esm/navigation/SceneNavigationState.js.map +1 -0
- package/dist/esm/navigation/SceneRoute.d.ts +6 -0
- package/dist/esm/navigation/SceneRoute.d.ts.map +1 -0
- package/dist/esm/navigation/SceneRoute.js +2 -0
- package/dist/esm/navigation/SceneRoute.js.map +1 -0
- package/dist/esm/navigation/createBrowserSceneHistory.d.ts +4 -0
- package/dist/esm/navigation/createBrowserSceneHistory.d.ts.map +1 -0
- package/dist/esm/navigation/createBrowserSceneHistory.js +37 -0
- package/dist/esm/navigation/createBrowserSceneHistory.js.map +1 -0
- package/dist/esm/navigation/createMemorySceneHistory.d.ts +7 -0
- package/dist/esm/navigation/createMemorySceneHistory.d.ts.map +1 -0
- package/dist/esm/navigation/createMemorySceneHistory.js +51 -0
- package/dist/esm/navigation/createMemorySceneHistory.js.map +1 -0
- package/dist/esm/navigation/index.d.ts +10 -1
- package/dist/esm/navigation/index.d.ts.map +1 -1
- package/dist/esm/navigation/index.js +10 -1
- package/dist/esm/navigation/index.js.map +1 -1
- package/dist/esm/navigation/matchSceneRoute.d.ts +7 -0
- package/dist/esm/navigation/matchSceneRoute.d.ts.map +1 -0
- package/dist/esm/navigation/matchSceneRoute.js +41 -0
- package/dist/esm/navigation/matchSceneRoute.js.map +1 -0
- package/dist/esm/navigation/resolveDestination.d.ts.map +1 -1
- package/dist/esm/navigation/resolveDestination.js +1 -0
- package/dist/esm/navigation/resolveDestination.js.map +1 -1
- package/dist/esm/navigation/sceneRoutesFrom.d.ts +4 -0
- package/dist/esm/navigation/sceneRoutesFrom.d.ts.map +1 -0
- package/dist/esm/navigation/sceneRoutesFrom.js +35 -0
- package/dist/esm/navigation/sceneRoutesFrom.js.map +1 -0
- package/dist/esm/navigation/useSceneHistoryNavigation.d.ts +6 -0
- package/dist/esm/navigation/useSceneHistoryNavigation.d.ts.map +1 -0
- package/dist/esm/navigation/useSceneHistoryNavigation.js +110 -0
- package/dist/esm/navigation/useSceneHistoryNavigation.js.map +1 -0
- package/dist/esm/packages/PackageHostConfiguration.d.ts +2 -0
- package/dist/esm/packages/PackageHostConfiguration.d.ts.map +1 -1
- package/dist/esm/packages/PackageHostConfiguration.js +19 -3
- package/dist/esm/packages/PackageHostConfiguration.js.map +1 -1
- package/dist/esm/packages/index.d.ts +1 -0
- package/dist/esm/packages/index.d.ts.map +1 -1
- package/dist/esm/packages/index.js +1 -0
- package/dist/esm/packages/index.js.map +1 -1
- package/dist/esm/packages/isNetworkAsset.d.ts +2 -0
- package/dist/esm/packages/isNetworkAsset.d.ts.map +1 -0
- package/dist/esm/packages/isNetworkAsset.js +16 -0
- package/dist/esm/packages/isNetworkAsset.js.map +1 -0
- package/dist/esm/renderer/RenderBindingScopeContext.d.ts.map +1 -1
- package/dist/esm/renderer/RenderBindingScopeContext.js +17 -7
- package/dist/esm/renderer/RenderBindingScopeContext.js.map +1 -1
- package/dist/esm/renderer/index.d.ts +1 -0
- package/dist/esm/renderer/index.d.ts.map +1 -1
- package/dist/esm/renderer/index.js +1 -0
- package/dist/esm/renderer/index.js.map +1 -1
- package/dist/esm/renderer/useBoundQuery.d.ts +3 -0
- package/dist/esm/renderer/useBoundQuery.d.ts.map +1 -0
- package/dist/esm/renderer/useBoundQuery.js +48 -0
- package/dist/esm/renderer/useBoundQuery.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/navigation/DestinationResolution.ts +3 -0
- package/navigation/DialogResult.ts +8 -0
- package/navigation/SceneHistory.ts +24 -0
- package/navigation/SceneNavigationContext.tsx +16 -1
- package/navigation/SceneNavigationHost.tsx +30 -40
- package/navigation/SceneNavigationState.ts +19 -0
- package/navigation/SceneRoute.ts +12 -0
- package/navigation/createBrowserSceneHistory.ts +40 -0
- package/navigation/createMemorySceneHistory.ts +44 -0
- package/navigation/index.ts +10 -1
- package/navigation/matchSceneRoute.ts +45 -0
- package/navigation/resolveDestination.ts +1 -0
- package/navigation/sceneRoutesFrom.ts +24 -0
- package/navigation/useSceneHistoryNavigation.ts +80 -0
- package/package.json +5 -5
- package/packages/PackageHostConfiguration.ts +26 -3
- package/packages/index.ts +1 -0
- package/packages/isNetworkAsset.ts +15 -0
- package/renderer/RenderBindingScopeContext.tsx +12 -8
- package/renderer/index.ts +1 -0
- package/renderer/useBoundQuery.ts +50 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SceneNavigationState.d.ts","sourceRoot":"","sources":["../../../navigation/SceneNavigationState.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,MAAM,CAAC;IAGf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAGhB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SceneNavigationState.js","sourceRoot":"","sources":["../../../navigation/SceneNavigationState.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SceneRoute.d.ts","sourceRoot":"","sources":["../../../navigation/SceneRoute.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SceneRoute.js","sourceRoot":"","sources":["../../../navigation/SceneRoute.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SceneHistory } from './SceneHistory';
|
|
2
|
+
export type SceneBrowserWindow = Pick<Window, 'history' | 'location' | 'addEventListener' | 'removeEventListener'>;
|
|
3
|
+
export declare function createBrowserSceneHistory(browser?: SceneBrowserWindow, basePath?: string): SceneHistory;
|
|
4
|
+
//# sourceMappingURL=createBrowserSceneHistory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createBrowserSceneHistory.d.ts","sourceRoot":"","sources":["../../../navigation/createBrowserSceneHistory.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,kBAAkB,GAAG,qBAAqB,CAAC,CAAC;AASnH,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,kBAA2B,EAAE,QAAQ,SAAM,GAAG,YAAY,CAuB5G"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
const stateKey = 'sceneNavigation';
|
|
4
|
+
/**
|
|
5
|
+
* A history backed by the browser's `history` API under a base path such as `/app/`. Entries carry their
|
|
6
|
+
* navigation state, so back and forward restore the screen, outlet, parameters and dialog without
|
|
7
|
+
* re-resolving; an entry without state - a typed or bookmarked URL - is reported by URL alone.
|
|
8
|
+
*/ function createBrowserSceneHistory(browser = window, basePath = '/') {
|
|
9
|
+
const base = basePath.endsWith('/') ? basePath : `${basePath}/`;
|
|
10
|
+
const href = (url)=>`${base}${url ?? ''}`;
|
|
11
|
+
const location = ()=>{
|
|
12
|
+
const current = `${browser.location.pathname}${browser.location.search}`;
|
|
13
|
+
if (!current.startsWith(base)) return undefined;
|
|
14
|
+
const relative = current.substring(base.length);
|
|
15
|
+
return relative.length ? relative : undefined;
|
|
16
|
+
};
|
|
17
|
+
const stored = (value)=>value?.[stateKey];
|
|
18
|
+
return {
|
|
19
|
+
location,
|
|
20
|
+
state: ()=>stored(browser.history.state),
|
|
21
|
+
push: (state)=>browser.history.pushState({
|
|
22
|
+
[stateKey]: state
|
|
23
|
+
}, '', href(state.url)),
|
|
24
|
+
replace: (state)=>browser.history.replaceState({
|
|
25
|
+
[stateKey]: state
|
|
26
|
+
}, '', href(state.url)),
|
|
27
|
+
back: ()=>browser.history.back(),
|
|
28
|
+
listen: (listener)=>{
|
|
29
|
+
const onPopState = (event)=>listener(location(), stored(event.state));
|
|
30
|
+
browser.addEventListener('popstate', onPopState);
|
|
31
|
+
return ()=>browser.removeEventListener('popstate', onPopState);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { createBrowserSceneHistory };
|
|
37
|
+
//# sourceMappingURL=createBrowserSceneHistory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createBrowserSceneHistory.js","sources":["../../../navigation/createBrowserSceneHistory.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { SceneHistory } from './SceneHistory';\nimport { SceneNavigationState } from './SceneNavigationState';\n\n/** The part of `window` the browser history needs, so a host can pass its own frame's window. */\nexport type SceneBrowserWindow = Pick<Window, 'history' | 'location' | 'addEventListener' | 'removeEventListener'>;\n\nconst stateKey = 'sceneNavigation';\n\n/**\n * A history backed by the browser's `history` API under a base path such as `/app/`. Entries carry their\n * navigation state, so back and forward restore the screen, outlet, parameters and dialog without\n * re-resolving; an entry without state - a typed or bookmarked URL - is reported by URL alone.\n */\nexport function createBrowserSceneHistory(browser: SceneBrowserWindow = window, basePath = '/'): SceneHistory {\n const base = basePath.endsWith('/') ? basePath : `${basePath}/`;\n const href = (url: string | undefined) => `${base}${url ?? ''}`;\n const location = () => {\n const current = `${browser.location.pathname}${browser.location.search}`;\n if (!current.startsWith(base)) return undefined;\n const relative = current.substring(base.length);\n return relative.length ? relative : undefined;\n };\n const stored = (value: unknown) => (value as Record<string, SceneNavigationState> | null)?.[stateKey];\n\n return {\n location,\n state: () => stored(browser.history.state),\n push: state => browser.history.pushState({ [stateKey]: state }, '', href(state.url)),\n replace: state => browser.history.replaceState({ [stateKey]: state }, '', href(state.url)),\n back: () => browser.history.back(),\n listen: listener => {\n const onPopState = (event: PopStateEvent) => listener(location(), stored(event.state));\n browser.addEventListener('popstate', onPopState);\n return () => browser.removeEventListener('popstate', onPopState);\n },\n };\n}\n"],"names":["stateKey","createBrowserSceneHistory","browser","window","basePath","base","endsWith","href","url","location","current","pathname","search","startsWith","undefined","relative","substring","length","stored","value","state","history","push","pushState","replace","replaceState","back","listen","listener","onPopState","event","addEventListener","removeEventListener"],"mappings":"AAAA;AACA;AAQA,MAAMA,QAAAA,GAAW,iBAAA;AAEjB;;;;AAIC,IACM,SAASC,yBAAAA,CAA0BC,UAA8BC,MAAM,EAAEC,WAAW,GAAG,EAAA;IAC1F,MAAMC,IAAAA,GAAOD,SAASE,QAAQ,CAAC,OAAOF,QAAAA,GAAW,CAAA,EAAGA,QAAAA,CAAS,CAAC,CAAC;AAC/D,IAAA,MAAMG,OAAO,CAACC,GAAAA,GAA4B,CAAA,EAAGH,IAAAA,CAAAA,EAAOG,OAAO,EAAA,CAAA,CAAI;AAC/D,IAAA,MAAMC,QAAAA,GAAW,IAAA;QACb,MAAMC,OAAAA,GAAU,CAAA,EAAGR,OAAAA,CAAQO,QAAQ,CAACE,QAAQ,CAAA,EAAGT,OAAAA,CAAQO,QAAQ,CAACG,MAAM,CAAA,CAAE;AACxE,QAAA,IAAI,CAACF,OAAAA,CAAQG,UAAU,CAACR,OAAO,OAAOS,SAAAA;AACtC,QAAA,MAAMC,QAAAA,GAAWL,OAAAA,CAAQM,SAAS,CAACX,KAAKY,MAAM,CAAA;QAC9C,OAAOF,QAAAA,CAASE,MAAM,GAAGF,QAAAA,GAAWD,SAAAA;AACxC,IAAA,CAAA;AACA,IAAA,MAAMI,MAAAA,GAAS,CAACC,KAAAA,GAAoBA,KAAAA,GAAwDnB,QAAAA,CAAS;IAErG,OAAO;AACHS,QAAAA,QAAAA;AACAW,QAAAA,KAAAA,EAAO,IAAMF,MAAAA,CAAOhB,OAAAA,CAAQmB,OAAO,CAACD,KAAK,CAAA;AACzCE,QAAAA,IAAAA,EAAMF,CAAAA,KAAAA,GAASlB,OAAAA,CAAQmB,OAAO,CAACE,SAAS,CAAC;AAAE,gBAAA,CAACvB,WAAWoB;aAAM,EAAG,EAAA,EAAIb,IAAAA,CAAKa,KAAAA,CAAMZ,GAAG,CAAA,CAAA;AAClFgB,QAAAA,OAAAA,EAASJ,CAAAA,KAAAA,GAASlB,OAAAA,CAAQmB,OAAO,CAACI,YAAY,CAAC;AAAE,gBAAA,CAACzB,WAAWoB;aAAM,EAAG,EAAA,EAAIb,IAAAA,CAAKa,KAAAA,CAAMZ,GAAG,CAAA,CAAA;AACxFkB,QAAAA,IAAAA,EAAM,IAAMxB,OAAAA,CAAQmB,OAAO,CAACK,IAAI,EAAA;AAChCC,QAAAA,MAAAA,EAAQC,CAAAA,QAAAA,GAAAA;AACJ,YAAA,MAAMC,aAAa,CAACC,KAAAA,GAAyBF,SAASnB,QAAAA,EAAAA,EAAYS,MAAAA,CAAOY,MAAMV,KAAK,CAAA,CAAA;YACpFlB,OAAAA,CAAQ6B,gBAAgB,CAAC,UAAA,EAAYF,UAAAA,CAAAA;AACrC,YAAA,OAAO,IAAM3B,OAAAA,CAAQ8B,mBAAmB,CAAC,UAAA,EAAYH,UAAAA,CAAAA;AACzD,QAAA;AACJ,KAAA;AACJ;;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SceneHistory } from './SceneHistory';
|
|
2
|
+
import { SceneNavigationState } from './SceneNavigationState';
|
|
3
|
+
export declare function createMemorySceneHistory(initialUrl?: string): SceneHistory & {
|
|
4
|
+
forward(): void;
|
|
5
|
+
entries(): SceneNavigationState[];
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=createMemorySceneHistory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createMemorySceneHistory.d.ts","sourceRoot":"","sources":["../../../navigation/createMemorySceneHistory.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAO9D,wBAAgB,wBAAwB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG;IAAE,OAAO,IAAI,IAAI,CAAC;IAAC,OAAO,IAAI,oBAAoB,EAAE,CAAA;CAAE,CAgCnI"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
/**
|
|
4
|
+
* A history kept in memory with the same push, replace and back semantics as the browser's: pushing
|
|
5
|
+
* discards any forward entries, and going back notifies listeners. `forward` is exposed for hosts and specs
|
|
6
|
+
* that drive the stack themselves.
|
|
7
|
+
*/ function createMemorySceneHistory(initialUrl) {
|
|
8
|
+
const entries = [
|
|
9
|
+
{
|
|
10
|
+
url: initialUrl
|
|
11
|
+
}
|
|
12
|
+
];
|
|
13
|
+
let index = 0;
|
|
14
|
+
const listeners = new Set();
|
|
15
|
+
const notify = ()=>listeners.forEach((listener)=>listener(entries[index].url, entries[index].state));
|
|
16
|
+
return {
|
|
17
|
+
location: ()=>entries[index].url,
|
|
18
|
+
state: ()=>entries[index].state,
|
|
19
|
+
push: (state)=>{
|
|
20
|
+
entries.splice(index + 1, entries.length, {
|
|
21
|
+
url: state.url,
|
|
22
|
+
state
|
|
23
|
+
});
|
|
24
|
+
index = entries.length - 1;
|
|
25
|
+
},
|
|
26
|
+
replace: (state)=>{
|
|
27
|
+
entries[index] = {
|
|
28
|
+
url: state.url,
|
|
29
|
+
state
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
back: ()=>{
|
|
33
|
+
if (index === 0) return;
|
|
34
|
+
index--;
|
|
35
|
+
notify();
|
|
36
|
+
},
|
|
37
|
+
forward: ()=>{
|
|
38
|
+
if (index === entries.length - 1) return;
|
|
39
|
+
index++;
|
|
40
|
+
notify();
|
|
41
|
+
},
|
|
42
|
+
entries: ()=>entries.map((entry)=>entry.state).filter((state)=>state !== undefined),
|
|
43
|
+
listen: (listener)=>{
|
|
44
|
+
listeners.add(listener);
|
|
45
|
+
return ()=>listeners.delete(listener);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { createMemorySceneHistory };
|
|
51
|
+
//# sourceMappingURL=createMemorySceneHistory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createMemorySceneHistory.js","sources":["../../../navigation/createMemorySceneHistory.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { SceneHistory } from './SceneHistory';\nimport { SceneNavigationState } from './SceneNavigationState';\n\n/**\n * A history kept in memory with the same push, replace and back semantics as the browser's: pushing\n * discards any forward entries, and going back notifies listeners. `forward` is exposed for hosts and specs\n * that drive the stack themselves.\n */\nexport function createMemorySceneHistory(initialUrl?: string): SceneHistory & { forward(): void; entries(): SceneNavigationState[] } {\n const entries: { url?: string; state?: SceneNavigationState }[] = [{ url: initialUrl }];\n let index = 0;\n const listeners = new Set<(url: string | undefined, state: SceneNavigationState | undefined) => void>();\n const notify = () => listeners.forEach(listener => listener(entries[index].url, entries[index].state));\n\n return {\n location: () => entries[index].url,\n state: () => entries[index].state,\n push: state => {\n entries.splice(index + 1, entries.length, { url: state.url, state });\n index = entries.length - 1;\n },\n replace: state => {\n entries[index] = { url: state.url, state };\n },\n back: () => {\n if (index === 0) return;\n index--;\n notify();\n },\n forward: () => {\n if (index === entries.length - 1) return;\n index++;\n notify();\n },\n entries: () => entries.map(entry => entry.state).filter((state): state is SceneNavigationState => state !== undefined),\n listen: listener => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n"],"names":["createMemorySceneHistory","initialUrl","entries","url","index","listeners","Set","notify","forEach","listener","state","location","push","splice","length","replace","back","forward","map","entry","filter","undefined","listen","add","delete"],"mappings":"AAAA;AACA;AAKA;;;;IAKO,SAASA,wBAAAA,CAAyBC,UAAmB,EAAA;AACxD,IAAA,MAAMC,OAAAA,GAA4D;AAAC,QAAA;YAAEC,GAAAA,EAAKF;AAAW;AAAE,KAAA;AACvF,IAAA,IAAIG,KAAAA,GAAQ,CAAA;AACZ,IAAA,MAAMC,YAAY,IAAIC,GAAAA,EAAAA;AACtB,IAAA,MAAMC,SAAS,IAAMF,SAAAA,CAAUG,OAAO,CAACC,CAAAA,WAAYA,QAAAA,CAASP,OAAO,CAACE,KAAAA,CAAM,CAACD,GAAG,EAAED,OAAO,CAACE,KAAAA,CAAM,CAACM,KAAK,CAAA,CAAA;IAEpG,OAAO;AACHC,QAAAA,QAAAA,EAAU,IAAMT,OAAO,CAACE,KAAAA,CAAM,CAACD,GAAG;AAClCO,QAAAA,KAAAA,EAAO,IAAMR,OAAO,CAACE,KAAAA,CAAM,CAACM,KAAK;AACjCE,QAAAA,IAAAA,EAAMF,CAAAA,KAAAA,GAAAA;AACFR,YAAAA,OAAAA,CAAQW,MAAM,CAACT,KAAAA,GAAQ,CAAA,EAAGF,OAAAA,CAAQY,MAAM,EAAE;AAAEX,gBAAAA,GAAAA,EAAKO,MAAMP,GAAG;AAAEO,gBAAAA;AAAM,aAAA,CAAA;YAClEN,KAAAA,GAAQF,OAAAA,CAAQY,MAAM,GAAG,CAAA;AAC7B,QAAA,CAAA;AACAC,QAAAA,OAAAA,EAASL,CAAAA,KAAAA,GAAAA;YACLR,OAAO,CAACE,MAAM,GAAG;AAAED,gBAAAA,GAAAA,EAAKO,MAAMP,GAAG;AAAEO,gBAAAA;AAAM,aAAA;AAC7C,QAAA,CAAA;QACAM,IAAAA,EAAM,IAAA;AACF,YAAA,IAAIZ,UAAU,CAAA,EAAG;AACjBA,YAAAA,KAAAA,EAAAA;AACAG,YAAAA,MAAAA,EAAAA;AACJ,QAAA,CAAA;QACAU,OAAAA,EAAS,IAAA;AACL,YAAA,IAAIb,KAAAA,KAAUF,OAAAA,CAAQY,MAAM,GAAG,CAAA,EAAG;AAClCV,YAAAA,KAAAA,EAAAA;AACAG,YAAAA,MAAAA,EAAAA;AACJ,QAAA,CAAA;AACAL,QAAAA,OAAAA,EAAS,IAAMA,OAAAA,CAAQgB,GAAG,CAACC,CAAAA,KAAAA,GAASA,KAAAA,CAAMT,KAAK,CAAA,CAAEU,MAAM,CAAC,CAACV,QAAyCA,KAAAA,KAAUW,SAAAA,CAAAA;AAC5GC,QAAAA,MAAAA,EAAQb,CAAAA,QAAAA,GAAAA;AACJJ,YAAAA,SAAAA,CAAUkB,GAAG,CAACd,QAAAA,CAAAA;YACd,OAAO,IAAMJ,SAAAA,CAAUmB,MAAM,CAACf,QAAAA,CAAAA;AAClC,QAAA;AACJ,KAAA;AACJ;;"}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
export * from './DestinationResolution';
|
|
2
|
+
export * from './DialogResult';
|
|
3
|
+
export * from './SceneHistory';
|
|
2
4
|
export * from './SceneNavigationContext';
|
|
3
5
|
export * from './SceneNavigationHost';
|
|
4
|
-
export * from './
|
|
6
|
+
export * from './SceneNavigationState';
|
|
7
|
+
export * from './SceneRoute';
|
|
8
|
+
export * from './createBrowserSceneHistory';
|
|
9
|
+
export * from './createMemorySceneHistory';
|
|
5
10
|
export * from './diagnoseRenderedNavigation';
|
|
6
11
|
export * from './identityRoute';
|
|
12
|
+
export * from './matchSceneRoute';
|
|
7
13
|
export * from './navigationRouteKey';
|
|
14
|
+
export * from './resolveDestination';
|
|
15
|
+
export * from './sceneRoutesFrom';
|
|
16
|
+
export * from './useSceneHistoryNavigation';
|
|
8
17
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../navigation/index.ts"],"names":[],"mappings":"AAGA,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../navigation/index.ts"],"names":[],"mappings":"AAGA,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC"}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
export * from './DestinationResolution';
|
|
2
|
+
export * from './DialogResult';
|
|
3
|
+
export * from './SceneHistory';
|
|
2
4
|
export * from './SceneNavigationContext';
|
|
3
5
|
export * from './SceneNavigationHost';
|
|
4
|
-
export * from './
|
|
6
|
+
export * from './SceneNavigationState';
|
|
7
|
+
export * from './SceneRoute';
|
|
8
|
+
export * from './createBrowserSceneHistory';
|
|
9
|
+
export * from './createMemorySceneHistory';
|
|
5
10
|
export * from './diagnoseRenderedNavigation';
|
|
6
11
|
export * from './identityRoute';
|
|
12
|
+
export * from './matchSceneRoute';
|
|
7
13
|
export * from './navigationRouteKey';
|
|
14
|
+
export * from './resolveDestination';
|
|
15
|
+
export * from './sceneRoutesFrom';
|
|
16
|
+
export * from './useSceneHistoryNavigation';
|
|
8
17
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../navigation/index.ts"],"names":[],"mappings":"AAGA,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../navigation/index.ts"],"names":[],"mappings":"AAGA,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SceneRoute } from './SceneRoute';
|
|
2
|
+
export interface SceneRouteMatch {
|
|
3
|
+
route: SceneRoute;
|
|
4
|
+
parameters: Record<string, string>;
|
|
5
|
+
}
|
|
6
|
+
export declare function matchSceneRoute(url: string, routes: SceneRoute[]): SceneRouteMatch | undefined;
|
|
7
|
+
//# sourceMappingURL=matchSceneRoute.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchSceneRoute.d.ts","sourceRoot":"","sources":["../../../navigation/matchSceneRoute.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAOD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,eAAe,GAAG,SAAS,CAwB9F"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
/**
|
|
4
|
+
* Matches a URL - as a deep link, a refresh or a typed address delivers it - against route templates.
|
|
5
|
+
* `{name}` segments capture path parameters; the query string adds the rest. Literal segments win over
|
|
6
|
+
* parameters, so `orders/new` beats `orders/{orderId}`, and routes are otherwise tried in the given order.
|
|
7
|
+
*/ function matchSceneRoute(url, routes) {
|
|
8
|
+
const [path, query = ''] = url.split('?', 2);
|
|
9
|
+
const segments = path.split('/').filter((segment)=>segment.length > 0).map(decodeURIComponent);
|
|
10
|
+
const queryParameters = Object.fromEntries(new URLSearchParams(query));
|
|
11
|
+
const candidates = routes.map((route, order)=>({
|
|
12
|
+
route,
|
|
13
|
+
order,
|
|
14
|
+
template: route.route.split('/').filter((segment)=>segment.length > 0)
|
|
15
|
+
})).filter((candidate)=>candidate.template.length === segments.length).sort((left, right)=>literalCount(right.template) - literalCount(left.template) || left.order - right.order);
|
|
16
|
+
for (const { route, template } of candidates){
|
|
17
|
+
const parameters = {};
|
|
18
|
+
const matches = template.every((part, index)=>{
|
|
19
|
+
const name = /^\{([^}]+)\}$/.exec(part)?.[1];
|
|
20
|
+
if (name) {
|
|
21
|
+
parameters[name] = segments[index];
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
return part === segments[index];
|
|
25
|
+
});
|
|
26
|
+
if (matches) return {
|
|
27
|
+
route,
|
|
28
|
+
parameters: {
|
|
29
|
+
...queryParameters,
|
|
30
|
+
...parameters
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
function literalCount(template) {
|
|
37
|
+
return template.filter((part)=>!/^\{[^}]+\}$/.test(part)).length;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { matchSceneRoute };
|
|
41
|
+
//# sourceMappingURL=matchSceneRoute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchSceneRoute.js","sources":["../../../navigation/matchSceneRoute.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { SceneRoute } from './SceneRoute';\n\n/** A URL matched to the route that opens it. */\nexport interface SceneRouteMatch {\n route: SceneRoute;\n parameters: Record<string, string>;\n}\n\n/**\n * Matches a URL - as a deep link, a refresh or a typed address delivers it - against route templates.\n * `{name}` segments capture path parameters; the query string adds the rest. Literal segments win over\n * parameters, so `orders/new` beats `orders/{orderId}`, and routes are otherwise tried in the given order.\n */\nexport function matchSceneRoute(url: string, routes: SceneRoute[]): SceneRouteMatch | undefined {\n const [path, query = ''] = url.split('?', 2);\n const segments = path.split('/').filter(segment => segment.length > 0).map(decodeURIComponent);\n const queryParameters = Object.fromEntries(new URLSearchParams(query));\n\n const candidates = routes\n .map((route, order) => ({ route, order, template: route.route.split('/').filter(segment => segment.length > 0) }))\n .filter(candidate => candidate.template.length === segments.length)\n .sort((left, right) => literalCount(right.template) - literalCount(left.template) || left.order - right.order);\n\n for (const { route, template } of candidates) {\n const parameters: Record<string, string> = {};\n const matches = template.every((part, index) => {\n const name = /^\\{([^}]+)\\}$/.exec(part)?.[1];\n if (name) {\n parameters[name] = segments[index];\n return true;\n }\n return part === segments[index];\n });\n if (matches) return { route, parameters: { ...queryParameters, ...parameters } };\n }\n\n return undefined;\n}\n\nfunction literalCount(template: string[]): number {\n return template.filter(part => !/^\\{[^}]+\\}$/.test(part)).length;\n}\n"],"names":["matchSceneRoute","url","routes","path","query","split","segments","filter","segment","length","map","decodeURIComponent","queryParameters","Object","fromEntries","URLSearchParams","candidates","route","order","template","candidate","sort","left","right","literalCount","parameters","matches","every","part","index","name","exec","undefined","test"],"mappings":"AAAA;AACA;AAUA;;;;AAIC,IACM,SAASA,eAAAA,CAAgBC,GAAW,EAAEC,MAAoB,EAAA;IAC7D,MAAM,CAACC,MAAMC,KAAAA,GAAQ,EAAE,CAAC,GAAGH,GAAAA,CAAII,KAAK,CAAC,GAAA,EAAK,CAAA,CAAA;AAC1C,IAAA,MAAMC,QAAAA,GAAWH,IAAAA,CAAKE,KAAK,CAAC,KAAKE,MAAM,CAACC,CAAAA,OAAAA,GAAWA,OAAAA,CAAQC,MAAM,GAAG,CAAA,CAAA,CAAGC,GAAG,CAACC,kBAAAA,CAAAA;AAC3E,IAAA,MAAMC,eAAAA,GAAkBC,MAAAA,CAAOC,WAAW,CAAC,IAAIC,eAAAA,CAAgBX,KAAAA,CAAAA,CAAAA;AAE/D,IAAA,MAAMY,aAAad,MAAAA,CACdQ,GAAG,CAAC,CAACO,KAAAA,EAAOC,SAAW;AAAED,YAAAA,KAAAA;AAAOC,YAAAA,KAAAA;AAAOC,YAAAA,QAAAA,EAAUF,KAAAA,CAAMA,KAAK,CAACZ,KAAK,CAAC,GAAA,CAAA,CAAKE,MAAM,CAACC,CAAAA,OAAAA,GAAWA,OAAAA,CAAQC,MAAM,GAAG,CAAA;AAAG,SAAA,CAAA,CAAA,CAC9GF,MAAM,CAACa,CAAAA,SAAAA,GAAaA,SAAAA,CAAUD,QAAQ,CAACV,MAAM,KAAKH,QAAAA,CAASG,MAAM,EACjEY,IAAI,CAAC,CAACC,IAAAA,EAAMC,KAAAA,GAAUC,YAAAA,CAAaD,KAAAA,CAAMJ,QAAQ,CAAA,GAAIK,YAAAA,CAAaF,IAAAA,CAAKH,QAAQ,CAAA,IAAKG,IAAAA,CAAKJ,KAAK,GAAGK,MAAML,KAAK,CAAA;AAEjH,IAAA,KAAK,MAAM,EAAED,KAAK,EAAEE,QAAQ,EAAE,IAAIH,UAAAA,CAAY;AAC1C,QAAA,MAAMS,aAAqC,EAAC;AAC5C,QAAA,MAAMC,OAAAA,GAAUP,QAAAA,CAASQ,KAAK,CAAC,CAACC,IAAAA,EAAMC,KAAAA,GAAAA;AAClC,YAAA,MAAMC,OAAO,eAAA,CAAgBC,IAAI,CAACH,IAAAA,CAAAA,GAAQ,CAAA,CAAE;AAC5C,YAAA,IAAIE,IAAAA,EAAM;AACNL,gBAAAA,UAAU,CAACK,IAAAA,CAAK,GAAGxB,QAAQ,CAACuB,KAAAA,CAAM;gBAClC,OAAO,IAAA;AACX,YAAA;YACA,OAAOD,IAAAA,KAAStB,QAAQ,CAACuB,KAAAA,CAAM;AACnC,QAAA,CAAA,CAAA;AACA,QAAA,IAAIH,SAAS,OAAO;AAAET,YAAAA,KAAAA;YAAOQ,UAAAA,EAAY;AAAE,gBAAA,GAAGb,eAAe;AAAE,gBAAA,GAAGa;AAAW;AAAE,SAAA;AACnF,IAAA;IAEA,OAAOO,SAAAA;AACX;AAEA,SAASR,aAAaL,QAAkB,EAAA;IACpC,OAAOA,QAAAA,CAASZ,MAAM,CAACqB,CAAAA,IAAAA,GAAQ,CAAC,aAAA,CAAcK,IAAI,CAACL,IAAAA,CAAAA,CAAAA,CAAOnB,MAAM;AACpE;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveDestination.d.ts","sourceRoot":"","sources":["../../../navigation/resolveDestination.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAA4B,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAmB,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAMhE,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,oBAAoB,EAAE,KAAK,GAAE,YAAiB,GAAG,qBAAqB,
|
|
1
|
+
{"version":3,"file":"resolveDestination.d.ts","sourceRoot":"","sources":["../../../navigation/resolveDestination.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAA4B,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAmB,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAMhE,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,oBAAoB,EAAE,KAAK,GAAE,YAAiB,GAAG,qBAAqB,CAkBrH"}
|
|
@@ -21,6 +21,7 @@ import { identityRoute } from './identityRoute.js';
|
|
|
21
21
|
url,
|
|
22
22
|
outlet: destination.outlet,
|
|
23
23
|
dialog: destination.dialog,
|
|
24
|
+
parameters: Object.fromEntries(parameters),
|
|
24
25
|
action: kind === DestinationKind.Dialog ? 'openDialog' : kind === DestinationKind.External ? 'openExternal' : 'navigate',
|
|
25
26
|
diagnostics
|
|
26
27
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveDestination.js","sources":["../../../navigation/resolveDestination.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { BindingScope, resolveBindingExpression } from '@cratis/scene.engine';\nimport { DestinationKind, DestinationReference } from '@cratis/scene.model';\nimport { DestinationResolution } from './DestinationResolution';\nimport { identityRoute } from './identityRoute';\n\n/**\n * Resolves a destination into a renderer-neutral navigation action, deep link and target outlet/dialog.\n */\nexport function resolveDestination(destination: DestinationReference, scope: BindingScope = {}): DestinationResolution {\n const diagnostics: string[] = [];\n const kind = destination.kind ?? (destination.dialog ? DestinationKind.Dialog : DestinationKind.Outlet);\n const parameters = Object.entries(destination.routeParameterBindings ?? {})\n .map(([name, binding]) => [name, String(resolveBindingExpression(binding, scope) ?? '')] as const);\n const base = destination.route ?? identityRoute(destination);\n if (!base && kind !== DestinationKind.Dialog) diagnostics.push('Destination has no routeable screen, stable identity or route.');\n\n const url = base ? appendParameters(base, parameters) : undefined;\n return {\n kind,\n url,\n outlet: destination.outlet,\n dialog: destination.dialog,\n action: kind === DestinationKind.Dialog ? 'openDialog' : kind === DestinationKind.External ? 'openExternal' : 'navigate',\n diagnostics,\n };\n}\n\nfunction appendParameters(route: string, parameters: readonly (readonly [string, string])[]): string {\n if (!parameters.length) return route;\n let replaced = route;\n const unused: string[] = [];\n for (const [name, value] of parameters) {\n const marker = `{${name}}`;\n if (replaced.includes(marker)) {\n replaced = replaced.split(marker).join(encodeURIComponent(value));\n } else {\n unused.push(`${encodeURIComponent(name)}=${encodeURIComponent(value)}`);\n }\n }\n\n return unused.length ? `${replaced}?${unused.join('&')}` : replaced;\n}\n"],"names":["resolveDestination","destination","scope","diagnostics","kind","dialog","DestinationKind","Dialog","Outlet","parameters","Object","entries","routeParameterBindings","map","name","binding","String","resolveBindingExpression","base","route","identityRoute","push","url","appendParameters","undefined","outlet","action","External","length","replaced","unused","value","marker","includes","split","join","encodeURIComponent"],"mappings":";;;;AAAA;AACA;AAOA;;AAEC,IACM,SAASA,kBAAAA,CAAmBC,WAAiC,EAAEC,KAAAA,GAAsB,EAAE,EAAA;AAC1F,IAAA,MAAMC,cAAwB,EAAE;AAChC,IAAA,MAAMC,IAAAA,GAAOH,WAAAA,CAAYG,IAAI,KAAKH,WAAAA,CAAYI,MAAM,GAAGC,eAAAA,CAAgBC,MAAM,GAAGD,eAAAA,CAAgBE,MAAM,CAAD;AACrG,IAAA,MAAMC,UAAAA,GAAaC,MAAAA,CAAOC,OAAO,CAACV,YAAYW,sBAAsB,IAAI,EAAC,CAAA,CACpEC,GAAG,CAAC,CAAC,CAACC,IAAAA,EAAMC,QAAQ,GAAK;AAACD,YAAAA,IAAAA;YAAME,MAAAA,CAAOC,wBAAAA,CAAyBF,SAASb,KAAAA,CAAAA,IAAU,EAAA;AAAI,SAAA,CAAA;AAC5F,IAAA,MAAMgB,IAAAA,GAAOjB,WAAAA,CAAYkB,KAAK,IAAIC,aAAAA,CAAcnB,WAAAA,CAAAA;IAChD,IAAI,CAACiB,QAAQd,IAAAA,KAASE,eAAAA,CAAgBC,MAAM,EAAEJ,WAAAA,CAAYkB,IAAI,CAAC,gEAAA,CAAA;AAE/D,IAAA,MAAMC,GAAAA,GAAMJ,IAAAA,GAAOK,gBAAAA,CAAiBL,IAAAA,EAAMT,UAAAA,CAAAA,GAAce,SAAAA;IACxD,OAAO;AACHpB,QAAAA,IAAAA;AACAkB,QAAAA,GAAAA;AACAG,QAAAA,MAAAA,EAAQxB,YAAYwB,MAAM;AAC1BpB,QAAAA,MAAAA,EAAQJ,YAAYI,MAAM;
|
|
1
|
+
{"version":3,"file":"resolveDestination.js","sources":["../../../navigation/resolveDestination.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { BindingScope, resolveBindingExpression } from '@cratis/scene.engine';\nimport { DestinationKind, DestinationReference } from '@cratis/scene.model';\nimport { DestinationResolution } from './DestinationResolution';\nimport { identityRoute } from './identityRoute';\n\n/**\n * Resolves a destination into a renderer-neutral navigation action, deep link and target outlet/dialog.\n */\nexport function resolveDestination(destination: DestinationReference, scope: BindingScope = {}): DestinationResolution {\n const diagnostics: string[] = [];\n const kind = destination.kind ?? (destination.dialog ? DestinationKind.Dialog : DestinationKind.Outlet);\n const parameters = Object.entries(destination.routeParameterBindings ?? {})\n .map(([name, binding]) => [name, String(resolveBindingExpression(binding, scope) ?? '')] as const);\n const base = destination.route ?? identityRoute(destination);\n if (!base && kind !== DestinationKind.Dialog) diagnostics.push('Destination has no routeable screen, stable identity or route.');\n\n const url = base ? appendParameters(base, parameters) : undefined;\n return {\n kind,\n url,\n outlet: destination.outlet,\n dialog: destination.dialog,\n parameters: Object.fromEntries(parameters),\n action: kind === DestinationKind.Dialog ? 'openDialog' : kind === DestinationKind.External ? 'openExternal' : 'navigate',\n diagnostics,\n };\n}\n\nfunction appendParameters(route: string, parameters: readonly (readonly [string, string])[]): string {\n if (!parameters.length) return route;\n let replaced = route;\n const unused: string[] = [];\n for (const [name, value] of parameters) {\n const marker = `{${name}}`;\n if (replaced.includes(marker)) {\n replaced = replaced.split(marker).join(encodeURIComponent(value));\n } else {\n unused.push(`${encodeURIComponent(name)}=${encodeURIComponent(value)}`);\n }\n }\n\n return unused.length ? `${replaced}?${unused.join('&')}` : replaced;\n}\n"],"names":["resolveDestination","destination","scope","diagnostics","kind","dialog","DestinationKind","Dialog","Outlet","parameters","Object","entries","routeParameterBindings","map","name","binding","String","resolveBindingExpression","base","route","identityRoute","push","url","appendParameters","undefined","outlet","fromEntries","action","External","length","replaced","unused","value","marker","includes","split","join","encodeURIComponent"],"mappings":";;;;AAAA;AACA;AAOA;;AAEC,IACM,SAASA,kBAAAA,CAAmBC,WAAiC,EAAEC,KAAAA,GAAsB,EAAE,EAAA;AAC1F,IAAA,MAAMC,cAAwB,EAAE;AAChC,IAAA,MAAMC,IAAAA,GAAOH,WAAAA,CAAYG,IAAI,KAAKH,WAAAA,CAAYI,MAAM,GAAGC,eAAAA,CAAgBC,MAAM,GAAGD,eAAAA,CAAgBE,MAAM,CAAD;AACrG,IAAA,MAAMC,UAAAA,GAAaC,MAAAA,CAAOC,OAAO,CAACV,YAAYW,sBAAsB,IAAI,EAAC,CAAA,CACpEC,GAAG,CAAC,CAAC,CAACC,IAAAA,EAAMC,QAAQ,GAAK;AAACD,YAAAA,IAAAA;YAAME,MAAAA,CAAOC,wBAAAA,CAAyBF,SAASb,KAAAA,CAAAA,IAAU,EAAA;AAAI,SAAA,CAAA;AAC5F,IAAA,MAAMgB,IAAAA,GAAOjB,WAAAA,CAAYkB,KAAK,IAAIC,aAAAA,CAAcnB,WAAAA,CAAAA;IAChD,IAAI,CAACiB,QAAQd,IAAAA,KAASE,eAAAA,CAAgBC,MAAM,EAAEJ,WAAAA,CAAYkB,IAAI,CAAC,gEAAA,CAAA;AAE/D,IAAA,MAAMC,GAAAA,GAAMJ,IAAAA,GAAOK,gBAAAA,CAAiBL,IAAAA,EAAMT,UAAAA,CAAAA,GAAce,SAAAA;IACxD,OAAO;AACHpB,QAAAA,IAAAA;AACAkB,QAAAA,GAAAA;AACAG,QAAAA,MAAAA,EAAQxB,YAAYwB,MAAM;AAC1BpB,QAAAA,MAAAA,EAAQJ,YAAYI,MAAM;QAC1BI,UAAAA,EAAYC,MAAAA,CAAOgB,WAAW,CAACjB,UAAAA,CAAAA;QAC/BkB,MAAAA,EAAQvB,IAAAA,KAASE,gBAAgBC,MAAM,GAAG,eAAeH,IAAAA,KAASE,eAAAA,CAAgBsB,QAAQ,GAAG,cAAA,GAAiB,UAAA;AAC9GzB,QAAAA;AACJ,KAAA;AACJ;AAEA,SAASoB,gBAAAA,CAAiBJ,KAAa,EAAEV,UAAkD,EAAA;AACvF,IAAA,IAAI,CAACA,UAAAA,CAAWoB,MAAM,EAAE,OAAOV,KAAAA;AAC/B,IAAA,IAAIW,QAAAA,GAAWX,KAAAA;AACf,IAAA,MAAMY,SAAmB,EAAE;AAC3B,IAAA,KAAK,MAAM,CAACjB,IAAAA,EAAMkB,KAAAA,CAAM,IAAIvB,UAAAA,CAAY;AACpC,QAAA,MAAMwB,SAAS,CAAC,CAAC,EAAEnB,IAAAA,CAAK,CAAC,CAAC;QAC1B,IAAIgB,QAAAA,CAASI,QAAQ,CAACD,MAAAA,CAAAA,EAAS;AAC3BH,YAAAA,QAAAA,GAAWA,SAASK,KAAK,CAACF,MAAAA,CAAAA,CAAQG,IAAI,CAACC,kBAAAA,CAAmBL,KAAAA,CAAAA,CAAAA;QAC9D,CAAA,MAAO;YACHD,MAAAA,CAAOV,IAAI,CAAC,CAAA,EAAGgB,kBAAAA,CAAmBvB,MAAM,CAAC,EAAEuB,mBAAmBL,KAAAA,CAAAA,CAAAA,CAAQ,CAAA;AAC1E,QAAA;AACJ,IAAA;IAEA,OAAOD,MAAAA,CAAOF,MAAM,GAAG,CAAA,EAAGC,QAAAA,CAAS,CAAC,EAAEC,MAAAA,CAAOK,IAAI,CAAC,GAAA,CAAA,CAAA,CAAM,GAAGN,QAAAA;AAC/D;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sceneRoutesFrom.d.ts","sourceRoot":"","sources":["../../../navigation/sceneRoutesFrom.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE5E,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAO1C,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,YAAY,GAAE,oBAAoB,EAAO,GAAG,UAAU,EAAE,CAW1G"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { DestinationKind } from '@cratis/scene.model';
|
|
2
|
+
import { identityRoute } from './identityRoute.js';
|
|
3
|
+
|
|
4
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
5
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
6
|
+
/**
|
|
7
|
+
* The routes a host can deep link to: every screen at its own name, and every outlet destination at its
|
|
8
|
+
* authored route override or identity route. A destination listed earlier wins a route it shares with a
|
|
9
|
+
* later one, and authored overrides come before the screen-name defaults.
|
|
10
|
+
*/ function sceneRoutesFrom(screens, destinations = []) {
|
|
11
|
+
const routes = [];
|
|
12
|
+
for (const destination of destinations){
|
|
13
|
+
const kind = destination.kind ?? (destination.dialog ? DestinationKind.Dialog : DestinationKind.Outlet);
|
|
14
|
+
const screen = destination.screen ?? destination.slice;
|
|
15
|
+
const route = destination.route ?? identityRoute(destination);
|
|
16
|
+
if (kind !== DestinationKind.Outlet || !screen || !route) continue;
|
|
17
|
+
routes.push({
|
|
18
|
+
route,
|
|
19
|
+
screen,
|
|
20
|
+
...destination.outlet ? {
|
|
21
|
+
outlet: destination.outlet
|
|
22
|
+
} : {}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return [
|
|
26
|
+
...routes,
|
|
27
|
+
...screens.map((screen)=>({
|
|
28
|
+
route: screen,
|
|
29
|
+
screen
|
|
30
|
+
}))
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { sceneRoutesFrom };
|
|
35
|
+
//# sourceMappingURL=sceneRoutesFrom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sceneRoutesFrom.js","sources":["../../../navigation/sceneRoutesFrom.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DestinationKind, DestinationReference } from '@cratis/scene.model';\nimport { identityRoute } from './identityRoute';\nimport { SceneRoute } from './SceneRoute';\n\n/**\n * The routes a host can deep link to: every screen at its own name, and every outlet destination at its\n * authored route override or identity route. A destination listed earlier wins a route it shares with a\n * later one, and authored overrides come before the screen-name defaults.\n */\nexport function sceneRoutesFrom(screens: string[], destinations: DestinationReference[] = []): SceneRoute[] {\n const routes: SceneRoute[] = [];\n for (const destination of destinations) {\n const kind = destination.kind ?? (destination.dialog ? DestinationKind.Dialog : DestinationKind.Outlet);\n const screen = destination.screen ?? destination.slice;\n const route = destination.route ?? identityRoute(destination);\n if (kind !== DestinationKind.Outlet || !screen || !route) continue;\n routes.push({ route, screen, ...(destination.outlet ? { outlet: destination.outlet } : {}) });\n }\n\n return [...routes, ...screens.map(screen => ({ route: screen, screen }))];\n}\n"],"names":["sceneRoutesFrom","screens","destinations","routes","destination","kind","dialog","DestinationKind","Dialog","Outlet","screen","slice","route","identityRoute","push","outlet","map"],"mappings":";;;AAAA;AACA;AAMA;;;;AAIC,IACM,SAASA,eAAAA,CAAgBC,OAAiB,EAAEC,eAAuC,EAAE,EAAA;AACxF,IAAA,MAAMC,SAAuB,EAAE;IAC/B,KAAK,MAAMC,eAAeF,YAAAA,CAAc;AACpC,QAAA,MAAMG,IAAAA,GAAOD,WAAAA,CAAYC,IAAI,KAAKD,WAAAA,CAAYE,MAAM,GAAGC,eAAAA,CAAgBC,MAAM,GAAGD,eAAAA,CAAgBE,MAAM,CAAD;AACrG,QAAA,MAAMC,MAAAA,GAASN,WAAAA,CAAYM,MAAM,IAAIN,YAAYO,KAAK;AACtD,QAAA,MAAMC,KAAAA,GAAQR,WAAAA,CAAYQ,KAAK,IAAIC,aAAAA,CAAcT,WAAAA,CAAAA;AACjD,QAAA,IAAIC,SAASE,eAAAA,CAAgBE,MAAM,IAAI,CAACC,MAAAA,IAAU,CAACE,KAAAA,EAAO;AAC1DT,QAAAA,MAAAA,CAAOW,IAAI,CAAC;AAAEF,YAAAA,KAAAA;AAAOF,YAAAA,MAAAA;YAAQ,GAAIN,WAAAA,CAAYW,MAAM,GAAG;AAAEA,gBAAAA,MAAAA,EAAQX,YAAYW;AAAO,aAAA,GAAI;AAAI,SAAA,CAAA;AAC/F,IAAA;IAEA,OAAO;AAAIZ,QAAAA,GAAAA,MAAAA;AAAWF,QAAAA,GAAAA,OAAAA,CAAQe,GAAG,CAACN,CAAAA,MAAAA,IAAW;gBAAEE,KAAAA,EAAOF,MAAAA;AAAQA,gBAAAA;aAAO,CAAA;AAAI,KAAA;AAC7E;;"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { BindingScope } from '@cratis/scene.engine';
|
|
2
|
+
import { SceneHistory } from './SceneHistory';
|
|
3
|
+
import { SceneNavigationContextValue } from './SceneNavigationContext';
|
|
4
|
+
import { SceneRoute } from './SceneRoute';
|
|
5
|
+
export declare function useSceneHistoryNavigation(history: SceneHistory, routes: SceneRoute[], initialScreen: string, bindingScope: BindingScope): SceneNavigationContextValue;
|
|
6
|
+
//# sourceMappingURL=useSceneHistoryNavigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSceneHistoryNavigation.d.ts","sourceRoot":"","sources":["../../../navigation/useSceneHistoryNavigation.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAKpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAO1C,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,GAAG,2BAA2B,CA4DrK"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { useCallback, useMemo, useState, useRef, useEffect } from 'react';
|
|
2
|
+
import { DestinationKind } from '@cratis/scene.model';
|
|
3
|
+
import { matchSceneRoute } from './matchSceneRoute.js';
|
|
4
|
+
import { resolveDestination } from './resolveDestination.js';
|
|
5
|
+
|
|
6
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
7
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
8
|
+
/**
|
|
9
|
+
* Keeps a navigation host's state in a {@link SceneHistory}: every navigation and every dialog is an entry,
|
|
10
|
+
* so back and forward step through them, a refresh restores the stored entry, and a deep link is matched
|
|
11
|
+
* against the route table. Closing a dialog goes back to the entry that opened it.
|
|
12
|
+
*/ function useSceneHistoryNavigation(history, routes, initialScreen, bindingScope) {
|
|
13
|
+
const fromLocation = useCallback((url)=>{
|
|
14
|
+
const match = url ? matchSceneRoute(url, routes) : undefined;
|
|
15
|
+
return match ? {
|
|
16
|
+
screen: match.route.screen,
|
|
17
|
+
url,
|
|
18
|
+
outlet: match.route.outlet,
|
|
19
|
+
parameters: match.parameters
|
|
20
|
+
} : undefined;
|
|
21
|
+
}, [
|
|
22
|
+
routes
|
|
23
|
+
]);
|
|
24
|
+
const fallback = useMemo(()=>({
|
|
25
|
+
screen: initialScreen,
|
|
26
|
+
url: initialScreen,
|
|
27
|
+
parameters: {}
|
|
28
|
+
}), [
|
|
29
|
+
initialScreen
|
|
30
|
+
]);
|
|
31
|
+
const [unresolvedUrl] = useState(()=>{
|
|
32
|
+
const url = history.location();
|
|
33
|
+
return !history.state() && url && !fromLocation(url) ? url : undefined;
|
|
34
|
+
});
|
|
35
|
+
const [state, setState] = useState(()=>history.state() ?? fromLocation(history.location()) ?? fallback);
|
|
36
|
+
const [dialogResult, setDialogResult] = useState();
|
|
37
|
+
// Back and forward restore the stored entry, or match a URL the host never wrote against the current routes.
|
|
38
|
+
const restore = useRef((url, stored)=>stored ?? fromLocation(url) ?? fallback);
|
|
39
|
+
restore.current = (url, stored)=>stored ?? fromLocation(url) ?? fallback;
|
|
40
|
+
const initialState = useRef(state);
|
|
41
|
+
// The current entry is written once, when a history is attached; later entries are written by navigate.
|
|
42
|
+
useEffect(()=>{
|
|
43
|
+
history.replace(initialState.current);
|
|
44
|
+
return history.listen((url, stored)=>setState(restore.current(url, stored)));
|
|
45
|
+
}, [
|
|
46
|
+
history
|
|
47
|
+
]);
|
|
48
|
+
const go = useCallback((next)=>{
|
|
49
|
+
history.push(next);
|
|
50
|
+
setState(next);
|
|
51
|
+
}, [
|
|
52
|
+
history
|
|
53
|
+
]);
|
|
54
|
+
const navigate = useCallback((destination)=>{
|
|
55
|
+
const resolution = resolveDestination(destination, bindingScope);
|
|
56
|
+
if (resolution.kind === DestinationKind.Dialog) {
|
|
57
|
+
if (resolution.dialog) go({
|
|
58
|
+
...state,
|
|
59
|
+
dialog: resolution.dialog
|
|
60
|
+
});
|
|
61
|
+
} else if (resolution.kind !== DestinationKind.External) {
|
|
62
|
+
go({
|
|
63
|
+
screen: destination.screen ?? destination.slice ?? state.screen,
|
|
64
|
+
url: resolution.url,
|
|
65
|
+
outlet: resolution.outlet,
|
|
66
|
+
parameters: resolution.parameters
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return resolution;
|
|
70
|
+
}, [
|
|
71
|
+
bindingScope,
|
|
72
|
+
go,
|
|
73
|
+
state
|
|
74
|
+
]);
|
|
75
|
+
const closeDialog = useCallback((result)=>{
|
|
76
|
+
if (!state.dialog) return;
|
|
77
|
+
setDialogResult({
|
|
78
|
+
dialog: state.dialog,
|
|
79
|
+
result
|
|
80
|
+
});
|
|
81
|
+
history.back();
|
|
82
|
+
}, [
|
|
83
|
+
history,
|
|
84
|
+
state.dialog
|
|
85
|
+
]);
|
|
86
|
+
return useMemo(()=>({
|
|
87
|
+
currentScreen: state.screen,
|
|
88
|
+
currentUrl: state.url,
|
|
89
|
+
currentOutlet: state.outlet,
|
|
90
|
+
currentDialog: state.dialog,
|
|
91
|
+
currentParameters: state.parameters,
|
|
92
|
+
dialogResult,
|
|
93
|
+
unresolvedUrl,
|
|
94
|
+
bindingScope,
|
|
95
|
+
navigate,
|
|
96
|
+
closeDialog,
|
|
97
|
+
back: ()=>history.back()
|
|
98
|
+
}), [
|
|
99
|
+
bindingScope,
|
|
100
|
+
closeDialog,
|
|
101
|
+
dialogResult,
|
|
102
|
+
history,
|
|
103
|
+
navigate,
|
|
104
|
+
state,
|
|
105
|
+
unresolvedUrl
|
|
106
|
+
]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export { useSceneHistoryNavigation };
|
|
110
|
+
//# sourceMappingURL=useSceneHistoryNavigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSceneHistoryNavigation.js","sources":["../../../navigation/useSceneHistoryNavigation.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { BindingScope } from '@cratis/scene.engine';\nimport { DestinationKind, DestinationReference } from '@cratis/scene.model';\nimport { DialogResult } from './DialogResult';\nimport { matchSceneRoute } from './matchSceneRoute';\nimport { resolveDestination } from './resolveDestination';\nimport { SceneHistory } from './SceneHistory';\nimport { SceneNavigationContextValue } from './SceneNavigationContext';\nimport { SceneNavigationState } from './SceneNavigationState';\nimport { SceneRoute } from './SceneRoute';\n\n/**\n * Keeps a navigation host's state in a {@link SceneHistory}: every navigation and every dialog is an entry,\n * so back and forward step through them, a refresh restores the stored entry, and a deep link is matched\n * against the route table. Closing a dialog goes back to the entry that opened it.\n */\nexport function useSceneHistoryNavigation(history: SceneHistory, routes: SceneRoute[], initialScreen: string, bindingScope: BindingScope): SceneNavigationContextValue {\n const fromLocation = useCallback((url: string | undefined): SceneNavigationState | undefined => {\n const match = url ? matchSceneRoute(url, routes) : undefined;\n return match ? { screen: match.route.screen, url, outlet: match.route.outlet, parameters: match.parameters } : undefined;\n }, [routes]);\n const fallback = useMemo<SceneNavigationState>(() => ({ screen: initialScreen, url: initialScreen, parameters: {} }), [initialScreen]);\n\n const [unresolvedUrl] = useState(() => {\n const url = history.location();\n return !history.state() && url && !fromLocation(url) ? url : undefined;\n });\n const [state, setState] = useState<SceneNavigationState>(() => history.state() ?? fromLocation(history.location()) ?? fallback);\n const [dialogResult, setDialogResult] = useState<DialogResult>();\n\n // Back and forward restore the stored entry, or match a URL the host never wrote against the current routes.\n const restore = useRef((url: string | undefined, stored: SceneNavigationState | undefined) => stored ?? fromLocation(url) ?? fallback);\n restore.current = (url, stored) => stored ?? fromLocation(url) ?? fallback;\n const initialState = useRef(state);\n\n // The current entry is written once, when a history is attached; later entries are written by navigate.\n useEffect(() => {\n history.replace(initialState.current);\n return history.listen((url, stored) => setState(restore.current(url, stored)));\n }, [history]);\n\n const go = useCallback((next: SceneNavigationState) => {\n history.push(next);\n setState(next);\n }, [history]);\n\n const navigate = useCallback((destination: DestinationReference) => {\n const resolution = resolveDestination(destination, bindingScope);\n if (resolution.kind === DestinationKind.Dialog) {\n if (resolution.dialog) go({ ...state, dialog: resolution.dialog });\n } else if (resolution.kind !== DestinationKind.External) {\n go({ screen: destination.screen ?? destination.slice ?? state.screen, url: resolution.url, outlet: resolution.outlet, parameters: resolution.parameters });\n }\n\n return resolution;\n }, [bindingScope, go, state]);\n\n const closeDialog = useCallback((result?: unknown) => {\n if (!state.dialog) return;\n setDialogResult({ dialog: state.dialog, result });\n history.back();\n }, [history, state.dialog]);\n\n return useMemo(() => ({\n currentScreen: state.screen,\n currentUrl: state.url,\n currentOutlet: state.outlet,\n currentDialog: state.dialog,\n currentParameters: state.parameters,\n dialogResult,\n unresolvedUrl,\n bindingScope,\n navigate,\n closeDialog,\n back: () => history.back(),\n }), [bindingScope, closeDialog, dialogResult, history, navigate, state, unresolvedUrl]);\n}\n"],"names":["useSceneHistoryNavigation","history","routes","initialScreen","bindingScope","fromLocation","useCallback","url","match","matchSceneRoute","undefined","screen","route","outlet","parameters","fallback","useMemo","unresolvedUrl","useState","location","state","setState","dialogResult","setDialogResult","restore","useRef","stored","current","initialState","useEffect","replace","listen","go","next","push","navigate","destination","resolution","resolveDestination","kind","DestinationKind","Dialog","dialog","External","slice","closeDialog","result","back","currentScreen","currentUrl","currentOutlet","currentDialog","currentParameters"],"mappings":"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"}
|
|
@@ -20,6 +20,8 @@ export interface ResolvedPackageHost {
|
|
|
20
20
|
screenTemplates: ScreenTemplate[];
|
|
21
21
|
dialogTemplates: DialogTemplate[];
|
|
22
22
|
themes: Theme[];
|
|
23
|
+
layout?: Layout;
|
|
24
|
+
theme?: Theme;
|
|
23
25
|
templates: TemplateCatalogEntry[];
|
|
24
26
|
icons: IconAdapterRegistry;
|
|
25
27
|
assets: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PackageHostConfiguration.d.ts","sourceRoot":"","sources":["../../../packages/PackageHostConfiguration.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"PackageHostConfiguration.d.ts","sourceRoot":"","sources":["../../../packages/PackageHostConfiguration.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EAAE,oBAAoB,EAA6E,MAAM,sBAAsB,CAAC;AACvI,OAAO,EAAE,mBAAmB,EAA6B,MAAM,8BAA8B,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAyB,MAAM,sBAAsB,CAAC;AAGzG,MAAM,WAAW,iBAAiB;IAC9B,sBAAsB,EAAE,OAAO,CAAC;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAG5B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACrC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,OAAO,EAAE,SAAS,CAAC;IACnB,MAAM,EAAE,iBAAiB,CAAC;IAG1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAChC,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,UAAU,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;IACtD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,MAAM,EAAE,KAAK,EAAE,CAAC;IAGhB,MAAM,CAAC,EAAE,MAAM,CAAC;IAGhB,KAAK,CAAC,EAAE,KAAK,CAAC;IAMd,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAKD,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,wBAAwB,GAAG,mBAAmB,CAsF/F"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { resolvePackageDependencies, describeTemplateCatalog } from '@cratis/scene.engine';
|
|
1
|
+
import { resolvePackageDependencies, incompatiblePackages, describeTemplateCatalog } from '@cratis/scene.engine';
|
|
2
2
|
import { createIconAdapterRegistry } from '../icons/IconAdapterRegistry.js';
|
|
3
3
|
import { validatePackageBundle, mergePackageRegistries } from './ScenePackageBundle.js';
|
|
4
|
+
import { isNetworkAsset } from './isNetworkAsset.js';
|
|
4
5
|
|
|
5
6
|
// Copyright (c) Cratis. All rights reserved.
|
|
6
7
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
@@ -39,8 +40,9 @@ import { validatePackageBundle, mergePackageRegistries } from './ScenePackageBun
|
|
|
39
40
|
diagnostics.push(`Package '${packageName}' provides executable design-time contributions, but host policy forbids them`);
|
|
40
41
|
}
|
|
41
42
|
const packageAssets = bundle.manifest.assets ?? [];
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
const networkAssets = packageAssets.filter(isNetworkAsset);
|
|
44
|
+
if (!configuration.policy.allowNetworkAssets && networkAssets.length > 0) {
|
|
45
|
+
diagnostics.push(`Package '${packageName}' declares network assets (${networkAssets.join(', ')}), but host policy forbids them`);
|
|
44
46
|
}
|
|
45
47
|
assets.push(...packageAssets);
|
|
46
48
|
for (const dependency of bundle.manifest.runtimeSingletons ?? []){
|
|
@@ -52,6 +54,18 @@ import { validatePackageBundle, mergePackageRegistries } from './ScenePackageBun
|
|
|
52
54
|
}
|
|
53
55
|
bundles.push(bundle);
|
|
54
56
|
}
|
|
57
|
+
const layouts = bundles.flatMap((bundle)=>bundle.layouts ?? []);
|
|
58
|
+
const themes = bundles.flatMap((bundle)=>bundle.themes ?? []);
|
|
59
|
+
const layout = configuration.profile.layout ? layouts.find((candidate)=>candidate.name === configuration.profile.layout) : undefined;
|
|
60
|
+
const theme = configuration.profile.theme ? themes.find((candidate)=>candidate.name === configuration.profile.theme) : undefined;
|
|
61
|
+
if (configuration.profile.layout && !layout) {
|
|
62
|
+
diagnostics.push(`UI profile '${configuration.profile.name}' uses layout '${configuration.profile.layout}', which no approved package provides`);
|
|
63
|
+
}
|
|
64
|
+
if (configuration.profile.theme && !theme) {
|
|
65
|
+
diagnostics.push(`UI profile '${configuration.profile.name}' uses theme '${configuration.profile.theme}', which no approved package provides`);
|
|
66
|
+
} else if (theme && incompatiblePackages(theme, configuration.profile).length > 0) {
|
|
67
|
+
diagnostics.push(`Theme '${theme.name}' is not compatible with ${incompatiblePackages(theme, configuration.profile).join(', ')} in UI profile '${configuration.profile.name}'`);
|
|
68
|
+
}
|
|
55
69
|
const blocked = diagnostics.length > 0;
|
|
56
70
|
const approved = blocked ? [] : bundles;
|
|
57
71
|
const approvedAssets = blocked ? [] : assets;
|
|
@@ -62,6 +76,8 @@ import { validatePackageBundle, mergePackageRegistries } from './ScenePackageBun
|
|
|
62
76
|
screenTemplates: approved.flatMap((bundle)=>bundle.screenTemplates ?? []),
|
|
63
77
|
dialogTemplates: approved.flatMap((bundle)=>bundle.dialogTemplates ?? []),
|
|
64
78
|
themes: approved.flatMap((bundle)=>bundle.themes ?? []),
|
|
79
|
+
layout: blocked ? undefined : layout,
|
|
80
|
+
theme: blocked ? undefined : theme,
|
|
65
81
|
templates: describeTemplateCatalog(approved, configuration.sceneVersion),
|
|
66
82
|
icons: createIconAdapterRegistry(approved.map((bundle)=>bundle.iconLibrary?.adapter).filter((adapter)=>adapter !== undefined)),
|
|
67
83
|
assets: approvedAssets,
|