@tamagui/core 1.129.5 → 1.129.6-1751237024118
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/index.cjs +15 -9
- package/dist/cjs/index.js +11 -7
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/index.native.js +15 -7
- package/dist/cjs/index.native.js.map +2 -2
- package/dist/esm/index.js +15 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +11 -6
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +13 -6
- package/dist/esm/index.native.js.map +1 -1
- package/dist/native.js +427 -356
- package/dist/native.js.map +3 -3
- package/dist/test.native.js +407 -335
- package/dist/test.native.js.map +3 -3
- package/package.json +9 -8
- package/src/index.tsx +19 -3
- package/types/index.d.ts +3 -2
- package/types/index.d.ts.map +1 -1
- package/dist/cjs/helpers/getBoundingClientRect.cjs +0 -41
- package/dist/cjs/helpers/getBoundingClientRect.js +0 -39
- package/dist/cjs/helpers/getBoundingClientRect.js.map +0 -6
- package/dist/cjs/helpers/getBoundingClientRect.native.js +0 -48
- package/dist/cjs/helpers/getBoundingClientRect.native.js.map +0 -6
- package/dist/cjs/helpers/getRect.cjs +0 -44
- package/dist/cjs/helpers/getRect.js +0 -27
- package/dist/cjs/helpers/getRect.js.map +0 -6
- package/dist/cjs/helpers/getRect.native.js +0 -39
- package/dist/cjs/helpers/getRect.native.js.map +0 -6
- package/dist/cjs/hooks/useElementLayout.cjs +0 -203
- package/dist/cjs/hooks/useElementLayout.js +0 -152
- package/dist/cjs/hooks/useElementLayout.js.map +0 -6
- package/dist/cjs/hooks/useElementLayout.native.js +0 -185
- package/dist/cjs/hooks/useElementLayout.native.js.map +0 -6
- package/dist/esm/helpers/getBoundingClientRect.js +0 -23
- package/dist/esm/helpers/getBoundingClientRect.js.map +0 -6
- package/dist/esm/helpers/getBoundingClientRect.mjs +0 -17
- package/dist/esm/helpers/getBoundingClientRect.mjs.map +0 -1
- package/dist/esm/helpers/getBoundingClientRect.native.js +0 -24
- package/dist/esm/helpers/getBoundingClientRect.native.js.map +0 -1
- package/dist/esm/helpers/getRect.js +0 -11
- package/dist/esm/helpers/getRect.js.map +0 -6
- package/dist/esm/helpers/getRect.mjs +0 -21
- package/dist/esm/helpers/getRect.mjs.map +0 -1
- package/dist/esm/helpers/getRect.native.js +0 -22
- package/dist/esm/helpers/getRect.native.js.map +0 -1
- package/dist/esm/hooks/useElementLayout.js +0 -140
- package/dist/esm/hooks/useElementLayout.js.map +0 -6
- package/dist/esm/hooks/useElementLayout.mjs +0 -175
- package/dist/esm/hooks/useElementLayout.mjs.map +0 -1
- package/dist/esm/hooks/useElementLayout.native.js +0 -189
- package/dist/esm/hooks/useElementLayout.native.js.map +0 -1
- package/src/helpers/getBoundingClientRect.tsx +0 -30
- package/src/helpers/getRect.tsx +0 -8
- package/src/hooks/useElementLayout.tsx +0 -292
- package/types/helpers/getBoundingClientRect.d.ts +0 -3
- package/types/helpers/getBoundingClientRect.d.ts.map +0 -1
- package/types/helpers/getRect.d.ts +0 -9
- package/types/helpers/getRect.d.ts.map +0 -1
- package/types/hooks/useElementLayout.d.ts +0 -26
- package/types/hooks/useElementLayout.d.ts.map +0 -1
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
import { isClient, useIsomorphicLayoutEffect } from '@tamagui/constants'
|
|
2
|
-
import {
|
|
3
|
-
isEqualShallow,
|
|
4
|
-
type TamaguiComponentStateRef,
|
|
5
|
-
___onDidFinishClientRender,
|
|
6
|
-
} from '@tamagui/web'
|
|
7
|
-
import type { RefObject } from 'react'
|
|
8
|
-
|
|
9
|
-
const LayoutHandlers = new WeakMap<HTMLElement, Function>()
|
|
10
|
-
const Nodes = new Set<HTMLElement>()
|
|
11
|
-
|
|
12
|
-
type LayoutMeasurementStrategy = 'off' | 'sync' | 'async'
|
|
13
|
-
|
|
14
|
-
let strategy: LayoutMeasurementStrategy = 'async'
|
|
15
|
-
|
|
16
|
-
export function setOnLayoutStrategy(state: LayoutMeasurementStrategy) {
|
|
17
|
-
strategy = state
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export type LayoutValue = {
|
|
21
|
-
x: number
|
|
22
|
-
y: number
|
|
23
|
-
width: number
|
|
24
|
-
height: number
|
|
25
|
-
left: number
|
|
26
|
-
top: number
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export type LayoutEvent = {
|
|
30
|
-
nativeEvent: {
|
|
31
|
-
layout: LayoutValue
|
|
32
|
-
target: any
|
|
33
|
-
}
|
|
34
|
-
timeStamp: number
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const NodeRectCache = new WeakMap<HTMLElement, DOMRect>()
|
|
38
|
-
const ParentRectCache = new WeakMap<HTMLElement, DOMRect>()
|
|
39
|
-
const DebounceTimers = new WeakMap<HTMLElement, NodeJS.Timeout>()
|
|
40
|
-
const LastChangeTime = new WeakMap<HTMLElement, number>()
|
|
41
|
-
|
|
42
|
-
const rAF = typeof window !== 'undefined' ? window.requestAnimationFrame : undefined
|
|
43
|
-
const DEBOUNCE_DELAY = 32 // 32ms debounce (2 frames at 60fps)
|
|
44
|
-
|
|
45
|
-
if (isClient) {
|
|
46
|
-
if (rAF) {
|
|
47
|
-
// prevent thrashing during first hydration (somewhat, streaming gets trickier)
|
|
48
|
-
let avoidUpdates = true
|
|
49
|
-
const queuedUpdates = new Map<HTMLElement, Function>()
|
|
50
|
-
|
|
51
|
-
// track frame timing to detect sync work and avoid updates during heavy periods
|
|
52
|
-
let lastFrameAt = Date.now()
|
|
53
|
-
const numDroppedFramesUntilPause = 2 // adjust sensitivity
|
|
54
|
-
|
|
55
|
-
___onDidFinishClientRender(() => {
|
|
56
|
-
avoidUpdates = false
|
|
57
|
-
if (queuedUpdates) {
|
|
58
|
-
queuedUpdates.forEach((cb) => cb())
|
|
59
|
-
queuedUpdates.clear()
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
async function updateLayoutIfChanged(node: HTMLElement) {
|
|
64
|
-
const nodeRect = node.getBoundingClientRect()
|
|
65
|
-
const parentNode = node.parentElement
|
|
66
|
-
const parentRect = parentNode?.getBoundingClientRect()
|
|
67
|
-
|
|
68
|
-
const onLayout = LayoutHandlers.get(node)
|
|
69
|
-
if (typeof onLayout !== 'function') return
|
|
70
|
-
|
|
71
|
-
const cachedRect = NodeRectCache.get(node)
|
|
72
|
-
const cachedParentRect = parentNode ? NodeRectCache.get(parentNode) : null
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
!cachedRect ||
|
|
76
|
-
// has changed one rect
|
|
77
|
-
(!isEqualShallow(cachedRect, nodeRect) &&
|
|
78
|
-
(!cachedParentRect || !isEqualShallow(cachedParentRect, parentRect)))
|
|
79
|
-
) {
|
|
80
|
-
NodeRectCache.set(node, nodeRect)
|
|
81
|
-
if (parentRect && parentNode) {
|
|
82
|
-
ParentRectCache.set(parentNode, parentRect)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
if (avoidUpdates) {
|
|
86
|
-
// Use sync version for queued updates to avoid promise complications
|
|
87
|
-
const event = getElementLayoutEvent(node)
|
|
88
|
-
queuedUpdates.set(node, () => onLayout(event))
|
|
89
|
-
} else if (strategy === 'async') {
|
|
90
|
-
// For async strategy, debounce the layout update
|
|
91
|
-
const now = Date.now()
|
|
92
|
-
LastChangeTime.set(node, now)
|
|
93
|
-
|
|
94
|
-
// Clear existing debounce timer
|
|
95
|
-
const existingTimer = DebounceTimers.get(node)
|
|
96
|
-
if (existingTimer) {
|
|
97
|
-
clearTimeout(existingTimer)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Set new debounce timer
|
|
101
|
-
const timer = setTimeout(async () => {
|
|
102
|
-
const lastChange = LastChangeTime.get(node) || 0
|
|
103
|
-
const timeSinceChange = Date.now() - lastChange
|
|
104
|
-
|
|
105
|
-
// Only fire if at least DEBOUNCE_DELAY has passed since last change
|
|
106
|
-
if (timeSinceChange >= DEBOUNCE_DELAY) {
|
|
107
|
-
const event = await getElementLayoutEventAsync(node)
|
|
108
|
-
onLayout(event)
|
|
109
|
-
DebounceTimers.delete(node)
|
|
110
|
-
} else {
|
|
111
|
-
// Reschedule if not enough time has passed
|
|
112
|
-
const remainingDelay = DEBOUNCE_DELAY - timeSinceChange
|
|
113
|
-
const newTimer = setTimeout(async () => {
|
|
114
|
-
const event = await getElementLayoutEventAsync(node)
|
|
115
|
-
onLayout(event)
|
|
116
|
-
DebounceTimers.delete(node)
|
|
117
|
-
}, remainingDelay)
|
|
118
|
-
DebounceTimers.set(node, newTimer)
|
|
119
|
-
}
|
|
120
|
-
}, DEBOUNCE_DELAY)
|
|
121
|
-
|
|
122
|
-
DebounceTimers.set(node, timer)
|
|
123
|
-
} else {
|
|
124
|
-
// Sync strategy - use sync version
|
|
125
|
-
const event = getElementLayoutEvent(node)
|
|
126
|
-
onLayout(event)
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// note that getBoundingClientRect() does not thrash layout if its after an animation frame
|
|
132
|
-
rAF!(layoutOnAnimationFrame)
|
|
133
|
-
function layoutOnAnimationFrame() {
|
|
134
|
-
const now = Date.now()
|
|
135
|
-
const timeSinceLastFrame = now - lastFrameAt
|
|
136
|
-
lastFrameAt = now
|
|
137
|
-
|
|
138
|
-
if (strategy !== 'off') {
|
|
139
|
-
// avoid updates if we've been dropping frames (indicates sync work happening)
|
|
140
|
-
const expectedFrameTime = 16.67 // ~60fps
|
|
141
|
-
const hasRecentSyncWork =
|
|
142
|
-
timeSinceLastFrame > expectedFrameTime * numDroppedFramesUntilPause
|
|
143
|
-
|
|
144
|
-
if (!hasRecentSyncWork) {
|
|
145
|
-
Nodes.forEach(updateLayoutIfChanged)
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
rAF!(layoutOnAnimationFrame)
|
|
149
|
-
}
|
|
150
|
-
} else {
|
|
151
|
-
if (process.env.NODE_ENV === 'development') {
|
|
152
|
-
console.warn(
|
|
153
|
-
`No requestAnimationFrame - please polyfill for onLayout to work correctly`
|
|
154
|
-
)
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Sync versions
|
|
160
|
-
export const getElementLayoutEvent = (target: HTMLElement): LayoutEvent => {
|
|
161
|
-
let res: LayoutEvent | null = null
|
|
162
|
-
measureLayout(target, null, (x, y, width, height, left, top) => {
|
|
163
|
-
res = {
|
|
164
|
-
nativeEvent: {
|
|
165
|
-
layout: { x, y, width, height, left, top },
|
|
166
|
-
target,
|
|
167
|
-
},
|
|
168
|
-
timeStamp: Date.now(),
|
|
169
|
-
}
|
|
170
|
-
})
|
|
171
|
-
if (!res) {
|
|
172
|
-
throw new Error(`‼️`) // impossible
|
|
173
|
-
}
|
|
174
|
-
return res
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export const measureLayout = (
|
|
178
|
-
node: HTMLElement,
|
|
179
|
-
relativeTo: HTMLElement | null,
|
|
180
|
-
callback: (
|
|
181
|
-
x: number,
|
|
182
|
-
y: number,
|
|
183
|
-
width: number,
|
|
184
|
-
height: number,
|
|
185
|
-
left: number,
|
|
186
|
-
top: number
|
|
187
|
-
) => void
|
|
188
|
-
) => {
|
|
189
|
-
const relativeNode = relativeTo || node?.parentElement
|
|
190
|
-
if (relativeNode instanceof HTMLElement) {
|
|
191
|
-
const nodeDim = node.getBoundingClientRect()
|
|
192
|
-
const relativeNodeDim = relativeNode.getBoundingClientRect()
|
|
193
|
-
|
|
194
|
-
if (relativeNodeDim && nodeDim) {
|
|
195
|
-
const { x, y, width, height, left, top } = getRelativeDimensions(
|
|
196
|
-
nodeDim,
|
|
197
|
-
relativeNodeDim
|
|
198
|
-
)
|
|
199
|
-
callback(x, y, width, height, left, top)
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
export const getElementLayoutEventAsync = async (
|
|
205
|
-
target: HTMLElement
|
|
206
|
-
): Promise<LayoutEvent> => {
|
|
207
|
-
let res: LayoutEvent | null = null
|
|
208
|
-
await measureLayoutAsync(target, null, (x, y, width, height, left, top) => {
|
|
209
|
-
res = {
|
|
210
|
-
nativeEvent: {
|
|
211
|
-
layout: { x, y, width, height, left, top },
|
|
212
|
-
target,
|
|
213
|
-
},
|
|
214
|
-
timeStamp: Date.now(),
|
|
215
|
-
}
|
|
216
|
-
})
|
|
217
|
-
if (!res) {
|
|
218
|
-
throw new Error(`‼️`) // impossible
|
|
219
|
-
}
|
|
220
|
-
return res
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
export const measureLayoutAsync = async (
|
|
224
|
-
node: HTMLElement,
|
|
225
|
-
relativeTo: HTMLElement | null,
|
|
226
|
-
callback: (
|
|
227
|
-
x: number,
|
|
228
|
-
y: number,
|
|
229
|
-
width: number,
|
|
230
|
-
height: number,
|
|
231
|
-
left: number,
|
|
232
|
-
top: number
|
|
233
|
-
) => void
|
|
234
|
-
) => {
|
|
235
|
-
const relativeNode = relativeTo || node?.parentElement
|
|
236
|
-
if (relativeNode instanceof HTMLElement) {
|
|
237
|
-
const [nodeDim, relativeNodeDim] = await Promise.all([
|
|
238
|
-
node.getBoundingClientRect(),
|
|
239
|
-
relativeNode.getBoundingClientRect(),
|
|
240
|
-
])
|
|
241
|
-
|
|
242
|
-
if (relativeNodeDim && nodeDim) {
|
|
243
|
-
const { x, y, width, height, left, top } = getRelativeDimensions(
|
|
244
|
-
nodeDim,
|
|
245
|
-
relativeNodeDim
|
|
246
|
-
)
|
|
247
|
-
callback(x, y, width, height, left, top)
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const getRelativeDimensions = (a: DOMRectReadOnly, b: DOMRectReadOnly) => {
|
|
253
|
-
const { height, left, top, width } = a
|
|
254
|
-
const x = left - b.left
|
|
255
|
-
const y = top - b.top
|
|
256
|
-
return { x, y, width, height, left, top }
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
export function useElementLayout(
|
|
260
|
-
ref: RefObject<TamaguiComponentStateRef>,
|
|
261
|
-
onLayout?: ((e: LayoutEvent) => void) | null
|
|
262
|
-
) {
|
|
263
|
-
// ensure always up to date so we can avoid re-running effect
|
|
264
|
-
const node = ref.current?.host as HTMLElement
|
|
265
|
-
if (node && onLayout) {
|
|
266
|
-
LayoutHandlers.set(node, onLayout)
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
useIsomorphicLayoutEffect(() => {
|
|
270
|
-
if (!onLayout) return
|
|
271
|
-
const node = ref.current?.host as HTMLElement
|
|
272
|
-
if (!node) return
|
|
273
|
-
|
|
274
|
-
LayoutHandlers.set(node, onLayout)
|
|
275
|
-
Nodes.add(node)
|
|
276
|
-
onLayout(getElementLayoutEvent(node))
|
|
277
|
-
|
|
278
|
-
return () => {
|
|
279
|
-
Nodes.delete(node)
|
|
280
|
-
LayoutHandlers.delete(node)
|
|
281
|
-
NodeRectCache.delete(node)
|
|
282
|
-
|
|
283
|
-
// Clean up debounce timer and tracking
|
|
284
|
-
const timer = DebounceTimers.get(node)
|
|
285
|
-
if (timer) {
|
|
286
|
-
clearTimeout(timer)
|
|
287
|
-
DebounceTimers.delete(node)
|
|
288
|
-
}
|
|
289
|
-
LastChangeTime.delete(node)
|
|
290
|
-
}
|
|
291
|
-
}, [ref, !!onLayout])
|
|
292
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getBoundingClientRect.d.ts","sourceRoot":"","sources":["../../src/helpers/getBoundingClientRect.tsx"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,GAAI,MAAM,WAAW,GAAG,IAAI,KAAG,SAAS,GAAG,OAG5E,CAAA;AAED,eAAO,MAAM,0BAA0B,GACrC,SAAS,WAAW,KACnB,OAAO,CAAC,eAAe,GAAG,SAAS,CAsBrC,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getRect.d.ts","sourceRoot":"","sources":["../../src/helpers/getRect.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO,GAAI,MAAM,WAAW;;;;;;;aAKxC,CAAA"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { type TamaguiComponentStateRef } from '@tamagui/web';
|
|
2
|
-
import type { RefObject } from 'react';
|
|
3
|
-
type LayoutMeasurementStrategy = 'off' | 'sync' | 'async';
|
|
4
|
-
export declare function setOnLayoutStrategy(state: LayoutMeasurementStrategy): void;
|
|
5
|
-
export type LayoutValue = {
|
|
6
|
-
x: number;
|
|
7
|
-
y: number;
|
|
8
|
-
width: number;
|
|
9
|
-
height: number;
|
|
10
|
-
left: number;
|
|
11
|
-
top: number;
|
|
12
|
-
};
|
|
13
|
-
export type LayoutEvent = {
|
|
14
|
-
nativeEvent: {
|
|
15
|
-
layout: LayoutValue;
|
|
16
|
-
target: any;
|
|
17
|
-
};
|
|
18
|
-
timeStamp: number;
|
|
19
|
-
};
|
|
20
|
-
export declare const getElementLayoutEvent: (target: HTMLElement) => LayoutEvent;
|
|
21
|
-
export declare const measureLayout: (node: HTMLElement, relativeTo: HTMLElement | null, callback: (x: number, y: number, width: number, height: number, left: number, top: number) => void) => void;
|
|
22
|
-
export declare const getElementLayoutEventAsync: (target: HTMLElement) => Promise<LayoutEvent>;
|
|
23
|
-
export declare const measureLayoutAsync: (node: HTMLElement, relativeTo: HTMLElement | null, callback: (x: number, y: number, width: number, height: number, left: number, top: number) => void) => Promise<void>;
|
|
24
|
-
export declare function useElementLayout(ref: RefObject<TamaguiComponentStateRef>, onLayout?: ((e: LayoutEvent) => void) | null): void;
|
|
25
|
-
export {};
|
|
26
|
-
//# sourceMappingURL=useElementLayout.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useElementLayout.d.ts","sourceRoot":"","sources":["../../src/hooks/useElementLayout.tsx"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,wBAAwB,EAE9B,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtC,KAAK,yBAAyB,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAA;AAIzD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,yBAAyB,QAEnE;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE;QACX,MAAM,EAAE,WAAW,CAAA;QACnB,MAAM,EAAE,GAAG,CAAA;KACZ,CAAA;IACD,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AA6HD,eAAO,MAAM,qBAAqB,GAAI,QAAQ,WAAW,KAAG,WAe3D,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,MAAM,WAAW,EACjB,YAAY,WAAW,GAAG,IAAI,EAC9B,UAAU,CACR,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,KACR,IAAI,SAeV,CAAA;AAED,eAAO,MAAM,0BAA0B,GACrC,QAAQ,WAAW,KAClB,OAAO,CAAC,WAAW,CAerB,CAAA;AAED,eAAO,MAAM,kBAAkB,GAC7B,MAAM,WAAW,EACjB,YAAY,WAAW,GAAG,IAAI,EAC9B,UAAU,CACR,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,KACR,IAAI,kBAiBV,CAAA;AASD,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,SAAS,CAAC,wBAAwB,CAAC,EACxC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,QA+B7C"}
|