@terreno/ui 0.12.2 → 0.13.3

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 (58) hide show
  1. package/dist/ConsentFormScreen.js +8 -7
  2. package/dist/ConsentFormScreen.js.map +1 -1
  3. package/dist/Field.js.map +1 -1
  4. package/dist/PickerSelect.d.ts +22 -10
  5. package/dist/PickerSelect.js +11 -9
  6. package/dist/PickerSelect.js.map +1 -1
  7. package/dist/SelectBadge.js +11 -1
  8. package/dist/SelectBadge.js.map +1 -1
  9. package/dist/SelectField.js +2 -2
  10. package/dist/SelectField.js.map +1 -1
  11. package/dist/SidebarNavigation.native.js.map +1 -1
  12. package/dist/Signature.js +4 -0
  13. package/dist/Signature.js.map +1 -1
  14. package/dist/Signature.native.js +4 -0
  15. package/dist/Signature.native.js.map +1 -1
  16. package/dist/Theme.d.ts +1 -1
  17. package/dist/Theme.js.map +1 -1
  18. package/dist/useConsentForms.d.ts +4 -3
  19. package/dist/useConsentForms.js +26 -4
  20. package/dist/useConsentForms.js.map +1 -1
  21. package/dist/useConsentHistory.d.ts +4 -3
  22. package/dist/useConsentHistory.js +26 -4
  23. package/dist/useConsentHistory.js.map +1 -1
  24. package/dist/useSubmitConsent.d.ts +7 -6
  25. package/dist/useSubmitConsent.js +25 -3
  26. package/dist/useSubmitConsent.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/ConsentFormScreen.test.tsx +91 -23
  29. package/src/ConsentFormScreen.tsx +21 -0
  30. package/src/Field.tsx +1 -1
  31. package/src/HeightField.test.tsx +68 -0
  32. package/src/Modal.tsx +2 -2
  33. package/src/NumberField.test.tsx +13 -19
  34. package/src/PickerSelect.tsx +48 -34
  35. package/src/SelectBadge.tsx +7 -3
  36. package/src/SelectField.tsx +2 -2
  37. package/src/SidebarNavigation.native.tsx +6 -2
  38. package/src/Signature.native.tsx +4 -0
  39. package/src/Signature.test.tsx +10 -0
  40. package/src/Signature.tsx +4 -0
  41. package/src/Theme.tsx +17 -14
  42. package/src/Tooltip.test.tsx +41 -22
  43. package/src/__snapshots__/AddressField.test.tsx.snap +0 -1
  44. package/src/__snapshots__/CustomSelectField.test.tsx.snap +0 -7
  45. package/src/__snapshots__/Field.test.tsx.snap +0 -6
  46. package/src/__snapshots__/PickerSelect.test.tsx.snap +0 -7
  47. package/src/__snapshots__/SelectField.test.tsx.snap +0 -6
  48. package/src/__snapshots__/TerrenoProvider.test.tsx.snap +4 -18
  49. package/src/__snapshots__/TimezonePicker.test.tsx.snap +0 -6
  50. package/src/bunSetup.ts +22 -0
  51. package/src/polyfill.d.ts +1 -1
  52. package/src/table/__snapshots__/TableBadge.test.tsx.snap +0 -1
  53. package/src/useConsentForms.test.ts +25 -0
  54. package/src/useConsentForms.ts +32 -7
  55. package/src/useConsentHistory.test.ts +99 -0
  56. package/src/useConsentHistory.ts +31 -6
  57. package/src/useSubmitConsent.test.ts +24 -0
  58. package/src/useSubmitConsent.ts +35 -10
@@ -25,15 +25,18 @@
25
25
 
26
26
  import {Picker} from "@react-native-picker/picker";
27
27
  import isEqual from "lodash/isEqual";
28
- import {useCallback, useEffect, useMemo, useState} from "react";
28
+ import {type ComponentType, type ReactNode, useCallback, useEffect, useMemo, useState} from "react";
29
29
  import {
30
30
  Keyboard,
31
31
  Modal,
32
+ type ModalProps,
32
33
  Platform,
33
34
  Pressable,
35
+ type PressableProps,
34
36
  StyleSheet,
35
37
  Text,
36
38
  TextInput,
39
+ type TextInputProps,
37
40
  TouchableOpacity,
38
41
  View,
39
42
  } from "react-native";
@@ -67,14 +70,23 @@ export const defaultStyles = StyleSheet.create({
67
70
  },
68
71
  });
69
72
 
73
+ /** A single option for the picker select component. */
74
+ export interface PickerSelectItem {
75
+ label: string;
76
+ value: string | number | null;
77
+ key?: string | number;
78
+ color?: string;
79
+ inputLabel?: string;
80
+ }
81
+
70
82
  export interface RNPickerSelectProps {
71
- onValueChange: (value: any, index: any) => void;
72
- items: any[];
73
- value?: any;
74
- placeholder?: any;
83
+ onValueChange: (value: string | number | null, index: number) => void;
84
+ items: PickerSelectItem[];
85
+ value?: string | number | null;
86
+ placeholder?: Partial<PickerSelectItem>;
75
87
  disabled?: boolean;
76
88
  itemKey?: string | number;
77
- children?: any;
89
+ children?: ReactNode;
78
90
  onOpen?: () => void;
79
91
  useNativeAndroidPickerStyle?: boolean;
80
92
  fixAndroidTouchableBug?: boolean;
@@ -87,18 +99,18 @@ export interface RNPickerSelectProps {
87
99
  onClose?: () => void;
88
100
 
89
101
  // Modal props (iOS only)
90
- modalProps?: any;
102
+ modalProps?: Partial<ModalProps>;
91
103
 
92
104
  // TextInput props
93
- textInputProps?: any;
105
+ textInputProps?: Partial<TextInputProps>;
94
106
 
95
107
  // Touchable Done props (iOS only)
96
- touchableDoneProps?: any;
108
+ touchableDoneProps?: Partial<PressableProps>;
97
109
 
98
110
  // Touchable wrapper props
99
- touchableWrapperProps?: any;
111
+ touchableWrapperProps?: Partial<PressableProps>;
100
112
 
101
- InputAccessoryView?: any;
113
+ InputAccessoryView?: ComponentType<{testID?: string}>;
102
114
  }
103
115
 
104
116
  export function RNPickerSelect({
@@ -125,7 +137,9 @@ export function RNPickerSelect({
125
137
  InputAccessoryView,
126
138
  }: RNPickerSelectProps) {
127
139
  const [showPicker, setShowPicker] = useState<boolean>(false);
128
- const [animationType, setAnimationType] = useState(undefined);
140
+ const [animationType, setAnimationType] = useState<"none" | "slide" | "fade" | undefined>(
141
+ undefined
142
+ );
129
143
  const [orientation, setOrientation] = useState<"portrait" | "landscape">("portrait");
130
144
  const [doneDepressed, setDoneDepressed] = useState<boolean>(false);
131
145
  const {theme} = useTheme();
@@ -159,12 +173,12 @@ export function RNPickerSelect({
159
173
  }, [items, placeholder]);
160
174
 
161
175
  const getSelectedItem = useCallback(
162
- (key: any, val: any) => {
163
- let idx = options.findIndex((item: any) => {
164
- if (item.key && key) {
176
+ (key: string | number | undefined, val: string | number | null | undefined) => {
177
+ let idx = options.findIndex((item) => {
178
+ if (item?.key && key) {
165
179
  return isEqual(item.key, key);
166
180
  }
167
- return isEqual(item.value, val);
181
+ return isEqual(item?.value, val);
168
182
  });
169
183
  if (idx === -1) {
170
184
  idx = 0;
@@ -177,7 +191,7 @@ export function RNPickerSelect({
177
191
  [options]
178
192
  );
179
193
 
180
- const [selectedItem, setSelectedItem] = useState<any>(() => {
194
+ const [selectedItem, setSelectedItem] = useState<Partial<PickerSelectItem>>(() => {
181
195
  return getSelectedItem(itemKey, value).selectedItem;
182
196
  });
183
197
 
@@ -195,13 +209,17 @@ export function RNPickerSelect({
195
209
  togglePicker(false, onDownArrow);
196
210
  };
197
211
 
198
- const onValueChangeEvent = (val: any, index: any) => {
212
+ const onValueChangeEvent = (val: string | number | null, index: number) => {
199
213
  const item = getSelectedItem(itemKey, val);
200
214
  onValueChange(val, index);
201
215
  setSelectedItem(item.selectedItem);
202
216
  };
203
217
 
204
- const onOrientationChange = ({nativeEvent}: any) => {
218
+ const onOrientationChange = ({
219
+ nativeEvent,
220
+ }: {
221
+ nativeEvent: {orientation: "portrait" | "landscape"};
222
+ }) => {
205
223
  setOrientation(nativeEvent.orientation);
206
224
  };
207
225
 
@@ -215,7 +233,7 @@ export function RNPickerSelect({
215
233
  }
216
234
  };
217
235
 
218
- const togglePicker = (animate = false, postToggleCallback?: any) => {
236
+ const togglePicker = (animate = false, postToggleCallback?: () => void) => {
219
237
  if (disabled) {
220
238
  return;
221
239
  }
@@ -237,13 +255,13 @@ export function RNPickerSelect({
237
255
  };
238
256
 
239
257
  const renderPickerItems = () => {
240
- return options?.map((item: any) => {
258
+ return options?.map((item) => {
241
259
  return (
242
260
  <Picker.Item
243
- color={item.color}
244
- key={item.key || item.label}
245
- label={item.label}
246
- value={item.value}
261
+ color={item?.color}
262
+ key={item?.key || item?.label}
263
+ label={item?.label}
264
+ value={item?.value}
247
265
  />
248
266
  );
249
267
  });
@@ -408,7 +426,6 @@ export function RNPickerSelect({
408
426
  ]}
409
427
  >
410
428
  <Pressable
411
- activeOpacity={1}
412
429
  onPress={() => {
413
430
  togglePicker(true);
414
431
  }}
@@ -467,14 +484,11 @@ export function RNPickerSelect({
467
484
  };
468
485
 
469
486
  const renderAndroidHeadless = () => {
470
- const Component: any = fixAndroidTouchableBug ? View : Pressable;
487
+ // noExplicitAny: Component is View or Pressable depending on a bug workaround flag. View
488
+ // ignores Pressable-specific props (onPress) at runtime. A type-safe union cannot express this.
489
+ const Component = (fixAndroidTouchableBug ? View : Pressable) as unknown as typeof Pressable;
471
490
  return (
472
- <Component
473
- activeOpacity={1}
474
- onPress={onOpen}
475
- testID="android_touchable_wrapper"
476
- {...touchableWrapperProps}
477
- >
491
+ <Component onPress={onOpen} testID="android_touchable_wrapper" {...touchableWrapperProps}>
478
492
  <View>
479
493
  {renderTextInputOrChildren()}
480
494
  <Picker
@@ -636,7 +650,7 @@ export function RNPickerSelect({
636
650
  // Pass the original (non-stringified) value through so lodash
637
651
  // `isEqual` matching in `getSelectedItem` works for number /
638
652
  // object values.
639
- const originalValue = options[originalIndex]?.value;
653
+ const originalValue = options[originalIndex]?.value ?? null;
640
654
  onValueChangeEvent(originalValue, originalIndex);
641
655
  closeWebMenu();
642
656
  }}
@@ -3,7 +3,7 @@ import type React from "react";
3
3
  import {useCallback, useMemo, useState} from "react";
4
4
  import {Modal, Platform, Text, TouchableOpacity, View} from "react-native";
5
5
 
6
- import type {FieldOption, SelectBadgeProps, SurfaceTheme, TextTheme} from "./Common";
6
+ import type {FieldOption, IconColor, SelectBadgeProps, SurfaceTheme, TextTheme} from "./Common";
7
7
  import {Icon} from "./Icon";
8
8
  import {useTheme} from "./Theme";
9
9
  import {useWebDropdownAnchor, WebDropdownMenu, type WebDropdownMenuOption} from "./WebDropdownMenu";
@@ -98,7 +98,7 @@ export const SelectBadge = ({
98
98
  );
99
99
 
100
100
  const renderPickerItems = useCallback(() => {
101
- return options?.map((item: any) => (
101
+ return options?.map((item: FieldOption) => (
102
102
  <Picker.Item key={item.key || item.label} label={item.label} value={item.value} />
103
103
  ));
104
104
  }, [options]);
@@ -321,7 +321,11 @@ export const SelectBadge = ({
321
321
  }}
322
322
  >
323
323
  <Icon
324
- color={textColor as any}
324
+ // noExplicitAny: textColor is a resolved hex string from the theme, but Icon's
325
+ // color prop expects an IconColor key. Icon falls back to the raw string at runtime
326
+ // (theme.text[color] ?? color), but the type cannot be narrowed without changing
327
+ // Icon's type signature to accept arbitrary strings.
328
+ color={textColor as unknown as IconColor}
325
329
  iconName={showPicker ? "chevron-up" : "chevron-down"}
326
330
  size="sm"
327
331
  />
@@ -26,10 +26,10 @@ export const SelectField: FC<SelectFieldProps> = ({
26
26
  disabled={disabled}
27
27
  items={options}
28
28
  onValueChange={(v) => {
29
- if (v === undefined || v === "") {
29
+ if (v === undefined || v === null || v === "") {
30
30
  onChange("");
31
31
  } else {
32
- onChange(v);
32
+ onChange(String(v));
33
33
  }
34
34
  }}
35
35
  placeholder={!requireValue ? clearOption : {}}
@@ -5,7 +5,7 @@ import {Navigator, Slot} from "expo-router";
5
5
  // update the import path here — this is the only place in the codebase that references it.
6
6
  // eslint-disable-next-line import/no-internal-modules
7
7
  import {Screen} from "expo-router/build/views/Screen";
8
- import {type FC, useCallback, useEffect, useMemo, useRef, useState} from "react";
8
+ import {type FC, type ReactNode, useCallback, useEffect, useMemo, useRef, useState} from "react";
9
9
  import {
10
10
  Animated,
11
11
  Dimensions,
@@ -361,7 +361,11 @@ const SidebarHeader: FC<{onOpen: () => void}> = ({onOpen}) => {
361
361
  const insets = useSafeAreaInsets();
362
362
  const {state, descriptors} = Navigator.useContext();
363
363
  const activeRoute = state.routes[state.index];
364
- const {headerLeft, headerRight, title} = (descriptors[activeRoute?.key]?.options ?? {}) as any;
364
+ const {headerLeft, headerRight, title} = (descriptors[activeRoute?.key]?.options ?? {}) as {
365
+ headerLeft?: (props: object) => ReactNode;
366
+ headerRight?: (props: object) => ReactNode;
367
+ title?: string;
368
+ };
365
369
 
366
370
  return (
367
371
  <View
@@ -18,6 +18,10 @@ export const Signature: FC<Props> = ({onChange, onStart, onEnd}: Props) => {
18
18
 
19
19
  const handleClear = () => {
20
20
  ref.current?.clearSignature();
21
+ // `clearSignature` on the underlying canvas does not fire `onOK`, so the
22
+ // parent never learns the signature is gone. Push an empty value so any
23
+ // "signature required" gating reflects the cleared state immediately.
24
+ onChange("");
21
25
  };
22
26
 
23
27
  const onBegin = () => {
@@ -49,6 +49,16 @@ describe("Signature", () => {
49
49
  expect(clearMock).toHaveBeenCalledTimes(1);
50
50
  });
51
51
 
52
+ it("notifies the parent with an empty value when Clear is pressed", () => {
53
+ clearMock.mockClear();
54
+ const mockOnChange = mock(() => {});
55
+ const {getByText} = renderWithTheme(<Signature onChange={mockOnChange} />);
56
+ fireEvent.press(getByText("Clear"));
57
+ // Without this, "signature required" gating in parents would never reset
58
+ // because the underlying canvas clear() does not fire onEnd/onOK.
59
+ expect(mockOnChange).toHaveBeenCalledWith("");
60
+ });
61
+
52
62
  it("calls onChange with the data URL when a stroke ends", () => {
53
63
  toDataURLReturn = "data:image/png;base64,abc";
54
64
  const mockOnChange = mock(() => {});
package/src/Signature.tsx CHANGED
@@ -17,6 +17,10 @@ export const Signature = ({onChange}: SignatureProps): ReactElement | null => {
17
17
 
18
18
  const onClear = () => {
19
19
  ref.current?.clear();
20
+ // `clear()` on the underlying canvas does not fire `onEnd`, so the parent
21
+ // never learns the signature is gone. Push an empty value so any
22
+ // "signature required" gating reflects the cleared state immediately.
23
+ onChange("");
20
24
  };
21
25
 
22
26
  const onUpdatedSignature = () => {
package/src/Theme.tsx CHANGED
@@ -172,18 +172,21 @@ const computeTheme = (
172
172
  return acc;
173
173
  }
174
174
  const value = themeConfig[key as keyof TerrenoThemeConfig] ?? {};
175
- acc[key as keyof TerrenoTheme] = Object.keys(value).reduce((accKey, valueKey) => {
176
- const primitiveKey = value[valueKey as keyof typeof value] as keyof ThemePrimitives;
177
- if (key === "font") {
178
- accKey[valueKey] = primitiveKey;
179
- } else {
180
- if (primitives[primitiveKey] === undefined) {
181
- console.error(`Primitive ${primitiveKey} not found in theme.`);
175
+ (acc as unknown as Record<string, unknown>)[key] = Object.keys(value).reduce(
176
+ (accKey, valueKey) => {
177
+ const primitiveKey = value[valueKey as keyof typeof value] as keyof ThemePrimitives;
178
+ if (key === "font") {
179
+ accKey[valueKey] = primitiveKey;
180
+ } else {
181
+ if (primitives[primitiveKey] === undefined) {
182
+ console.error(`Primitive ${primitiveKey} not found in theme.`);
183
+ }
184
+ accKey[valueKey] = primitives[primitiveKey];
182
185
  }
183
- accKey[valueKey as keyof typeof accKey] = primitives[primitiveKey];
184
- }
185
- return accKey;
186
- }, {} as any);
186
+ return accKey;
187
+ },
188
+ {} as Record<string, string | number>
189
+ );
187
190
  return acc;
188
191
  }, {} as TerrenoTheme);
189
192
  return {...theme, primitives};
@@ -199,7 +202,7 @@ export const ThemeContext = createContext({
199
202
  });
200
203
 
201
204
  interface ThemeProviderProps {
202
- children: any;
205
+ children: React.ReactNode;
203
206
  }
204
207
 
205
208
  export const ThemeProvider = ({children}: ThemeProviderProps) => {
@@ -225,12 +228,12 @@ export const ThemeProvider = ({children}: ThemeProviderProps) => {
225
228
  const prevSubTheme = prev[key as keyof TerrenoThemeConfig];
226
229
 
227
230
  if (newSubTheme && typeof newSubTheme === "object") {
228
- (mergedTheme as any)[key as keyof TerrenoThemeConfig] = {
231
+ (mergedTheme as Record<string, unknown>)[key] = {
229
232
  ...prevSubTheme,
230
233
  ...newSubTheme,
231
234
  };
232
235
  } else {
233
- mergedTheme[key as keyof TerrenoThemeConfig] = newSubTheme as any;
236
+ (mergedTheme as Record<string, unknown>)[key] = newSubTheme;
234
237
  }
235
238
  }
236
239
  }
@@ -6,6 +6,20 @@ import {Text} from "./Text";
6
6
  import {Tooltip} from "./Tooltip";
7
7
  import {renderWithTheme} from "./test-utils";
8
8
 
9
+ // Minimal shape of the tree returned by toJSON() that we rely on here.
10
+ interface TestNode {
11
+ type: string;
12
+ props: {
13
+ onPointerEnter?: () => void;
14
+ onPointerLeave?: () => void;
15
+ onTouchStart?: (event?: {nativeEvent: object}) => void;
16
+ onLayout?: (event: {
17
+ nativeEvent: {layout: {height: number; width: number; x: number; y: number}};
18
+ }) => void;
19
+ };
20
+ children: null | Array<TestNode | string>;
21
+ }
22
+
9
23
  // Mock react-native-portalize so Portal renders inline in tests
10
24
  mock.module("react-native-portalize", () => ({
11
25
  Host: ({children}: {children: React.ReactNode}) => <View testID="portal-host">{children}</View>,
@@ -13,10 +27,10 @@ mock.module("react-native-portalize", () => ({
13
27
  }));
14
28
 
15
29
  beforeAll(() => {
16
- (global as any).requestAnimationFrame = (callback: FrameRequestCallback) => {
30
+ globalThis.requestAnimationFrame = (callback: FrameRequestCallback) => {
17
31
  return setTimeout(() => callback(Date.now()), 0) as unknown as number;
18
32
  };
19
- (global as any).cancelAnimationFrame = (id: number) => {
33
+ globalThis.cancelAnimationFrame = (id: number) => {
20
34
  clearTimeout(id);
21
35
  };
22
36
  });
@@ -111,14 +125,14 @@ describe("Tooltip", () => {
111
125
  </Tooltip>
112
126
  );
113
127
 
114
- const wrapper = toJSON() as any;
128
+ const wrapper = toJSON();
115
129
  expect(wrapper).toBeTruthy();
116
130
  expect(queryByTestId("tooltip-container")).toBeNull();
117
131
 
118
- const tree = toJSON();
132
+ const tree = toJSON() as TestNode | null;
119
133
  await act(async () => {
120
134
  // Trigger pointer enter on the wrapper
121
- const root = (tree as any).children?.[0];
135
+ const root = tree?.children?.[0] as TestNode | undefined;
122
136
  if (root?.props?.onPointerEnter) {
123
137
  root.props.onPointerEnter();
124
138
  }
@@ -138,8 +152,8 @@ describe("Tooltip", () => {
138
152
  </Tooltip>
139
153
  );
140
154
 
141
- const tree = toJSON() as any;
142
- const root = tree.children?.[0];
155
+ const tree = toJSON() as TestNode;
156
+ const root = tree.children?.[0] as TestNode;
143
157
 
144
158
  await act(async () => {
145
159
  root.props.onTouchStart?.({nativeEvent: {}});
@@ -151,8 +165,10 @@ describe("Tooltip", () => {
151
165
  expect(queryByTestId("tooltip-container")).toBeTruthy();
152
166
 
153
167
  // Second touch should hide
154
- const treeAfterShow = toJSON() as any;
155
- const updatedRoot = treeAfterShow.children?.[treeAfterShow.children.length - 1];
168
+ const treeAfterShow = toJSON() as TestNode;
169
+ const updatedRoot = (treeAfterShow.children as Array<TestNode | string>)[
170
+ (treeAfterShow.children as Array<TestNode | string>).length - 1
171
+ ] as TestNode;
156
172
  await act(async () => {
157
173
  updatedRoot.props.onTouchStart?.({nativeEvent: {}});
158
174
  });
@@ -167,8 +183,8 @@ describe("Tooltip", () => {
167
183
  </Tooltip>
168
184
  );
169
185
 
170
- const tree = toJSON() as any;
171
- const root = tree.children?.[0];
186
+ const tree = toJSON() as TestNode;
187
+ const root = tree.children?.[0] as TestNode;
172
188
 
173
189
  await act(async () => {
174
190
  root.props.onPointerEnter?.();
@@ -179,8 +195,10 @@ describe("Tooltip", () => {
179
195
 
180
196
  expect(queryByTestId("tooltip-container")).toBeTruthy();
181
197
 
182
- const treeAfter = toJSON() as any;
183
- const wrapper = treeAfter.children?.[treeAfter.children.length - 1];
198
+ const treeAfter = toJSON() as TestNode;
199
+ const wrapper = (treeAfter.children as Array<TestNode | string>)[
200
+ (treeAfter.children as Array<TestNode | string>).length - 1
201
+ ] as TestNode;
184
202
  await act(async () => {
185
203
  wrapper.props.onPointerLeave?.();
186
204
  });
@@ -206,8 +224,8 @@ describe("Tooltip", () => {
206
224
  </Tooltip>
207
225
  );
208
226
 
209
- const tree = toJSON() as any;
210
- const root = tree.children?.[0];
227
+ const tree = toJSON() as TestNode;
228
+ const root = tree.children?.[0] as TestNode;
211
229
 
212
230
  await act(async () => {
213
231
  root.props.onPointerEnter?.();
@@ -227,8 +245,8 @@ describe("Tooltip", () => {
227
245
  </Tooltip>
228
246
  );
229
247
 
230
- const tree = toJSON() as any;
231
- const root = tree.children?.[0];
248
+ const tree = toJSON() as TestNode;
249
+ const root = tree.children?.[0] as TestNode;
232
250
 
233
251
  // Show the tooltip
234
252
  await act(async () => {
@@ -241,11 +259,12 @@ describe("Tooltip", () => {
241
259
 
242
260
  // Find any views with onLayout to simulate layout event
243
261
  const {View: ViewComp} = await import("react-native");
244
- const allViews = UNSAFE_getAllByType(ViewComp as any);
262
+ const allViews = UNSAFE_getAllByType(ViewComp);
245
263
  for (const v of allViews) {
246
- if ((v.props as any).onLayout) {
264
+ const props = v.props as TestNode["props"];
265
+ if (props.onLayout) {
247
266
  await act(async () => {
248
- (v.props as any).onLayout({
267
+ props.onLayout?.({
249
268
  nativeEvent: {
250
269
  layout: {height: 100, width: 200, x: 0, y: 0},
251
270
  },
@@ -280,8 +299,8 @@ describe("Tooltip", () => {
280
299
  </Tooltip>
281
300
  );
282
301
 
283
- const tree = toJSON() as any;
284
- const root = tree.children?.[0];
302
+ const tree = toJSON() as TestNode;
303
+ const root = tree.children?.[0] as TestNode;
285
304
  await act(async () => {
286
305
  root.props.onPointerEnter?.();
287
306
  });
@@ -421,7 +421,6 @@ exports[`AddressField renders correctly with default props 1`] = `
421
421
  },
422
422
  ],
423
423
  "props": {
424
- "activeOpacity": 1,
425
424
  "onPress": [Function],
426
425
  "style": {
427
426
  "alignItems": "center",
@@ -57,7 +57,6 @@ exports[`CustomSelectField renders correctly with default props 1`] = `
57
57
  },
58
58
  ],
59
59
  "props": {
60
- "activeOpacity": 1,
61
60
  "onPress": [Function],
62
61
  "style": {
63
62
  "alignItems": "center",
@@ -385,7 +384,6 @@ exports[`CustomSelectField renders with title 1`] = `
385
384
  },
386
385
  ],
387
386
  "props": {
388
- "activeOpacity": 1,
389
387
  "onPress": [Function],
390
388
  "style": {
391
389
  "alignItems": "center",
@@ -698,7 +696,6 @@ exports[`CustomSelectField renders with placeholder 1`] = `
698
696
  },
699
697
  ],
700
698
  "props": {
701
- "activeOpacity": 1,
702
699
  "onPress": [Function],
703
700
  "style": {
704
701
  "alignItems": "center",
@@ -1011,7 +1008,6 @@ exports[`CustomSelectField renders with selected value 1`] = `
1011
1008
  },
1012
1009
  ],
1013
1010
  "props": {
1014
- "activeOpacity": 1,
1015
1011
  "onPress": [Function],
1016
1012
  "style": {
1017
1013
  "alignItems": "center",
@@ -1324,7 +1320,6 @@ exports[`CustomSelectField renders with custom value (not in options) 1`] = `
1324
1320
  },
1325
1321
  ],
1326
1322
  "props": {
1327
- "activeOpacity": 1,
1328
1323
  "onPress": [Function],
1329
1324
  "style": {
1330
1325
  "alignItems": "center",
@@ -1741,7 +1736,6 @@ exports[`CustomSelectField renders disabled state 1`] = `
1741
1736
  },
1742
1737
  ],
1743
1738
  "props": {
1744
- "activeOpacity": 1,
1745
1739
  "onPress": [Function],
1746
1740
  "style": {
1747
1741
  "alignItems": "center",
@@ -2056,7 +2050,6 @@ exports[`CustomSelectField includes custom option in dropdown 1`] = `
2056
2050
  },
2057
2051
  ],
2058
2052
  "props": {
2059
- "activeOpacity": 1,
2060
2053
  "onPress": [Function],
2061
2054
  "style": {
2062
2055
  "alignItems": "center",
@@ -1224,7 +1224,6 @@ exports[`Field renders time field 1`] = `
1224
1224
  },
1225
1225
  ],
1226
1226
  "props": {
1227
- "activeOpacity": 1,
1228
1227
  "onPress": [Function],
1229
1228
  "style": {
1230
1229
  "alignItems": "center",
@@ -1494,7 +1493,6 @@ exports[`Field renders time field 1`] = `
1494
1493
  },
1495
1494
  ],
1496
1495
  "props": {
1497
- "activeOpacity": 1,
1498
1496
  "onPress": [Function],
1499
1497
  "style": {
1500
1498
  "alignItems": "center",
@@ -2219,7 +2217,6 @@ exports[`Field renders datetime field 1`] = `
2219
2217
  },
2220
2218
  ],
2221
2219
  "props": {
2222
- "activeOpacity": 1,
2223
2220
  "onPress": [Function],
2224
2221
  "style": {
2225
2222
  "alignItems": "center",
@@ -2489,7 +2486,6 @@ exports[`Field renders datetime field 1`] = `
2489
2486
  },
2490
2487
  ],
2491
2488
  "props": {
2492
- "activeOpacity": 1,
2493
2489
  "onPress": [Function],
2494
2490
  "style": {
2495
2491
  "alignItems": "center",
@@ -2860,7 +2856,6 @@ exports[`Field renders select field 1`] = `
2860
2856
  },
2861
2857
  ],
2862
2858
  "props": {
2863
- "activeOpacity": 1,
2864
2859
  "onPress": [Function],
2865
2860
  "style": {
2866
2861
  "alignItems": "center",
@@ -3737,7 +3732,6 @@ exports[`Field renders address field 1`] = `
3737
3732
  },
3738
3733
  ],
3739
3734
  "props": {
3740
- "activeOpacity": 1,
3741
3735
  "onPress": [Function],
3742
3736
  "style": {
3743
3737
  "alignItems": "center",
@@ -48,7 +48,6 @@ exports[`PickerSelect renders correctly with default props 1`] = `
48
48
  },
49
49
  ],
50
50
  "props": {
51
- "activeOpacity": 1,
52
51
  "onPress": [Function],
53
52
  "style": {
54
53
  "alignItems": "center",
@@ -313,7 +312,6 @@ exports[`PickerSelect renders with selected value 1`] = `
313
312
  },
314
313
  ],
315
314
  "props": {
316
- "activeOpacity": 1,
317
315
  "onPress": [Function],
318
316
  "style": {
319
317
  "alignItems": "center",
@@ -578,7 +576,6 @@ exports[`PickerSelect renders disabled state 1`] = `
578
576
  },
579
577
  ],
580
578
  "props": {
581
- "activeOpacity": 1,
582
579
  "onPress": [Function],
583
580
  "style": {
584
581
  "alignItems": "center",
@@ -845,7 +842,6 @@ exports[`PickerSelect renders without placeholder when placeholder is empty obje
845
842
  },
846
843
  ],
847
844
  "props": {
848
- "activeOpacity": 1,
849
845
  "onPress": [Function],
850
846
  "style": {
851
847
  "alignItems": "center",
@@ -1100,7 +1096,6 @@ exports[`PickerSelect matches items by itemKey 1`] = `
1100
1096
  },
1101
1097
  ],
1102
1098
  "props": {
1103
- "activeOpacity": 1,
1104
1099
  "onPress": [Function],
1105
1100
  "style": {
1106
1101
  "alignItems": "center",
@@ -1355,7 +1350,6 @@ exports[`PickerSelect renders custom InputAccessoryView 1`] = `
1355
1350
  },
1356
1351
  ],
1357
1352
  "props": {
1358
- "activeOpacity": 1,
1359
1353
  "onPress": [Function],
1360
1354
  "style": {
1361
1355
  "alignItems": "center",
@@ -1541,7 +1535,6 @@ exports[`PickerSelect passes textInputProps to TextInput 1`] = `
1541
1535
  },
1542
1536
  ],
1543
1537
  "props": {
1544
- "activeOpacity": 1,
1545
1538
  "onPress": [Function],
1546
1539
  "style": {
1547
1540
  "alignItems": "center",