expo-router 0.0.1

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.
Files changed (132) hide show
  1. package/README.md +3 -0
  2. package/assets/file.png +0 -0
  3. package/assets/forward.png +0 -0
  4. package/assets/pkg.png +0 -0
  5. package/babel.js +77 -0
  6. package/build/ContextNavigationContainer.d.ts +33 -0
  7. package/build/ContextNavigationContainer.d.ts.map +1 -0
  8. package/build/ContextNavigationContainer.js +59 -0
  9. package/build/ContextNavigationContainer.js.map +1 -0
  10. package/build/ContextNavigator.d.ts +6 -0
  11. package/build/ContextNavigator.d.ts.map +1 -0
  12. package/build/ContextNavigator.js +52 -0
  13. package/build/ContextNavigator.js.map +1 -0
  14. package/build/Route.d.ts +34 -0
  15. package/build/Route.d.ts.map +1 -0
  16. package/build/Route.js +56 -0
  17. package/build/Route.js.map +1 -0
  18. package/build/aasa.d.ts +2 -0
  19. package/build/aasa.d.ts.map +1 -0
  20. package/build/aasa.js +25 -0
  21. package/build/aasa.js.map +1 -0
  22. package/build/context.d.ts +5 -0
  23. package/build/context.d.ts.map +1 -0
  24. package/build/context.js +14 -0
  25. package/build/context.js.map +1 -0
  26. package/build/fork/getPathFromState.d.ts +39 -0
  27. package/build/fork/getPathFromState.d.ts.map +1 -0
  28. package/build/fork/getPathFromState.js +209 -0
  29. package/build/fork/getPathFromState.js.map +1 -0
  30. package/build/fork/getStateFromPath.d.ts +33 -0
  31. package/build/fork/getStateFromPath.d.ts.map +1 -0
  32. package/build/fork/getStateFromPath.js +415 -0
  33. package/build/fork/getStateFromPath.js.map +1 -0
  34. package/build/getDevServer/index.d.ts +7 -0
  35. package/build/getDevServer/index.d.ts.map +1 -0
  36. package/build/getDevServer/index.js +30 -0
  37. package/build/getDevServer/index.js.map +1 -0
  38. package/build/getDevServer/index.native.d.ts +2 -0
  39. package/build/getDevServer/index.native.d.ts.map +1 -0
  40. package/build/getDevServer/index.native.js +2 -0
  41. package/build/getDevServer/index.native.js.map +1 -0
  42. package/build/getLinkingConfig.d.ts +5 -0
  43. package/build/getLinkingConfig.d.ts.map +1 -0
  44. package/build/getLinkingConfig.js +62 -0
  45. package/build/getLinkingConfig.js.map +1 -0
  46. package/build/getRoutes.d.ts +12 -0
  47. package/build/getRoutes.d.ts.map +1 -0
  48. package/build/getRoutes.js +165 -0
  49. package/build/getRoutes.js.map +1 -0
  50. package/build/index.d.ts +14 -0
  51. package/build/index.d.ts.map +1 -0
  52. package/build/index.js +13 -0
  53. package/build/index.js.map +1 -0
  54. package/build/layouts/Drawer.d.ts +132 -0
  55. package/build/layouts/Drawer.d.ts.map +1 -0
  56. package/build/layouts/Drawer.js +5 -0
  57. package/build/layouts/Drawer.js.map +1 -0
  58. package/build/layouts/NativeStack.d.ts +132 -0
  59. package/build/layouts/NativeStack.d.ts.map +1 -0
  60. package/build/layouts/NativeStack.js +5 -0
  61. package/build/layouts/NativeStack.js.map +1 -0
  62. package/build/layouts/Stack.d.ts +156 -0
  63. package/build/layouts/Stack.d.ts.map +1 -0
  64. package/build/layouts/Stack.js +6 -0
  65. package/build/layouts/Stack.js.map +1 -0
  66. package/build/layouts/Tabs.d.ts +136 -0
  67. package/build/layouts/Tabs.d.ts.map +1 -0
  68. package/build/layouts/Tabs.js +6 -0
  69. package/build/layouts/Tabs.js.map +1 -0
  70. package/build/layouts/withLayoutContext.d.ts +16 -0
  71. package/build/layouts/withLayoutContext.d.ts.map +1 -0
  72. package/build/layouts/withLayoutContext.js +73 -0
  73. package/build/layouts/withLayoutContext.js.map +1 -0
  74. package/build/matchers.d.ts +8 -0
  75. package/build/matchers.d.ts.map +1 -0
  76. package/build/matchers.js +25 -0
  77. package/build/matchers.js.map +1 -0
  78. package/build/onboard/Tutorial.d.ts +3 -0
  79. package/build/onboard/Tutorial.d.ts.map +1 -0
  80. package/build/onboard/Tutorial.js +129 -0
  81. package/build/onboard/Tutorial.js.map +1 -0
  82. package/build/onboard/createEntryFile.d.ts +3 -0
  83. package/build/onboard/createEntryFile.d.ts.map +1 -0
  84. package/build/onboard/createEntryFile.js +54 -0
  85. package/build/onboard/createEntryFile.js.map +1 -0
  86. package/build/primitives.d.ts +19 -0
  87. package/build/primitives.d.ts.map +1 -0
  88. package/build/primitives.js +5 -0
  89. package/build/primitives.js.map +1 -0
  90. package/build/types.d.ts +11 -0
  91. package/build/types.d.ts.map +1 -0
  92. package/build/types.js +2 -0
  93. package/build/types.js.map +1 -0
  94. package/build/useScreens.d.ts +10 -0
  95. package/build/useScreens.d.ts.map +1 -0
  96. package/build/useScreens.js +60 -0
  97. package/build/useScreens.js.map +1 -0
  98. package/build/views/Directory.d.ts +3 -0
  99. package/build/views/Directory.d.ts.map +1 -0
  100. package/build/views/Directory.js +142 -0
  101. package/build/views/Directory.js.map +1 -0
  102. package/build/views/ErrorBoundary.d.ts +4 -0
  103. package/build/views/ErrorBoundary.d.ts.map +1 -0
  104. package/build/views/ErrorBoundary.js +53 -0
  105. package/build/views/ErrorBoundary.js.map +1 -0
  106. package/build/views/Layout.d.ts +19 -0
  107. package/build/views/Layout.d.ts.map +1 -0
  108. package/build/views/Layout.js +48 -0
  109. package/build/views/Layout.js.map +1 -0
  110. package/build/views/Link.d.ts +26 -0
  111. package/build/views/Link.d.ts.map +1 -0
  112. package/build/views/Link.js +47 -0
  113. package/build/views/Link.js.map +1 -0
  114. package/build/views/Root.d.ts +6 -0
  115. package/build/views/Root.d.ts.map +1 -0
  116. package/build/views/Root.js +20 -0
  117. package/build/views/Root.js.map +1 -0
  118. package/build/views/Screen.d.ts +7 -0
  119. package/build/views/Screen.d.ts.map +1 -0
  120. package/build/views/Screen.js +19 -0
  121. package/build/views/Screen.js.map +1 -0
  122. package/build/views/Try.d.ts +24 -0
  123. package/build/views/Try.d.ts.map +1 -0
  124. package/build/views/Try.js +24 -0
  125. package/build/views/Try.js.map +1 -0
  126. package/build/views/Unmatched.d.ts +4 -0
  127. package/build/views/Unmatched.d.ts.map +1 -0
  128. package/build/views/Unmatched.js +46 -0
  129. package/build/views/Unmatched.js.map +1 -0
  130. package/entry.js +103 -0
  131. package/metro-config.js +14 -0
  132. package/package.json +62 -0
@@ -0,0 +1,209 @@
1
+ import * as queryString from "query-string";
2
+ import { validatePathConfig, } from "@react-navigation/core";
3
+ const getActiveRoute = (state) => {
4
+ const route = typeof state.index === "number"
5
+ ? state.routes[state.index]
6
+ : state.routes[state.routes.length - 1];
7
+ if (route.state) {
8
+ return getActiveRoute(route.state);
9
+ }
10
+ return route;
11
+ };
12
+ /**
13
+ * Utility to serialize a navigation state object to a path string.
14
+ *
15
+ * @example
16
+ * ```js
17
+ * getPathFromState(
18
+ * {
19
+ * routes: [
20
+ * {
21
+ * name: 'Chat',
22
+ * params: { author: 'Jane', id: 42 },
23
+ * },
24
+ * ],
25
+ * },
26
+ * {
27
+ * screens: {
28
+ * Chat: {
29
+ * path: 'chat/:author/:id',
30
+ * stringify: { author: author => author.toLowerCase() }
31
+ * }
32
+ * }
33
+ * }
34
+ * )
35
+ * ```
36
+ *
37
+ * @param state Navigation state to serialize.
38
+ * @param options Extra options to fine-tune how to serialize the path.
39
+ * @returns Path representing the state, e.g. /foo/bar?count=42.
40
+ */
41
+ export default function getPathFromState(state, options) {
42
+ if (state == null) {
43
+ throw Error("Got 'undefined' for the navigation state. You must pass a valid state object.");
44
+ }
45
+ if (options) {
46
+ validatePathConfig(options);
47
+ }
48
+ // Create a normalized configs object which will be easier to use
49
+ const configs = options?.screens
50
+ ? createNormalizedConfigs(options?.screens)
51
+ : {};
52
+ let path = "/";
53
+ let current = state;
54
+ const allParams = {};
55
+ while (current) {
56
+ let index = typeof current.index === "number" ? current.index : 0;
57
+ let route = current.routes[index];
58
+ let pattern;
59
+ let focusedParams;
60
+ let focusedRoute = getActiveRoute(state);
61
+ let currentOptions = configs;
62
+ // Keep all the route names that appeared during going deeper in config in case the pattern is resolved to undefined
63
+ let nestedRouteNames = [];
64
+ let hasNext = true;
65
+ while (route.name in currentOptions && hasNext) {
66
+ pattern = currentOptions[route.name].pattern;
67
+ // @ts-expect-error
68
+ nestedRouteNames.push(route.name);
69
+ if (route.params) {
70
+ const stringify = currentOptions[route.name]?.stringify;
71
+ const currentParams = Object.fromEntries(Object.entries(route.params).map(([key, value]) => [
72
+ key,
73
+ stringify?.[key] ? stringify[key](value) : String(value),
74
+ ]));
75
+ if (pattern) {
76
+ Object.assign(allParams, currentParams);
77
+ }
78
+ if (focusedRoute === route) {
79
+ // If this is the focused route, keep the params for later use
80
+ // We save it here since it's been stringified already
81
+ focusedParams = { ...currentParams };
82
+ pattern
83
+ ?.split("/")
84
+ .filter((p) => p.startsWith(":") || p === "*")
85
+ // eslint-disable-next-line no-loop-func
86
+ .forEach((p) => {
87
+ const name = getParamName(p);
88
+ // Remove the params present in the pattern since we'll only use the rest for query string
89
+ if (focusedParams) {
90
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
91
+ delete focusedParams[name];
92
+ }
93
+ });
94
+ }
95
+ }
96
+ // If there is no `screens` property or no nested state, we return pattern
97
+ if (!currentOptions[route.name].screens || route.state === undefined) {
98
+ hasNext = false;
99
+ }
100
+ else {
101
+ index =
102
+ typeof route.state.index === "number"
103
+ ? route.state.index
104
+ : route.state.routes.length - 1;
105
+ const nextRoute = route.state.routes[index];
106
+ const nestedConfig = currentOptions[route.name].screens;
107
+ // if there is config for next route name, we go deeper
108
+ if (nestedConfig && nextRoute.name in nestedConfig) {
109
+ route = nextRoute;
110
+ currentOptions = nestedConfig;
111
+ }
112
+ else {
113
+ // If not, there is no sense in going deeper in config
114
+ hasNext = false;
115
+ }
116
+ }
117
+ }
118
+ if (pattern === undefined) {
119
+ pattern = nestedRouteNames.join("/");
120
+ }
121
+ if (currentOptions[route.name] !== undefined) {
122
+ path += pattern
123
+ .split("/")
124
+ .map((p) => {
125
+ const name = getParamName(p);
126
+ // We don't know what to show for wildcard patterns
127
+ // Showing the route name seems ok, though whatever we show here will be incorrect
128
+ // Since the page doesn't actually exist
129
+ if (p === "*") {
130
+ // This can occur when a wildcard matches all routes and the given path was `/`.
131
+ return route.path ?? "";
132
+ }
133
+ // If the path has a pattern for a param, put the param in the path
134
+ if (p.startsWith(":")) {
135
+ const value = allParams[name];
136
+ if (value == null) {
137
+ // Optional params without value assigned in route.params should be ignored
138
+ return "";
139
+ }
140
+ return value;
141
+ }
142
+ return encodeURIComponent(p);
143
+ })
144
+ .join("/");
145
+ }
146
+ else {
147
+ path += encodeURIComponent(route.name);
148
+ }
149
+ if (!focusedParams) {
150
+ focusedParams = focusedRoute.params;
151
+ }
152
+ if (route.state) {
153
+ path += "/";
154
+ }
155
+ else if (focusedParams) {
156
+ for (let param in focusedParams) {
157
+ if (focusedParams[param] === "undefined") {
158
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
159
+ delete focusedParams[param];
160
+ }
161
+ }
162
+ const query = queryString.stringify(focusedParams, { sort: false });
163
+ if (query) {
164
+ path += `?${query}`;
165
+ }
166
+ }
167
+ current = route.state;
168
+ }
169
+ // Remove multiple as well as trailing slashes
170
+ path = path.replace(/\/+/g, "/");
171
+ path = path.length > 1 ? path.replace(/\/$/, "") : path;
172
+ return path;
173
+ }
174
+ const getParamName = (pattern) => pattern.replace(/^:/, "").replace(/\?$/, "");
175
+ const joinPaths = (...paths) => []
176
+ .concat(...paths.map((p) => p.split("/")))
177
+ .filter(Boolean)
178
+ .join("/");
179
+ const createConfigItem = (config, parentPattern) => {
180
+ if (typeof config === "string") {
181
+ // If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern
182
+ const pattern = parentPattern ? joinPaths(parentPattern, config) : config;
183
+ return { pattern };
184
+ }
185
+ // If an object is specified as the value (e.g. Foo: { ... }),
186
+ // It can have `path` property and `screens` prop which has nested configs
187
+ let pattern;
188
+ if (config.exact && config.path === undefined) {
189
+ throw new Error("A 'path' needs to be specified when specifying 'exact: true'. If you don't want this screen in the URL, specify it as empty string, e.g. `path: ''`.");
190
+ }
191
+ pattern =
192
+ config.exact !== true
193
+ ? joinPaths(parentPattern || "", config.path || "")
194
+ : config.path || "";
195
+ const screens = config.screens
196
+ ? createNormalizedConfigs(config.screens, pattern)
197
+ : undefined;
198
+ return {
199
+ // Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.
200
+ pattern: pattern?.split("/").filter(Boolean).join("/"),
201
+ stringify: config.stringify,
202
+ screens,
203
+ };
204
+ };
205
+ const createNormalizedConfigs = (options, pattern) => Object.fromEntries(Object.entries(options).map(([name, c]) => {
206
+ const result = createConfigItem(c, pattern);
207
+ return [name, result];
208
+ }));
209
+ //# sourceMappingURL=getPathFromState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getPathFromState.js","sourceRoot":"","sources":["../../src/fork/getPathFromState.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n NavigationState,\n PartialState,\n Route,\n} from \"@react-navigation/routers\";\nimport * as queryString from \"query-string\";\n\nimport {\n validatePathConfig,\n PathConfig,\n PathConfigMap,\n} from \"@react-navigation/core\";\n\ntype Options<ParamList extends {}> = {\n initialRouteName?: string;\n screens: PathConfigMap<ParamList>;\n};\n\ntype State = NavigationState | Omit<PartialState<NavigationState>, \"stale\">;\n\ntype StringifyConfig = Record<string, (value: any) => string>;\n\ntype ConfigItem = {\n pattern?: string;\n stringify?: StringifyConfig;\n screens?: Record<string, ConfigItem>;\n};\n\nconst getActiveRoute = (state: State): { name: string; params?: object } => {\n const route =\n typeof state.index === \"number\"\n ? state.routes[state.index]\n : state.routes[state.routes.length - 1];\n\n if (route.state) {\n return getActiveRoute(route.state);\n }\n\n return route;\n};\n\n/**\n * Utility to serialize a navigation state object to a path string.\n *\n * @example\n * ```js\n * getPathFromState(\n * {\n * routes: [\n * {\n * name: 'Chat',\n * params: { author: 'Jane', id: 42 },\n * },\n * ],\n * },\n * {\n * screens: {\n * Chat: {\n * path: 'chat/:author/:id',\n * stringify: { author: author => author.toLowerCase() }\n * }\n * }\n * }\n * )\n * ```\n *\n * @param state Navigation state to serialize.\n * @param options Extra options to fine-tune how to serialize the path.\n * @returns Path representing the state, e.g. /foo/bar?count=42.\n */\nexport default function getPathFromState<ParamList extends {}>(\n state: State,\n options?: Options<ParamList>\n): string {\n if (state == null) {\n throw Error(\n \"Got 'undefined' for the navigation state. You must pass a valid state object.\"\n );\n }\n\n if (options) {\n validatePathConfig(options);\n }\n\n // Create a normalized configs object which will be easier to use\n const configs: Record<string, ConfigItem> = options?.screens\n ? createNormalizedConfigs(options?.screens)\n : {};\n\n let path = \"/\";\n let current: State | undefined = state;\n\n const allParams: Record<string, any> = {};\n\n while (current) {\n let index = typeof current.index === \"number\" ? current.index : 0;\n let route = current.routes[index] as Route<string> & {\n state?: State;\n };\n\n let pattern: string | undefined;\n\n let focusedParams: Record<string, any> | undefined;\n let focusedRoute = getActiveRoute(state);\n let currentOptions = configs;\n\n // Keep all the route names that appeared during going deeper in config in case the pattern is resolved to undefined\n let nestedRouteNames = [];\n\n let hasNext = true;\n\n while (route.name in currentOptions && hasNext) {\n pattern = currentOptions[route.name].pattern;\n\n // @ts-expect-error\n nestedRouteNames.push(route.name);\n\n if (route.params) {\n const stringify = currentOptions[route.name]?.stringify;\n\n const currentParams = Object.fromEntries(\n Object.entries(route.params).map(([key, value]) => [\n key,\n stringify?.[key] ? stringify[key](value) : String(value),\n ])\n );\n\n if (pattern) {\n Object.assign(allParams, currentParams);\n }\n\n if (focusedRoute === route) {\n // If this is the focused route, keep the params for later use\n // We save it here since it's been stringified already\n focusedParams = { ...currentParams };\n\n pattern\n ?.split(\"/\")\n .filter((p) => p.startsWith(\":\") || p === \"*\")\n // eslint-disable-next-line no-loop-func\n .forEach((p) => {\n const name = getParamName(p);\n\n // Remove the params present in the pattern since we'll only use the rest for query string\n if (focusedParams) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete focusedParams[name];\n }\n });\n }\n }\n\n // If there is no `screens` property or no nested state, we return pattern\n if (!currentOptions[route.name].screens || route.state === undefined) {\n hasNext = false;\n } else {\n index =\n typeof route.state.index === \"number\"\n ? route.state.index\n : route.state.routes.length - 1;\n\n const nextRoute = route.state.routes[index];\n const nestedConfig = currentOptions[route.name].screens;\n\n // if there is config for next route name, we go deeper\n if (nestedConfig && nextRoute.name in nestedConfig) {\n route = nextRoute as Route<string> & { state?: State };\n currentOptions = nestedConfig;\n } else {\n // If not, there is no sense in going deeper in config\n hasNext = false;\n }\n }\n }\n\n if (pattern === undefined) {\n pattern = nestedRouteNames.join(\"/\");\n }\n\n if (currentOptions[route.name] !== undefined) {\n path += pattern\n .split(\"/\")\n .map((p) => {\n const name = getParamName(p);\n\n // We don't know what to show for wildcard patterns\n // Showing the route name seems ok, though whatever we show here will be incorrect\n // Since the page doesn't actually exist\n if (p === \"*\") {\n // This can occur when a wildcard matches all routes and the given path was `/`.\n return route.path ?? \"\";\n }\n\n // If the path has a pattern for a param, put the param in the path\n if (p.startsWith(\":\")) {\n const value = allParams[name];\n\n if (value == null) {\n // Optional params without value assigned in route.params should be ignored\n return \"\";\n }\n return value;\n }\n\n return encodeURIComponent(p);\n })\n .join(\"/\");\n } else {\n path += encodeURIComponent(route.name);\n }\n\n if (!focusedParams) {\n focusedParams = focusedRoute.params;\n }\n\n if (route.state) {\n path += \"/\";\n } else if (focusedParams) {\n for (let param in focusedParams) {\n if (focusedParams[param] === \"undefined\") {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete focusedParams[param];\n }\n }\n\n const query = queryString.stringify(focusedParams, { sort: false });\n\n if (query) {\n path += `?${query}`;\n }\n }\n\n current = route.state;\n }\n\n // Remove multiple as well as trailing slashes\n path = path.replace(/\\/+/g, \"/\");\n path = path.length > 1 ? path.replace(/\\/$/, \"\") : path;\n\n return path;\n}\n\nconst getParamName = (pattern: string) =>\n pattern.replace(/^:/, \"\").replace(/\\?$/, \"\");\n\nconst joinPaths = (...paths: string[]): string =>\n ([] as string[])\n .concat(...paths.map((p) => p.split(\"/\")))\n .filter(Boolean)\n .join(\"/\");\n\nconst createConfigItem = (\n config: PathConfig<object> | string,\n parentPattern?: string\n): ConfigItem => {\n if (typeof config === \"string\") {\n // If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern\n const pattern = parentPattern ? joinPaths(parentPattern, config) : config;\n\n return { pattern };\n }\n\n // If an object is specified as the value (e.g. Foo: { ... }),\n // It can have `path` property and `screens` prop which has nested configs\n let pattern: string | undefined;\n\n if (config.exact && config.path === undefined) {\n throw new Error(\n \"A 'path' needs to be specified when specifying 'exact: true'. If you don't want this screen in the URL, specify it as empty string, e.g. `path: ''`.\"\n );\n }\n\n pattern =\n config.exact !== true\n ? joinPaths(parentPattern || \"\", config.path || \"\")\n : config.path || \"\";\n\n const screens = config.screens\n ? createNormalizedConfigs(config.screens, pattern)\n : undefined;\n\n return {\n // Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.\n pattern: pattern?.split(\"/\").filter(Boolean).join(\"/\"),\n stringify: config.stringify,\n screens,\n };\n};\n\nconst createNormalizedConfigs = (\n options: PathConfigMap<object>,\n pattern?: string\n): Record<string, ConfigItem> =>\n Object.fromEntries(\n Object.entries(options).map(([name, c]) => {\n const result = createConfigItem(c, pattern);\n\n return [name, result];\n })\n );\n"]}
@@ -0,0 +1,33 @@
1
+ import type { NavigationState, PartialState } from "@react-navigation/routers";
2
+ import { PathConfigMap } from "@react-navigation/core";
3
+ declare type Options<ParamList extends {}> = {
4
+ initialRouteName?: string;
5
+ screens: PathConfigMap<ParamList>;
6
+ };
7
+ declare type ResultState = PartialState<NavigationState> & {
8
+ state?: ResultState;
9
+ };
10
+ /**
11
+ * Utility to parse a path string to initial state object accepted by the container.
12
+ * This is useful for deep linking when we need to handle the incoming URL.
13
+ *
14
+ * @example
15
+ * ```js
16
+ * getStateFromPath(
17
+ * '/chat/jane/42',
18
+ * {
19
+ * screens: {
20
+ * Chat: {
21
+ * path: 'chat/:author/:id',
22
+ * parse: { id: Number }
23
+ * }
24
+ * }
25
+ * }
26
+ * )
27
+ * ```
28
+ * @param path Path string to parse and convert, e.g. /foo/bar?count=42.
29
+ * @param options Extra options to fine-tune how to parse the path.
30
+ */
31
+ export default function getStateFromPath<ParamList extends {}>(path: string, options?: Options<ParamList>): ResultState | undefined;
32
+ export {};
33
+ //# sourceMappingURL=getStateFromPath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getStateFromPath.d.ts","sourceRoot":"","sources":["../../src/fork/getStateFromPath.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EACf,YAAY,EACb,MAAM,2BAA2B,CAAC;AAInC,OAAO,EACL,aAAa,EAGd,MAAM,wBAAwB,CAAC;AAMhC,aAAK,OAAO,CAAC,SAAS,SAAS,EAAE,IAAI;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;CACnC,CAAC;AAoBF,aAAK,WAAW,GAAG,YAAY,CAAC,eAAe,CAAC,GAAG;IACjD,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,CAAC;AAQF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,SAAS,SAAS,EAAE,EAC3D,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAC3B,WAAW,GAAG,SAAS,CA+OzB"}