@bigbinary/neetoui-rn 3.0.3 → 3.1.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 (56) hide show
  1. package/README.md +29 -1
  2. package/lib/typescript/src/components/BottomSheet/BottomSheet.d.ts +8 -1
  3. package/lib/typescript/src/components/BottomSheet/BottomSheet.d.ts.map +1 -1
  4. package/lib/typescript/src/components/ChatInput/AttachmentsView.d.ts.map +1 -1
  5. package/lib/typescript/src/components/ChatInput/ChatInput.d.ts.map +1 -1
  6. package/lib/typescript/src/components/CheckBox/CheckBox.d.ts +7 -1
  7. package/lib/typescript/src/components/CheckBox/CheckBox.d.ts.map +1 -1
  8. package/lib/typescript/src/components/Input/Input.d.ts +12 -11
  9. package/lib/typescript/src/components/Input/Input.d.ts.map +1 -1
  10. package/lib/typescript/src/components/Input/InputFrame.d.ts +41 -0
  11. package/lib/typescript/src/components/Input/InputFrame.d.ts.map +1 -0
  12. package/lib/typescript/src/components/Input/index.d.ts +1 -0
  13. package/lib/typescript/src/components/Input/index.d.ts.map +1 -1
  14. package/lib/typescript/src/components/NeetoUIProvider/NeetoUIProvider.d.ts.map +1 -1
  15. package/lib/typescript/src/components/RadioButton/RadioButton.d.ts +6 -1
  16. package/lib/typescript/src/components/RadioButton/RadioButton.d.ts.map +1 -1
  17. package/lib/typescript/src/components/SearchBar/SearchBar.d.ts.map +1 -1
  18. package/lib/typescript/src/components/Skeleton/Skeleton.d.ts.map +1 -1
  19. package/lib/typescript/src/components/Typography/Typography.d.ts +5 -0
  20. package/lib/typescript/src/components/Typography/Typography.d.ts.map +1 -1
  21. package/lib/typescript/src/components/Typography/index.d.ts +1 -1
  22. package/lib/typescript/src/components/Typography/index.d.ts.map +1 -1
  23. package/lib/typescript/src/index.d.ts +2 -2
  24. package/lib/typescript/src/index.d.ts.map +1 -1
  25. package/lib/typescript/src/unistyles.d.ts +28 -1
  26. package/lib/typescript/src/unistyles.d.ts.map +1 -1
  27. package/lib/typescript/src/utils/scale.d.ts +22 -0
  28. package/lib/typescript/src/utils/scale.d.ts.map +1 -1
  29. package/package.json +8 -6
  30. package/src/components/Alert/Alert.tsx +57 -46
  31. package/src/components/BottomSheet/BottomSheet.tsx +98 -55
  32. package/src/components/BottomSheetMenu/BottomSheetMenu.tsx +55 -48
  33. package/src/components/ChatInput/AttachmentsView.tsx +32 -18
  34. package/src/components/ChatInput/ChatInput.tsx +148 -99
  35. package/src/components/ChatInput/IconButton.tsx +21 -10
  36. package/src/components/ChatInput/MentionsInput.tsx +42 -27
  37. package/src/components/CheckBox/CheckBox.tsx +54 -33
  38. package/src/components/EmptyView/EmptyView.tsx +27 -20
  39. package/src/components/Header/Header.tsx +25 -18
  40. package/src/components/Header/ScreenHeader.tsx +17 -10
  41. package/src/components/Input/Input.tsx +118 -67
  42. package/src/components/Input/InputFrame.tsx +261 -0
  43. package/src/components/Input/index.ts +1 -0
  44. package/src/components/NeetoUIProvider/NeetoUIProvider.tsx +2 -1
  45. package/src/components/OnBoarding/OnBoarding.tsx +61 -54
  46. package/src/components/RadioButton/RadioButton.tsx +72 -31
  47. package/src/components/SearchBar/SearchBar.tsx +41 -26
  48. package/src/components/Skeleton/Skeleton.tsx +18 -11
  49. package/src/components/Toast/Toast.tsx +38 -31
  50. package/src/components/Typography/Typography.tsx +31 -2
  51. package/src/components/Typography/index.ts +5 -1
  52. package/src/index.ts +7 -2
  53. package/src/unistyles-init.ts +4 -0
  54. package/src/unistyles.ts +52 -4
  55. package/src/utils/scale.ts +36 -9
  56. package/src/types/neeto-icons-rn.d.ts +0 -33
@@ -7,21 +7,19 @@ import {
7
7
  type ReactNode,
8
8
  } from "react";
9
9
  import { type TextInput, View, type TextInputProps } from "react-native";
10
- import {
11
- Attachment,
12
- BookOpen,
13
- CannedResponses,
14
- ChatBubble,
15
- Down,
16
- Expand,
17
- Forward,
18
- Minimize,
19
- Notes,
20
- SendPlane,
21
- } from "@bigbinary/neeto-icons-rn";
10
+ import Attachment from "@bigbinary/neeto-icons-rn/icons/Attachment";
11
+ import BookOpen from "@bigbinary/neeto-icons-rn/icons/BookOpen";
12
+ import CannedResponses from "@bigbinary/neeto-icons-rn/icons/CannedResponses";
13
+ import ChatBubble from "@bigbinary/neeto-icons-rn/icons/ChatBubble";
14
+ import Down from "@bigbinary/neeto-icons-rn/icons/Down";
15
+ import Expand from "@bigbinary/neeto-icons-rn/icons/Expand";
16
+ import Forward from "@bigbinary/neeto-icons-rn/icons/Forward";
17
+ import Minimize from "@bigbinary/neeto-icons-rn/icons/Minimize";
18
+ import Notes from "@bigbinary/neeto-icons-rn/icons/Notes";
19
+ import SendPlane from "@bigbinary/neeto-icons-rn/icons/SendPlane";
22
20
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
23
21
 
24
- import { moderateScale } from "../../utils/scale";
22
+ import { moderateScale, scaleFor } from "../../utils/scale";
25
23
  import { BottomSheet } from "../BottomSheet";
26
24
  import { Skeleton } from "../Skeleton";
27
25
  import { Touchable } from "../Touchable";
@@ -209,7 +207,7 @@ export const ChatInput = forwardRef<ChatInputRef, ChatInputProps>(
209
207
  disabled || (isForwardSelected && toEmailsForForward.length === 0);
210
208
 
211
209
  return (
212
- <View>
210
+ <View style={styles.root}>
213
211
  {isLoading && (
214
212
  <Skeleton animated height={moderateScale(2)} variant="line" />
215
213
  )}
@@ -267,12 +265,14 @@ export const ChatInput = forwardRef<ChatInputRef, ChatInputProps>(
267
265
  />
268
266
  )}
269
267
  <View style={styles.toolbarDivider} />
268
+ {/* isActive is the selected-option tint for the three mode
269
+ toggles above. These two are actions, not modes, so they
270
+ stay at full strength like the attachment button. */}
270
271
  {onCannedResponse &&
271
272
  showCannedResponsesFor.includes(selectedOption) && (
272
273
  <IconButton
273
274
  accessibilityLabel="Canned responses"
274
275
  Icon={CannedResponses}
275
- isActive={false}
276
276
  onPress={onCannedResponse}
277
277
  />
278
278
  )}
@@ -280,7 +280,6 @@ export const ChatInput = forwardRef<ChatInputRef, ChatInputProps>(
280
280
  <IconButton
281
281
  accessibilityLabel="Articles"
282
282
  Icon={BookOpen}
283
- isActive={false}
284
283
  onPress={onArticles}
285
284
  />
286
285
  )}
@@ -292,49 +291,59 @@ export const ChatInput = forwardRef<ChatInputRef, ChatInputProps>(
292
291
  />
293
292
  </View>
294
293
  <View style={styles.toolbarGroup}>
295
- <Touchable
296
- accessibilityLabel="Send"
297
- accessibilityRole="button"
298
- disabled={isActionDisabled}
294
+ {/* Both actions share one filled pill, split by a divider, as
295
+ on web. The send affordance is the plane alone on a reply;
296
+ note and forward keep their labels. */}
297
+ <View
299
298
  style={[
300
- styles.sendButton,
301
- isActionDisabled && styles.sendButtonDisabled,
299
+ styles.sendGroup,
300
+ isActionDisabled && styles.sendGroupDisabled,
302
301
  ]}
303
- onPress={() => handleAction()}
304
302
  >
305
- {!!ACTION_LABELS[selectedOption] && (
306
- <Typography size="m" style={styles.sendLabel}>
307
- {ACTION_LABELS[selectedOption]}
308
- </Typography>
309
- )}
310
- {isReplySelected && (
311
- <SendPlane
312
- color={theme.colors.primary}
313
- size={moderateScale(22)}
314
- />
303
+ <Touchable
304
+ accessibilityLabel="Send"
305
+ accessibilityRole="button"
306
+ disabled={isActionDisabled}
307
+ style={styles.sendAction}
308
+ onPress={() => handleAction()}
309
+ >
310
+ {!!ACTION_LABELS[selectedOption] && (
311
+ <Typography size="m" style={styles.sendLabel}>
312
+ {ACTION_LABELS[selectedOption]}
313
+ </Typography>
314
+ )}
315
+ {isReplySelected && (
316
+ <SendPlane
317
+ color={theme.colors.text.inverse}
318
+ size={moderateScale(20)}
319
+ />
320
+ )}
321
+ </Touchable>
322
+ {showReplyMenuOptions && isReplySelected && (
323
+ <>
324
+ <View style={styles.sendGroupDivider} />
325
+ <Touchable
326
+ accessibilityLabel="More reply options"
327
+ accessibilityRole="button"
328
+ disabled={disabled}
329
+ style={styles.sendMenu}
330
+ onPress={() => setIsReplyMenuVisible(true)}
331
+ >
332
+ <Down
333
+ color={theme.colors.text.inverse}
334
+ size={moderateScale(20)}
335
+ />
336
+ </Touchable>
337
+ </>
315
338
  )}
316
- </Touchable>
339
+ </View>
317
340
  {showReplyMenuOptions && isReplySelected && (
318
- <>
319
- <Touchable
320
- accessibilityLabel="More reply options"
321
- accessibilityRole="button"
322
- disabled={disabled}
323
- style={styles.sendButton}
324
- onPress={() => setIsReplyMenuVisible(true)}
325
- >
326
- <Down
327
- color={theme.colors.text.primary}
328
- size={moderateScale(22)}
329
- />
330
- </Touchable>
331
- <BottomSheet
332
- data={["Send and set as closed"]}
333
- hide={() => setIsReplyMenuVisible(false)}
334
- isVisible={isReplyMenuVisible}
335
- onItemPress={() => handleAction({ status: "closed" })}
336
- />
337
- </>
341
+ <BottomSheet
342
+ data={["Send and set as closed"]}
343
+ hide={() => setIsReplyMenuVisible(false)}
344
+ isVisible={isReplyMenuVisible}
345
+ onItemPress={() => handleAction({ status: "closed" })}
346
+ />
338
347
  )}
339
348
  </View>
340
349
  </View>
@@ -346,48 +355,88 @@ export const ChatInput = forwardRef<ChatInputRef, ChatInputProps>(
346
355
 
347
356
  ChatInput.displayName = "ChatInput";
348
357
 
349
- const styles = StyleSheet.create(theme => ({
350
- container: {
351
- paddingBottom: moderateScale(5),
352
- paddingHorizontal: moderateScale(16),
353
- },
354
- noteSurface: {
355
- backgroundColor: theme.colors.background.oldLace,
356
- },
357
- inputRow: {
358
- flexDirection: "row",
359
- justifyContent: "space-between",
360
- },
361
- expandButton: {
362
- alignSelf: "center",
363
- },
364
- toolbar: {
365
- alignItems: "center",
366
- flexDirection: "row",
367
- justifyContent: "space-between",
368
- marginTop: moderateScale(10),
369
- },
370
- toolbarGroup: {
371
- alignItems: "center",
372
- flexDirection: "row",
373
- },
374
- toolbarDivider: {
375
- alignSelf: "stretch",
376
- backgroundColor: theme.colors.palette.grey400,
377
- marginHorizontal: moderateScale(5),
378
- width: moderateScale(2),
379
- },
380
- sendButton: {
381
- alignItems: "center",
382
- flexDirection: "row",
383
- gap: moderateScale(4),
384
- minHeight: moderateScale(30),
385
- paddingHorizontal: moderateScale(4),
386
- },
387
- sendButtonDisabled: {
388
- opacity: 0.5,
389
- },
390
- sendLabel: {
391
- color: theme.colors.primary,
392
- },
393
- }));
358
+ const styles = StyleSheet.create((theme, rt) => {
359
+ // Reading rt.screen registers the dependency that has this sheet
360
+ // recomputed on a window resize, so scaled sizes follow rotation,
361
+ // split-screen and foldables instead of freezing at first render.
362
+ const moderateScale = scaleFor(rt.screen);
363
+
364
+ return {
365
+ // A caller that caps this composer's height (desk clamps it to a share
366
+ // of the screen) would otherwise have Yoga keep every child at its
367
+ // natural height and let overflow clip the last one — the toolbar.
368
+ // Declaring what may shrink makes the text area absorb the squeeze
369
+ // instead, so the actions stay reachable however tall the attachments
370
+ // and typed content get.
371
+ root: {
372
+ flexShrink: 1,
373
+ },
374
+ container: {
375
+ flexShrink: 1,
376
+ paddingBottom: moderateScale(5),
377
+ paddingHorizontal: moderateScale(16),
378
+ },
379
+ noteSurface: {
380
+ backgroundColor: theme.colors.background.oldLace,
381
+ },
382
+ inputRow: {
383
+ flexDirection: "row",
384
+ flexShrink: 1,
385
+ justifyContent: "space-between",
386
+ },
387
+ expandButton: {
388
+ alignSelf: "center",
389
+ },
390
+ toolbar: {
391
+ alignItems: "center",
392
+ flexDirection: "row",
393
+ flexShrink: 0,
394
+ justifyContent: "space-between",
395
+ marginTop: moderateScale(10),
396
+ },
397
+ toolbarGroup: {
398
+ alignItems: "center",
399
+ flexDirection: "row",
400
+ },
401
+ toolbarDivider: {
402
+ alignSelf: "stretch",
403
+ backgroundColor: theme.colors.palette.grey400,
404
+ marginHorizontal: moderateScale(5),
405
+ width: moderateScale(2),
406
+ },
407
+ sendGroup: {
408
+ alignItems: "center",
409
+ backgroundColor: theme.colors.primary,
410
+ borderRadius: moderateScale(8),
411
+ flexDirection: "row",
412
+ // Clips the divider to the rounded corners.
413
+ overflow: "hidden",
414
+ },
415
+ sendGroupDisabled: {
416
+ opacity: 0.5,
417
+ },
418
+ sendAction: {
419
+ alignItems: "center",
420
+ flexDirection: "row",
421
+ gap: moderateScale(6),
422
+ justifyContent: "center",
423
+ minHeight: moderateScale(34),
424
+ paddingHorizontal: moderateScale(12),
425
+ },
426
+ sendGroupDivider: {
427
+ alignSelf: "stretch",
428
+ backgroundColor: theme.colors.white,
429
+ opacity: 0.3,
430
+ width: moderateScale(1),
431
+ },
432
+ sendMenu: {
433
+ alignItems: "center",
434
+ justifyContent: "center",
435
+ minHeight: moderateScale(34),
436
+ paddingHorizontal: moderateScale(8),
437
+ },
438
+ sendLabel: {
439
+ color: theme.colors.text.inverse,
440
+ },
441
+ };
442
+ });
@@ -2,7 +2,7 @@ import { type ComponentType } from "react";
2
2
  import { type StyleProp, type ViewStyle } from "react-native";
3
3
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
4
4
 
5
- import { moderateScale } from "../../utils/scale";
5
+ import { moderateScale, scaleFor } from "../../utils/scale";
6
6
  import { Touchable } from "../Touchable";
7
7
 
8
8
  type IconButtonProps = {
@@ -40,13 +40,24 @@ export const IconButton = ({
40
40
  );
41
41
  };
42
42
 
43
- const styles = StyleSheet.create({
44
- container: {
45
- alignItems: "center",
46
- justifyContent: "center",
47
- paddingHorizontal: moderateScale(8),
48
- },
49
- inactive: {
50
- opacity: 0.5,
51
- },
43
+ const styles = StyleSheet.create((_theme, rt) => {
44
+ // Reading rt.screen registers the dependency that has this sheet
45
+ // recomputed on a window resize, so scaled sizes follow rotation,
46
+ // split-screen and foldables instead of freezing at first render.
47
+ const moderateScale = scaleFor(rt.screen);
48
+
49
+ return {
50
+ container: {
51
+ alignItems: "center",
52
+ justifyContent: "center",
53
+ // Adjacent buttons each contribute their padding, so this is half the
54
+ // gap between two icons. Vertical padding buys back some of the touch
55
+ // target the tighter sides give up.
56
+ paddingHorizontal: moderateScale(4),
57
+ paddingVertical: moderateScale(4),
58
+ },
59
+ inactive: {
60
+ opacity: 0.5,
61
+ },
62
+ };
52
63
  });
@@ -3,7 +3,7 @@ import { ScrollView, TextInput, View, type TextInputProps } from "react-native";
3
3
  import { useMentions } from "react-native-controlled-mentions";
4
4
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
5
5
 
6
- import { moderateScale } from "../../utils/scale";
6
+ import { scaleFor } from "../../utils/scale";
7
7
  import { Avatar } from "../Avatar";
8
8
  import { Touchable } from "../Touchable";
9
9
  import { Typography } from "../Typography";
@@ -98,29 +98,44 @@ export const MentionsInput = ({
98
98
  );
99
99
  };
100
100
 
101
- const styles = StyleSheet.create(theme => ({
102
- container: {
103
- flex: 1,
104
- marginVertical: moderateScale(10),
105
- },
106
- suggestionsCard: {
107
- backgroundColor: theme.colors.background.secondary,
108
- borderRadius: moderateScale(10),
109
- maxHeight: moderateScale(200),
110
- ...theme.elevation.medium,
111
- },
112
- suggestionRow: {
113
- alignItems: "center",
114
- flexDirection: "row",
115
- gap: moderateScale(8),
116
- height: moderateScale(50),
117
- paddingHorizontal: moderateScale(10),
118
- },
119
- input: {
120
- color: theme.colors.text.primary,
121
- fontFamily: theme.fonts.regular,
122
- fontSize: theme.fontSizes.m,
123
- minHeight: moderateScale(50),
124
- padding: 0,
125
- },
126
- }));
101
+ const styles = StyleSheet.create((theme, rt) => {
102
+ // Reading rt.screen registers the dependency that has this sheet
103
+ // recomputed on a window resize, so scaled sizes follow rotation,
104
+ // split-screen and foldables instead of freezing at first render.
105
+ const moderateScale = scaleFor(rt.screen);
106
+
107
+ return {
108
+ container: {
109
+ flex: 1,
110
+ marginVertical: moderateScale(10),
111
+ },
112
+ suggestionsCard: {
113
+ backgroundColor: theme.colors.background.secondary,
114
+ borderRadius: moderateScale(10),
115
+ maxHeight: moderateScale(200),
116
+ ...theme.elevation.medium,
117
+ },
118
+ suggestionRow: {
119
+ alignItems: "center",
120
+ flexDirection: "row",
121
+ gap: moderateScale(8),
122
+ height: moderateScale(50),
123
+ paddingHorizontal: moderateScale(10),
124
+ },
125
+ input: {
126
+ color: theme.colors.text.primary,
127
+ fontFamily: theme.fonts.regular,
128
+ fontSize: theme.fontSizes.m,
129
+ // Android measures the composer from the typeface's glyph bbox (first
130
+ // and last line) but lays the text out from the hhea ascent +
131
+ // descent. SF Pro Text's bbox is the shorter of the two, so once the
132
+ // composer grows past minHeight it comes out ~3dp shorter than its
133
+ // own text: scrollable by that slack, last line's descenders clipped.
134
+ // Sizing from ascent + descent on both sides removes it; iOS ignores
135
+ // the flag.
136
+ includeFontPadding: false,
137
+ minHeight: moderateScale(50),
138
+ padding: 0,
139
+ },
140
+ };
141
+ });
@@ -1,11 +1,9 @@
1
- import {
2
- Checkbox as CheckboxIcon,
3
- CheckboxInactive,
4
- } from "@bigbinary/neeto-icons-rn";
1
+ import CheckboxIcon from "@bigbinary/neeto-icons-rn/icons/Checkbox";
2
+ import CheckboxInactive from "@bigbinary/neeto-icons-rn/icons/CheckboxInactive";
5
3
  import { type StyleProp, type TextStyle } from "react-native";
6
4
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
7
5
 
8
- import { moderateScale } from "../../utils/scale";
6
+ import { moderateScale, scaleFor } from "../../utils/scale";
9
7
  import { Touchable, type TouchableProps } from "../Touchable";
10
8
  import { Typography } from "../Typography";
11
9
 
@@ -16,6 +14,12 @@ export type CheckBoxProps = Omit<TouchableProps, "onPress"> & {
16
14
  label: string;
17
15
  labelStyle?: StyleProp<TextStyle>;
18
16
  isRequiredLabel?: boolean;
17
+ /**
18
+ * Ties the label's emphasis to the checked state: dimmed when unchecked,
19
+ * semibold when checked. Turn it off where the label names the field
20
+ * rather than the choice — an unchecked one then reads as disabled.
21
+ */
22
+ dimsUncheckedLabel?: boolean;
19
23
  iconSize?: number;
20
24
  };
21
25
 
@@ -26,13 +30,17 @@ export const CheckBox = ({
26
30
  label,
27
31
  labelStyle,
28
32
  isRequiredLabel = false,
33
+ dimsUncheckedLabel = true,
29
34
  iconSize,
30
35
  style,
31
36
  ...rest
32
37
  }: CheckBoxProps) => {
33
38
  const { theme } = useUnistyles();
34
39
 
35
- styles.useVariants({ checked, disabled });
40
+ const emphasis = checked ? "emphasized" : "dim";
41
+ const labelState = dimsUncheckedLabel ? emphasis : "plain";
42
+
43
+ styles.useVariants({ labelState, disabled });
36
44
 
37
45
  const Icon = checked ? CheckboxIcon : CheckboxInactive;
38
46
 
@@ -45,42 +53,55 @@ export const CheckBox = ({
45
53
  onPress={onSelect}
46
54
  {...rest}
47
55
  >
48
- <Typography size="m" style={[styles.label, labelStyle]}>
49
- {isRequiredLabel ? `${label}*` : label}
50
- </Typography>
51
56
  <Icon
52
57
  color={theme.colors.text.primary}
53
58
  size={iconSize ?? moderateScale(22)}
54
59
  />
60
+ <Typography size="m" style={[styles.label, labelStyle]}>
61
+ {isRequiredLabel ? `${label}*` : label}
62
+ </Typography>
55
63
  </Touchable>
56
64
  );
57
65
  };
58
66
 
59
- const styles = StyleSheet.create(theme => ({
60
- container: {
61
- alignItems: "center",
62
- flexDirection: "row",
63
- flexShrink: 1,
64
- paddingVertical: moderateScale(8),
65
- },
66
- label: {
67
- flex: 1,
68
- lineHeight: moderateScale(22),
69
- variants: {
70
- checked: {
71
- true: {
72
- color: theme.colors.text.primary,
73
- fontFamily: theme.fonts.semibold,
67
+ const styles = StyleSheet.create((theme, rt) => {
68
+ // Reading rt.screen registers the dependency that has this sheet
69
+ // recomputed on a window resize, so scaled sizes follow rotation,
70
+ // split-screen and foldables instead of freezing at first render.
71
+ const moderateScale = scaleFor(rt.screen);
72
+
73
+ return {
74
+ container: {
75
+ alignItems: "center",
76
+ flexDirection: "row",
77
+ flexShrink: 1,
78
+ gap: moderateScale(8),
79
+ paddingVertical: moderateScale(8),
80
+ },
81
+ label: {
82
+ flex: 1,
83
+ lineHeight: moderateScale(22),
84
+ variants: {
85
+ labelState: {
86
+ emphasized: {
87
+ color: theme.colors.text.primary,
88
+ fontFamily: theme.fonts.semibold,
89
+ },
90
+ dim: {
91
+ color: theme.colors.palette.grey400,
92
+ fontFamily: theme.fonts.regular,
93
+ },
94
+ plain: {
95
+ color: theme.colors.text.primary,
96
+ fontFamily: theme.fonts.regular,
97
+ },
98
+ default: {},
74
99
  },
75
- false: {
76
- color: theme.colors.palette.grey400,
77
- fontFamily: theme.fonts.regular,
100
+ disabled: {
101
+ true: { color: theme.colors.palette.grey400 },
102
+ false: {},
78
103
  },
79
104
  },
80
- disabled: {
81
- true: { color: theme.colors.palette.grey400 },
82
- false: {},
83
- },
84
105
  },
85
- },
86
- }));
106
+ };
107
+ });
@@ -2,7 +2,7 @@ import { type ComponentType, type ReactNode } from "react";
2
2
  import { View, type StyleProp, type ViewStyle } from "react-native";
3
3
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
4
4
 
5
- import { moderateScale } from "../../utils/scale";
5
+ import { moderateScale, scaleFor } from "../../utils/scale";
6
6
  import { Button } from "../Button";
7
7
  import { Typography } from "../Typography";
8
8
 
@@ -59,22 +59,29 @@ export const EmptyView = ({
59
59
  );
60
60
  };
61
61
 
62
- const styles = StyleSheet.create(theme => ({
63
- container: {
64
- alignItems: "center",
65
- gap: moderateScale(16),
66
- justifyContent: "center",
67
- paddingHorizontal: moderateScale(24),
68
- paddingVertical: moderateScale(32),
69
- },
70
- textBlock: {
71
- alignItems: "center",
72
- gap: moderateScale(4),
73
- },
74
- centered: {
75
- textAlign: "center",
76
- },
77
- description: {
78
- color: theme.colors.text.muted,
79
- },
80
- }));
62
+ const styles = StyleSheet.create((theme, rt) => {
63
+ // Reading rt.screen registers the dependency that has this sheet
64
+ // recomputed on a window resize, so scaled sizes follow rotation,
65
+ // split-screen and foldables instead of freezing at first render.
66
+ const moderateScale = scaleFor(rt.screen);
67
+
68
+ return {
69
+ container: {
70
+ alignItems: "center",
71
+ gap: moderateScale(16),
72
+ justifyContent: "center",
73
+ paddingHorizontal: moderateScale(24),
74
+ paddingVertical: moderateScale(32),
75
+ },
76
+ textBlock: {
77
+ alignItems: "center",
78
+ gap: moderateScale(4),
79
+ },
80
+ centered: {
81
+ textAlign: "center",
82
+ },
83
+ description: {
84
+ color: theme.colors.text.muted,
85
+ },
86
+ };
87
+ });
@@ -5,10 +5,10 @@ import {
5
5
  type ReactNode,
6
6
  } from "react";
7
7
  import { View } from "react-native";
8
- import { LeftArrow } from "@bigbinary/neeto-icons-rn";
8
+ import LeftArrow from "@bigbinary/neeto-icons-rn/icons/LeftArrow";
9
9
  import { StyleSheet, useUnistyles } from "react-native-unistyles";
10
10
 
11
- import { moderateScale } from "../../utils/scale";
11
+ import { moderateScale, scaleFor } from "../../utils/scale";
12
12
  import { Skeleton } from "../Skeleton";
13
13
  import { Touchable } from "../Touchable";
14
14
  import { Typography } from "../Typography";
@@ -96,19 +96,26 @@ export const Header = ({
96
96
  );
97
97
  };
98
98
 
99
- const styles = StyleSheet.create(theme => ({
100
- container: {
101
- gap: moderateScale(8),
102
- minHeight: moderateScale(48),
103
- paddingHorizontal: moderateScale(16),
104
- },
105
- backButton: {
106
- marginLeft: moderateScale(-8),
107
- },
108
- titleBlock: {
109
- flex: 1,
110
- },
111
- subTitle: {
112
- color: theme.colors.text.muted,
113
- },
114
- }));
99
+ const styles = StyleSheet.create((theme, rt) => {
100
+ // Reading rt.screen registers the dependency that has this sheet
101
+ // recomputed on a window resize, so scaled sizes follow rotation,
102
+ // split-screen and foldables instead of freezing at first render.
103
+ const moderateScale = scaleFor(rt.screen);
104
+
105
+ return {
106
+ container: {
107
+ gap: moderateScale(8),
108
+ minHeight: moderateScale(48),
109
+ paddingHorizontal: moderateScale(16),
110
+ },
111
+ backButton: {
112
+ marginLeft: moderateScale(-8),
113
+ },
114
+ titleBlock: {
115
+ flex: 1,
116
+ },
117
+ subTitle: {
118
+ color: theme.colors.text.muted,
119
+ },
120
+ };
121
+ });