@helpwave/hightide-native 0.0.8 → 0.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 (125) hide show
  1. package/README.md +4 -4
  2. package/package.json +8 -19
  3. package/src/components/card/Card.tsx +41 -0
  4. package/src/components/card/index.ts +1 -0
  5. package/src/components/chat/ChatAttachmentMessageBubble.tsx +246 -0
  6. package/src/components/chat/ChatConversationRow.tsx +21 -16
  7. package/src/components/chat/ChatDateDivider.tsx +2 -2
  8. package/src/components/chat/ChatMessageBubble.tsx +62 -52
  9. package/src/components/chat/ChatMessageComposer.tsx +16 -14
  10. package/src/components/chat/ChatQuickReplyChip.tsx +41 -43
  11. package/src/components/chat/ChatSystemLine.tsx +14 -7
  12. package/src/components/chat/ChatThreadHeader.tsx +60 -6
  13. package/src/components/chat/index.ts +1 -2
  14. package/src/components/index.ts +3 -1
  15. package/src/components/layout/Divider.tsx +60 -0
  16. package/src/components/layout/index.ts +1 -0
  17. package/src/components/list/ListActionItem.tsx +99 -0
  18. package/src/components/list/ListItem.tsx +96 -0
  19. package/src/components/list/ListNavigationItem.tsx +102 -0
  20. package/src/components/list/index.ts +3 -0
  21. package/src/components/user-interaction/Button.tsx +80 -31
  22. package/src/components/user-interaction/Checkbox.tsx +72 -32
  23. package/src/components/user-interaction/IconButton.tsx +68 -30
  24. package/src/components/user-interaction/Input.tsx +61 -14
  25. package/src/components/user-interaction/MultiSelect.tsx +142 -75
  26. package/src/components/user-interaction/SearchBar.tsx +222 -0
  27. package/src/components/user-interaction/Select.tsx +129 -58
  28. package/src/components/user-interaction/Switch.tsx +110 -80
  29. package/src/components/user-interaction/ThemedPressable.tsx +136 -0
  30. package/src/components/user-interaction/index.ts +2 -0
  31. package/src/components/visualization-and-display/Avatar.tsx +112 -93
  32. package/src/components/visualization-and-display/Chip.tsx +22 -22
  33. package/src/components/visualization-and-display/ThemedIcon.tsx +72 -0
  34. package/src/components/visualization-and-display/ThemedText.tsx +38 -0
  35. package/src/components/visualization-and-display/index.ts +2 -1
  36. package/src/global-contexts/HightideProvider.tsx +19 -10
  37. package/src/global-contexts/content-theme/ContentThemeContext.ts +22 -0
  38. package/src/global-contexts/content-theme/ContentThemeProvider.tsx +32 -0
  39. package/src/global-contexts/content-theme/index.ts +2 -0
  40. package/src/global-contexts/debug/forward-exports.ts +10 -0
  41. package/src/global-contexts/debug/index.ts +1 -0
  42. package/src/global-contexts/index.ts +2 -0
  43. package/src/global-contexts/theme/ThemeProvider.tsx +7 -1
  44. package/src/icons/HightideIconRegistry.ts +33 -0
  45. package/src/icons/index.ts +2 -0
  46. package/src/icons/types.ts +11 -0
  47. package/src/theme/adapters/container-adapter.ts +323 -0
  48. package/src/theme/adapters/defined.ts +11 -0
  49. package/src/theme/adapters/icon-style-adapter.ts +10 -0
  50. package/src/theme/adapters/index.ts +4 -0
  51. package/src/theme/adapters/text-style-adapter.ts +16 -0
  52. package/src/theme/index.ts +1 -0
  53. package/src/theme/resolvers/avatar.ts +385 -186
  54. package/src/theme/resolvers/button.ts +50 -82
  55. package/src/theme/resolvers/card.ts +27 -0
  56. package/src/theme/resolvers/chat/attachment-message-bubble.ts +163 -0
  57. package/src/theme/resolvers/chat/chat-theme.ts +69 -0
  58. package/src/theme/resolvers/chat/conversation-list.ts +35 -0
  59. package/src/theme/resolvers/chat/conversation-row.ts +64 -0
  60. package/src/theme/resolvers/chat/date-divider.ts +31 -0
  61. package/src/theme/resolvers/chat/index.ts +11 -0
  62. package/src/theme/resolvers/chat/message-bubble.ts +57 -0
  63. package/src/theme/resolvers/chat/message-composer.ts +38 -0
  64. package/src/theme/resolvers/chat/message-list.ts +27 -0
  65. package/src/theme/resolvers/chat/quick-reply-chip.ts +80 -0
  66. package/src/theme/resolvers/chat/system-line.ts +41 -0
  67. package/src/theme/resolvers/chat/thread-header.ts +85 -0
  68. package/src/theme/resolvers/checkbox.ts +87 -74
  69. package/src/theme/resolvers/chip.ts +30 -67
  70. package/src/theme/resolvers/colorScheme.ts +136 -0
  71. package/src/theme/resolvers/divider.ts +34 -0
  72. package/src/theme/resolvers/icon.ts +21 -0
  73. package/src/theme/resolvers/iconButton.ts +45 -61
  74. package/src/theme/resolvers/index.ts +7 -2
  75. package/src/theme/resolvers/input.ts +64 -42
  76. package/src/theme/resolvers/listItem.ts +115 -0
  77. package/src/theme/resolvers/multiSelect.ts +159 -84
  78. package/src/theme/resolvers/searchBar.ts +121 -0
  79. package/src/theme/resolvers/select.ts +141 -66
  80. package/src/theme/resolvers/switch.ts +59 -53
  81. package/src/theme/resolvers/themedPressable.ts +54 -0
  82. package/src/theme/themes/createHightideTheme.ts +214 -51
  83. package/src/theme/themes/hightideThemes.ts +10 -6
  84. package/src/theme/types/color.ts +2 -59
  85. package/src/theme/types/components/avatar.ts +37 -36
  86. package/src/theme/types/components/button.ts +13 -14
  87. package/src/theme/types/components/card.ts +9 -0
  88. package/src/theme/types/components/chat.ts +124 -103
  89. package/src/theme/types/components/checkbox.ts +11 -12
  90. package/src/theme/types/components/chip.ts +8 -14
  91. package/src/theme/types/components/divider.ts +18 -0
  92. package/src/theme/types/components/hightide.ts +41 -42
  93. package/src/theme/types/components/iconButton.ts +19 -14
  94. package/src/theme/types/components/index.ts +5 -1
  95. package/src/theme/types/components/input.ts +17 -8
  96. package/src/theme/types/components/listItem.ts +86 -0
  97. package/src/theme/types/components/multiSelect.ts +14 -12
  98. package/src/theme/types/components/searchBar.ts +28 -0
  99. package/src/theme/types/components/select.ts +21 -9
  100. package/src/theme/types/components/switch.ts +12 -5
  101. package/src/theme/types/components/themedPressable.ts +31 -0
  102. package/src/theme/types/decoration.ts +1 -11
  103. package/src/theme/types/icongraphy.ts +8 -0
  104. package/src/theme/types/index.ts +2 -0
  105. package/src/theme/types/layout.ts +25 -57
  106. package/src/theme/types/resolver.ts +54 -1
  107. package/src/theme/types/semantics.ts +72 -0
  108. package/src/theme/types/theme.ts +26 -13
  109. package/src/theme/types/typography.ts +16 -17
  110. package/src/utils/hitBoxOverlay.ts +44 -0
  111. package/src/utils/index.ts +2 -0
  112. package/src/utils/minimumTouchTargetHitSlop.ts +68 -0
  113. package/src/components/chat/ChatAttachmentCard.tsx +0 -110
  114. package/src/components/chat/ChatMessageCard.tsx +0 -118
  115. package/src/components/menu/Menu.tsx +0 -61
  116. package/src/components/menu/MenuActionItem.tsx +0 -90
  117. package/src/components/menu/MenuItem.tsx +0 -73
  118. package/src/components/menu/MenuNavigationItem.tsx +0 -90
  119. package/src/components/menu/index.ts +0 -4
  120. package/src/components/visualization-and-display/Icon.tsx +0 -27
  121. package/src/storybook/helper.tsx +0 -36
  122. package/src/theme/resolvers/chat.ts +0 -418
  123. package/src/theme/resolvers/coloring.ts +0 -94
  124. package/src/theme/resolvers/menu.ts +0 -120
  125. package/src/theme/types/components/menu.ts +0 -57
package/README.md CHANGED
@@ -31,18 +31,18 @@ import { HightideProvider } from "@helpwave/hightide-native/global-contexts";
31
31
  Import from the package subpaths (there is no root export):
32
32
 
33
33
  ```tsx
34
- import { Button, Input, Select } from "@helpwave/hightide-native/components";
34
+ import { Button, Input, Select, ThemedIcon } from "@helpwave/hightide-native/components";
35
35
  import { HightideProvider } from "@helpwave/hightide-native/global-contexts";
36
36
  import { useSelect } from "@helpwave/hightide-native/hooks";
37
- import { Icon } from "@helpwave/hightide-native/icons";
37
+ import { HightideIconRegistry } from "@helpwave/hightide-native/icons";
38
38
  ```
39
39
 
40
40
  | Subpath | Contents |
41
41
  | --- | --- |
42
- | `@helpwave/hightide-native/components` | UI components (`Button`, `Checkbox`, `Chip`, `Input`, …) |
42
+ | `@helpwave/hightide-native/components` | UI components (`Button`, `Checkbox`, `Chip`, `Input`, `ThemedText`, `ThemedIcon`, …) |
43
43
  | `@helpwave/hightide-native/global-contexts` | `HightideProvider` and related context providers |
44
44
  | `@helpwave/hightide-native/hooks` | Native hooks (`useSelect`, `useMultiSelect`, …) |
45
- | `@helpwave/hightide-native/icons` | Icon components |
45
+ | `@helpwave/hightide-native/icons` | Icon registry (`HightideIconRegistry`) |
46
46
  | `@helpwave/hightide-native/theme` | Theme factories and style resolvers |
47
47
  | `@helpwave/hightide-native/types` | Shared TypeScript types |
48
48
 
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "access": "public"
11
11
  },
12
12
  "license": "AGPL-3.0-only",
13
- "version": "0.0.8",
13
+ "version": "0.1.1",
14
14
  "type": "module",
15
15
  "files": [
16
16
  "src"
@@ -43,8 +43,8 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "lucide-react-native": "0.561.0",
46
- "@helpwave/hightide-design": "0.0.6",
47
- "@helpwave/hightide-utils": "0.0.5"
46
+ "@helpwave/hightide-design": "0.1.1",
47
+ "@helpwave/hightide-utils": "0.1.0"
48
48
  },
49
49
  "peerDependencies": {
50
50
  "@react-native-async-storage/async-storage": ">=2.0.0",
@@ -55,22 +55,13 @@
55
55
  "devDependencies": {
56
56
  "@helpwave/eslint-config": "0.0.11",
57
57
  "@react-native-async-storage/async-storage": "2.2.0",
58
- "@storybook/addon-docs": "10.4.5",
59
- "@storybook/addon-links": "10.4.5",
60
- "@storybook/react-native-web-vite": "10.4.5",
61
- "@types/react": "19.2.3",
62
- "@types/react-dom": "19.2.3",
58
+ "@types/react": "19.0.10",
63
59
  "eslint": "9.31.0",
64
60
  "eslint-plugin-import": "2.32.0",
65
- "eslint-plugin-storybook": "10.4.5",
66
- "react": "19.2.3",
67
- "react-dom": "19.2.3",
68
- "react-native": "0.79.2",
61
+ "react": "19.0.0",
62
+ "react-native": "0.79.6",
69
63
  "react-native-svg": "15.12.0",
70
- "react-native-web": "0.20.0",
71
- "storybook": "10.4.5",
72
- "typescript": "5.7.2",
73
- "vite": "7.3.5"
64
+ "typescript": "5.7.2"
74
65
  },
75
66
  "keywords": [
76
67
  "react-native",
@@ -81,13 +72,11 @@
81
72
  "url": "https://github.com/helpwave/hightide/issues"
82
73
  },
83
74
  "scripts": {
84
- "clean": "pnpm run barrel -- --clean && rm -rf node_modules storybook-static",
75
+ "clean": "pnpm run barrel -- --clean && rm -rf node_modules",
85
76
  "init": "pnpm run barrel",
86
77
  "barrel": "node node_modules/@helpwave/hightide-utils/scripts/barrel.js",
87
78
  "barrel:check": "node node_modules/@helpwave/hightide-utils/scripts/barrel.js --check",
88
79
  "build": "pnpm run barrel",
89
- "storybook": "storybook dev -p 6007",
90
- "build-storybook": "storybook build",
91
80
  "lint": "eslint .",
92
81
  "test": "node -e \"process.exit(0)\""
93
82
  }
@@ -0,0 +1,41 @@
1
+ import {
2
+ useMemo,
3
+ type ReactNode
4
+ } from 'react'
5
+ import {
6
+ View,
7
+ type StyleProp,
8
+ type ViewProps,
9
+ type ViewStyle
10
+ } from 'react-native'
11
+
12
+ import { useTheme } from '../../global-contexts/theme/ThemeContext'
13
+ import type { CardStyle } from '../../theme/types/components/card'
14
+ import type { StyleOverwrite } from '../../theme/types/resolver'
15
+
16
+ export type CardProps = Omit<ViewProps, 'children' | 'style'> & {
17
+ children?: ReactNode,
18
+ style?: StyleProp<ViewStyle>,
19
+ cardStyle?: StyleOverwrite<Record<string, never>, CardStyle>,
20
+ }
21
+
22
+ export const Card = ({
23
+ children,
24
+ style,
25
+ cardStyle,
26
+ ...props
27
+ }: CardProps) => {
28
+ const { theme } = useTheme()
29
+ const state = useMemo(() => ({}), [])
30
+
31
+ const resolvedCardStyle = useMemo(
32
+ () => theme.components.card.container(state, cardStyle),
33
+ [theme, state, cardStyle]
34
+ )
35
+
36
+ return (
37
+ <View {...props} style={[resolvedCardStyle, style]}>
38
+ {children}
39
+ </View>
40
+ )
41
+ }
@@ -0,0 +1 @@
1
+ export * from './Card'
@@ -0,0 +1,246 @@
1
+ import {
2
+ useMemo,
3
+ type ReactNode
4
+ } from 'react'
5
+ import {
6
+ View,
7
+ type StyleProp,
8
+ type ViewStyle
9
+ } from 'react-native'
10
+ import { HightideIconRegistry } from '../../icons/HightideIconRegistry'
11
+ import { ThemedIcon } from '../visualization-and-display/ThemedIcon'
12
+ import { ThemedText } from '../visualization-and-display/ThemedText'
13
+ import { ThemedPressable } from '../user-interaction/ThemedPressable'
14
+ import { useTheme } from '../../global-contexts/theme/ThemeContext'
15
+ import type {
16
+ ChatAttachmentMessageBubbleFileMetadataTextStyle,
17
+ ChatAttachmentMessageBubbleFileNameTextStyle,
18
+ ChatAttachmentMessageBubbleState,
19
+ ChatMessageBubbleBodyStyle,
20
+ ChatMessageBubbleBodyTextStyle,
21
+ ChatMessageBubbleContainerStyle,
22
+ ChatMessageBubbleMetaDataContainerStyle,
23
+ ChatMessageBubbleMetaDataStatusContainerStyle,
24
+ ChatMessageBubbleMetaDataTextStyle,
25
+ ChatMessageBubbleState,
26
+ PressableContainerStyle,
27
+ PressableState
28
+ } from '../../theme/types/components/chat'
29
+ import type { StyleOverwrite } from '../../theme/types/resolver'
30
+ import {
31
+ ChatMessageBubble,
32
+ type ChatMessageBubbleProps
33
+ } from './ChatMessageBubble'
34
+
35
+ export type ChatAttachmentMessageBubbleProps = Omit<ChatMessageBubbleProps, 'children'> & {
36
+ children?: ReactNode,
37
+ name: ReactNode,
38
+ metadata?: ReactNode,
39
+ icon?: ReactNode,
40
+ downloadLabel?: string,
41
+ onDownload?: () => void,
42
+ contentContainerStyle?: StyleOverwrite<
43
+ PressableState,
44
+ PressableContainerStyle
45
+ >,
46
+ fileNameTextStyle?: StyleOverwrite<
47
+ ChatAttachmentMessageBubbleState,
48
+ ChatAttachmentMessageBubbleFileNameTextStyle
49
+ >,
50
+ fileMetadataTextStyle?: StyleOverwrite<
51
+ ChatAttachmentMessageBubbleState,
52
+ ChatAttachmentMessageBubbleFileMetadataTextStyle
53
+ >,
54
+ }
55
+
56
+ const mergeBubbleStyleOverwrite = <TStyle extends StyleProp<ViewStyle> | object>(
57
+ tokenOverride: TStyle,
58
+ userOverwrite?: StyleOverwrite<ChatMessageBubbleState, TStyle>
59
+ ): StyleOverwrite<ChatMessageBubbleState, TStyle> => (
60
+ (prev, state) => {
61
+ const withTokenOverride = {
62
+ ...(prev as object),
63
+ ...(tokenOverride as object),
64
+ } as TStyle
65
+
66
+ if (userOverwrite === undefined) {
67
+ return withTokenOverride
68
+ }
69
+
70
+ if (typeof userOverwrite === 'function') {
71
+ return userOverwrite(withTokenOverride, state)
72
+ }
73
+
74
+ return {
75
+ ...(withTokenOverride as object),
76
+ ...(userOverwrite as object),
77
+ } as TStyle
78
+ }
79
+ )
80
+
81
+ export const ChatAttachmentMessageBubble = ({
82
+ children,
83
+ name,
84
+ metadata,
85
+ icon,
86
+ direction,
87
+ downloadLabel = 'Download',
88
+ onDownload,
89
+ timestamp,
90
+ readReceipt,
91
+ style,
92
+ containerStyle,
93
+ bodyStyle,
94
+ bodyTextStyle,
95
+ metaDataContainerStyle,
96
+ metaDataStatusContainerStyle,
97
+ metaDataTextStyle,
98
+ contentContainerStyle,
99
+ fileNameTextStyle,
100
+ fileMetadataTextStyle,
101
+ ...props
102
+ }: ChatAttachmentMessageBubbleProps) => {
103
+ const { theme } = useTheme()
104
+ const state = useMemo(() => ({ direction }), [direction])
105
+ const attachment = theme.components.chat.attachmentMessageBubble
106
+ const bubbleOverrides = attachment.chatMessageBubbleOverrides
107
+ const contentResolvers = useMemo(
108
+ () => attachment.contentContainer(state),
109
+ [attachment, state]
110
+ )
111
+
112
+ const resolvedFileIconContainerStyle = useMemo(
113
+ () => attachment.fileIconContainer(state),
114
+ [attachment, state]
115
+ )
116
+ const resolvedFileIcon = useMemo(
117
+ () => attachment.fileIcon(state),
118
+ [attachment, state]
119
+ )
120
+ const resolvedDownloadIconContainerStyle = useMemo(
121
+ () => attachment.downloadIconContainer(state),
122
+ [attachment, state]
123
+ )
124
+ const resolvedDownloadIcon = useMemo(
125
+ () => attachment.downloadIcon(state),
126
+ [attachment, state]
127
+ )
128
+ const resolvedFileNameTextStyle = useMemo(
129
+ () => attachment.fileNameText(state, fileNameTextStyle),
130
+ [attachment, state, fileNameTextStyle]
131
+ )
132
+ const resolvedFileMetadataTextStyle = useMemo(
133
+ () => attachment.fileMetadataText(state, fileMetadataTextStyle),
134
+ [attachment, state, fileMetadataTextStyle]
135
+ )
136
+
137
+ const resolvedContainerStyle = useMemo(
138
+ () => mergeBubbleStyleOverwrite<ChatMessageBubbleContainerStyle>(
139
+ bubbleOverrides.container(state),
140
+ containerStyle
141
+ ),
142
+ [bubbleOverrides, state, containerStyle]
143
+ )
144
+ const resolvedBodyStyle = useMemo(
145
+ () => mergeBubbleStyleOverwrite<ChatMessageBubbleBodyStyle>(
146
+ bubbleOverrides.body(state),
147
+ bodyStyle
148
+ ),
149
+ [bubbleOverrides, state, bodyStyle]
150
+ )
151
+ const resolvedBodyTextStyle = useMemo(
152
+ () => mergeBubbleStyleOverwrite<ChatMessageBubbleBodyTextStyle>(
153
+ bubbleOverrides.bodyText(state),
154
+ bodyTextStyle
155
+ ),
156
+ [bubbleOverrides, state, bodyTextStyle]
157
+ )
158
+ const resolvedMetaDataContainerStyle = useMemo(
159
+ () => mergeBubbleStyleOverwrite<ChatMessageBubbleMetaDataContainerStyle>(
160
+ bubbleOverrides.metaDataContainer(state),
161
+ metaDataContainerStyle
162
+ ),
163
+ [bubbleOverrides, state, metaDataContainerStyle]
164
+ )
165
+ const resolvedMetaDataStatusContainerStyle = useMemo(
166
+ () => mergeBubbleStyleOverwrite<ChatMessageBubbleMetaDataStatusContainerStyle>(
167
+ bubbleOverrides.metaDataStatusContainer(state),
168
+ metaDataStatusContainerStyle
169
+ ),
170
+ [bubbleOverrides, state, metaDataStatusContainerStyle]
171
+ )
172
+ const resolvedMetaDataTextStyle = useMemo(
173
+ () => mergeBubbleStyleOverwrite<ChatMessageBubbleMetaDataTextStyle>(
174
+ bubbleOverrides.metaDataText(state),
175
+ metaDataTextStyle
176
+ ),
177
+ [bubbleOverrides, state, metaDataTextStyle]
178
+ )
179
+
180
+ return (
181
+ <ChatMessageBubble
182
+ {...props}
183
+ direction={direction}
184
+ timestamp={timestamp}
185
+ readReceipt={readReceipt}
186
+ style={style}
187
+ containerStyle={resolvedContainerStyle}
188
+ bodyStyle={resolvedBodyStyle}
189
+ bodyTextStyle={resolvedBodyTextStyle}
190
+ metaDataContainerStyle={resolvedMetaDataContainerStyle}
191
+ metaDataStatusContainerStyle={resolvedMetaDataStatusContainerStyle}
192
+ metaDataTextStyle={resolvedMetaDataTextStyle}
193
+ >
194
+ {children}
195
+ <ThemedPressable
196
+ accessibilityLabel={downloadLabel}
197
+ disabled={onDownload == null}
198
+ onPress={onDownload}
199
+ containerStyle={(_, pressableState) => (
200
+ contentResolvers.container(pressableState, contentContainerStyle)
201
+ )}
202
+ stateLayerStyle={(_, pressableState) => (
203
+ contentResolvers.stateLayer(pressableState)
204
+ )}
205
+ textStyle={(_, pressableState) => (
206
+ contentResolvers.text(pressableState)
207
+ )}
208
+ >
209
+ <View style={resolvedFileIconContainerStyle}>
210
+ {icon ?? (
211
+ <ThemedIcon
212
+ icon={HightideIconRegistry.FileText}
213
+ size={resolvedFileIcon.size}
214
+ strokeWidth={resolvedFileIcon.strokeWidth}
215
+ color={resolvedFileIcon.color}
216
+ />
217
+ )}
218
+ </View>
219
+ <View style={{ flex: 1, minWidth: 0, gap: 2 }}>
220
+ {typeof name === 'string' || typeof name === 'number' ? (
221
+ <ThemedText style={resolvedFileNameTextStyle} numberOfLines={1}>{name}</ThemedText>
222
+ ) : (
223
+ name
224
+ )}
225
+ {metadata != null && (
226
+ typeof metadata === 'string' || typeof metadata === 'number' ? (
227
+ <ThemedText appearance="description" style={resolvedFileMetadataTextStyle}>
228
+ {metadata}
229
+ </ThemedText>
230
+ ) : (
231
+ metadata
232
+ )
233
+ )}
234
+ </View>
235
+ <View style={resolvedDownloadIconContainerStyle}>
236
+ <ThemedIcon
237
+ icon={HightideIconRegistry.Download}
238
+ size={resolvedDownloadIcon.size}
239
+ strokeWidth={resolvedDownloadIcon.strokeWidth}
240
+ color={resolvedDownloadIcon.color}
241
+ />
242
+ </View>
243
+ </ThemedPressable>
244
+ </ChatMessageBubble>
245
+ )
246
+ }
@@ -4,18 +4,14 @@ import {
4
4
  type ReactNode
5
5
  } from 'react'
6
6
  import {
7
- Pressable,
8
- Text,
9
7
  View,
10
8
  type PressableProps,
11
9
  type StyleProp,
12
10
  type ViewStyle
13
11
  } from 'react-native'
14
- import {
15
- Check,
16
- CheckCheck
17
- } from 'lucide-react-native'
18
-
12
+ import { HightideIconRegistry } from '../../icons/HightideIconRegistry'
13
+ import { ThemedIcon } from '../visualization-and-display/ThemedIcon'
14
+ import { ThemedText } from '../visualization-and-display/ThemedText'
19
15
  import { useTheme } from '../../global-contexts/theme/ThemeContext'
20
16
  import type {
21
17
  ChatConversationRowPreviewStyle,
@@ -25,6 +21,7 @@ import type {
25
21
  ChatConversationRowTitleStyle
26
22
  } from '../../theme/types/components/chat'
27
23
  import type { StyleOverwrite } from '../../theme/types/resolver'
24
+ import { ThemedPressable } from '../user-interaction'
28
25
 
29
26
  export type ChatConversationSentIndicator = 'sent' | 'sentAndReceived'
30
27
 
@@ -47,6 +44,7 @@ type PressableInteraction = {
47
44
  pressed: boolean,
48
45
  hovered?: boolean,
49
46
  focused?: boolean,
47
+ focusVisible?: boolean,
50
48
  }
51
49
 
52
50
  export const ChatConversationRow = ({
@@ -67,7 +65,9 @@ export const ChatConversationRow = ({
67
65
  }: ChatConversationRowProps) => {
68
66
  const { theme } = useTheme()
69
67
  const isUnread = (unreadCount ?? 0) > 0
70
- const SentIndicatorIcon = sentIndicator === 'sentAndReceived' ? CheckCheck : Check
68
+ const sentIndicatorIcon = sentIndicator === 'sentAndReceived'
69
+ ? HightideIconRegistry.CheckCheck
70
+ : HightideIconRegistry.Check
71
71
 
72
72
  const resolveState = (interaction: PressableInteraction): ChatConversationRowState => ({
73
73
  isUnread,
@@ -76,6 +76,7 @@ export const ChatConversationRow = ({
76
76
  isPressed: interaction.pressed,
77
77
  isHovered: !!interaction.hovered,
78
78
  isFocused: !!interaction.focused,
79
+ isFocusVisible: !!interaction.focusVisible,
79
80
  })
80
81
 
81
82
  const staticState = useMemo(() => ({}), [])
@@ -93,7 +94,7 @@ export const ChatConversationRow = ({
93
94
  )
94
95
 
95
96
  return (
96
- <Pressable
97
+ <ThemedPressable
97
98
  {...props}
98
99
  disabled={disabled}
99
100
  style={(pressableState) => {
@@ -111,15 +112,15 @@ export const ChatConversationRow = ({
111
112
  <Fragment>
112
113
  {avatar}
113
114
  <View style={{ flex: 1, minWidth: 0, gap: 5 }}>
114
- <View style={{ flexDirection: 'row', alignItems: 'baseline', justifyContent: 'space-between', gap: 8 }}>
115
+ <View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
115
116
  {typeof title === 'string' || typeof title === 'number' ? (
116
- <Text style={resolvedTitle} numberOfLines={1}>{title}</Text>
117
+ <ThemedText style={resolvedTitle} numberOfLines={1}>{title}</ThemedText>
117
118
  ) : (
118
119
  title
119
120
  )}
120
121
  {timestamp != null && (
121
122
  typeof timestamp === 'string' || typeof timestamp === 'number' ? (
122
- <Text style={resolvedTimestamp}>{timestamp}</Text>
123
+ <ThemedText style={resolvedTimestamp}>{timestamp}</ThemedText>
123
124
  ) : (
124
125
  timestamp
125
126
  )
@@ -128,11 +129,15 @@ export const ChatConversationRow = ({
128
129
  <View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
129
130
  <View style={{ flex: 1, flexDirection: 'row', alignItems: 'center', gap: 4, minWidth: 0 }}>
130
131
  {sentIndicator && (
131
- <SentIndicatorIcon size={14} color={sentIndicatorColor} />
132
+ <ThemedIcon
133
+ icon={sentIndicatorIcon}
134
+ size={16}
135
+ color={sentIndicatorColor}
136
+ />
132
137
  )}
133
138
  {preview != null && (
134
139
  typeof preview === 'string' || typeof preview === 'number' ? (
135
- <Text style={resolvedPreview} numberOfLines={1}>{preview}</Text>
140
+ <ThemedText style={resolvedPreview} numberOfLines={1}>{preview}</ThemedText>
136
141
  ) : (
137
142
  preview
138
143
  )
@@ -140,7 +145,7 @@ export const ChatConversationRow = ({
140
145
  </View>
141
146
  {isUnread && (
142
147
  <View style={unreadBadge}>
143
- <Text style={unreadBadgeText}>{unreadCount}</Text>
148
+ <ThemedText style={unreadBadgeText}>{unreadCount}</ThemedText>
144
149
  </View>
145
150
  )}
146
151
  </View>
@@ -148,6 +153,6 @@ export const ChatConversationRow = ({
148
153
  </Fragment>
149
154
  )
150
155
  }}
151
- </Pressable>
156
+ </ThemedPressable>
152
157
  )
153
158
  }
@@ -3,7 +3,6 @@ import {
3
3
  type ReactNode
4
4
  } from 'react'
5
5
  import {
6
- Text,
7
6
  View,
8
7
  type StyleProp,
9
8
  type ViewProps,
@@ -11,6 +10,7 @@ import {
11
10
  } from 'react-native'
12
11
 
13
12
  import { useTheme } from '../../global-contexts/theme/ThemeContext'
13
+ import { ThemedText } from '../visualization-and-display/ThemedText'
14
14
  import type {
15
15
  ChatDateDividerStyle,
16
16
  ChatDateDividerTextStyle
@@ -46,7 +46,7 @@ export const ChatDateDivider = ({
46
46
  return (
47
47
  <View {...props} style={[resolvedDividerStyle, style]}>
48
48
  {typeof children === 'string' || typeof children === 'number' ? (
49
- <Text style={resolvedTextStyle}>{children}</Text>
49
+ <ThemedText style={resolvedTextStyle}>{children}</ThemedText>
50
50
  ) : (
51
51
  children
52
52
  )}