@noego/wood 0.1.1 → 0.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noego/wood",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -18,8 +18,10 @@
18
18
  "dist",
19
19
  "bin",
20
20
  "loaders",
21
- "src/stick/WoodRecursiveRender.svelte",
22
- "src/components/"
21
+ "src/components/",
22
+ "src/client/controller_contract.ts",
23
+ "src/controller/controller_lifecycle.ts",
24
+ "src/navigation/navigation_identity.ts"
23
25
  ],
24
26
  "exports": {
25
27
  ".": {
@@ -0,0 +1,18 @@
1
+ import type { ControllerLifecycle } from '../controller/controller_lifecycle';
2
+ export type { ControllerLifecycle } from '../controller/controller_lifecycle';
3
+
4
+ export interface ControllerState {}
5
+
6
+ export interface ControllerInput {}
7
+
8
+ export interface ControllerEvents {}
9
+
10
+ export interface PageController<
11
+ S extends ControllerState = ControllerState,
12
+ I extends ControllerInput = ControllerInput,
13
+ E extends ControllerEvents = ControllerEvents,
14
+ > extends ControllerLifecycle {
15
+ readonly data?: S;
16
+ readonly input?: I;
17
+ readonly events?: E;
18
+ }
@@ -0,0 +1,24 @@
1
+ export interface ControllerLifecycle {
2
+ dispose?(): void | Promise<void>;
3
+ destroy?(): void | Promise<void>;
4
+ }
5
+
6
+ /**
7
+ * Dispose a controller or controller-like instance if it exposes a lifecycle
8
+ * hook. `dispose` is the preferred Wood lifecycle name; `destroy` is supported
9
+ * for existing page controllers.
10
+ */
11
+ export async function disposeControllerLifecycle(target: unknown): Promise<void> {
12
+ if (!target || (typeof target !== 'object' && typeof target !== 'function')) {
13
+ return;
14
+ }
15
+
16
+ const lifecycle = target as ControllerLifecycle;
17
+ if (typeof lifecycle.dispose === 'function') {
18
+ await lifecycle.dispose();
19
+ return;
20
+ }
21
+ if (typeof lifecycle.destroy === 'function') {
22
+ await lifecycle.destroy();
23
+ }
24
+ }
@@ -0,0 +1,23 @@
1
+ export type NavigationParams = Record<string, unknown>;
2
+
3
+ function normalizeParamValue(value: unknown): string {
4
+ if (value === null || value === undefined) {
5
+ return '';
6
+ }
7
+ return String(value);
8
+ }
9
+
10
+ export function hashNavigationParams(params: NavigationParams = {}): string {
11
+ const normalizedEntries = Object.entries(params)
12
+ .map(([key, value]) => [String(key), normalizeParamValue(value)] as const)
13
+ .sort(([left], [right]) => left.localeCompare(right));
14
+
15
+ return JSON.stringify(normalizedEntries);
16
+ }
17
+
18
+ export function createNavigationMountKey(
19
+ page: string,
20
+ params: NavigationParams = {},
21
+ ): string {
22
+ return `${page}:${hashNavigationParams(params)}`;
23
+ }
@@ -1,74 +0,0 @@
1
- <script lang="ts">
2
- // SSR-only recursive layout renderer for stick (wood's visual preview CLI).
3
- // Simplified version of Forge's RecursiveRender — no stores, navigation, or error boundaries.
4
- let {
5
- layouts = [],
6
- view = null,
7
- data = { layout: [], view: {} },
8
- wood = undefined,
9
- } = $props<{
10
- layouts?: any[];
11
- view?: any;
12
- data?: { layout?: any[]; view?: any };
13
- wood?: any;
14
- }>();
15
-
16
- let topLayout = $derived(layouts[0]);
17
- let childLayouts = $derived(layouts.slice(1));
18
- let topData = $derived((data.layout || [])[0]);
19
- let otherData = $derived((data.layout || []).slice(1));
20
- let viewData = $derived(data.view);
21
- let recursiveChildData = $derived({
22
- layout: otherData,
23
- view: data.view,
24
- });
25
- </script>
26
-
27
- {#if childLayouts.length > 0}
28
- {#snippet nested_child()}
29
- <svelte:self
30
- layouts={childLayouts}
31
- view={view}
32
- data={recursiveChildData}
33
- {wood}
34
- />
35
- {/snippet}
36
- <svelte:component
37
- this={topLayout}
38
- {...(topData || {})}
39
- data={topData?.controller?.data}
40
- input={topData?.controller?.input}
41
- events={topData?.controller?.events}
42
- {wood}
43
- children={nested_child}
44
- />
45
- {:else if topLayout}
46
- {#snippet view_child()}
47
- <svelte:component
48
- this={view}
49
- {...(viewData || {})}
50
- data={viewData?.controller?.data}
51
- input={viewData?.controller?.input}
52
- events={viewData?.controller?.events}
53
- {wood}
54
- />
55
- {/snippet}
56
- <svelte:component
57
- this={topLayout}
58
- {...(topData || {})}
59
- data={topData?.controller?.data}
60
- input={topData?.controller?.input}
61
- events={topData?.controller?.events}
62
- {wood}
63
- children={view_child}
64
- />
65
- {:else}
66
- <svelte:component
67
- this={view}
68
- {...(viewData || {})}
69
- data={viewData?.controller?.data}
70
- input={viewData?.controller?.input}
71
- events={viewData?.controller?.events}
72
- {wood}
73
- />
74
- {/if}