@tanstack/router-core 0.0.1-beta.19 → 0.0.1-beta.191

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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/build/cjs/defer.js +39 -0
  3. package/build/cjs/defer.js.map +1 -0
  4. package/build/cjs/fileRoute.js +29 -0
  5. package/build/cjs/fileRoute.js.map +1 -0
  6. package/build/cjs/history.js +228 -0
  7. package/build/cjs/history.js.map +1 -0
  8. package/build/cjs/index.js +86 -0
  9. package/build/cjs/{packages/router-core/src/index.js.map → index.js.map} +1 -1
  10. package/build/cjs/{packages/router-core/src/path.js → path.js} +45 -56
  11. package/build/cjs/path.js.map +1 -0
  12. package/build/cjs/{packages/router-core/src/qss.js → qss.js} +10 -16
  13. package/build/cjs/qss.js.map +1 -0
  14. package/build/cjs/route.js +114 -0
  15. package/build/cjs/route.js.map +1 -0
  16. package/build/cjs/router.js +1267 -0
  17. package/build/cjs/router.js.map +1 -0
  18. package/build/cjs/scroll-restoration.js +139 -0
  19. package/build/cjs/scroll-restoration.js.map +1 -0
  20. package/build/cjs/{packages/router-core/src/searchParams.js → searchParams.js} +32 -19
  21. package/build/cjs/searchParams.js.map +1 -0
  22. package/build/cjs/{packages/router-core/src/utils.js → utils.js} +69 -64
  23. package/build/cjs/utils.js.map +1 -0
  24. package/build/esm/index.js +1746 -2121
  25. package/build/esm/index.js.map +1 -1
  26. package/build/stats-html.html +59 -49
  27. package/build/stats-react.json +197 -211
  28. package/build/types/defer.d.ts +19 -0
  29. package/build/types/fileRoute.d.ts +35 -0
  30. package/build/types/history.d.ts +36 -0
  31. package/build/types/index.d.ts +13 -609
  32. package/build/types/link.d.ts +96 -0
  33. package/build/types/path.d.ts +16 -0
  34. package/build/types/qss.d.ts +2 -0
  35. package/build/types/route.d.ts +251 -0
  36. package/build/types/routeInfo.d.ts +22 -0
  37. package/build/types/router.d.ts +260 -0
  38. package/build/types/scroll-restoration.d.ts +6 -0
  39. package/build/types/searchParams.d.ts +5 -0
  40. package/build/types/utils.d.ts +44 -0
  41. package/build/umd/index.development.js +1978 -2243
  42. package/build/umd/index.development.js.map +1 -1
  43. package/build/umd/index.production.js +13 -2
  44. package/build/umd/index.production.js.map +1 -1
  45. package/package.json +11 -7
  46. package/src/defer.ts +55 -0
  47. package/src/fileRoute.ts +161 -0
  48. package/src/history.ts +300 -0
  49. package/src/index.ts +5 -10
  50. package/src/link.ts +136 -125
  51. package/src/path.ts +37 -17
  52. package/src/qss.ts +1 -2
  53. package/src/route.ts +948 -218
  54. package/src/routeInfo.ts +45 -211
  55. package/src/router.ts +1778 -1075
  56. package/src/scroll-restoration.ts +179 -0
  57. package/src/searchParams.ts +31 -9
  58. package/src/utils.ts +84 -49
  59. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -33
  60. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
  61. package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js +0 -33
  62. package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js.map +0 -1
  63. package/build/cjs/node_modules/history/index.js +0 -815
  64. package/build/cjs/node_modules/history/index.js.map +0 -1
  65. package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js +0 -30
  66. package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +0 -1
  67. package/build/cjs/packages/router-core/src/index.js +0 -58
  68. package/build/cjs/packages/router-core/src/path.js.map +0 -1
  69. package/build/cjs/packages/router-core/src/qss.js.map +0 -1
  70. package/build/cjs/packages/router-core/src/route.js +0 -147
  71. package/build/cjs/packages/router-core/src/route.js.map +0 -1
  72. package/build/cjs/packages/router-core/src/routeConfig.js +0 -69
  73. package/build/cjs/packages/router-core/src/routeConfig.js.map +0 -1
  74. package/build/cjs/packages/router-core/src/routeMatch.js +0 -220
  75. package/build/cjs/packages/router-core/src/routeMatch.js.map +0 -1
  76. package/build/cjs/packages/router-core/src/router.js +0 -870
  77. package/build/cjs/packages/router-core/src/router.js.map +0 -1
  78. package/build/cjs/packages/router-core/src/searchParams.js.map +0 -1
  79. package/build/cjs/packages/router-core/src/utils.js.map +0 -1
  80. package/src/frameworks.ts +0 -11
  81. package/src/routeConfig.ts +0 -511
  82. package/src/routeMatch.ts +0 -312
@@ -0,0 +1,179 @@
1
+ import { AnyRouter, ParsedLocation } from './router'
2
+
3
+ const windowKey = 'window'
4
+ const delimiter = '___'
5
+
6
+ let weakScrolledElementsByRestoreKey: Record<string, WeakSet<any>> = {}
7
+
8
+ type CacheValue = Record<string, { scrollX: number; scrollY: number }>
9
+
10
+ type Cache = {
11
+ current: CacheValue
12
+ set: (key: string, value: any) => void
13
+ }
14
+
15
+ let cache: Cache
16
+
17
+ let pathDidChange = false
18
+
19
+ const sessionsStorage = typeof window !== 'undefined' && window.sessionStorage
20
+
21
+ export type ScrollRestorationOptions = {
22
+ getKey?: (location: ParsedLocation) => string
23
+ }
24
+
25
+ const defaultGetKey = (location: ParsedLocation) => location.state.key!
26
+
27
+ export function watchScrollPositions(
28
+ router: AnyRouter,
29
+ opts?: ScrollRestorationOptions,
30
+ ) {
31
+ const getKey = opts?.getKey || defaultGetKey
32
+
33
+ if (sessionsStorage) {
34
+ if (!cache) {
35
+ cache = (() => {
36
+ const storageKey = 'tsr-scroll-restoration-v1'
37
+
38
+ const current: CacheValue = JSON.parse(
39
+ window.sessionStorage.getItem(storageKey) || '{}',
40
+ )
41
+
42
+ return {
43
+ current,
44
+ set: (key: string, value: any) => {
45
+ current[key] = value
46
+ window.sessionStorage.setItem(storageKey, JSON.stringify(cache))
47
+ },
48
+ }
49
+ })()
50
+ }
51
+ }
52
+
53
+ const { history } = window
54
+ if (history.scrollRestoration) {
55
+ history.scrollRestoration = 'manual'
56
+ }
57
+
58
+ const onScroll = (event: Event) => {
59
+ const restoreKey = getKey(router.state.resolvedLocation)
60
+
61
+ if (!weakScrolledElementsByRestoreKey[restoreKey]) {
62
+ weakScrolledElementsByRestoreKey[restoreKey] = new WeakSet()
63
+ }
64
+
65
+ const set = weakScrolledElementsByRestoreKey[restoreKey]!
66
+
67
+ if (set.has(event.target)) return
68
+ set.add(event.target)
69
+
70
+ const cacheKey = [
71
+ restoreKey,
72
+ event.target === document || event.target === window
73
+ ? windowKey
74
+ : getCssSelector(event.target),
75
+ ].join(delimiter)
76
+
77
+ if (!cache.current[cacheKey]) {
78
+ cache.set(cacheKey, {
79
+ scrollX: NaN,
80
+ scrollY: NaN,
81
+ })
82
+ }
83
+ }
84
+
85
+ const getCssSelector = (el: any): string => {
86
+ let path = [],
87
+ parent
88
+ while ((parent = el.parentNode)) {
89
+ path.unshift(
90
+ `${el.tagName}:nth-child(${
91
+ ([].indexOf as any).call(parent.children, el) + 1
92
+ })`,
93
+ )
94
+ el = parent
95
+ }
96
+ return `${path.join(' > ')}`.toLowerCase()
97
+ }
98
+
99
+ const onPathWillChange = (from: ParsedLocation) => {
100
+ const restoreKey = getKey(from)
101
+ for (const cacheKey in cache.current) {
102
+ const entry = cache.current[cacheKey]!
103
+ const [key, elementSelector] = cacheKey.split(delimiter)
104
+ if (restoreKey === key) {
105
+ if (elementSelector === windowKey) {
106
+ entry.scrollX = window.scrollX || 0
107
+ entry.scrollY = window.scrollY || 0
108
+ } else if (elementSelector) {
109
+ const element = document.querySelector(elementSelector)
110
+ entry.scrollX = element?.scrollLeft || 0
111
+ entry.scrollY = element?.scrollTop || 0
112
+ }
113
+
114
+ cache.set(cacheKey, entry)
115
+ }
116
+ }
117
+ }
118
+
119
+ const onPathChange = () => {
120
+ pathDidChange = true
121
+ }
122
+
123
+ if (typeof document !== 'undefined') {
124
+ document.addEventListener('scroll', onScroll, true)
125
+ }
126
+
127
+ const unsubOnBeforeLoad = router.subscribe('onBeforeLoad', (event) => {
128
+ if (event.pathChanged) onPathWillChange(event.from)
129
+ })
130
+
131
+ const unsubOnLoad = router.subscribe('onLoad', (event) => {
132
+ if (event.pathChanged) onPathChange()
133
+ })
134
+
135
+ return () => {
136
+ document.removeEventListener('scroll', onScroll)
137
+ unsubOnBeforeLoad()
138
+ unsubOnLoad()
139
+ }
140
+ }
141
+
142
+ export function restoreScrollPositions(
143
+ router: AnyRouter,
144
+ opts?: ScrollRestorationOptions,
145
+ ) {
146
+ if (pathDidChange) {
147
+ if (!router.resetNextScroll) {
148
+ return
149
+ }
150
+
151
+ const getKey = opts?.getKey || defaultGetKey
152
+
153
+ pathDidChange = false
154
+
155
+ const restoreKey = getKey(router.state.location)
156
+ let windowRestored = false
157
+
158
+ for (const cacheKey in cache.current) {
159
+ const entry = cache.current[cacheKey]!
160
+ const [key, elementSelector] = cacheKey.split(delimiter)
161
+ if (key === restoreKey) {
162
+ if (elementSelector === windowKey) {
163
+ windowRestored = true
164
+ window.scrollTo(entry.scrollX, entry.scrollY)
165
+ } else if (elementSelector) {
166
+ const element = document.querySelector(elementSelector)
167
+ if (element) {
168
+ element.scrollLeft = entry.scrollX
169
+ element.scrollTop = entry.scrollY
170
+ }
171
+ }
172
+ }
173
+ }
174
+
175
+ if (!windowRestored) {
176
+ window.scrollTo(0, 0)
177
+ }
178
+ }
179
+ }
@@ -1,8 +1,11 @@
1
1
  import { decode, encode } from './qss'
2
- import { AnySearchSchema } from './routeConfig'
2
+ import { AnySearchSchema } from './route'
3
3
 
4
4
  export const defaultParseSearch = parseSearchWith(JSON.parse)
5
- export const defaultStringifySearch = stringifySearchWith(JSON.stringify)
5
+ export const defaultStringifySearch = stringifySearchWith(
6
+ JSON.stringify,
7
+ JSON.parse,
8
+ )
6
9
 
7
10
  export function parseSearchWith(parser: (str: string) => any) {
8
11
  return (searchStr: string): AnySearchSchema => {
@@ -28,7 +31,30 @@ export function parseSearchWith(parser: (str: string) => any) {
28
31
  }
29
32
  }
30
33
 
31
- export function stringifySearchWith(stringify: (search: any) => string) {
34
+ export function stringifySearchWith(
35
+ stringify: (search: any) => string,
36
+ parser?: (str: string) => any,
37
+ ) {
38
+ function stringifyValue(val: any) {
39
+ if (typeof val === 'object' && val !== null) {
40
+ try {
41
+ return stringify(val)
42
+ } catch (err) {
43
+ // silent
44
+ }
45
+ } else if (typeof val === 'string' && typeof parser === 'function') {
46
+ try {
47
+ // Check if it's a valid parseable string.
48
+ // If it is, then stringify it again.
49
+ parser(val)
50
+ return stringify(val)
51
+ } catch (err) {
52
+ // silent
53
+ }
54
+ }
55
+ return val
56
+ }
57
+
32
58
  return (search: Record<string, any>) => {
33
59
  search = { ...search }
34
60
 
@@ -37,12 +63,8 @@ export function stringifySearchWith(stringify: (search: any) => string) {
37
63
  const val = search[key]
38
64
  if (typeof val === 'undefined' || val === undefined) {
39
65
  delete search[key]
40
- } else if (val && typeof val === 'object' && val !== null) {
41
- try {
42
- search[key] = stringify(val)
43
- } catch (err) {
44
- // silent
45
- }
66
+ } else {
67
+ search[key] = stringifyValue(val)
46
68
  }
47
69
  })
48
70
  }
package/src/utils.ts CHANGED
@@ -7,13 +7,14 @@ export type PickAsRequired<T, K extends keyof T> = Omit<T, K> &
7
7
  export type PickAsPartial<T, K extends keyof T> = Omit<T, K> &
8
8
  Partial<Pick<T, K>>
9
9
  export type PickUnsafe<T, K> = K extends keyof T ? Pick<T, K> : never
10
- export type PickExtra<T, K> = Expand<{
10
+ export type PickExtra<T, K> = {
11
11
  [TKey in keyof K as string extends TKey
12
12
  ? never
13
13
  : TKey extends keyof T
14
14
  ? never
15
15
  : TKey]: K[TKey]
16
- }>
16
+ }
17
+
17
18
  export type PickRequired<T> = {
18
19
  [K in keyof T as undefined extends T[K] ? never : K]: T[K]
19
20
  }
@@ -24,11 +25,27 @@ export type Expand<T> = T extends object
24
25
  : never
25
26
  : T
26
27
 
27
- // type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
28
- // k: infer I,
29
- // ) => any
30
- // ? I
31
- // : never
28
+ export type UnionToIntersection<U> = (
29
+ U extends any ? (k: U) => void : never
30
+ ) extends (k: infer I) => any
31
+ ? I
32
+ : never
33
+
34
+ // type Compute<T> = { [K in keyof T]: T[K] } | never
35
+
36
+ // type AllKeys<T> = T extends any ? keyof T : never
37
+
38
+ // export type MergeUnion<T, Keys extends keyof T = keyof T> = Compute<
39
+ // {
40
+ // [K in Keys]: T[Keys]
41
+ // } & {
42
+ // [K in AllKeys<T>]?: T extends any
43
+ // ? K extends keyof T
44
+ // ? T[K]
45
+ // : never
46
+ // : never
47
+ // }
48
+ // >
32
49
 
33
50
  export type Values<O> = O[ValueKeys<O>]
34
51
  export type ValueKeys<O> = Extract<keyof O, PropertyKey>
@@ -40,9 +57,9 @@ export type DeepAwaited<T> = T extends Promise<infer A>
40
57
  : T
41
58
 
42
59
  export type PathParamMask<TRoutePath extends string> =
43
- TRoutePath extends `${infer L}/:${infer C}/${infer R}`
60
+ TRoutePath extends `${infer L}/$${infer C}/${infer R}`
44
61
  ? PathParamMask<`${L}/${string}/${R}`>
45
- : TRoutePath extends `${infer L}/:${infer C}`
62
+ : TRoutePath extends `${infer L}/$${infer C}`
46
63
  ? PathParamMask<`${L}/${string}`>
47
64
  : TRoutePath
48
65
 
@@ -52,6 +69,10 @@ export type Updater<TPrevious, TResult = TPrevious> =
52
69
  | TResult
53
70
  | ((prev?: TPrevious) => TResult)
54
71
 
72
+ export type NonNullableUpdater<TPrevious, TResult = TPrevious> =
73
+ | TResult
74
+ | ((prev: TPrevious) => TResult)
75
+
55
76
  export type PickExtract<T, U> = {
56
77
  [K in keyof T as T[K] extends U ? K : never]: T[K]
57
78
  }
@@ -60,42 +81,71 @@ export type PickExclude<T, U> = {
60
81
  [K in keyof T as T[K] extends U ? never : K]: T[K]
61
82
  }
62
83
 
84
+ export function last<T>(arr: T[]) {
85
+ return arr[arr.length - 1]
86
+ }
87
+
88
+ function isFunction(d: any): d is Function {
89
+ return typeof d === 'function'
90
+ }
91
+
92
+ export function functionalUpdate<TResult>(
93
+ updater: Updater<TResult> | NonNullableUpdater<TResult>,
94
+ previous: TResult,
95
+ ): TResult {
96
+ if (isFunction(updater)) {
97
+ return updater(previous as TResult)
98
+ }
99
+
100
+ return updater
101
+ }
102
+
103
+ export function pick<T, K extends keyof T>(parent: T, keys: K[]): Pick<T, K> {
104
+ return keys.reduce((obj: any, key: K) => {
105
+ obj[key] = parent[key]
106
+ return obj
107
+ }, {} as any)
108
+ }
109
+
63
110
  /**
64
111
  * This function returns `a` if `b` is deeply equal.
65
112
  * If not, it will replace any deeply equal children of `b` with those of `a`.
66
- * This can be used for structural sharing between JSON values for example.
113
+ * This can be used for structural sharing between immutable JSON values for example.
114
+ * Do not use this with signals
67
115
  */
68
- export function replaceEqualDeep(prev: any, next: any) {
69
- if (prev === next) {
116
+ export function replaceEqualDeep<T>(prev: any, _next: T): T {
117
+ if (prev === _next) {
70
118
  return prev
71
119
  }
72
120
 
121
+ const next = _next as any
122
+
73
123
  const array = Array.isArray(prev) && Array.isArray(next)
74
124
 
75
125
  if (array || (isPlainObject(prev) && isPlainObject(next))) {
76
- const aSize = array ? prev.length : Object.keys(prev).length
77
- const bItems = array ? next : Object.keys(next)
78
- const bSize = bItems.length
126
+ const prevSize = array ? prev.length : Object.keys(prev).length
127
+ const nextItems = array ? next : Object.keys(next)
128
+ const nextSize = nextItems.length
79
129
  const copy: any = array ? [] : {}
80
130
 
81
131
  let equalItems = 0
82
132
 
83
- for (let i = 0; i < bSize; i++) {
84
- const key = array ? i : bItems[i]
133
+ for (let i = 0; i < nextSize; i++) {
134
+ const key = array ? i : nextItems[i]
85
135
  copy[key] = replaceEqualDeep(prev[key], next[key])
86
136
  if (copy[key] === prev[key]) {
87
137
  equalItems++
88
138
  }
89
139
  }
90
140
 
91
- return aSize === bSize && equalItems === aSize ? prev : copy
141
+ return prevSize === nextSize && equalItems === prevSize ? prev : copy
92
142
  }
93
143
 
94
144
  return next
95
145
  }
96
146
 
97
147
  // Copied from: https://github.com/jonschlinkert/is-plain-object
98
- function isPlainObject(o: any) {
148
+ export function isPlainObject(o: any) {
99
149
  if (!hasObjectPrototype(o)) {
100
150
  return false
101
151
  }
@@ -125,40 +175,25 @@ function hasObjectPrototype(o: any) {
125
175
  return Object.prototype.toString.call(o) === '[object Object]'
126
176
  }
127
177
 
128
- export function last<T>(arr: T[]) {
129
- return arr[arr.length - 1]
130
- }
131
-
132
- export function warning(cond: any, message: string): cond is true {
133
- if (cond) {
134
- if (typeof console !== 'undefined') console.warn(message)
135
-
136
- try {
137
- throw new Error(message)
138
- } catch {}
178
+ export function partialDeepEqual(a: any, b: any): boolean {
179
+ if (a === b) {
180
+ return true
139
181
  }
140
182
 
141
- return true
142
- }
143
-
144
- function isFunction(d: any): d is Function {
145
- return typeof d === 'function'
146
- }
183
+ if (typeof a !== typeof b) {
184
+ return false
185
+ }
147
186
 
148
- export function functionalUpdate<TResult>(
149
- updater: Updater<TResult>,
150
- previous: TResult,
151
- ) {
152
- if (isFunction(updater)) {
153
- return updater(previous as TResult)
187
+ if (isPlainObject(a) && isPlainObject(b)) {
188
+ return !Object.keys(b).some((key) => !partialDeepEqual(a[key], b[key]))
154
189
  }
155
190
 
156
- return updater
157
- }
191
+ if (Array.isArray(a) && Array.isArray(b)) {
192
+ return (
193
+ a.length === b.length &&
194
+ a.every((item, index) => partialDeepEqual(item, b[index]))
195
+ )
196
+ }
158
197
 
159
- export function pick<T, K extends keyof T>(parent: T, keys: K[]): Pick<T, K> {
160
- return keys.reduce((obj: any, key: K) => {
161
- obj[key] = parent[key]
162
- return obj
163
- }, {} as any)
198
+ return false
164
199
  }
@@ -1,33 +0,0 @@
1
- /**
2
- * router-core
3
- *
4
- * Copyright (c) TanStack
5
- *
6
- * This source code is licensed under the MIT license found in the
7
- * LICENSE.md file in the root directory of this source tree.
8
- *
9
- * @license MIT
10
- */
11
- 'use strict';
12
-
13
- Object.defineProperty(exports, '__esModule', { value: true });
14
-
15
- function _extends() {
16
- _extends = Object.assign ? Object.assign.bind() : function (target) {
17
- for (var i = 1; i < arguments.length; i++) {
18
- var source = arguments[i];
19
-
20
- for (var key in source) {
21
- if (Object.prototype.hasOwnProperty.call(source, key)) {
22
- target[key] = source[key];
23
- }
24
- }
25
- }
26
-
27
- return target;
28
- };
29
- return _extends.apply(this, arguments);
30
- }
31
-
32
- exports["extends"] = _extends;
33
- //# sourceMappingURL=_rollupPluginBabelHelpers.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"_rollupPluginBabelHelpers.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,33 +0,0 @@
1
- /**
2
- * router-core
3
- *
4
- * Copyright (c) TanStack
5
- *
6
- * This source code is licensed under the MIT license found in the
7
- * LICENSE.md file in the root directory of this source tree.
8
- *
9
- * @license MIT
10
- */
11
- 'use strict';
12
-
13
- Object.defineProperty(exports, '__esModule', { value: true });
14
-
15
- function _extends() {
16
- _extends = Object.assign ? Object.assign.bind() : function (target) {
17
- for (var i = 1; i < arguments.length; i++) {
18
- var source = arguments[i];
19
-
20
- for (var key in source) {
21
- if (Object.prototype.hasOwnProperty.call(source, key)) {
22
- target[key] = source[key];
23
- }
24
- }
25
- }
26
-
27
- return target;
28
- };
29
- return _extends.apply(this, arguments);
30
- }
31
-
32
- exports["default"] = _extends;
33
- //# sourceMappingURL=extends.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extends.js","sources":["../../../../../../../../../node_modules/@babel/runtime/helpers/esm/extends.js"],"sourcesContent":["export default function _extends() {\n _extends = Object.assign ? Object.assign.bind() : function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n };\n return _extends.apply(this, arguments);\n}"],"names":[],"mappings":";;;;;;;;;;;;;;AAAe,SAAS,QAAQ,GAAG;AACnC,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,UAAU,MAAM,EAAE;AACtE,IAAI,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC/C,MAAM,IAAI,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;AAChC;AACA,MAAM,KAAK,IAAI,GAAG,IAAI,MAAM,EAAE;AAC9B,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE;AAC/D,UAAU,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;AACpC,SAAS;AACT,OAAO;AACP,KAAK;AACL;AACA,IAAI,OAAO,MAAM,CAAC;AAClB,GAAG,CAAC;AACJ,EAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACzC;;;;"}