@sigx/lynx-navigation 0.4.0 → 0.4.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/dist/components/Drawer.js +74 -0
- package/dist/components/Drawer.js.map +1 -0
- package/dist/components/EdgeBackHandle.js +144 -0
- package/dist/components/EdgeBackHandle.js.map +1 -0
- package/dist/components/EntryScope.d.ts +1 -1
- package/dist/components/EntryScope.d.ts.map +1 -1
- package/dist/components/EntryScope.js +39 -0
- package/dist/components/EntryScope.js.map +1 -0
- package/dist/components/Header.js +103 -0
- package/dist/components/Header.js.map +1 -0
- package/dist/components/Layer.d.ts +2 -2
- package/dist/components/Layer.d.ts.map +1 -1
- package/dist/components/Layer.js +66 -0
- package/dist/components/Layer.js.map +1 -0
- package/dist/components/Link.d.ts +2 -2
- package/dist/components/Link.d.ts.map +1 -1
- package/dist/components/Link.js +51 -0
- package/dist/components/Link.js.map +1 -0
- package/dist/components/NavigationRoot.d.ts +2 -2
- package/dist/components/NavigationRoot.d.ts.map +1 -1
- package/dist/components/NavigationRoot.js +67 -0
- package/dist/components/NavigationRoot.js.map +1 -0
- package/dist/components/Screen.js +98 -0
- package/dist/components/Screen.js.map +1 -0
- package/dist/components/Stack.js +257 -0
- package/dist/components/Stack.js.map +1 -0
- package/dist/components/TabBar.d.ts +1 -1
- package/dist/components/TabBar.d.ts.map +1 -1
- package/dist/components/TabBar.js +63 -0
- package/dist/components/TabBar.js.map +1 -0
- package/dist/components/Tabs.d.ts +8 -3
- package/dist/components/Tabs.d.ts.map +1 -1
- package/dist/components/Tabs.js +168 -0
- package/dist/components/Tabs.js.map +1 -0
- package/dist/define-routes.d.ts +1 -1
- package/dist/define-routes.d.ts.map +1 -1
- package/{src/define-routes.d.ts → dist/define-routes.js} +4 -2
- package/dist/define-routes.js.map +1 -0
- package/dist/hooks/use-focus.js +87 -0
- package/dist/hooks/use-focus.js.map +1 -0
- package/dist/hooks/use-hardware-back.js +84 -0
- package/dist/hooks/use-hardware-back.js.map +1 -0
- package/dist/hooks/use-linking-nav.d.ts +3 -3
- package/dist/hooks/use-linking-nav.d.ts.map +1 -1
- package/dist/hooks/use-linking-nav.js +109 -0
- package/dist/hooks/use-linking-nav.js.map +1 -0
- package/dist/hooks/use-nav-internal.d.ts +2 -2
- package/dist/hooks/use-nav-internal.d.ts.map +1 -1
- package/dist/hooks/use-nav-internal.js +55 -0
- package/dist/hooks/use-nav-internal.js.map +1 -0
- package/dist/hooks/use-nav-serializer.d.ts +1 -1
- package/dist/hooks/use-nav-serializer.d.ts.map +1 -1
- package/dist/hooks/use-nav-serializer.js +181 -0
- package/dist/hooks/use-nav-serializer.js.map +1 -0
- package/dist/hooks/use-nav.d.ts +2 -2
- package/dist/hooks/use-nav.d.ts.map +1 -1
- package/dist/hooks/use-nav.js +11 -0
- package/dist/hooks/use-nav.js.map +1 -0
- package/dist/hooks/use-params.d.ts +1 -1
- package/dist/hooks/use-params.d.ts.map +1 -1
- package/{src/hooks/use-params.d.ts → dist/hooks/use-params.js} +6 -2
- package/dist/hooks/use-params.js.map +1 -0
- package/dist/hooks/use-screen-chrome.d.ts +1 -1
- package/dist/hooks/use-screen-chrome.d.ts.map +1 -1
- package/dist/hooks/use-screen-chrome.js +102 -0
- package/dist/hooks/use-screen-chrome.js.map +1 -0
- package/dist/hooks/use-screen-options.d.ts +1 -1
- package/dist/hooks/use-screen-options.d.ts.map +1 -1
- package/dist/hooks/use-screen-options.js +43 -0
- package/dist/hooks/use-screen-options.js.map +1 -0
- package/dist/hooks/use-search.d.ts +1 -1
- package/dist/hooks/use-search.d.ts.map +1 -1
- package/{src/hooks/use-search.d.ts → dist/hooks/use-search.js} +6 -2
- package/dist/hooks/use-search.js.map +1 -0
- package/dist/href.d.ts +2 -2
- package/dist/href.d.ts.map +1 -1
- package/dist/href.js +57 -0
- package/dist/href.js.map +1 -0
- package/dist/index.d.ts +33 -33
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -1160
- package/dist/index.js.map +1 -1
- package/dist/internal/layer-plan.d.ts +1 -1
- package/dist/internal/layer-plan.d.ts.map +1 -1
- package/dist/internal/layer-plan.js +102 -0
- package/dist/internal/layer-plan.js.map +1 -0
- package/dist/internal/screen-registry.d.ts +1 -1
- package/dist/internal/screen-registry.d.ts.map +1 -1
- package/{src/internal/screen-registry.d.ts → dist/internal/screen-registry.js} +32 -21
- package/dist/internal/screen-registry.js.map +1 -0
- package/{src/internal/screen-width.d.ts → dist/internal/screen-width.js} +17 -2
- package/dist/internal/screen-width.js.map +1 -0
- package/dist/navigator/core.d.ts +3 -3
- package/dist/navigator/core.d.ts.map +1 -1
- package/dist/navigator/core.js +394 -0
- package/dist/navigator/core.js.map +1 -0
- package/dist/register.d.ts +1 -1
- package/dist/register.d.ts.map +1 -1
- package/dist/register.js +2 -0
- package/dist/register.js.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/url/build.js +30 -0
- package/dist/url/build.js.map +1 -0
- package/dist/url/compile.js +83 -0
- package/dist/url/compile.js.map +1 -0
- package/dist/url/format.js +102 -0
- package/dist/url/format.js.map +1 -0
- package/dist/url/index.d.ts +6 -6
- package/dist/url/index.d.ts.map +1 -1
- package/dist/url/index.js +13 -0
- package/dist/url/index.js.map +1 -0
- package/dist/url/parse.d.ts +1 -1
- package/dist/url/parse.d.ts.map +1 -1
- package/dist/url/parse.js +94 -0
- package/dist/url/parse.js.map +1 -0
- package/dist/url/registry.d.ts +2 -2
- package/dist/url/registry.d.ts.map +1 -1
- package/{src/url/registry.d.ts → dist/url/registry.js} +28 -12
- package/dist/url/registry.js.map +1 -0
- package/dist/url/validate.d.ts +1 -1
- package/dist/url/validate.d.ts.map +1 -1
- package/dist/url/validate.js +37 -0
- package/dist/url/validate.js.map +1 -0
- package/package.json +16 -13
- package/src/components/EdgeBackHandle.tsx +2 -2
- package/src/components/EntryScope.tsx +3 -3
- package/src/components/Header.tsx +3 -3
- package/src/components/Layer.tsx +3 -3
- package/src/components/Link.tsx +4 -4
- package/src/components/NavigationRoot.tsx +6 -6
- package/src/components/Screen.tsx +3 -3
- package/src/components/Stack.tsx +8 -8
- package/src/components/TabBar.tsx +1 -1
- package/src/components/Tabs.tsx +8 -3
- package/src/define-routes.ts +1 -1
- package/src/hooks/use-focus.ts +2 -2
- package/src/hooks/use-hardware-back.ts +1 -1
- package/src/hooks/use-linking-nav.ts +4 -4
- package/src/hooks/use-nav-internal.ts +2 -2
- package/src/hooks/use-nav-serializer.ts +3 -3
- package/src/hooks/use-nav.ts +2 -2
- package/src/hooks/use-params.ts +2 -2
- package/src/hooks/use-screen-chrome.ts +3 -3
- package/src/hooks/use-screen-options.ts +3 -3
- package/src/hooks/use-search.ts +2 -2
- package/src/href.ts +6 -6
- package/src/index.ts +33 -33
- package/src/internal/layer-plan.ts +2 -2
- package/src/internal/screen-registry.ts +1 -1
- package/src/navigator/core.ts +3 -3
- package/src/register.ts +1 -1
- package/src/url/build.ts +2 -2
- package/src/url/index.ts +6 -6
- package/src/url/parse.ts +6 -6
- package/src/url/registry.ts +3 -3
- package/src/url/validate.ts +1 -1
- package/src/components/Drawer.d.ts +0 -55
- package/src/components/EdgeBackHandle.d.ts +0 -1
- package/src/components/EntryScope.d.ts +0 -25
- package/src/components/Header.d.ts +0 -6
- package/src/components/Layer.d.ts +0 -33
- package/src/components/Link.d.ts +0 -60
- package/src/components/NavigationRoot.d.ts +0 -36
- package/src/components/Screen.d.ts +0 -97
- package/src/components/Stack.d.ts +0 -90
- package/src/components/TabBar.d.ts +0 -38
- package/src/components/Tabs.d.ts +0 -109
- package/src/hooks/use-focus.d.ts +0 -45
- package/src/hooks/use-hardware-back.d.ts +0 -37
- package/src/hooks/use-linking-nav.d.ts +0 -91
- package/src/hooks/use-nav-internal.d.ts +0 -91
- package/src/hooks/use-nav-serializer.d.ts +0 -82
- package/src/hooks/use-nav.d.ts +0 -111
- package/src/hooks/use-screen-chrome.d.ts +0 -18
- package/src/hooks/use-screen-options.d.ts +0 -2
- package/src/href.d.ts +0 -54
- package/src/index.d.ts +0 -39
- package/src/internal/layer-plan.d.ts +0 -68
- package/src/navigator/core.d.ts +0 -96
- package/src/register.d.ts +0 -37
- package/src/types.d.ts +0 -217
- package/src/url/build.d.ts +0 -15
- package/src/url/compile.d.ts +0 -34
- package/src/url/format.d.ts +0 -28
- package/src/url/parse.d.ts +0 -20
- package/src/url/validate.d.ts +0 -23
package/dist/register.d.ts
CHANGED
package/dist/register.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,QAAQ;CAExB;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,SAAS;IAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,QAAQ,CAAC;AAEnF,8EAA8E;AAC9E,MAAM,MAAM,OAAO,GAAG,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEtD,+CAA+C;AAC/C,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,OAAO,IAAI,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;AAE3E,+CAA+C;AAC/C,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,OAAO,IAAI,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/register.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":""}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for @sigx/lynx-navigation.
|
|
3
|
+
*
|
|
4
|
+
* The type machinery here is the differentiating DX: route names, params, and
|
|
5
|
+
* search are all inferred end-to-end from the user's `defineRoutes` call so
|
|
6
|
+
* `nav.push('profile', { id: 42 })` is a TS error if `id` is typed as string.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed → URL: build the `url` field of an Href from a route's params/search.
|
|
3
|
+
*
|
|
4
|
+
* Mirror of parse.ts. Used by `hrefFor()` after schema validation succeeds.
|
|
5
|
+
*/
|
|
6
|
+
import { formatSearch } from './format.js';
|
|
7
|
+
import { getCompiledPath, getRouteRegistry } from './registry.js';
|
|
8
|
+
/**
|
|
9
|
+
* Build the URL form of a route + params + search, or `null` if the route
|
|
10
|
+
* declares no `path` template (typed navigation still works — only deep-link
|
|
11
|
+
* serialization is unavailable).
|
|
12
|
+
*
|
|
13
|
+
* Params must already be valid for the route's schema (callers run this after
|
|
14
|
+
* `validateSync`). Search values are stringified as-is — schema-validated
|
|
15
|
+
* inputs survive round-tripping because `parseHref` re-runs the same schema.
|
|
16
|
+
*/
|
|
17
|
+
export function buildUrl(routeName, params, search) {
|
|
18
|
+
const registry = getRouteRegistry();
|
|
19
|
+
const compiled = getCompiledPath(registry, routeName);
|
|
20
|
+
if (!compiled)
|
|
21
|
+
return null;
|
|
22
|
+
const formatted = compiled.format(
|
|
23
|
+
// The compiler accepts string|number; we widen to unknown and let it
|
|
24
|
+
// String()-coerce. Booleans/null get filtered by the missing-param
|
|
25
|
+
// check, which is what we want — boolean path params don't exist.
|
|
26
|
+
(params ?? {}));
|
|
27
|
+
const querystring = formatSearch(search);
|
|
28
|
+
return querystring.length > 0 ? `${formatted}?${querystring}` : formatted;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/url/build.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAElE;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CACpB,SAAiB,EACjB,MAA2C,EAC3C,MAA2C;IAE3C,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM;IAC7B,qEAAqE;IACrE,mEAAmE;IACnE,kEAAkE;IAClE,CAAC,MAAM,IAAI,EAAE,CAAoC,CACpD,CAAC;IACF,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACzC,OAAO,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path template compiler.
|
|
3
|
+
*
|
|
4
|
+
* Turns a route's `path` (e.g. `/users/:id/posts/:postId`) into a compiled
|
|
5
|
+
* object that can both match a URL pathname against it and format a typed
|
|
6
|
+
* params object back into a URL.
|
|
7
|
+
*
|
|
8
|
+
* Supported syntax (intentionally minimal for v1):
|
|
9
|
+
* - Literal segments: `/users`, `/users/me`
|
|
10
|
+
* - Named params: `:id` (matches `[^/]+`)
|
|
11
|
+
* - Trailing slashes tolerated on match
|
|
12
|
+
*
|
|
13
|
+
* Out of scope for v1 (future-compatible — additions won't break v1 paths):
|
|
14
|
+
* - Wildcards `*`
|
|
15
|
+
* - Optional params `:id?`
|
|
16
|
+
* - Typed/constrained params `:id<number>` or `:id(\\d+)`
|
|
17
|
+
*/
|
|
18
|
+
const PARAM_RE = /:([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
19
|
+
/**
|
|
20
|
+
* Compile a path template. Throws on malformed input (duplicate param names,
|
|
21
|
+
* unexpected `:` syntax). Pure — safe to memoize.
|
|
22
|
+
*/
|
|
23
|
+
export function compilePath(template) {
|
|
24
|
+
if (typeof template !== 'string') {
|
|
25
|
+
throw new TypeError(`compilePath: expected string, got ${typeof template}`);
|
|
26
|
+
}
|
|
27
|
+
if (template.length === 0) {
|
|
28
|
+
throw new Error('compilePath: path template must not be empty');
|
|
29
|
+
}
|
|
30
|
+
// Normalize: ensure leading `/`. Trailing slashes are tolerated on match,
|
|
31
|
+
// but the canonical formatted output preserves the template's trailing
|
|
32
|
+
// slash policy.
|
|
33
|
+
const normalized = template.startsWith('/') ? template : `/${template}`;
|
|
34
|
+
const paramNames = [];
|
|
35
|
+
// Build the regex by replacing :name with a capture group. We escape the
|
|
36
|
+
// surrounding literal text so paths with regex-special chars (`.`, `+`)
|
|
37
|
+
// match literally — only `:name` is treated as a placeholder.
|
|
38
|
+
let lastIndex = 0;
|
|
39
|
+
let pattern = '';
|
|
40
|
+
PARAM_RE.lastIndex = 0;
|
|
41
|
+
for (let m = PARAM_RE.exec(normalized); m !== null; m = PARAM_RE.exec(normalized)) {
|
|
42
|
+
const name = m[1];
|
|
43
|
+
if (paramNames.includes(name)) {
|
|
44
|
+
throw new Error(`compilePath: duplicate param name ':${name}' in '${template}'`);
|
|
45
|
+
}
|
|
46
|
+
paramNames.push(name);
|
|
47
|
+
pattern += escapeRegex(normalized.slice(lastIndex, m.index));
|
|
48
|
+
pattern += '([^/]+)';
|
|
49
|
+
lastIndex = m.index + m[0].length;
|
|
50
|
+
}
|
|
51
|
+
pattern += escapeRegex(normalized.slice(lastIndex));
|
|
52
|
+
// Trim a trailing slash from the pattern so `/users/` and `/users` both
|
|
53
|
+
// match `/users/:?`. We keep the formatter's output as-templated.
|
|
54
|
+
const matchPattern = pattern.endsWith('/') ? pattern.slice(0, -1) : pattern;
|
|
55
|
+
const regex = new RegExp(`^${matchPattern}/?$`);
|
|
56
|
+
return {
|
|
57
|
+
source: template,
|
|
58
|
+
paramNames,
|
|
59
|
+
regex,
|
|
60
|
+
format(params) {
|
|
61
|
+
let out = '';
|
|
62
|
+
let i = 0;
|
|
63
|
+
PARAM_RE.lastIndex = 0;
|
|
64
|
+
for (let m = PARAM_RE.exec(normalized); m !== null; m = PARAM_RE.exec(normalized)) {
|
|
65
|
+
const name = m[1];
|
|
66
|
+
const value = params[name];
|
|
67
|
+
if (value === undefined || value === null) {
|
|
68
|
+
throw new Error(`compilePath.format: missing required param ':${name}' for '${template}'`);
|
|
69
|
+
}
|
|
70
|
+
out += normalized.slice(i, m.index);
|
|
71
|
+
out += encodeURIComponent(String(value));
|
|
72
|
+
i = m.index + m[0].length;
|
|
73
|
+
}
|
|
74
|
+
out += normalized.slice(i);
|
|
75
|
+
return out;
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const REGEX_SPECIALS = /[.*+?^${}()|[\]\\]/g;
|
|
80
|
+
function escapeRegex(s) {
|
|
81
|
+
return s.replace(REGEX_SPECIALS, '\\$&');
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=compile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../../src/url/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format helpers: typed params/search → URL string.
|
|
3
|
+
*
|
|
4
|
+
* Used by `hrefFor()` to render the `url` field of an Href.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Serialize an object as a `key=value&key=value` querystring.
|
|
8
|
+
*
|
|
9
|
+
* Keys are sorted to make the output deterministic (useful for tests and
|
|
10
|
+
* persistence diffs). `undefined`/`null` values are skipped. Non-primitive
|
|
11
|
+
* values are JSON-stringified on the way out — `parseSearch` returns the
|
|
12
|
+
* raw string and leaves any JSON decoding to the route's `search` schema
|
|
13
|
+
* (e.g. a Zod `transform`), so the round-trip is intentionally one-way at
|
|
14
|
+
* this layer.
|
|
15
|
+
*
|
|
16
|
+
* Returns `''` (empty string) when there are no entries — callers join with
|
|
17
|
+
* `?` only when the result is non-empty.
|
|
18
|
+
*/
|
|
19
|
+
export function formatSearch(search) {
|
|
20
|
+
if (!search)
|
|
21
|
+
return '';
|
|
22
|
+
const keys = Object.keys(search).sort();
|
|
23
|
+
const parts = [];
|
|
24
|
+
for (const key of keys) {
|
|
25
|
+
const value = search[key];
|
|
26
|
+
if (value === undefined || value === null)
|
|
27
|
+
continue;
|
|
28
|
+
const encoded = encodeURIComponent(key);
|
|
29
|
+
if (Array.isArray(value)) {
|
|
30
|
+
for (const item of value) {
|
|
31
|
+
if (item === undefined || item === null)
|
|
32
|
+
continue;
|
|
33
|
+
parts.push(`${encoded}=${encodeURIComponent(serializeScalar(item))}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
parts.push(`${encoded}=${encodeURIComponent(serializeScalar(value))}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return parts.join('&');
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Parse a `key=value&key=value` querystring into a string-keyed bag. Values
|
|
44
|
+
* are decoded but kept as strings — typed coercion happens in the route's
|
|
45
|
+
* `search` schema (e.g. Zod's `z.coerce.number()`).
|
|
46
|
+
*
|
|
47
|
+
* Multiple occurrences of the same key produce an array. Schemas that don't
|
|
48
|
+
* expect arrays will reject this — that's the right failure mode.
|
|
49
|
+
*/
|
|
50
|
+
export function parseSearch(query) {
|
|
51
|
+
const result = {};
|
|
52
|
+
if (!query)
|
|
53
|
+
return result;
|
|
54
|
+
// Strip leading `?` if present (formatHref doesn't include it but callers
|
|
55
|
+
// sometimes pass `?a=1`).
|
|
56
|
+
const cleaned = query.startsWith('?') ? query.slice(1) : query;
|
|
57
|
+
if (!cleaned)
|
|
58
|
+
return result;
|
|
59
|
+
for (const pair of cleaned.split('&')) {
|
|
60
|
+
if (!pair)
|
|
61
|
+
continue;
|
|
62
|
+
const eqIdx = pair.indexOf('=');
|
|
63
|
+
const rawKey = eqIdx === -1 ? pair : pair.slice(0, eqIdx);
|
|
64
|
+
const rawValue = eqIdx === -1 ? '' : pair.slice(eqIdx + 1);
|
|
65
|
+
const key = safeDecode(rawKey);
|
|
66
|
+
const value = safeDecode(rawValue);
|
|
67
|
+
const existing = result[key];
|
|
68
|
+
if (existing === undefined) {
|
|
69
|
+
result[key] = value;
|
|
70
|
+
}
|
|
71
|
+
else if (Array.isArray(existing)) {
|
|
72
|
+
existing.push(value);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
result[key] = [existing, value];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
function serializeScalar(v) {
|
|
81
|
+
switch (typeof v) {
|
|
82
|
+
case 'string': return v;
|
|
83
|
+
case 'number':
|
|
84
|
+
case 'boolean':
|
|
85
|
+
case 'bigint':
|
|
86
|
+
return String(v);
|
|
87
|
+
default:
|
|
88
|
+
// Objects/arrays/etc — JSON. Schemas can decide how to interpret.
|
|
89
|
+
return JSON.stringify(v);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function safeDecode(s) {
|
|
93
|
+
try {
|
|
94
|
+
return decodeURIComponent(s.replace(/\+/g, ' '));
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Malformed % escape — fall back to the raw text rather than throwing
|
|
98
|
+
// from a navigation hot path. The schema will reject if it matters.
|
|
99
|
+
return s;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/url/format.ts"],"names":[],"mappings":"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"}
|
package/dist/url/index.d.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* Not re-exported from the package root. Public surface is `hrefFor` /
|
|
5
5
|
* `parseHref` in ../href.ts plus `_setRouteRegistry` for tests/bootstrap.
|
|
6
6
|
*/
|
|
7
|
-
export { compilePath, type CompiledPath } from './compile';
|
|
8
|
-
export { buildUrl } from './build';
|
|
9
|
-
export { parseHrefImpl } from './parse';
|
|
10
|
-
export { formatSearch, parseSearch } from './format';
|
|
11
|
-
export { _setRouteRegistry, _clearRouteRegistry, getRouteRegistry, getCompiledPath, } from './registry';
|
|
12
|
-
export { validateSync, type ValidateOutcome } from './validate';
|
|
7
|
+
export { compilePath, type CompiledPath } from './compile.js';
|
|
8
|
+
export { buildUrl } from './build.js';
|
|
9
|
+
export { parseHrefImpl } from './parse.js';
|
|
10
|
+
export { formatSearch, parseSearch } from './format.js';
|
|
11
|
+
export { _setRouteRegistry, _clearRouteRegistry, getRouteRegistry, getCompiledPath, } from './registry.js';
|
|
12
|
+
export { validateSync, type ValidateOutcome } from './validate.js';
|
|
13
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/url/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/url/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/url/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EACH,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL bridge — internal barrel.
|
|
3
|
+
*
|
|
4
|
+
* Not re-exported from the package root. Public surface is `hrefFor` /
|
|
5
|
+
* `parseHref` in ../href.ts plus `_setRouteRegistry` for tests/bootstrap.
|
|
6
|
+
*/
|
|
7
|
+
export { compilePath } from './compile.js';
|
|
8
|
+
export { buildUrl } from './build.js';
|
|
9
|
+
export { parseHrefImpl } from './parse.js';
|
|
10
|
+
export { formatSearch, parseSearch } from './format.js';
|
|
11
|
+
export { _setRouteRegistry, _clearRouteRegistry, getRouteRegistry, getCompiledPath, } from './registry.js';
|
|
12
|
+
export { validateSync } from './validate.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/url/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAqB,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EACH,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAwB,MAAM,eAAe,CAAC"}
|
package/dist/url/parse.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Validation failures return `null` rather than throwing — deep-link handlers
|
|
10
10
|
* fall back to the initial route on a bad URL instead of crashing the app.
|
|
11
11
|
*/
|
|
12
|
-
import type { Href } from '../href';
|
|
12
|
+
import type { Href } from '../href.js';
|
|
13
13
|
/**
|
|
14
14
|
* Parse a URL string against the active route registry.
|
|
15
15
|
*
|
package/dist/url/parse.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/url/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/url/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAQvC;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAkCtD"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL → typed Href parser.
|
|
3
|
+
*
|
|
4
|
+
* Walks every registered route with a `path`, tries to match its compiled
|
|
5
|
+
* regex against the URL's pathname, and on a hit validates the extracted
|
|
6
|
+
* params + search through the route's Standard Schema. First match wins;
|
|
7
|
+
* iteration order follows `Object.keys` of the registered routes map.
|
|
8
|
+
*
|
|
9
|
+
* Validation failures return `null` rather than throwing — deep-link handlers
|
|
10
|
+
* fall back to the initial route on a bad URL instead of crashing the app.
|
|
11
|
+
*/
|
|
12
|
+
import { parse as parseUrl } from '@sigx/lynx-linking';
|
|
13
|
+
import { parseSearch } from './format.js';
|
|
14
|
+
import { getCompiledPath, getRouteRegistry } from './registry.js';
|
|
15
|
+
import { validateSync } from './validate.js';
|
|
16
|
+
/**
|
|
17
|
+
* Parse a URL string against the active route registry.
|
|
18
|
+
*
|
|
19
|
+
* Accepts both absolute URLs (`myapp://host/users/42?tab=about`) and
|
|
20
|
+
* pathname-only forms (`/users/42?tab=about`). Returns `null` if no route's
|
|
21
|
+
* `path` matches the URL or if schema validation rejects the extracted bits.
|
|
22
|
+
*/
|
|
23
|
+
export function parseHrefImpl(url) {
|
|
24
|
+
if (typeof url !== 'string' || url.length === 0)
|
|
25
|
+
return null;
|
|
26
|
+
// Use lynx-linking's parser for the scheme/host split — but accept paths
|
|
27
|
+
// that don't have a scheme too (raw `/users/42` is the common case from
|
|
28
|
+
// in-app routing).
|
|
29
|
+
const { pathname, query } = splitPathAndQuery(url);
|
|
30
|
+
if (!pathname)
|
|
31
|
+
return null;
|
|
32
|
+
const registry = getRouteRegistry();
|
|
33
|
+
const rawSearch = parseSearch(query);
|
|
34
|
+
for (const name of Object.keys(registry.routes)) {
|
|
35
|
+
const compiled = getCompiledPath(registry, name);
|
|
36
|
+
if (!compiled)
|
|
37
|
+
continue;
|
|
38
|
+
const match = compiled.regex.exec(pathname);
|
|
39
|
+
if (!match)
|
|
40
|
+
continue;
|
|
41
|
+
const rawParams = extractParams(compiled, match);
|
|
42
|
+
const def = registry.routes[name];
|
|
43
|
+
const paramsOutcome = validateSync(def.params, rawParams);
|
|
44
|
+
if (!paramsOutcome.ok)
|
|
45
|
+
continue;
|
|
46
|
+
const searchOutcome = validateSync(def.search, rawSearch);
|
|
47
|
+
if (!searchOutcome.ok)
|
|
48
|
+
continue;
|
|
49
|
+
return {
|
|
50
|
+
route: name,
|
|
51
|
+
params: paramsOutcome.value,
|
|
52
|
+
search: searchOutcome.value,
|
|
53
|
+
url,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
function extractParams(compiled, match) {
|
|
59
|
+
const out = {};
|
|
60
|
+
for (let i = 0; i < compiled.paramNames.length; i++) {
|
|
61
|
+
const raw = match[i + 1];
|
|
62
|
+
try {
|
|
63
|
+
out[compiled.paramNames[i]] = decodeURIComponent(raw);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
out[compiled.paramNames[i]] = raw;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
function splitPathAndQuery(url) {
|
|
72
|
+
// Drop the fragment before any path/query work — `#…` is a client-side
|
|
73
|
+
// anchor that must not leak into the route pathname or query values.
|
|
74
|
+
const hashIdx = url.indexOf('#');
|
|
75
|
+
const noHash = hashIdx >= 0 ? url.slice(0, hashIdx) : url;
|
|
76
|
+
// If the URL has a scheme, defer to lynx-linking's parser — handles
|
|
77
|
+
// `myapp://host/path?q` correctly. Otherwise treat the whole thing as
|
|
78
|
+
// pathname+query.
|
|
79
|
+
const hasScheme = /^[a-zA-Z][a-zA-Z0-9+.\-]*:/.test(noHash);
|
|
80
|
+
if (hasScheme) {
|
|
81
|
+
const parsed = parseUrl(noHash);
|
|
82
|
+
// Reconstruct the query string from the already-parsed bag. We have
|
|
83
|
+
// to do this because parseUrl decoded keys/values, but parseSearch
|
|
84
|
+
// expects encoded form. Simpler: split the original ourselves.
|
|
85
|
+
const qIdx = noHash.indexOf('?');
|
|
86
|
+
const query = qIdx >= 0 ? noHash.slice(qIdx + 1) : '';
|
|
87
|
+
return { pathname: parsed.path, query };
|
|
88
|
+
}
|
|
89
|
+
const qIdx = noHash.indexOf('?');
|
|
90
|
+
if (qIdx === -1)
|
|
91
|
+
return { pathname: noHash, query: '' };
|
|
92
|
+
return { pathname: noHash.slice(0, qIdx), query: noHash.slice(qIdx + 1) };
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/url/parse.ts"],"names":[],"mappings":"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"}
|
package/dist/url/registry.d.ts
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* directly. The leading underscore is a convention: not part of the supported
|
|
12
12
|
* public API (test/integration use only).
|
|
13
13
|
*/
|
|
14
|
-
import type { CompiledPath } from './compile';
|
|
15
|
-
import type { RouteMap } from '../types';
|
|
14
|
+
import type { CompiledPath } from './compile.js';
|
|
15
|
+
import type { RouteMap } from '../types.js';
|
|
16
16
|
interface RegistryState {
|
|
17
17
|
readonly routes: RouteMap;
|
|
18
18
|
/** Lazy-compiled paths keyed by route name. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/url/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/url/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,UAAU,aAAa;IACnB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC1B,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAChD;AAID;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAExD;AAED,+EAA+E;AAC/E,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,IAAI,aAAa,CAOhD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAU1F"}
|
|
@@ -11,13 +11,8 @@
|
|
|
11
11
|
* directly. The leading underscore is a convention: not part of the supported
|
|
12
12
|
* public API (test/integration use only).
|
|
13
13
|
*/
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
interface RegistryState {
|
|
17
|
-
readonly routes: RouteMap;
|
|
18
|
-
/** Lazy-compiled paths keyed by route name. */
|
|
19
|
-
readonly compiled: Map<string, CompiledPath>;
|
|
20
|
-
}
|
|
14
|
+
import { compilePath } from './compile.js';
|
|
15
|
+
let current = null;
|
|
21
16
|
/**
|
|
22
17
|
* Set the active route registry. Called by `<NavigationRoot>` on setup and
|
|
23
18
|
* available to tests/bootstrap code as `_setRouteRegistry`.
|
|
@@ -27,14 +22,35 @@ interface RegistryState {
|
|
|
27
22
|
* specific registry for a one-off call, pass it explicitly to the helper
|
|
28
23
|
* (parseHrefWithRoutes / hrefForWithRoutes — currently internal).
|
|
29
24
|
*/
|
|
30
|
-
export
|
|
25
|
+
export function _setRouteRegistry(routes) {
|
|
26
|
+
current = { routes, compiled: new Map() };
|
|
27
|
+
}
|
|
31
28
|
/** Clear the registry. Mainly for tests that want to assert the unset path. */
|
|
32
|
-
export
|
|
29
|
+
export function _clearRouteRegistry() {
|
|
30
|
+
current = null;
|
|
31
|
+
}
|
|
33
32
|
/** Get the active registry or throw a friendly error if none is set. */
|
|
34
|
-
export
|
|
33
|
+
export function getRouteRegistry() {
|
|
34
|
+
if (!current) {
|
|
35
|
+
throw new Error('[lynx-navigation] No route registry set — render a <NavigationRoot> first, or call _setRouteRegistry() for tests.');
|
|
36
|
+
}
|
|
37
|
+
return current;
|
|
38
|
+
}
|
|
35
39
|
/**
|
|
36
40
|
* Look up (or lazily compile) the path template for a route name. Returns
|
|
37
41
|
* `null` when the route exists but declares no `path`.
|
|
38
42
|
*/
|
|
39
|
-
export
|
|
40
|
-
|
|
43
|
+
export function getCompiledPath(registry, name) {
|
|
44
|
+
const def = registry.routes[name];
|
|
45
|
+
if (!def)
|
|
46
|
+
return null;
|
|
47
|
+
if (!def.path)
|
|
48
|
+
return null;
|
|
49
|
+
let compiled = registry.compiled.get(name);
|
|
50
|
+
if (!compiled) {
|
|
51
|
+
compiled = compilePath(def.path);
|
|
52
|
+
registry.compiled.set(name, compiled);
|
|
53
|
+
}
|
|
54
|
+
return compiled;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/url/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAS3C,IAAI,OAAO,GAAyB,IAAI,CAAC;AAEzC;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAgB;IAC9C,OAAO,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;AAC9C,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,mBAAmB;IAC/B,OAAO,GAAG,IAAI,CAAC;AACnB,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,gBAAgB;IAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACX,mHAAmH,CACtH,CAAC;IACN,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,QAAuB,EAAE,IAAY;IACjE,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC"}
|
package/dist/url/validate.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* resolution) so we restrict to sync validators. Zod/Valibot/ArkType are all
|
|
6
6
|
* sync, which covers the common case. Async validators throw a clear error.
|
|
7
7
|
*/
|
|
8
|
-
import type { StandardSchemaV1 } from '../types';
|
|
8
|
+
import type { StandardSchemaV1 } from '../types.js';
|
|
9
9
|
/** Outcome of a sync validation call — discriminated for explicit handling. */
|
|
10
10
|
export type ValidateOutcome = {
|
|
11
11
|
readonly ok: true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/url/validate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/url/validate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAmBpD,+EAA+E;AAC/E,MAAM,MAAM,eAAe,GACrB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC9C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC;AAErE;;;;;GAKG;AACH,wBAAgB,YAAY,CACxB,MAAM,EAAE,gBAAgB,GAAG,SAAS,EACpC,KAAK,EAAE,OAAO,GACf,eAAe,CAiBjB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard Schema validation helper (sync only).
|
|
3
|
+
*
|
|
4
|
+
* `hrefFor` and `parseHref` run on hot paths (link rendering, deep-link
|
|
5
|
+
* resolution) so we restrict to sync validators. Zod/Valibot/ArkType are all
|
|
6
|
+
* sync, which covers the common case. Async validators throw a clear error.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Run a Standard Schema's `validate` synchronously. When the schema lacks a
|
|
10
|
+
* `validate` function (e.g. our test `fakeSchema`), passthrough — assume the
|
|
11
|
+
* input is already in the correct shape. This is a deliberate ergonomic
|
|
12
|
+
* choice so the type-spike fixtures stay terse.
|
|
13
|
+
*/
|
|
14
|
+
export function validateSync(schema, input) {
|
|
15
|
+
if (!schema)
|
|
16
|
+
return { ok: true, value: input };
|
|
17
|
+
const validate = schema['~standard']?.validate;
|
|
18
|
+
if (!validate)
|
|
19
|
+
return { ok: true, value: input };
|
|
20
|
+
const result = validate(input);
|
|
21
|
+
if (isPromiseLike(result)) {
|
|
22
|
+
throw new Error('[lynx-navigation] Async schema validation is not supported on the URL bridge — use a sync validator (Zod/Valibot/ArkType are all sync).');
|
|
23
|
+
}
|
|
24
|
+
if (result.issues !== undefined && result.issues.length > 0) {
|
|
25
|
+
return {
|
|
26
|
+
ok: false,
|
|
27
|
+
issues: result.issues.map((i) => i.message),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return { ok: true, value: result.value };
|
|
31
|
+
}
|
|
32
|
+
function isPromiseLike(v) {
|
|
33
|
+
return (v !== null
|
|
34
|
+
&& typeof v === 'object'
|
|
35
|
+
&& typeof v.then === 'function');
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/url/validate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA0BH;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CACxB,MAAoC,EACpC,KAAc;IAEd,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC/C,MAAM,QAAQ,GAAI,MAAgC,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC;IAC1E,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IACjD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACX,yIAAyI,CAC5I,CAAC;IACN,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1D,OAAO;YACH,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;SAC9C,CAAC;IACN,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAG,MAA6B,CAAC,KAAK,EAAE,CAAC;AACrE,CAAC;AAED,SAAS,aAAa,CAAI,CAAU;IAChC,OAAO,CACH,CAAC,KAAK,IAAI;WACP,OAAO,CAAC,KAAK,QAAQ;WACrB,OAAQ,CAAwB,CAAC,IAAI,KAAK,UAAU,CAC1D,CAAC;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sigx/lynx-navigation",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Type-first native navigator for sigx-lynx — Stack, Tabs, Drawer, modals, lazy routes, deep links",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
18
|
"peerDependencies": {
|
|
19
|
-
"@sigx/lynx
|
|
20
|
-
"@sigx/lynx": "^0.4.
|
|
21
|
-
"@sigx/lynx-
|
|
19
|
+
"@sigx/lynx": "^0.4.2",
|
|
20
|
+
"@sigx/lynx-linking": "^0.4.2",
|
|
21
|
+
"@sigx/lynx-icons": "^0.4.2",
|
|
22
|
+
"@sigx/lynx-motion": "^0.4.2"
|
|
22
23
|
},
|
|
23
24
|
"peerDependenciesMeta": {
|
|
24
25
|
"@sigx/lynx-linking": {
|
|
@@ -26,13 +27,14 @@
|
|
|
26
27
|
}
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
30
|
+
"@typescript/native-preview": "7.0.0-dev.20260521.1",
|
|
29
31
|
"typescript": "^6.0.3",
|
|
30
|
-
"vitest": "^4.1.
|
|
31
|
-
"@sigx/
|
|
32
|
-
"@sigx/lynx": "^0.4.
|
|
33
|
-
"@sigx/lynx-
|
|
34
|
-
"@sigx/lynx-
|
|
35
|
-
"@sigx/lynx-
|
|
32
|
+
"vitest": "^4.1.7",
|
|
33
|
+
"@sigx/lynx": "^0.4.2",
|
|
34
|
+
"@sigx/lynx-linking": "^0.4.2",
|
|
35
|
+
"@sigx/lynx-icons": "^0.4.2",
|
|
36
|
+
"@sigx/lynx-motion": "^0.4.2",
|
|
37
|
+
"@sigx/lynx-testing": "^0.4.2"
|
|
36
38
|
},
|
|
37
39
|
"keywords": [
|
|
38
40
|
"sigx",
|
|
@@ -60,10 +62,11 @@
|
|
|
60
62
|
"access": "public"
|
|
61
63
|
},
|
|
62
64
|
"scripts": {
|
|
63
|
-
"build": "
|
|
64
|
-
"dev": "
|
|
65
|
+
"build": "node ../../scripts/clean.mjs dist && tsgo",
|
|
66
|
+
"dev": "tsgo --watch",
|
|
65
67
|
"test": "vitest run",
|
|
66
68
|
"test:types": "tsc --noEmit",
|
|
67
|
-
"bench": "vitest bench --run"
|
|
69
|
+
"bench": "vitest bench --run",
|
|
70
|
+
"clean": "node ../../scripts/clean.mjs dist .turbo"
|
|
68
71
|
}
|
|
69
72
|
}
|
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
type MainThread,
|
|
8
8
|
} from '@sigx/lynx';
|
|
9
9
|
import { withTiming } from '@sigx/lynx-motion';
|
|
10
|
-
import { useNavInternals } from '../hooks/use-nav-internal';
|
|
11
|
-
import { SCREEN_WIDTH } from '../internal/screen-width';
|
|
10
|
+
import { useNavInternals } from '../hooks/use-nav-internal.js';
|
|
11
|
+
import { SCREEN_WIDTH } from '../internal/screen-width.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Edge-pan recognizer for iOS-style swipe-back. Mounts as an absolutely-
|