@planningcenter/chat-react-native 3.44.2 → 3.44.3-qa-staging.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/build/components/conversation/message.js +2 -2
  2. package/build/components/conversation/message.js.map +1 -1
  3. package/build/components/conversation/message_form.js +2 -2
  4. package/build/components/conversation/message_form.js.map +1 -1
  5. package/build/components/conversation/message_reaction.js +4 -4
  6. package/build/components/conversation/message_reaction.js.map +1 -1
  7. package/build/components/display/toggle_button.js +9 -5
  8. package/build/components/display/toggle_button.js.map +1 -1
  9. package/build/hooks/index.d.ts +2 -1
  10. package/build/hooks/index.d.ts.map +1 -1
  11. package/build/hooks/index.js +2 -1
  12. package/build/hooks/index.js.map +1 -1
  13. package/build/hooks/use_interaction_tinted_background_color.d.ts +6 -0
  14. package/build/hooks/use_interaction_tinted_background_color.d.ts.map +1 -0
  15. package/build/hooks/use_interaction_tinted_background_color.js +15 -0
  16. package/build/hooks/use_interaction_tinted_background_color.js.map +1 -0
  17. package/build/hooks/use_rest_away_from_dismiss_edge.d.ts +4 -0
  18. package/build/hooks/use_rest_away_from_dismiss_edge.d.ts.map +1 -1
  19. package/build/hooks/use_rest_away_from_dismiss_edge.js +4 -0
  20. package/build/hooks/use_rest_away_from_dismiss_edge.js.map +1 -1
  21. package/build/hooks/use_selected_chip_background_color.d.ts +7 -0
  22. package/build/hooks/use_selected_chip_background_color.d.ts.map +1 -0
  23. package/build/hooks/use_selected_chip_background_color.js +16 -0
  24. package/build/hooks/use_selected_chip_background_color.js.map +1 -0
  25. package/build/screens/design_system_screen.js +3 -3
  26. package/build/screens/design_system_screen.js.map +1 -1
  27. package/build/utils/response_error.d.ts.map +1 -1
  28. package/build/utils/response_error.js +3 -2
  29. package/build/utils/response_error.js.map +1 -1
  30. package/build/utils/theme.d.ts +16 -0
  31. package/build/utils/theme.d.ts.map +1 -1
  32. package/build/utils/theme.js +9 -0
  33. package/build/utils/theme.js.map +1 -1
  34. package/package.json +3 -3
  35. package/src/__tests__/hooks/use_interaction_tinted_background_color.test.tsx +67 -0
  36. package/src/__tests__/hooks/use_selected_chip_background_color.test.tsx +78 -0
  37. package/src/__tests__/utils/theme.ts +23 -0
  38. package/src/components/conversation/message.tsx +2 -2
  39. package/src/components/conversation/message_form.tsx +2 -2
  40. package/src/components/conversation/message_reaction.tsx +4 -4
  41. package/src/components/display/__tests__/toggle_button.test.tsx +135 -0
  42. package/src/components/display/toggle_button.tsx +9 -5
  43. package/src/hooks/index.ts +2 -1
  44. package/src/hooks/use_interaction_tinted_background_color.ts +20 -0
  45. package/src/hooks/use_rest_away_from_dismiss_edge.ts +4 -0
  46. package/src/hooks/use_selected_chip_background_color.ts +21 -0
  47. package/src/screens/design_system_screen.tsx +3 -3
  48. package/src/types/whatwg-fetch.d.ts +5 -0
  49. package/src/utils/__tests__/response_error.test.ts +13 -0
  50. package/src/utils/response_error.ts +3 -2
  51. package/src/utils/theme.ts +28 -0
  52. package/build/hooks/use_interaction_ghost_color.d.ts +0 -2
  53. package/build/hooks/use_interaction_ghost_color.d.ts.map +0 -1
  54. package/build/hooks/use_interaction_ghost_color.js +0 -14
  55. package/build/hooks/use_interaction_ghost_color.js.map +0 -1
  56. package/src/hooks/use_interaction_ghost_color.ts +0 -15
@@ -0,0 +1,21 @@
1
+ import colorFunction from 'color'
2
+ import { useMemo } from 'react'
3
+ import { useTheme } from './use_theme'
4
+
5
+ /**
6
+ * Background color for a chip surface (filter button, reaction pill) in its
7
+ * selected state. Falls back to `colors.interaction` when a consumer hasn't
8
+ * supplied `colors.fillColorChipSelected`.
9
+ */
10
+ export function useSelectedChipBackgroundColor() {
11
+ const { colors, chip } = useTheme()
12
+
13
+ return useMemo(
14
+ () =>
15
+ colorFunction(colors.fillColorChipSelected ?? colors.interaction)
16
+ .hsl()
17
+ .lightness(chip.hslLightnessChipSelected)
18
+ .string(),
19
+ [colors.fillColorChipSelected, colors.interaction, chip.hslLightnessChipSelected]
20
+ )
21
+ }
@@ -29,7 +29,7 @@ import {
29
29
  import { VideoAttachmentPreview } from '../components/display/video_attachment_preview'
30
30
  import BannerPrimitive from '../components/primitive/banner_primitive'
31
31
  import BlankState from '../components/primitive/blank_state_primitive'
32
- import { useInteractionGhostBackgroundColor, useTheme } from '../hooks'
32
+ import { useSelectedChipBackgroundColor, useTheme } from '../hooks'
33
33
  import {
34
34
  MAX_FONT_SIZE_MULTIPLIER,
35
35
  platformPressedOpacityStyle,
@@ -1325,7 +1325,7 @@ function HapticButton({ title, onPress }: { title: string; onPress: () => void }
1325
1325
 
1326
1326
  const useStyles = () => {
1327
1327
  const { colors } = useTheme()
1328
- const interactionGhostBackgroundColor = useInteractionGhostBackgroundColor()
1328
+ const selectedChipBackgroundColor = useSelectedChipBackgroundColor()
1329
1329
 
1330
1330
  return StyleSheet.create({
1331
1331
  hapticButton: {
@@ -1334,7 +1334,7 @@ const useStyles = () => {
1334
1334
  padding: 16,
1335
1335
  alignItems: 'center',
1336
1336
  justifyContent: 'center',
1337
- backgroundColor: interactionGhostBackgroundColor,
1337
+ backgroundColor: selectedChipBackgroundColor,
1338
1338
  borderWidth: 1,
1339
1339
  borderColor: colors.interaction,
1340
1340
  borderRadius: 8,
@@ -0,0 +1,5 @@
1
+ declare module 'whatwg-fetch' {
2
+ export const Response: {
3
+ new (body?: BodyInit | null, init?: ResponseInit): globalThis.Response
4
+ }
5
+ }
@@ -1,3 +1,5 @@
1
+ import { Response as ReactNativeResponse } from 'whatwg-fetch'
2
+
1
3
  import { isResponseLike, ResponseError, throwResponseError } from '../response_error'
2
4
 
3
5
  // Mimics Expo's winter `FetchResponse`: the full Response shape, but NOT an
@@ -24,6 +26,17 @@ describe('isResponseLike', () => {
24
26
  expect(isResponseLike(notARealResponse)).toBe(true)
25
27
  })
26
28
 
29
+ it("recognizes React Native's fetch Response, which never assigns `redirected`", () => {
30
+ const response = new ReactNativeResponse(JSON.stringify({ errors: [] }), {
31
+ status: 401,
32
+ statusText: 'Unauthorized',
33
+ headers: { 'Content-Type': 'application/json' },
34
+ })
35
+
36
+ expect('redirected' in response).toBe(false)
37
+ expect(isResponseLike(response)).toBe(true)
38
+ })
39
+
27
40
  it('rejects things that are not responses', () => {
28
41
  expect(isResponseLike(null)).toBe(false)
29
42
  expect(isResponseLike(new Error('boom'))).toBe(false)
@@ -18,7 +18,9 @@ export class ResponseError extends Error {
18
18
 
19
19
  // Detect a fetch Response by shape, not `instanceof`: Expo's winter runtime
20
20
  // swaps in a `fetch` whose `FetchResponse` isn't an instance of the global
21
- // `Response`, so `instanceof` silently misses it under Expo.
21
+ // `Response`, so `instanceof` silently misses it under Expo. We avoid checking
22
+ // `redirected` because React Native's whatwg-fetch polyfill never assigns it,
23
+ // which would reject every real response under RN's fetch.
22
24
  export const isResponseLike = (value: unknown): value is Response => {
23
25
  if (typeof value !== 'object' || value === null) return false
24
26
 
@@ -27,7 +29,6 @@ export const isResponseLike = (value: unknown): value is Response => {
27
29
  typeof candidate.status === 'number' &&
28
30
  typeof candidate.statusText === 'string' &&
29
31
  typeof candidate.ok === 'boolean' &&
30
- typeof candidate.redirected === 'boolean' &&
31
32
  typeof candidate.url === 'string' &&
32
33
  typeof candidate.headers === 'object' &&
33
34
  candidate.headers !== null &&
@@ -28,6 +28,9 @@ export interface DefaultTheme {
28
28
  button: {
29
29
  borderRadius: number
30
30
  }
31
+ chip: {
32
+ hslLightnessChipSelected: number
33
+ }
31
34
  showBadgeProductLogo: boolean
32
35
  }
33
36
 
@@ -44,6 +47,9 @@ export const defaultTheme = (colorScheme: ColorSchemeName | null): ChatTheme =>
44
47
  button: {
45
48
  borderRadius: 40,
46
49
  },
50
+ chip: {
51
+ hslLightnessChipSelected: scheme === 'dark' ? 12 : 92,
52
+ },
47
53
  showBadgeProductLogo: true, // Overrides visibility of the product logo in `src/display/badge.tsx`
48
54
  }
49
55
  }
@@ -91,6 +97,22 @@ interface ChatColors {
91
97
  statusNeutralComposedIcon: string
92
98
  statusNeutralComposedText: string
93
99
  statusNeutralComposedBackground: string
100
+ // borderColorChip / textColorChip match the alias tokens
101
+ // `borderColorDefaultBase` / `textColorDefaultSecondary` the unselected
102
+ // `ToggleButton` state used before dedicated chip tokens existed.
103
+ borderColorChip: string
104
+ fillColorChip: string
105
+ textColorChip: string
106
+ /**
107
+ * Selected-chip colors (border/fill/text). Never assign a static default
108
+ * directly — these stay optional so they always fall back to
109
+ * `colors.interaction` via `??` at the read site. Every current consumer
110
+ * overrides `interaction` at runtime, and a seeded default here could win
111
+ * over that override depending on merge order.
112
+ */
113
+ borderColorChipSelected?: string
114
+ fillColorChipSelected?: string
115
+ textColorChipSelected?: string
94
116
  }
95
117
 
96
118
  // 'link' is an iOS-only semantic color name — constructing it on Android is
@@ -138,6 +160,9 @@ const colorsChatLight: ChatColors = {
138
160
  statusNeutralComposedIcon: tokens.iconColorStatusNeutralPrimary,
139
161
  statusNeutralComposedText: tokens.textColorStatusNeutral,
140
162
  statusNeutralComposedBackground: tokens.fillColorStatusNeutralGhost,
163
+ borderColorChip: tokens.colorNeutral88,
164
+ fillColorChip: 'transparent',
165
+ textColorChip: tokens.colorNeutral45,
141
166
  }
142
167
 
143
168
  const colorsChatDark: ChatColors = {
@@ -183,6 +208,9 @@ const colorsChatDark: ChatColors = {
183
208
  statusNeutralComposedIcon: tokens.iconColorStatusNeutralPrimaryDark,
184
209
  statusNeutralComposedText: tokens.textColorStatusNeutralDark,
185
210
  statusNeutralComposedBackground: tokens.fillColorStatusNeutralGhostDark,
211
+ borderColorChip: tokens.colorNeutral24,
212
+ fillColorChip: 'transparent',
213
+ textColorChip: tokens.colorNeutral68,
186
214
  }
187
215
 
188
216
  const chatThemeColorMap = {
@@ -1,2 +0,0 @@
1
- export declare function useInteractionGhostBackgroundColor(): string;
2
- //# sourceMappingURL=use_interaction_ghost_color.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use_interaction_ghost_color.d.ts","sourceRoot":"","sources":["../../src/hooks/use_interaction_ghost_color.ts"],"names":[],"mappings":"AAIA,wBAAgB,kCAAkC,WAUjD"}
@@ -1,14 +0,0 @@
1
- import colorFunction from 'color';
2
- import { useMemo } from 'react';
3
- import { useTheme } from './use_theme';
4
- export function useInteractionGhostBackgroundColor() {
5
- const { colors } = useTheme();
6
- const interactionGhostColor = useMemo(() => {
7
- return colorFunction(colors.interaction)
8
- .hsl()
9
- .lightness(colors.name === 'dark' ? 12 : 92)
10
- .string();
11
- }, [colors.interaction, colors.name]);
12
- return interactionGhostColor;
13
- }
14
- //# sourceMappingURL=use_interaction_ghost_color.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use_interaction_ghost_color.js","sourceRoot":"","sources":["../../src/hooks/use_interaction_ghost_color.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAEtC,MAAM,UAAU,kCAAkC;IAChD,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAA;IAC7B,MAAM,qBAAqB,GAAG,OAAO,CAAC,GAAG,EAAE;QACzC,OAAO,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC;aACrC,GAAG,EAAE;aACL,SAAS,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAC3C,MAAM,EAAE,CAAA;IACb,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;IAErC,OAAO,qBAAqB,CAAA;AAC9B,CAAC","sourcesContent":["import colorFunction from 'color'\nimport { useMemo } from 'react'\nimport { useTheme } from './use_theme'\n\nexport function useInteractionGhostBackgroundColor() {\n const { colors } = useTheme()\n const interactionGhostColor = useMemo(() => {\n return colorFunction(colors.interaction)\n .hsl()\n .lightness(colors.name === 'dark' ? 12 : 92)\n .string()\n }, [colors.interaction, colors.name])\n\n return interactionGhostColor\n}\n"]}
@@ -1,15 +0,0 @@
1
- import colorFunction from 'color'
2
- import { useMemo } from 'react'
3
- import { useTheme } from './use_theme'
4
-
5
- export function useInteractionGhostBackgroundColor() {
6
- const { colors } = useTheme()
7
- const interactionGhostColor = useMemo(() => {
8
- return colorFunction(colors.interaction)
9
- .hsl()
10
- .lightness(colors.name === 'dark' ? 12 : 92)
11
- .string()
12
- }, [colors.interaction, colors.name])
13
-
14
- return interactionGhostColor
15
- }