@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.
- package/build/components/conversation/message.js +2 -2
- package/build/components/conversation/message.js.map +1 -1
- package/build/components/conversation/message_form.js +2 -2
- package/build/components/conversation/message_form.js.map +1 -1
- package/build/components/conversation/message_reaction.js +4 -4
- package/build/components/conversation/message_reaction.js.map +1 -1
- package/build/components/display/toggle_button.js +9 -5
- package/build/components/display/toggle_button.js.map +1 -1
- package/build/hooks/index.d.ts +2 -1
- package/build/hooks/index.d.ts.map +1 -1
- package/build/hooks/index.js +2 -1
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/use_interaction_tinted_background_color.d.ts +6 -0
- package/build/hooks/use_interaction_tinted_background_color.d.ts.map +1 -0
- package/build/hooks/use_interaction_tinted_background_color.js +15 -0
- package/build/hooks/use_interaction_tinted_background_color.js.map +1 -0
- package/build/hooks/use_rest_away_from_dismiss_edge.d.ts +4 -0
- package/build/hooks/use_rest_away_from_dismiss_edge.d.ts.map +1 -1
- package/build/hooks/use_rest_away_from_dismiss_edge.js +4 -0
- package/build/hooks/use_rest_away_from_dismiss_edge.js.map +1 -1
- package/build/hooks/use_selected_chip_background_color.d.ts +7 -0
- package/build/hooks/use_selected_chip_background_color.d.ts.map +1 -0
- package/build/hooks/use_selected_chip_background_color.js +16 -0
- package/build/hooks/use_selected_chip_background_color.js.map +1 -0
- package/build/screens/design_system_screen.js +3 -3
- package/build/screens/design_system_screen.js.map +1 -1
- package/build/utils/response_error.d.ts.map +1 -1
- package/build/utils/response_error.js +3 -2
- package/build/utils/response_error.js.map +1 -1
- package/build/utils/theme.d.ts +16 -0
- package/build/utils/theme.d.ts.map +1 -1
- package/build/utils/theme.js +9 -0
- package/build/utils/theme.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/hooks/use_interaction_tinted_background_color.test.tsx +67 -0
- package/src/__tests__/hooks/use_selected_chip_background_color.test.tsx +78 -0
- package/src/__tests__/utils/theme.ts +23 -0
- package/src/components/conversation/message.tsx +2 -2
- package/src/components/conversation/message_form.tsx +2 -2
- package/src/components/conversation/message_reaction.tsx +4 -4
- package/src/components/display/__tests__/toggle_button.test.tsx +135 -0
- package/src/components/display/toggle_button.tsx +9 -5
- package/src/hooks/index.ts +2 -1
- package/src/hooks/use_interaction_tinted_background_color.ts +20 -0
- package/src/hooks/use_rest_away_from_dismiss_edge.ts +4 -0
- package/src/hooks/use_selected_chip_background_color.ts +21 -0
- package/src/screens/design_system_screen.tsx +3 -3
- package/src/types/whatwg-fetch.d.ts +5 -0
- package/src/utils/__tests__/response_error.test.ts +13 -0
- package/src/utils/response_error.ts +3 -2
- package/src/utils/theme.ts +28 -0
- package/build/hooks/use_interaction_ghost_color.d.ts +0 -2
- package/build/hooks/use_interaction_ghost_color.d.ts.map +0 -1
- package/build/hooks/use_interaction_ghost_color.js +0 -14
- package/build/hooks/use_interaction_ghost_color.js.map +0 -1
- package/src/hooks/use_interaction_ghost_color.ts +0 -15
|
@@ -14,7 +14,9 @@ export class ResponseError extends Error {
|
|
|
14
14
|
}
|
|
15
15
|
// Detect a fetch Response by shape, not `instanceof`: Expo's winter runtime
|
|
16
16
|
// swaps in a `fetch` whose `FetchResponse` isn't an instance of the global
|
|
17
|
-
// `Response`, so `instanceof` silently misses it under Expo.
|
|
17
|
+
// `Response`, so `instanceof` silently misses it under Expo. We avoid checking
|
|
18
|
+
// `redirected` because React Native's whatwg-fetch polyfill never assigns it,
|
|
19
|
+
// which would reject every real response under RN's fetch.
|
|
18
20
|
export const isResponseLike = (value) => {
|
|
19
21
|
if (typeof value !== 'object' || value === null)
|
|
20
22
|
return false;
|
|
@@ -22,7 +24,6 @@ export const isResponseLike = (value) => {
|
|
|
22
24
|
return (typeof candidate.status === 'number' &&
|
|
23
25
|
typeof candidate.statusText === 'string' &&
|
|
24
26
|
typeof candidate.ok === 'boolean' &&
|
|
25
|
-
typeof candidate.redirected === 'boolean' &&
|
|
26
27
|
typeof candidate.url === 'string' &&
|
|
27
28
|
typeof candidate.headers === 'object' &&
|
|
28
29
|
candidate.headers !== null &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response_error.js","sourceRoot":"","sources":["../../src/utils/response_error.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,MAAM,CAAQ;IACd,UAAU,CAAQ;IAClB,MAAM,CAA0B;IAChC,QAAQ,CAAgB;IAExB,YAAY,QAAwB;QAClC,KAAK,CAAC,kBAAkB,QAAQ,EAAE,MAAM,IAAI,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAA;QACnE,IAAI,CAAC,IAAI,GAAG,eAAe,CAAA;QAC3B,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,MAAM,CAAA;QAC9B,IAAI,CAAC,UAAU,GAAG,QAAQ,EAAE,UAAU,CAAA;QACtC,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAA;QACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;CACF;AAED,4EAA4E;AAC5E,2EAA2E;AAC3E,
|
|
1
|
+
{"version":3,"file":"response_error.js","sourceRoot":"","sources":["../../src/utils/response_error.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,MAAM,CAAQ;IACd,UAAU,CAAQ;IAClB,MAAM,CAA0B;IAChC,QAAQ,CAAgB;IAExB,YAAY,QAAwB;QAClC,KAAK,CAAC,kBAAkB,QAAQ,EAAE,MAAM,IAAI,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAA;QACnE,IAAI,CAAC,IAAI,GAAG,eAAe,CAAA;QAC3B,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,MAAM,CAAA;QAC9B,IAAI,CAAC,UAAU,GAAG,QAAQ,EAAE,UAAU,CAAA;QACtC,IAAI,CAAC,MAAM,GAAG,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAA;QACpC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;CACF;AAED,4EAA4E;AAC5E,2EAA2E;AAC3E,+EAA+E;AAC/E,8EAA8E;AAC9E,2DAA2D;AAC3D,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAc,EAAqB,EAAE;IAClE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAA;IAE7D,MAAM,SAAS,GAAG,KAAgC,CAAA;IAClD,OAAO,CACL,OAAO,SAAS,CAAC,MAAM,KAAK,QAAQ;QACpC,OAAO,SAAS,CAAC,UAAU,KAAK,QAAQ;QACxC,OAAO,SAAS,CAAC,EAAE,KAAK,SAAS;QACjC,OAAO,SAAS,CAAC,GAAG,KAAK,QAAQ;QACjC,OAAO,SAAS,CAAC,OAAO,KAAK,QAAQ;QACrC,SAAS,CAAC,OAAO,KAAK,IAAI;QAC1B,OAAO,SAAS,CAAC,KAAK,KAAK,UAAU;QACrC,OAAO,SAAS,CAAC,IAAI,KAAK,UAAU;QACpC,OAAO,SAAS,CAAC,IAAI,KAAK,UAAU;QACpC,OAAO,SAAS,CAAC,WAAW,KAAK,UAAU,CAC5C,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,KAAc,EAAE,EAAE;IACnD,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,aAAa,CAAC,KAAuB,CAAC,CAAA;IAClD,CAAC;IAED,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC9B,CAAC,CAAA","sourcesContent":["import { FailedResponse } from '../types/api_primitives'\n\nexport class ResponseError extends Error {\n status: number\n statusText: string\n errors: FailedResponse['errors']\n response: FailedResponse\n\n constructor(response: FailedResponse) {\n super(`ResponseError: ${response?.status} ${response?.statusText}`)\n this.name = 'ResponseError'\n this.status = response?.status\n this.statusText = response?.statusText\n this.errors = response?.errors || []\n this.response = response\n }\n}\n\n// Detect a fetch Response by shape, not `instanceof`: Expo's winter runtime\n// swaps in a `fetch` whose `FetchResponse` isn't an instance of the global\n// `Response`, so `instanceof` silently misses it under Expo. We avoid checking\n// `redirected` because React Native's whatwg-fetch polyfill never assigns it,\n// which would reject every real response under RN's fetch.\nexport const isResponseLike = (value: unknown): value is Response => {\n if (typeof value !== 'object' || value === null) return false\n\n const candidate = value as Record<string, unknown>\n return (\n typeof candidate.status === 'number' &&\n typeof candidate.statusText === 'string' &&\n typeof candidate.ok === 'boolean' &&\n typeof candidate.url === 'string' &&\n typeof candidate.headers === 'object' &&\n candidate.headers !== null &&\n typeof candidate.clone === 'function' &&\n typeof candidate.json === 'function' &&\n typeof candidate.text === 'function' &&\n typeof candidate.arrayBuffer === 'function'\n )\n}\n\nexport const throwResponseError = (error: unknown) => {\n if (isResponseLike(error)) {\n throw new ResponseError(error as FailedResponse)\n }\n\n return Promise.reject(error)\n}\n"]}
|
package/build/utils/theme.d.ts
CHANGED
|
@@ -22,6 +22,9 @@ export interface DefaultTheme {
|
|
|
22
22
|
button: {
|
|
23
23
|
borderRadius: number;
|
|
24
24
|
};
|
|
25
|
+
chip: {
|
|
26
|
+
hslLightnessChipSelected: number;
|
|
27
|
+
};
|
|
25
28
|
showBadgeProductLogo: boolean;
|
|
26
29
|
}
|
|
27
30
|
export declare const defaultTheme: (colorScheme: ColorSchemeName | null) => ChatTheme;
|
|
@@ -67,6 +70,19 @@ interface ChatColors {
|
|
|
67
70
|
statusNeutralComposedIcon: string;
|
|
68
71
|
statusNeutralComposedText: string;
|
|
69
72
|
statusNeutralComposedBackground: string;
|
|
73
|
+
borderColorChip: string;
|
|
74
|
+
fillColorChip: string;
|
|
75
|
+
textColorChip: string;
|
|
76
|
+
/**
|
|
77
|
+
* Selected-chip colors (border/fill/text). Never assign a static default
|
|
78
|
+
* directly — these stay optional so they always fall back to
|
|
79
|
+
* `colors.interaction` via `??` at the read site. Every current consumer
|
|
80
|
+
* overrides `interaction` at runtime, and a seeded default here could win
|
|
81
|
+
* over that override depending on merge order.
|
|
82
|
+
*/
|
|
83
|
+
borderColorChipSelected?: string;
|
|
84
|
+
fillColorChipSelected?: string;
|
|
85
|
+
textColorChipSelected?: string;
|
|
70
86
|
}
|
|
71
87
|
export {};
|
|
72
88
|
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/utils/theme.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAA;AAG/E,MAAM,WAAW,SAAU,SAAQ,YAAY;IAC7C,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,GAC5B,CAAC,OAAO,mBAAmB,CAAC,KAAK,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAA;CACvE;AAED;;;;;;;;;;;;;gDAagD;AAEhD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,UAAU,CAAA;IAClB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAA;KACrB,CAAA;IACD,oBAAoB,EAAE,OAAO,CAAA;CAC9B;AAED,eAAO,MAAM,YAAY,GAAI,aAAa,eAAe,GAAG,IAAI,KAAG,
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/utils/theme.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAA;AAG/E,MAAM,WAAW,SAAU,SAAQ,YAAY;IAC7C,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,GAC5B,CAAC,OAAO,mBAAmB,CAAC,KAAK,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAA;CACvE;AAED;;;;;;;;;;;;;gDAagD;AAEhD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,UAAU,CAAA;IAClB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAA;KACrB,CAAA;IACD,IAAI,EAAE;QACJ,wBAAwB,EAAE,MAAM,CAAA;KACjC,CAAA;IACD,oBAAoB,EAAE,OAAO,CAAA;CAC9B;AAED,eAAO,MAAM,YAAY,GAAI,aAAa,eAAe,GAAG,IAAI,KAAG,SAkBlE,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;AAE5D,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,WAAW,EAAE,MAAM,CAAA;IACnB,iCAAiC,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAAA;IAClE,6BAA6B,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAAA;IACpE,uBAAuB,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3C,6BAA6B,EAAE,MAAM,CAAA;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,iBAAiB,EAAE,MAAM,CAAA;IACzB,iBAAiB,EAAE,MAAM,CAAA;IACzB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,iBAAiB,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,gBAAgB,EAAE,MAAM,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,iBAAiB,EAAE,MAAM,CAAA;IACzB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,iBAAiB,EAAE,MAAM,CAAA;IACzB,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;IACzB,eAAe,EAAE,MAAM,CAAA;IACvB,yBAAyB,EAAE,MAAM,CAAA;IACjC,yBAAyB,EAAE,MAAM,CAAA;IACjC,+BAA+B,EAAE,MAAM,CAAA;IACvC,sBAAsB,EAAE,MAAM,CAAA;IAC9B,sBAAsB,EAAE,MAAM,CAAA;IAC9B,4BAA4B,EAAE,MAAM,CAAA;IACpC,yBAAyB,EAAE,MAAM,CAAA;IACjC,yBAAyB,EAAE,MAAM,CAAA;IACjC,+BAA+B,EAAE,MAAM,CAAA;IACvC,uBAAuB,EAAE,MAAM,CAAA;IAC/B,uBAAuB,EAAE,MAAM,CAAA;IAC/B,6BAA6B,EAAE,MAAM,CAAA;IACrC,yBAAyB,EAAE,MAAM,CAAA;IACjC,yBAAyB,EAAE,MAAM,CAAA;IACjC,+BAA+B,EAAE,MAAM,CAAA;IAIvC,eAAe,EAAE,MAAM,CAAA;IACvB,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB;;;;;;OAMG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC/B"}
|
package/build/utils/theme.js
CHANGED
|
@@ -12,6 +12,9 @@ export const defaultTheme = (colorScheme) => {
|
|
|
12
12
|
button: {
|
|
13
13
|
borderRadius: 40,
|
|
14
14
|
},
|
|
15
|
+
chip: {
|
|
16
|
+
hslLightnessChipSelected: scheme === 'dark' ? 12 : 92,
|
|
17
|
+
},
|
|
15
18
|
showBadgeProductLogo: true, // Overrides visibility of the product logo in `src/display/badge.tsx`
|
|
16
19
|
};
|
|
17
20
|
};
|
|
@@ -59,6 +62,9 @@ const colorsChatLight = {
|
|
|
59
62
|
statusNeutralComposedIcon: tokens.iconColorStatusNeutralPrimary,
|
|
60
63
|
statusNeutralComposedText: tokens.textColorStatusNeutral,
|
|
61
64
|
statusNeutralComposedBackground: tokens.fillColorStatusNeutralGhost,
|
|
65
|
+
borderColorChip: tokens.colorNeutral88,
|
|
66
|
+
fillColorChip: 'transparent',
|
|
67
|
+
textColorChip: tokens.colorNeutral45,
|
|
62
68
|
};
|
|
63
69
|
const colorsChatDark = {
|
|
64
70
|
name: 'dark',
|
|
@@ -102,6 +108,9 @@ const colorsChatDark = {
|
|
|
102
108
|
statusNeutralComposedIcon: tokens.iconColorStatusNeutralPrimaryDark,
|
|
103
109
|
statusNeutralComposedText: tokens.textColorStatusNeutralDark,
|
|
104
110
|
statusNeutralComposedBackground: tokens.fillColorStatusNeutralGhostDark,
|
|
111
|
+
borderColorChip: tokens.colorNeutral24,
|
|
112
|
+
fillColorChip: 'transparent',
|
|
113
|
+
textColorChip: tokens.colorNeutral68,
|
|
105
114
|
};
|
|
106
115
|
const chatThemeColorMap = {
|
|
107
116
|
light: colorsChatLight,
|
package/build/utils/theme.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/utils/theme.ts"],"names":[],"mappings":"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","sourcesContent":["import { Platform, PlatformColor } from 'react-native'\nimport type { ColorSchemeName, ColorValue, OpaqueColorValue } from 'react-native'\nimport { aliasTokensColorMap } from '../vendor/tapestry/alias_tokens_color_map'\nimport { tokens } from '../vendor/tapestry/tokens'\n\nexport interface ChatTheme extends DefaultTheme {\n colors: DefaultTheme['colors'] &\n (typeof aliasTokensColorMap.light | typeof aliasTokensColorMap.dark)\n}\n\n/** =============================================\n NOTE: The specific values for `colors` and the `productBadge` are temporary examples that can be replaced once we start building out UI. This line's comment can be removed at that time too.\n\n The default theme is intended to support two types of customizations:\n 1. Specific color properties for a chat component (eg. `primaryButtonBackgroundColor`)\n 2. Any styles for a specific component. (Use only one level of nesting.)\n ```\n primaryButton: {\n borderRadius: number\n container: ViewStyle\n text: TextStyle\n }\n ```\n============================================= */\n\nexport interface DefaultTheme {\n colors: ChatColors\n button: {\n borderRadius: number\n }\n showBadgeProductLogo: boolean\n}\n\nexport const defaultTheme = (colorScheme: ColorSchemeName | null): ChatTheme => {\n const scheme: 'light' | 'dark' = colorScheme === 'dark' ? 'dark' : 'light'\n\n const defaultColors = {\n ...chatThemeColorMap[scheme],\n ...aliasTokensColorMap[scheme],\n }\n\n return {\n colors: defaultColors,\n button: {\n borderRadius: 40,\n },\n showBadgeProductLogo: true, // Overrides visibility of the product logo in `src/display/badge.tsx`\n }\n}\n\nexport type TemporaryDefaultColorsType = Partial<ChatColors>\n\ninterface ChatColors {\n name: string\n buttonStart: string | undefined\n buttonEnd: string | undefined\n interaction: string\n androidModalHeaderButtonTextColor: ColorValue | string | undefined\n iOSModalHeaderButtonTextColor: OpaqueColorValue | string | undefined\n androidSwitchThumbColor: string | undefined\n conversationActionsBackground: string\n testColor: string\n statusSuccessIcon: string\n statusSuccessText: string\n statusSuccessBorder: string\n statusSuccessFill: string\n statusInfoIcon: string\n statusInfoText: string\n statusInfoBorder: string\n statusInfoFill: string\n statusWarningIcon: string\n statusWarningText: string\n statusWarningBorder: string\n statusWarningFill: string\n statusErrorIcon: string\n statusErrorText: string\n statusErrorBorder: string\n statusErrorFill: string\n statusSuccessComposedIcon: string\n statusSuccessComposedText: string\n statusSuccessComposedBackground: string\n statusInfoComposedIcon: string\n statusInfoComposedText: string\n statusInfoComposedBackground: string\n statusWarningComposedIcon: string\n statusWarningComposedText: string\n statusWarningComposedBackground: string\n statusErrorComposedIcon: string\n statusErrorComposedText: string\n statusErrorComposedBackground: string\n statusNeutralComposedIcon: string\n statusNeutralComposedText: string\n statusNeutralComposedBackground: string\n}\n\n// 'link' is an iOS-only semantic color name — constructing it on Android is\n// undefined behavior, so only build it when the code is actually running on iOS\nconst iOSLinkColor = Platform.OS === 'ios' ? PlatformColor('link') : undefined\n\nconst colorsChatLight: ChatColors = {\n name: 'light',\n androidModalHeaderButtonTextColor: tokens.fillColorInteractionDefault,\n iOSModalHeaderButtonTextColor: iOSLinkColor,\n buttonStart: undefined,\n buttonEnd: undefined,\n interaction: tokens.fillColorInteractionDefault,\n androidSwitchThumbColor: undefined,\n conversationActionsBackground: tokens.colorNeutral100White,\n testColor: 'hotpink',\n statusInfoIcon: tokens.iconColorStatusInfoPrimary,\n statusInfoText: tokens.textColorStatusInfo,\n statusInfoBorder: tokens.borderColorStatusInfo,\n statusInfoFill: tokens.fillColorStatusInfoSolid,\n statusSuccessIcon: tokens.iconColorStatusSuccessPrimary,\n statusSuccessText: tokens.textColorStatusSuccess,\n statusSuccessBorder: tokens.borderColorStatusSuccess,\n statusSuccessFill: tokens.fillColorStatusSuccessSolid,\n statusWarningIcon: tokens.iconColorStatusWarningPrimary,\n statusWarningText: tokens.textColorStatusWarning,\n statusWarningBorder: tokens.borderColorStatusWarning,\n statusWarningFill: tokens.fillColorStatusWarningSolid,\n statusErrorIcon: tokens.iconColorStatusErrorPrimary,\n statusErrorText: tokens.textColorStatusError,\n statusErrorBorder: tokens.borderColorStatusError,\n statusErrorFill: tokens.fillColorStatusErrorSolid,\n statusInfoComposedIcon: tokens.iconColorStatusInfoPrimary,\n statusInfoComposedText: tokens.textColorStatusInfo,\n statusInfoComposedBackground: tokens.fillColorStatusInfoGhost,\n statusSuccessComposedIcon: tokens.iconColorStatusSuccessPrimary,\n statusSuccessComposedText: tokens.textColorStatusSuccess,\n statusSuccessComposedBackground: tokens.fillColorStatusSuccessGhost,\n statusWarningComposedIcon: tokens.iconColorStatusWarningPrimary,\n statusWarningComposedText: tokens.textColorStatusWarning,\n statusWarningComposedBackground: tokens.fillColorStatusWarningGhost,\n statusErrorComposedIcon: tokens.iconColorStatusErrorPrimary,\n statusErrorComposedText: tokens.textColorStatusError,\n statusErrorComposedBackground: tokens.fillColorStatusErrorGhost,\n statusNeutralComposedIcon: tokens.iconColorStatusNeutralPrimary,\n statusNeutralComposedText: tokens.textColorStatusNeutral,\n statusNeutralComposedBackground: tokens.fillColorStatusNeutralGhost,\n}\n\nconst colorsChatDark: ChatColors = {\n name: 'dark',\n androidModalHeaderButtonTextColor: tokens.fillColorInteractionDefaultDark,\n iOSModalHeaderButtonTextColor: iOSLinkColor,\n buttonStart: undefined,\n buttonEnd: undefined,\n interaction: tokens.fillColorInteractionDefaultDark,\n androidSwitchThumbColor: undefined,\n conversationActionsBackground: tokens.colorNeutral7,\n testColor: 'pink',\n statusInfoIcon: tokens.iconColorStatusInfoPrimaryDark,\n statusInfoText: tokens.textColorStatusInfoDark,\n statusInfoBorder: tokens.borderColorStatusInfoDark,\n statusInfoFill: tokens.fillColorStatusInfoSolidDark,\n statusSuccessIcon: tokens.iconColorStatusSuccessPrimaryDark,\n statusSuccessText: tokens.textColorStatusSuccessDark,\n statusSuccessBorder: tokens.borderColorStatusSuccessDark,\n statusSuccessFill: tokens.fillColorStatusSuccessSolidDark,\n statusWarningIcon: tokens.iconColorStatusWarningPrimaryDark,\n statusWarningText: tokens.textColorStatusWarningDark,\n statusWarningBorder: tokens.borderColorStatusWarningDark,\n statusWarningFill: tokens.fillColorStatusWarningSolidDark,\n statusErrorIcon: tokens.iconColorStatusErrorPrimaryDark,\n statusErrorText: tokens.textColorStatusErrorDark,\n statusErrorBorder: tokens.borderColorStatusErrorDark,\n statusErrorFill: tokens.fillColorStatusErrorSolidDark,\n\n // Note: CCA inverts composed status colors in dark mode\n statusInfoComposedIcon: tokens.iconColorStatusInfoPrimaryDark,\n statusInfoComposedText: tokens.textColorStatusInfoDark,\n statusInfoComposedBackground: tokens.fillColorStatusInfoGhostDark,\n statusSuccessComposedIcon: tokens.iconColorStatusSuccessPrimaryDark,\n statusSuccessComposedText: tokens.textColorStatusSuccessDark,\n statusSuccessComposedBackground: tokens.fillColorStatusSuccessGhostDark,\n statusWarningComposedIcon: tokens.iconColorStatusWarningPrimaryDark,\n statusWarningComposedText: tokens.textColorStatusWarningDark,\n statusWarningComposedBackground: tokens.fillColorStatusWarningGhostDark,\n statusErrorComposedIcon: tokens.iconColorStatusErrorPrimaryDark,\n statusErrorComposedText: tokens.textColorStatusErrorDark,\n statusErrorComposedBackground: tokens.fillColorStatusErrorGhostDark,\n statusNeutralComposedIcon: tokens.iconColorStatusNeutralPrimaryDark,\n statusNeutralComposedText: tokens.textColorStatusNeutralDark,\n statusNeutralComposedBackground: tokens.fillColorStatusNeutralGhostDark,\n}\n\nconst chatThemeColorMap = {\n light: colorsChatLight,\n dark: colorsChatDark,\n}\n"]}
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/utils/theme.ts"],"names":[],"mappings":"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","sourcesContent":["import { Platform, PlatformColor } from 'react-native'\nimport type { ColorSchemeName, ColorValue, OpaqueColorValue } from 'react-native'\nimport { aliasTokensColorMap } from '../vendor/tapestry/alias_tokens_color_map'\nimport { tokens } from '../vendor/tapestry/tokens'\n\nexport interface ChatTheme extends DefaultTheme {\n colors: DefaultTheme['colors'] &\n (typeof aliasTokensColorMap.light | typeof aliasTokensColorMap.dark)\n}\n\n/** =============================================\n NOTE: The specific values for `colors` and the `productBadge` are temporary examples that can be replaced once we start building out UI. This line's comment can be removed at that time too.\n\n The default theme is intended to support two types of customizations:\n 1. Specific color properties for a chat component (eg. `primaryButtonBackgroundColor`)\n 2. Any styles for a specific component. (Use only one level of nesting.)\n ```\n primaryButton: {\n borderRadius: number\n container: ViewStyle\n text: TextStyle\n }\n ```\n============================================= */\n\nexport interface DefaultTheme {\n colors: ChatColors\n button: {\n borderRadius: number\n }\n chip: {\n hslLightnessChipSelected: number\n }\n showBadgeProductLogo: boolean\n}\n\nexport const defaultTheme = (colorScheme: ColorSchemeName | null): ChatTheme => {\n const scheme: 'light' | 'dark' = colorScheme === 'dark' ? 'dark' : 'light'\n\n const defaultColors = {\n ...chatThemeColorMap[scheme],\n ...aliasTokensColorMap[scheme],\n }\n\n return {\n colors: defaultColors,\n button: {\n borderRadius: 40,\n },\n chip: {\n hslLightnessChipSelected: scheme === 'dark' ? 12 : 92,\n },\n showBadgeProductLogo: true, // Overrides visibility of the product logo in `src/display/badge.tsx`\n }\n}\n\nexport type TemporaryDefaultColorsType = Partial<ChatColors>\n\ninterface ChatColors {\n name: string\n buttonStart: string | undefined\n buttonEnd: string | undefined\n interaction: string\n androidModalHeaderButtonTextColor: ColorValue | string | undefined\n iOSModalHeaderButtonTextColor: OpaqueColorValue | string | undefined\n androidSwitchThumbColor: string | undefined\n conversationActionsBackground: string\n testColor: string\n statusSuccessIcon: string\n statusSuccessText: string\n statusSuccessBorder: string\n statusSuccessFill: string\n statusInfoIcon: string\n statusInfoText: string\n statusInfoBorder: string\n statusInfoFill: string\n statusWarningIcon: string\n statusWarningText: string\n statusWarningBorder: string\n statusWarningFill: string\n statusErrorIcon: string\n statusErrorText: string\n statusErrorBorder: string\n statusErrorFill: string\n statusSuccessComposedIcon: string\n statusSuccessComposedText: string\n statusSuccessComposedBackground: string\n statusInfoComposedIcon: string\n statusInfoComposedText: string\n statusInfoComposedBackground: string\n statusWarningComposedIcon: string\n statusWarningComposedText: string\n statusWarningComposedBackground: string\n statusErrorComposedIcon: string\n statusErrorComposedText: string\n statusErrorComposedBackground: string\n statusNeutralComposedIcon: string\n statusNeutralComposedText: string\n statusNeutralComposedBackground: string\n // borderColorChip / textColorChip match the alias tokens\n // `borderColorDefaultBase` / `textColorDefaultSecondary` the unselected\n // `ToggleButton` state used before dedicated chip tokens existed.\n borderColorChip: string\n fillColorChip: string\n textColorChip: string\n /**\n * Selected-chip colors (border/fill/text). Never assign a static default\n * directly — these stay optional so they always fall back to\n * `colors.interaction` via `??` at the read site. Every current consumer\n * overrides `interaction` at runtime, and a seeded default here could win\n * over that override depending on merge order.\n */\n borderColorChipSelected?: string\n fillColorChipSelected?: string\n textColorChipSelected?: string\n}\n\n// 'link' is an iOS-only semantic color name — constructing it on Android is\n// undefined behavior, so only build it when the code is actually running on iOS\nconst iOSLinkColor = Platform.OS === 'ios' ? PlatformColor('link') : undefined\n\nconst colorsChatLight: ChatColors = {\n name: 'light',\n androidModalHeaderButtonTextColor: tokens.fillColorInteractionDefault,\n iOSModalHeaderButtonTextColor: iOSLinkColor,\n buttonStart: undefined,\n buttonEnd: undefined,\n interaction: tokens.fillColorInteractionDefault,\n androidSwitchThumbColor: undefined,\n conversationActionsBackground: tokens.colorNeutral100White,\n testColor: 'hotpink',\n statusInfoIcon: tokens.iconColorStatusInfoPrimary,\n statusInfoText: tokens.textColorStatusInfo,\n statusInfoBorder: tokens.borderColorStatusInfo,\n statusInfoFill: tokens.fillColorStatusInfoSolid,\n statusSuccessIcon: tokens.iconColorStatusSuccessPrimary,\n statusSuccessText: tokens.textColorStatusSuccess,\n statusSuccessBorder: tokens.borderColorStatusSuccess,\n statusSuccessFill: tokens.fillColorStatusSuccessSolid,\n statusWarningIcon: tokens.iconColorStatusWarningPrimary,\n statusWarningText: tokens.textColorStatusWarning,\n statusWarningBorder: tokens.borderColorStatusWarning,\n statusWarningFill: tokens.fillColorStatusWarningSolid,\n statusErrorIcon: tokens.iconColorStatusErrorPrimary,\n statusErrorText: tokens.textColorStatusError,\n statusErrorBorder: tokens.borderColorStatusError,\n statusErrorFill: tokens.fillColorStatusErrorSolid,\n statusInfoComposedIcon: tokens.iconColorStatusInfoPrimary,\n statusInfoComposedText: tokens.textColorStatusInfo,\n statusInfoComposedBackground: tokens.fillColorStatusInfoGhost,\n statusSuccessComposedIcon: tokens.iconColorStatusSuccessPrimary,\n statusSuccessComposedText: tokens.textColorStatusSuccess,\n statusSuccessComposedBackground: tokens.fillColorStatusSuccessGhost,\n statusWarningComposedIcon: tokens.iconColorStatusWarningPrimary,\n statusWarningComposedText: tokens.textColorStatusWarning,\n statusWarningComposedBackground: tokens.fillColorStatusWarningGhost,\n statusErrorComposedIcon: tokens.iconColorStatusErrorPrimary,\n statusErrorComposedText: tokens.textColorStatusError,\n statusErrorComposedBackground: tokens.fillColorStatusErrorGhost,\n statusNeutralComposedIcon: tokens.iconColorStatusNeutralPrimary,\n statusNeutralComposedText: tokens.textColorStatusNeutral,\n statusNeutralComposedBackground: tokens.fillColorStatusNeutralGhost,\n borderColorChip: tokens.colorNeutral88,\n fillColorChip: 'transparent',\n textColorChip: tokens.colorNeutral45,\n}\n\nconst colorsChatDark: ChatColors = {\n name: 'dark',\n androidModalHeaderButtonTextColor: tokens.fillColorInteractionDefaultDark,\n iOSModalHeaderButtonTextColor: iOSLinkColor,\n buttonStart: undefined,\n buttonEnd: undefined,\n interaction: tokens.fillColorInteractionDefaultDark,\n androidSwitchThumbColor: undefined,\n conversationActionsBackground: tokens.colorNeutral7,\n testColor: 'pink',\n statusInfoIcon: tokens.iconColorStatusInfoPrimaryDark,\n statusInfoText: tokens.textColorStatusInfoDark,\n statusInfoBorder: tokens.borderColorStatusInfoDark,\n statusInfoFill: tokens.fillColorStatusInfoSolidDark,\n statusSuccessIcon: tokens.iconColorStatusSuccessPrimaryDark,\n statusSuccessText: tokens.textColorStatusSuccessDark,\n statusSuccessBorder: tokens.borderColorStatusSuccessDark,\n statusSuccessFill: tokens.fillColorStatusSuccessSolidDark,\n statusWarningIcon: tokens.iconColorStatusWarningPrimaryDark,\n statusWarningText: tokens.textColorStatusWarningDark,\n statusWarningBorder: tokens.borderColorStatusWarningDark,\n statusWarningFill: tokens.fillColorStatusWarningSolidDark,\n statusErrorIcon: tokens.iconColorStatusErrorPrimaryDark,\n statusErrorText: tokens.textColorStatusErrorDark,\n statusErrorBorder: tokens.borderColorStatusErrorDark,\n statusErrorFill: tokens.fillColorStatusErrorSolidDark,\n\n // Note: CCA inverts composed status colors in dark mode\n statusInfoComposedIcon: tokens.iconColorStatusInfoPrimaryDark,\n statusInfoComposedText: tokens.textColorStatusInfoDark,\n statusInfoComposedBackground: tokens.fillColorStatusInfoGhostDark,\n statusSuccessComposedIcon: tokens.iconColorStatusSuccessPrimaryDark,\n statusSuccessComposedText: tokens.textColorStatusSuccessDark,\n statusSuccessComposedBackground: tokens.fillColorStatusSuccessGhostDark,\n statusWarningComposedIcon: tokens.iconColorStatusWarningPrimaryDark,\n statusWarningComposedText: tokens.textColorStatusWarningDark,\n statusWarningComposedBackground: tokens.fillColorStatusWarningGhostDark,\n statusErrorComposedIcon: tokens.iconColorStatusErrorPrimaryDark,\n statusErrorComposedText: tokens.textColorStatusErrorDark,\n statusErrorComposedBackground: tokens.fillColorStatusErrorGhostDark,\n statusNeutralComposedIcon: tokens.iconColorStatusNeutralPrimaryDark,\n statusNeutralComposedText: tokens.textColorStatusNeutralDark,\n statusNeutralComposedBackground: tokens.fillColorStatusNeutralGhostDark,\n borderColorChip: tokens.colorNeutral24,\n fillColorChip: 'transparent',\n textColorChip: tokens.colorNeutral68,\n}\n\nconst chatThemeColorMap = {\n light: colorsChatLight,\n dark: colorsChatDark,\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "3.44.
|
|
3
|
+
"version": "3.44.3-qa-staging.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@fortawesome/fontawesome-svg-core": "^7.2.0",
|
|
33
33
|
"@fortawesome/react-native-fontawesome": "^0.3.2",
|
|
34
|
-
"@planningcenter/emoji-keyboard": "3.44.1",
|
|
34
|
+
"@planningcenter/emoji-keyboard": "3.44.3-qa-staging.1",
|
|
35
35
|
"lodash-inflection": "^1.5.0",
|
|
36
36
|
"react-compiler-runtime": "^1.0.0"
|
|
37
37
|
},
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
"sf-symbols-typescript": "^2.2.0",
|
|
79
79
|
"typescript": "~6.0.3"
|
|
80
80
|
},
|
|
81
|
-
"gitHead": "
|
|
81
|
+
"gitHead": "898af4cb2b72d9aa4e34746f9594a5b510092a9a"
|
|
82
82
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
2
|
+
import { renderHook } from '@testing-library/react-native'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { buildTestQueryClient } from '../../__utils__/query_client'
|
|
5
|
+
import { ChatProvider, CreateChatThemeProps } from '../../contexts/chat_context'
|
|
6
|
+
import { useInteractionTintedBackgroundColor } from '../../hooks'
|
|
7
|
+
|
|
8
|
+
let themeProps: CreateChatThemeProps
|
|
9
|
+
let queryClient: QueryClient
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
queryClient = buildTestQueryClient({
|
|
13
|
+
defaultOptions: {
|
|
14
|
+
queries: {
|
|
15
|
+
refetchInterval: false,
|
|
16
|
+
refetchOnWindowFocus: false,
|
|
17
|
+
refetchOnReconnect: false,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
queryClient.clear()
|
|
25
|
+
queryClient.cancelQueries()
|
|
26
|
+
queryClient.removeQueries()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const Wrapper = ({ children }: { children: React.ReactNode }) => {
|
|
30
|
+
return (
|
|
31
|
+
<QueryClientProvider client={queryClient}>
|
|
32
|
+
<ChatProvider value={{ onUnauthorizedResponse: () => {}, theme: themeProps }}>
|
|
33
|
+
{children}
|
|
34
|
+
</ChatProvider>
|
|
35
|
+
</QueryClientProvider>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe('useInteractionTintedBackgroundColor (non-chip surfaces)', () => {
|
|
40
|
+
test('ignores fillColorChipSelected', () => {
|
|
41
|
+
themeProps = {
|
|
42
|
+
theme: {
|
|
43
|
+
colors: {
|
|
44
|
+
interaction: 'rgb(0, 255, 0)',
|
|
45
|
+
fillColorChipSelected: 'rgb(9, 9, 9)',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const { result: withChipToken } = renderHook(() => useInteractionTintedBackgroundColor(), {
|
|
51
|
+
wrapper: Wrapper,
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
themeProps = {
|
|
55
|
+
theme: {
|
|
56
|
+
colors: { interaction: 'rgb(0, 255, 0)' },
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const { result: withoutChipToken } = renderHook(() => useInteractionTintedBackgroundColor(), {
|
|
61
|
+
wrapper: Wrapper,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
expect(withChipToken.current).toBe(withoutChipToken.current)
|
|
65
|
+
expect(withoutChipToken.current).toBe('hsl(120, 100%, 92%)')
|
|
66
|
+
})
|
|
67
|
+
})
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
2
|
+
import { renderHook } from '@testing-library/react-native'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { buildTestQueryClient } from '../../__utils__/query_client'
|
|
5
|
+
import { ChatProvider, CreateChatThemeProps } from '../../contexts/chat_context'
|
|
6
|
+
import { useSelectedChipBackgroundColor } from '../../hooks'
|
|
7
|
+
|
|
8
|
+
let themeProps: CreateChatThemeProps
|
|
9
|
+
let queryClient: QueryClient
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
queryClient = buildTestQueryClient({
|
|
13
|
+
defaultOptions: {
|
|
14
|
+
queries: {
|
|
15
|
+
refetchInterval: false,
|
|
16
|
+
refetchOnWindowFocus: false,
|
|
17
|
+
refetchOnReconnect: false,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
queryClient.clear()
|
|
25
|
+
queryClient.cancelQueries()
|
|
26
|
+
queryClient.removeQueries()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const Wrapper = ({ children }: { children: React.ReactNode }) => {
|
|
30
|
+
return (
|
|
31
|
+
<QueryClientProvider client={queryClient}>
|
|
32
|
+
<ChatProvider value={{ onUnauthorizedResponse: () => {}, theme: themeProps }}>
|
|
33
|
+
{children}
|
|
34
|
+
</ChatProvider>
|
|
35
|
+
</QueryClientProvider>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe('useSelectedChipBackgroundColor', () => {
|
|
40
|
+
test('falls back to colors.interaction when fillColorChipSelected is absent', () => {
|
|
41
|
+
themeProps = { theme: { colors: { interaction: 'rgb(0, 255, 0)' } } }
|
|
42
|
+
|
|
43
|
+
const { result } = renderHook(() => useSelectedChipBackgroundColor(), {
|
|
44
|
+
wrapper: Wrapper,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
expect(result.current).toBe('hsl(120, 100%, 92%)')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('prefers fillColorChipSelected over colors.interaction when supplied', () => {
|
|
51
|
+
themeProps = {
|
|
52
|
+
theme: {
|
|
53
|
+
colors: { interaction: 'rgb(0, 255, 0)', fillColorChipSelected: 'rgb(255, 0, 0)' },
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const { result } = renderHook(() => useSelectedChipBackgroundColor(), {
|
|
58
|
+
wrapper: Wrapper,
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
expect(result.current).toBe('hsl(0, 100%, 92%)')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
test('respects a custom hslLightnessChipSelected', () => {
|
|
65
|
+
themeProps = {
|
|
66
|
+
theme: {
|
|
67
|
+
colors: { interaction: 'rgb(0, 255, 0)' },
|
|
68
|
+
chip: { hslLightnessChipSelected: 50 },
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const { result } = renderHook(() => useSelectedChipBackgroundColor(), {
|
|
73
|
+
wrapper: Wrapper,
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
expect(result.current).toBe('hsl(120, 100%, 50%)')
|
|
77
|
+
})
|
|
78
|
+
})
|
|
@@ -20,4 +20,27 @@ describe('defaultTheme', () => {
|
|
|
20
20
|
// render an unstyled or misthemed UI.
|
|
21
21
|
expect(defaultTheme('unspecified').colors).toMatchObject(aliasTokensColorMap.light)
|
|
22
22
|
})
|
|
23
|
+
|
|
24
|
+
describe('chip tokens', () => {
|
|
25
|
+
test('seeds static defaults for the non-selected chip trio in both schemes', () => {
|
|
26
|
+
const light = defaultTheme('light').colors
|
|
27
|
+
const dark = defaultTheme('dark').colors
|
|
28
|
+
|
|
29
|
+
expect(light.borderColorChip).toBe('hsl(0, 0%, 88%)')
|
|
30
|
+
expect(light.fillColorChip).toBe('transparent')
|
|
31
|
+
expect(light.textColorChip).toBe('hsl(0, 0%, 45%)')
|
|
32
|
+
|
|
33
|
+
expect(dark.borderColorChip).toBe('hsl(0, 0%, 24%)')
|
|
34
|
+
expect(dark.fillColorChip).toBe('transparent')
|
|
35
|
+
expect(dark.textColorChip).toBe('hsl(0, 0%, 68%)')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
test('never seeds a static default for the selected chip trio', () => {
|
|
39
|
+
const { colors } = defaultTheme('light')
|
|
40
|
+
|
|
41
|
+
expect(colors.borderColorChipSelected).toBeUndefined()
|
|
42
|
+
expect(colors.fillColorChipSelected).toBeUndefined()
|
|
43
|
+
expect(colors.textColorChipSelected).toBeUndefined()
|
|
44
|
+
})
|
|
45
|
+
})
|
|
23
46
|
})
|
|
@@ -13,7 +13,7 @@ import { MessageReaction } from '../../components/conversation/message_reaction'
|
|
|
13
13
|
import { Avatar, Icon, Spinner, Text, TextButton, TextInlineButton } from '../../components/display'
|
|
14
14
|
import {
|
|
15
15
|
useAnimatedMessageBackgroundColor,
|
|
16
|
-
|
|
16
|
+
useInteractionTintedBackgroundColor,
|
|
17
17
|
useTheme,
|
|
18
18
|
} from '../../hooks'
|
|
19
19
|
import { useDeletingIds } from '../../hooks'
|
|
@@ -341,7 +341,7 @@ export function Message({
|
|
|
341
341
|
|
|
342
342
|
const useMessageStyles = (mine: boolean, isDeleting: boolean) => {
|
|
343
343
|
const { colors } = useTheme()
|
|
344
|
-
const myMessageBackgroundColor =
|
|
344
|
+
const myMessageBackgroundColor = useInteractionTintedBackgroundColor()
|
|
345
345
|
const { width } = useWindowDimensions()
|
|
346
346
|
const tabletWidth = width >= 744 // Smallest iPad Mini's width
|
|
347
347
|
|
|
@@ -17,7 +17,7 @@ import { ChatContext } from '../../contexts/chat_context'
|
|
|
17
17
|
import {
|
|
18
18
|
useCreateAndroidRippleColor,
|
|
19
19
|
useTheme,
|
|
20
|
-
|
|
20
|
+
useInteractionTintedBackgroundColor,
|
|
21
21
|
useScalableNumberOfLines,
|
|
22
22
|
useFontScale,
|
|
23
23
|
} from '../../hooks'
|
|
@@ -783,7 +783,7 @@ const useMessageFormStyles = () => {
|
|
|
783
783
|
const navigationTheme = useNavigationTheme()
|
|
784
784
|
const buttonSize = 38
|
|
785
785
|
|
|
786
|
-
const giphyBadgeBackgroundColor =
|
|
786
|
+
const giphyBadgeBackgroundColor = useInteractionTintedBackgroundColor()
|
|
787
787
|
|
|
788
788
|
return StyleSheet.create({
|
|
789
789
|
container: {
|
|
@@ -3,7 +3,7 @@ import colorFunction from 'color'
|
|
|
3
3
|
import React, { useMemo } from 'react'
|
|
4
4
|
import { StyleSheet } from 'react-native'
|
|
5
5
|
import { Text } from '../../components/display'
|
|
6
|
-
import {
|
|
6
|
+
import { useSelectedChipBackgroundColor, useTheme } from '../../hooks'
|
|
7
7
|
import { useCreateAndroidRippleColor } from '../../hooks/use_create_android_ripple_color'
|
|
8
8
|
import { useMessageReactionToggle } from '../../hooks/use_message_reaction_toggle'
|
|
9
9
|
import { MessageResource } from '../../types'
|
|
@@ -57,12 +57,12 @@ export function MessageReaction({
|
|
|
57
57
|
export const useReactionStyles = ({ mine }: { mine: number }) => {
|
|
58
58
|
const { colors } = useTheme()
|
|
59
59
|
const activeBorderColor = useMemo(() => {
|
|
60
|
-
return colorFunction(colors.interaction)
|
|
60
|
+
return colorFunction(colors.borderColorChipSelected ?? colors.interaction)
|
|
61
61
|
.hsl()
|
|
62
62
|
.lightness(colors.name === 'dark' ? 20 : 80)
|
|
63
63
|
.string()
|
|
64
|
-
}, [colors.interaction, colors.name])
|
|
65
|
-
const activeBackgroundColor =
|
|
64
|
+
}, [colors.borderColorChipSelected, colors.interaction, colors.name])
|
|
65
|
+
const activeBackgroundColor = useSelectedChipBackgroundColor()
|
|
66
66
|
|
|
67
67
|
return StyleSheet.create({
|
|
68
68
|
reaction: {
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
2
|
+
import { render } from '@testing-library/react-native'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { buildTestQueryClient } from '../../../__utils__/query_client'
|
|
5
|
+
import { ChatProvider, CreateChatThemeProps } from '../../../contexts/chat_context'
|
|
6
|
+
import { ToggleButton } from '../toggle_button'
|
|
7
|
+
|
|
8
|
+
let themeProps: CreateChatThemeProps
|
|
9
|
+
let queryClient: QueryClient
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
queryClient = buildTestQueryClient({
|
|
13
|
+
defaultOptions: {
|
|
14
|
+
queries: {
|
|
15
|
+
refetchInterval: false,
|
|
16
|
+
refetchOnWindowFocus: false,
|
|
17
|
+
refetchOnReconnect: false,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
queryClient.clear()
|
|
25
|
+
queryClient.cancelQueries()
|
|
26
|
+
queryClient.removeQueries()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const Wrapper = ({ children }: { children: React.ReactNode }) => {
|
|
30
|
+
return (
|
|
31
|
+
<QueryClientProvider client={queryClient}>
|
|
32
|
+
<ChatProvider
|
|
33
|
+
value={{
|
|
34
|
+
token: {
|
|
35
|
+
access_token: '',
|
|
36
|
+
created_at: 0,
|
|
37
|
+
expires_in: 0,
|
|
38
|
+
scope: '',
|
|
39
|
+
refresh_token: '',
|
|
40
|
+
token_type: '',
|
|
41
|
+
},
|
|
42
|
+
onUnauthorizedResponse: () => {},
|
|
43
|
+
theme: themeProps,
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
</ChatProvider>
|
|
48
|
+
</QueryClientProvider>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const renderToggleButton = (active: boolean) => {
|
|
53
|
+
const view = render(<ToggleButton active={active} accessibilityLabel="Filter" title="Filter" />, {
|
|
54
|
+
wrapper: Wrapper,
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
button: view.getByLabelText('Filter'),
|
|
59
|
+
text: view.getByText('Filter'),
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
describe('ToggleButton chip colors', () => {
|
|
64
|
+
describe('backward compatibility (Services / sandbox pass only colors.interaction)', () => {
|
|
65
|
+
const distinctiveGreen = 'rgb(0, 255, 0)'
|
|
66
|
+
|
|
67
|
+
beforeEach(() => {
|
|
68
|
+
themeProps = {
|
|
69
|
+
theme: {
|
|
70
|
+
colors: {
|
|
71
|
+
interaction: distinctiveGreen,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
test('active state derives border, fill, and text color from colors.interaction', () => {
|
|
78
|
+
const { button, text } = renderToggleButton(true)
|
|
79
|
+
|
|
80
|
+
expect(button).toHaveStyle({ borderColor: distinctiveGreen })
|
|
81
|
+
// The active fill is the green interaction color lightened via the
|
|
82
|
+
// chip-background hook (hsl lightness 92 in the light scheme), not
|
|
83
|
+
// the raw interaction color — pins the hook's transform in place.
|
|
84
|
+
expect(button).toHaveStyle({ backgroundColor: 'hsl(120, 100%, 92%)' })
|
|
85
|
+
expect(text).toHaveStyle({ color: distinctiveGreen })
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
test.each([
|
|
89
|
+
['light', undefined, 'hsl(0, 0%, 88%)', 'hsl(0, 0%, 45%)'],
|
|
90
|
+
['dark', 'dark' as const, 'hsl(0, 0%, 24%)', 'hsl(0, 0%, 68%)'],
|
|
91
|
+
])(
|
|
92
|
+
'inactive state uses the static chip defaults in the %s scheme',
|
|
93
|
+
(_label, colorScheme, borderColor, color) => {
|
|
94
|
+
themeProps = {
|
|
95
|
+
theme: { colors: { interaction: distinctiveGreen } },
|
|
96
|
+
colorScheme,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const { button, text } = renderToggleButton(false)
|
|
100
|
+
|
|
101
|
+
expect(button).toHaveStyle({ borderColor })
|
|
102
|
+
expect(text).toHaveStyle({ color })
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
describe('explicit chip token overrides', () => {
|
|
108
|
+
const explicitBorder = 'rgb(1, 2, 3)'
|
|
109
|
+
const explicitFill = 'rgb(4, 5, 6)'
|
|
110
|
+
const explicitText = 'rgb(7, 8, 9)'
|
|
111
|
+
|
|
112
|
+
beforeEach(() => {
|
|
113
|
+
themeProps = {
|
|
114
|
+
theme: {
|
|
115
|
+
colors: {
|
|
116
|
+
interaction: 'rgb(0, 255, 0)',
|
|
117
|
+
borderColorChipSelected: explicitBorder,
|
|
118
|
+
fillColorChipSelected: explicitFill,
|
|
119
|
+
textColorChipSelected: explicitText,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
test('active state prefers explicit chip tokens over colors.interaction', () => {
|
|
126
|
+
const { button, text } = renderToggleButton(true)
|
|
127
|
+
|
|
128
|
+
expect(button).toHaveStyle({ borderColor: explicitBorder })
|
|
129
|
+
// fillColorChipSelected still passes through the chip-background hook's
|
|
130
|
+
// lightness transform, so the rendered fill isn't the raw override.
|
|
131
|
+
expect(button).toHaveStyle({ backgroundColor: 'hsl(210, 20%, 92%)' })
|
|
132
|
+
expect(text).toHaveStyle({ color: explicitText })
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
})
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
useTheme,
|
|
6
6
|
useFontScale,
|
|
7
7
|
useCreateAndroidRippleColor,
|
|
8
|
-
|
|
8
|
+
useSelectedChipBackgroundColor,
|
|
9
9
|
} from '../../hooks'
|
|
10
10
|
import {
|
|
11
11
|
MAX_FONT_SIZE_MULTIPLIER_LANDMARK,
|
|
@@ -164,16 +164,20 @@ const useStyles = ({ active, maxFontSizeMultiplier }: Partial<ToggleButtonProps>
|
|
|
164
164
|
const { colors, button } = useTheme()
|
|
165
165
|
const fontScale = useFontScale({ maxFontSizeMultiplier })
|
|
166
166
|
|
|
167
|
-
const activeBackgroundColor =
|
|
167
|
+
const activeBackgroundColor = useSelectedChipBackgroundColor()
|
|
168
168
|
|
|
169
|
-
const
|
|
169
|
+
const borderColor = active
|
|
170
|
+
? (colors.borderColorChipSelected ?? colors.interaction)
|
|
171
|
+
: colors.borderColorChip
|
|
172
|
+
const fillColor = active ? activeBackgroundColor : colors.fillColorChip
|
|
173
|
+
const color = active ? (colors.textColorChipSelected ?? colors.interaction) : colors.textColorChip
|
|
170
174
|
|
|
171
175
|
return StyleSheet.create({
|
|
172
176
|
pressable: {
|
|
173
177
|
borderRadius: button.borderRadius * fontScale,
|
|
174
178
|
borderWidth: 1,
|
|
175
|
-
borderColor
|
|
176
|
-
backgroundColor:
|
|
179
|
+
borderColor,
|
|
180
|
+
backgroundColor: fillColor,
|
|
177
181
|
paddingHorizontal: 16 * fontScale,
|
|
178
182
|
flexDirection: 'row',
|
|
179
183
|
alignItems: 'center',
|
package/src/hooks/index.ts
CHANGED
|
@@ -13,7 +13,8 @@ export * from './use_font_scale'
|
|
|
13
13
|
export * from './use_has_direct_messages'
|
|
14
14
|
export * from './use_groups_groups'
|
|
15
15
|
export * from './use_groups'
|
|
16
|
-
export * from './
|
|
16
|
+
export * from './use_selected_chip_background_color'
|
|
17
|
+
export * from './use_interaction_tinted_background_color'
|
|
17
18
|
export * from './use_message_reaction_toggle'
|
|
18
19
|
export * from './use_new_conversation_entry'
|
|
19
20
|
export * from './use_organization'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import colorFunction from 'color'
|
|
2
|
+
import { useMemo } from 'react'
|
|
3
|
+
import { useTheme } from './use_theme'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Background color for non-chip surfaces (message bubbles, the Giphy badge)
|
|
7
|
+
* that are tinted from `colors.interaction`. Unaffected by chip tokens.
|
|
8
|
+
*/
|
|
9
|
+
export function useInteractionTintedBackgroundColor() {
|
|
10
|
+
const { colors } = useTheme()
|
|
11
|
+
|
|
12
|
+
return useMemo(
|
|
13
|
+
() =>
|
|
14
|
+
colorFunction(colors.interaction)
|
|
15
|
+
.hsl()
|
|
16
|
+
.lightness(colors.name === 'dark' ? 12 : 92)
|
|
17
|
+
.string(),
|
|
18
|
+
[colors.interaction, colors.name]
|
|
19
|
+
)
|
|
20
|
+
}
|
|
@@ -9,6 +9,10 @@ const REST_OFFSET = 1
|
|
|
9
9
|
* top content edge — for an inverted list, wherever the newest message rests. Resting
|
|
10
10
|
* the list 1pt in from that edge keeps a drag at the bottom of a conversation scrolling
|
|
11
11
|
* history instead of swiping the modal away.
|
|
12
|
+
*
|
|
13
|
+
* Returns the offset the list rests at plus the scroll listeners that nudge it back
|
|
14
|
+
* there: once on first layout, then after each gesture settles. On Android there is no
|
|
15
|
+
* sheet gesture to avoid, so the offset is 0 and the listeners are undefined.
|
|
12
16
|
*/
|
|
13
17
|
export const useRestAwayFromDismissEdge = ({
|
|
14
18
|
listRef,
|