@helpwave/hightide-native 0.0.8 → 0.1.0

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
@@ -3,21 +3,23 @@ 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,
10
9
  type ViewStyle
11
10
  } from 'react-native'
12
- import { CheckCheck } from 'lucide-react-native'
13
-
11
+ import { HightideIconRegistry } from '../../icons/HightideIconRegistry'
12
+ import { ThemedIcon } from '../visualization-and-display/ThemedIcon'
13
+ import { ThemedText } from '../visualization-and-display/ThemedText'
14
14
  import { useTheme } from '../../global-contexts/theme/ThemeContext'
15
15
  import type {
16
+ ChatMessageBubbleBodyStyle,
17
+ ChatMessageBubbleBodyTextStyle,
16
18
  ChatMessageBubbleContainerStyle,
17
- ChatMessageBubbleContentStyle,
19
+ ChatMessageBubbleMetaDataContainerStyle,
20
+ ChatMessageBubbleMetaDataStatusContainerStyle,
21
+ ChatMessageBubbleMetaDataTextStyle,
18
22
  ChatMessageBubbleState,
19
- ChatMessageBubbleStyle,
20
- ChatMessageBubbleTimestampStyle,
21
23
  ChatMessageDirection
22
24
  } from '../../theme/types/components/chat'
23
25
  import type { StyleOverwrite } from '../../theme/types/resolver'
@@ -25,88 +27,96 @@ import type { StyleOverwrite } from '../../theme/types/resolver'
25
27
  export type { ChatMessageDirection }
26
28
 
27
29
  export type ChatMessageBubbleProps = Omit<ViewProps, 'children' | 'style'> & {
28
- direction?: ChatMessageDirection,
29
- timestamp?: ReactNode,
30
+ direction: ChatMessageDirection,
31
+ timestamp: ReactNode,
30
32
  readReceipt?: ReactNode,
31
33
  children?: ReactNode,
32
34
  style?: StyleProp<ViewStyle>,
33
35
  containerStyle?: StyleOverwrite<ChatMessageBubbleState, ChatMessageBubbleContainerStyle>,
34
- bubbleStyle?: StyleOverwrite<ChatMessageBubbleState, ChatMessageBubbleStyle>,
35
- contentStyle?: StyleOverwrite<ChatMessageBubbleState, ChatMessageBubbleContentStyle>,
36
- timestampStyle?: StyleOverwrite<ChatMessageBubbleState, ChatMessageBubbleTimestampStyle>,
36
+ bodyStyle?: StyleOverwrite<ChatMessageBubbleState, ChatMessageBubbleBodyStyle>,
37
+ bodyTextStyle?: StyleOverwrite<ChatMessageBubbleState, ChatMessageBubbleBodyTextStyle>,
38
+ metaDataContainerStyle?: StyleOverwrite<ChatMessageBubbleState, ChatMessageBubbleMetaDataContainerStyle>,
39
+ metaDataStatusContainerStyle?: StyleOverwrite<ChatMessageBubbleState, ChatMessageBubbleMetaDataStatusContainerStyle>,
40
+ metaDataTextStyle?: StyleOverwrite<ChatMessageBubbleState, ChatMessageBubbleMetaDataTextStyle>,
37
41
  }
38
42
 
39
43
  export const ChatMessageBubble = ({
40
- direction = 'incoming',
44
+ direction,
41
45
  timestamp,
42
46
  readReceipt,
43
47
  children,
44
48
  style,
45
49
  containerStyle,
46
- bubbleStyle,
47
- contentStyle,
48
- timestampStyle,
50
+ bodyStyle,
51
+ bodyTextStyle,
52
+ metaDataContainerStyle,
53
+ metaDataStatusContainerStyle,
54
+ metaDataTextStyle,
49
55
  ...props
50
56
  }: ChatMessageBubbleProps) => {
51
57
  const { theme } = useTheme()
52
58
  const state = useMemo(() => ({ direction }), [direction])
53
- const staticState = useMemo(() => ({}), [])
54
59
 
55
60
  const resolvedContainerStyle = useMemo(
56
61
  () => theme.components.chat.messageBubble.container(state, containerStyle),
57
62
  [theme, state, containerStyle]
58
63
  )
59
- const resolvedBubbleStyle = useMemo(
60
- () => theme.components.chat.messageBubble.bubble(state, bubbleStyle),
61
- [theme, state, bubbleStyle]
64
+ const resolvedBodyStyle = useMemo(
65
+ () => theme.components.chat.messageBubble.body(state, bodyStyle),
66
+ [theme, state, bodyStyle]
62
67
  )
63
- const resolvedContentStyle = useMemo(
64
- () => theme.components.chat.messageBubble.content(state, contentStyle),
65
- [theme, state, contentStyle]
68
+ const resolvedBodyTextStyle = useMemo(
69
+ () => theme.components.chat.messageBubble.bodyText(state, bodyTextStyle),
70
+ [theme, state, bodyTextStyle]
66
71
  )
67
- const resolvedTimestampStyle = useMemo(
68
- () => theme.components.chat.messageBubble.timestamp(state, timestampStyle),
69
- [theme, state, timestampStyle]
72
+ const resolvedMetaDataContainerStyle = useMemo(
73
+ () => theme.components.chat.messageBubble.metaDataContainer(state, metaDataContainerStyle),
74
+ [theme, state, metaDataContainerStyle]
70
75
  )
71
- const resolvedReceiptStyle = useMemo(
72
- () => theme.components.chat.messageBubble.receipt(staticState),
73
- [theme, staticState]
76
+ const resolvedMetaDataStatusContainerStyle = useMemo(
77
+ () => theme.components.chat.messageBubble.metaDataStatusContainer(state, metaDataStatusContainerStyle),
78
+ [theme, state, metaDataStatusContainerStyle]
74
79
  )
75
- const resolvedReceiptTextStyle = useMemo(
76
- () => theme.components.chat.messageBubble.receiptText(staticState),
77
- [theme, staticState]
80
+ const resolvedMetaDataTextStyle = useMemo(
81
+ () => theme.components.chat.messageBubble.metaDataText(state, metaDataTextStyle),
82
+ [theme, state, metaDataTextStyle]
78
83
  )
79
- const resolvedReceiptIcon = useMemo(
80
- () => theme.components.chat.messageBubble.receiptIcon(staticState),
81
- [theme, staticState]
84
+ const resolvedMetaDataIcon = useMemo(
85
+ () => theme.components.chat.messageBubble.metaDataIcon(state),
86
+ [theme, state]
82
87
  )
83
88
 
84
89
  return (
85
90
  <View {...props} style={[resolvedContainerStyle, style]}>
86
- <View style={resolvedBubbleStyle}>
91
+ <View style={resolvedBodyStyle}>
87
92
  {typeof children === 'string' || typeof children === 'number' ? (
88
- <Text style={resolvedContentStyle}>{children}</Text>
93
+ <ThemedText style={resolvedBodyTextStyle}>{children}</ThemedText>
89
94
  ) : (
90
95
  children
91
96
  )}
92
- {timestamp != null && (
93
- typeof timestamp === 'string' || typeof timestamp === 'number' ? (
94
- <Text style={resolvedTimestampStyle}>{timestamp}</Text>
95
- ) : (
96
- timestamp
97
- )
97
+ </View>
98
+ <View style={resolvedMetaDataContainerStyle}>
99
+ {readReceipt != null && (
100
+ <View style={resolvedMetaDataStatusContainerStyle}>
101
+ <ThemedIcon
102
+ icon={HightideIconRegistry.CheckCheck}
103
+ size={resolvedMetaDataIcon.size}
104
+ strokeWidth={resolvedMetaDataIcon.strokeWidth}
105
+ color={resolvedMetaDataIcon.color}
106
+ />
107
+ {typeof readReceipt === 'string' || typeof readReceipt === 'number' ? (
108
+ <ThemedText style={resolvedMetaDataTextStyle}>{readReceipt}</ThemedText>
109
+ ) : (
110
+ readReceipt
111
+ )}
112
+ </View>
113
+ )}
114
+ {typeof timestamp === 'string' || typeof timestamp === 'number' ? (
115
+ <ThemedText style={resolvedMetaDataTextStyle}>{timestamp}</ThemedText>
116
+ ) : (
117
+ timestamp
98
118
  )}
99
119
  </View>
100
- {readReceipt != null && (
101
- <View style={resolvedReceiptStyle}>
102
- <CheckCheck size={14} color={resolvedReceiptIcon.color} />
103
- {typeof readReceipt === 'string' || typeof readReceipt === 'number' ? (
104
- <Text style={resolvedReceiptTextStyle}>{readReceipt}</Text>
105
- ) : (
106
- readReceipt
107
- )}
108
- </View>
109
- )}
110
120
  </View>
111
121
  )
112
122
  }
@@ -9,10 +9,10 @@ import {
9
9
  type ViewProps,
10
10
  type ViewStyle
11
11
  } from 'react-native'
12
- import { SendHorizontal } from 'lucide-react-native'
13
12
 
14
13
  import { useControlledState } from '@helpwave/hightide-utils/hooks'
15
14
 
15
+ import { HightideIconRegistry } from '../../icons/HightideIconRegistry'
16
16
  import { IconButton } from '../user-interaction/IconButton'
17
17
  import { useTheme } from '../../global-contexts/theme/ThemeContext'
18
18
  import type {
@@ -84,7 +84,7 @@ export const ChatMessageComposer = ({
84
84
  return (
85
85
  <View {...props} style={[resolvedComposerStyle, style]}>
86
86
  {actions != null && (
87
- <View style={{ flexDirection: 'row', alignItems: 'flex-start' }}>
87
+ <View style={{ flexDirection: 'row' }}>
88
88
  {actions}
89
89
  </View>
90
90
  )}
@@ -92,24 +92,26 @@ export const ChatMessageComposer = ({
92
92
  value={value ?? ''}
93
93
  onChangeText={setValue}
94
94
  placeholder={placeholder}
95
- placeholderTextColor={placeholderColor}
95
+ placeholderTextColor={placeholderColor.color}
96
96
  editable={!disabled}
97
97
  multiline
98
98
  style={resolvedInputStyle}
99
99
  onSubmitEditing={send}
100
100
  returnKeyType="send"
101
101
  />
102
- {trailing}
103
- <IconButton
104
- accessibilityLabel={sendLabel}
105
- color="primary"
106
- coloringStyle="solid"
107
- disabled={disabled || !(value ?? '').trim()}
108
- size="md"
109
- onPress={send}
110
- icon={SendHorizontal}
111
- buttonStyle={(prev) => ({ ...prev, borderRadius: 999 })}
112
- />
102
+ <View style={{ flexDirection: 'row', alignItems: 'flex-end' }}>
103
+ {trailing}
104
+ <IconButton
105
+ icon={HightideIconRegistry.SendHorizontal}
106
+ accessibilityLabel={sendLabel}
107
+ variant="filled"
108
+ disabled={disabled || !(value ?? '').trim()}
109
+ size="sm"
110
+ onPress={send}
111
+ containerStyle={(prev) => ({ ...prev, borderRadius: 999 })}
112
+ stateLayerStyle={(prev) => ({ ...prev, borderRadius: 999 })}
113
+ />
114
+ </View>
113
115
  </View>
114
116
  )
115
117
  }
@@ -1,32 +1,32 @@
1
- import type { ReactNode } from 'react'
2
1
  import {
3
- Pressable,
4
- Text,
5
- type PressableProps,
6
- type StyleProp,
7
- type ViewStyle
8
- } from 'react-native'
2
+ useMemo,
3
+ type ReactNode
4
+ } from 'react'
5
+ import type { StyleProp, ViewStyle } from 'react-native'
9
6
 
10
7
  import { useTheme } from '../../global-contexts/theme/ThemeContext'
8
+ import {
9
+ ThemedPressable,
10
+ type ThemedPressableProps
11
+ } from '../user-interaction/ThemedPressable'
12
+ import { ThemedText } from '../visualization-and-display/ThemedText'
11
13
  import type {
12
14
  ChatQuickReplyChipState,
13
- ChatQuickReplyChipStyle,
14
- ChatQuickReplyChipTextStyle
15
+ PressableContainerStyle,
16
+ PressableState,
17
+ PressableTextStyle
15
18
  } from '../../theme/types/components/chat'
16
19
  import type { StyleOverwrite } from '../../theme/types/resolver'
17
20
 
18
- export type ChatQuickReplyChipProps = Omit<PressableProps, 'children' | 'style'> & {
21
+ export type ChatQuickReplyChipProps = Omit<
22
+ ThemedPressableProps,
23
+ 'children' | 'containerStyle' | 'textStyle' | 'stateLayerStyle'
24
+ > & {
19
25
  isActive?: boolean,
20
26
  children?: ReactNode,
21
27
  style?: StyleProp<ViewStyle>,
22
- chipStyle?: StyleOverwrite<ChatQuickReplyChipState, ChatQuickReplyChipStyle>,
23
- textStyle?: StyleOverwrite<ChatQuickReplyChipState, ChatQuickReplyChipTextStyle>,
24
- }
25
-
26
- type PressableInteraction = {
27
- pressed: boolean,
28
- hovered?: boolean,
29
- focused?: boolean,
28
+ containerStyle?: StyleOverwrite<PressableState, PressableContainerStyle>,
29
+ textStyle?: StyleOverwrite<PressableState, PressableTextStyle>,
30
30
  }
31
31
 
32
32
  export const ChatQuickReplyChip = ({
@@ -34,39 +34,37 @@ export const ChatQuickReplyChip = ({
34
34
  children,
35
35
  disabled,
36
36
  style,
37
- chipStyle,
37
+ containerStyle,
38
38
  textStyle,
39
39
  ...props
40
40
  }: ChatQuickReplyChipProps) => {
41
41
  const { theme } = useTheme()
42
-
43
- const resolveState = (interaction: PressableInteraction): ChatQuickReplyChipState => ({
44
- isActive,
45
- isDisabled: !!disabled,
46
- isPressed: interaction.pressed,
47
- isHovered: !!interaction.hovered,
48
- isFocused: !!interaction.focused,
49
- })
42
+ const state = useMemo((): ChatQuickReplyChipState => ({ isActive }), [isActive])
43
+ const pressableResolvers = useMemo(
44
+ () => theme.components.chat.quickReplyChip.pressable(state),
45
+ [theme, state]
46
+ )
50
47
 
51
48
  return (
52
- <Pressable
49
+ <ThemedPressable
53
50
  {...props}
54
51
  disabled={disabled}
55
- style={(pressableState) => {
56
- const state = resolveState(pressableState as PressableInteraction)
57
- return [theme.components.chat.quickReplyChip.container(state, chipStyle), style]
58
- }}
52
+ style={style}
53
+ containerStyle={(_, pressableState) => (
54
+ pressableResolvers.container(pressableState, containerStyle)
55
+ )}
56
+ stateLayerStyle={(_, pressableState) => (
57
+ pressableResolvers.stateLayer(pressableState)
58
+ )}
59
+ textStyle={(_, pressableState) => (
60
+ pressableResolvers.text(pressableState, textStyle)
61
+ )}
59
62
  >
60
- {(pressableState) => {
61
- const state = resolveState(pressableState as PressableInteraction)
62
- const resolvedText = theme.components.chat.quickReplyChip.text(state, textStyle)
63
-
64
- if (typeof children === 'string' || typeof children === 'number') {
65
- return <Text style={resolvedText}>{children}</Text>
66
- }
67
-
68
- return children
69
- }}
70
- </Pressable>
63
+ {typeof children === 'string' || typeof children === 'number' ? (
64
+ <ThemedText>{children}</ThemedText>
65
+ ) : (
66
+ children
67
+ )}
68
+ </ThemedPressable>
71
69
  )
72
70
  }
@@ -3,16 +3,17 @@ 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,
10
9
  type ViewStyle
11
10
  } from 'react-native'
12
- import { CheckCheck } from 'lucide-react-native'
13
11
 
14
- import type { ColoringType } from '@helpwave/hightide-design/utils'
12
+ import type { ColorPairToken } from '@helpwave/hightide-design/theme-tokens'
15
13
 
14
+ import { HightideIconRegistry } from '../../icons/HightideIconRegistry'
15
+ import { ThemedIcon } from '../visualization-and-display/ThemedIcon'
16
+ import { ThemedText } from '../visualization-and-display/ThemedText'
16
17
  import { useTheme } from '../../global-contexts/theme/ThemeContext'
17
18
  import type {
18
19
  ChatSystemLineState,
@@ -23,7 +24,7 @@ import type { StyleOverwrite } from '../../theme/types/resolver'
23
24
 
24
25
  export type ChatSystemLineProps = Omit<ViewProps, 'children' | 'style'> & {
25
26
  icon?: ReactNode,
26
- color?: ColoringType,
27
+ color?: ColorPairToken,
27
28
  children?: ReactNode,
28
29
  style?: StyleProp<ViewStyle>,
29
30
  lineStyle?: StyleOverwrite<ChatSystemLineState, ChatSystemLineStyle>,
@@ -32,7 +33,7 @@ export type ChatSystemLineProps = Omit<ViewProps, 'children' | 'style'> & {
32
33
 
33
34
  export const ChatSystemLine = ({
34
35
  icon,
35
- color = 'primary',
36
+ color,
36
37
  children,
37
38
  style,
38
39
  lineStyle,
@@ -57,9 +58,15 @@ export const ChatSystemLine = ({
57
58
 
58
59
  return (
59
60
  <View {...props} style={[resolvedLineStyle, style]}>
60
- {icon ?? <CheckCheck size={14} color={resolvedIcon.color} />}
61
+ {icon ?? (
62
+ <ThemedIcon
63
+ icon={HightideIconRegistry.CheckCheck}
64
+ size={14}
65
+ color={resolvedIcon.color}
66
+ />
67
+ )}
61
68
  {typeof children === 'string' || typeof children === 'number' ? (
62
- <Text style={resolvedTextStyle}>{children}</Text>
69
+ <ThemedText style={resolvedTextStyle}>{children}</ThemedText>
63
70
  ) : (
64
71
  children
65
72
  )}
@@ -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,7 +10,13 @@ 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
+ import {
15
+ Avatar,
16
+ type AvatarProps
17
+ } from '../visualization-and-display/Avatar'
14
18
  import type {
19
+ ChatThreadHeaderContentRowStyle,
15
20
  ChatThreadHeaderStyle,
16
21
  ChatThreadHeaderSubtitleStyle,
17
22
  ChatThreadHeaderTitleStyle
@@ -19,13 +24,14 @@ import type {
19
24
  import type { StyleOverwrite } from '../../theme/types/resolver'
20
25
 
21
26
  export type ChatThreadHeaderProps = Omit<ViewProps, 'style'> & {
22
- avatar?: ReactNode,
27
+ avatar?: AvatarProps,
23
28
  title: ReactNode,
24
29
  subtitle?: ReactNode,
25
30
  leftActions?: ReactNode,
26
31
  rightActions?: ReactNode,
27
32
  style?: StyleProp<ViewStyle>,
28
33
  headerStyle?: StyleOverwrite<Record<string, never>, ChatThreadHeaderStyle>,
34
+ contentRowStyle?: StyleOverwrite<Record<string, never>, ChatThreadHeaderContentRowStyle>,
29
35
  titleStyle?: StyleOverwrite<Record<string, never>, ChatThreadHeaderTitleStyle>,
30
36
  subtitleStyle?: StyleOverwrite<Record<string, never>, ChatThreadHeaderSubtitleStyle>,
31
37
  }
@@ -38,17 +44,25 @@ export const ChatThreadHeader = ({
38
44
  rightActions,
39
45
  style,
40
46
  headerStyle,
47
+ contentRowStyle,
41
48
  titleStyle,
42
49
  subtitleStyle,
43
50
  ...props
44
51
  }: ChatThreadHeaderProps) => {
45
52
  const { theme } = useTheme()
46
53
  const state = useMemo(() => ({}), [])
54
+ const resolvedAvatar = useMemo(() => ({
55
+ ...avatar,
56
+ }), [avatar])
47
57
 
48
58
  const resolvedHeaderStyle = useMemo(
49
59
  () => theme.components.chat.threadHeader.container(state, headerStyle),
50
60
  [theme, state, headerStyle]
51
61
  )
62
+ const resolvedContentRowStyle = useMemo(
63
+ () => theme.components.chat.threadHeader.contentRow(state, contentRowStyle),
64
+ [theme, state, contentRowStyle]
65
+ )
52
66
  const resolvedTitleStyle = useMemo(
53
67
  () => theme.components.chat.threadHeader.title(state, titleStyle),
54
68
  [theme, state, titleStyle]
@@ -58,6 +72,16 @@ export const ChatThreadHeader = ({
58
72
  [theme, state, subtitleStyle]
59
73
  )
60
74
 
75
+ const avatarThemeState = useMemo(() => ({
76
+ size: resolvedAvatar.size,
77
+ color: resolvedAvatar.color,
78
+ }), [resolvedAvatar.size, resolvedAvatar.color])
79
+
80
+ const avatarTheme = useMemo(
81
+ () => theme.components.chat.threadHeader.avatar(avatarThemeState),
82
+ [theme, avatarThemeState]
83
+ )
84
+
61
85
  return (
62
86
  <View {...props} style={[resolvedHeaderStyle, style]}>
63
87
  {leftActions != null && (
@@ -65,16 +89,46 @@ export const ChatThreadHeader = ({
65
89
  {leftActions}
66
90
  </View>
67
91
  )}
68
- {avatar}
69
- <View style={{ flex: 1, minWidth: 0, gap: 2 }}>
92
+ <Avatar
93
+ {...resolvedAvatar}
94
+ avatarStyle={(_, avatarState) => avatarTheme.container(
95
+ {
96
+ ...avatarState,
97
+ size: resolvedAvatar.size,
98
+ },
99
+ resolvedAvatar.avatarStyle
100
+ )}
101
+ imageStyle={(_, avatarState) => avatarTheme.image(
102
+ {
103
+ ...avatarState,
104
+ size: resolvedAvatar.size,
105
+ },
106
+ resolvedAvatar.imageStyle
107
+ )}
108
+ textStyle={(_, avatarState) => avatarTheme.text(
109
+ {
110
+ ...avatarState,
111
+ size: resolvedAvatar.size,
112
+ },
113
+ resolvedAvatar.textStyle
114
+ )}
115
+ iconStyle={(_, avatarState) => avatarTheme.icon(
116
+ {
117
+ ...avatarState,
118
+ size: resolvedAvatar.size,
119
+ },
120
+ resolvedAvatar.iconStyle
121
+ )}
122
+ />
123
+ <View style={resolvedContentRowStyle}>
70
124
  {typeof title === 'string' || typeof title === 'number' ? (
71
- <Text style={resolvedTitleStyle} numberOfLines={1}>{title}</Text>
125
+ <ThemedText style={resolvedTitleStyle} numberOfLines={1}>{title}</ThemedText>
72
126
  ) : (
73
127
  title
74
128
  )}
75
129
  {subtitle != null && (
76
130
  typeof subtitle === 'string' || typeof subtitle === 'number' ? (
77
- <Text style={resolvedSubtitleStyle} numberOfLines={1}>{subtitle}</Text>
131
+ <ThemedText style={resolvedSubtitleStyle} numberOfLines={1}>{subtitle}</ThemedText>
78
132
  ) : (
79
133
  subtitle
80
134
  )
@@ -1,9 +1,8 @@
1
- export * from './ChatAttachmentCard'
1
+ export * from './ChatAttachmentMessageBubble'
2
2
  export * from './ChatConversationList'
3
3
  export * from './ChatConversationRow'
4
4
  export * from './ChatDateDivider'
5
5
  export * from './ChatMessageBubble'
6
- export * from './ChatMessageCard'
7
6
  export * from './ChatMessageComposer'
8
7
  export * from './ChatMessageList'
9
8
  export * from './ChatQuickReplyChip'
@@ -1,4 +1,6 @@
1
+ export * from './card'
1
2
  export * from './chat'
2
- export * from './menu'
3
+ export * from './layout'
4
+ export * from './list'
3
5
  export * from './user-interaction'
4
6
  export * from './visualization-and-display'
@@ -0,0 +1,60 @@
1
+ import {
2
+ forwardRef,
3
+ useMemo
4
+ } from 'react'
5
+ import {
6
+ View,
7
+ type StyleProp,
8
+ type ViewProps,
9
+ type ViewStyle
10
+ } from 'react-native'
11
+
12
+ import type { ColorToken } from '@helpwave/hightide-design/primitive-tokens'
13
+ import type { DividerDirection } from '@helpwave/hightide-design/component-token-resolvers'
14
+
15
+ import { useTheme } from '../../global-contexts/theme/ThemeContext'
16
+ import type {
17
+ DividerState,
18
+ DividerStyle
19
+ } from '../../theme/types/components/divider'
20
+ import type { StyleOverwrite } from '../../theme/types/resolver'
21
+
22
+ export type DividerProps = Omit<ViewProps, 'style'> & {
23
+ direction?: DividerDirection,
24
+ color?: ColorToken,
25
+ width?: number,
26
+ margin?: number,
27
+ style?: StyleProp<ViewStyle>,
28
+ dividerStyle?: StyleOverwrite<DividerState, DividerStyle>,
29
+ }
30
+
31
+ export const Divider = forwardRef<View, DividerProps>(function Divider({
32
+ direction = 'horizontal',
33
+ color,
34
+ width,
35
+ margin,
36
+ style,
37
+ dividerStyle,
38
+ ...props
39
+ }, ref) {
40
+ const { theme } = useTheme()
41
+ const state = useMemo((): DividerState => ({
42
+ direction,
43
+ color,
44
+ width,
45
+ margin,
46
+ }), [direction, color, width, margin])
47
+
48
+ const resolvedDividerStyle = useMemo(
49
+ () => theme.components.divider.container(state, dividerStyle),
50
+ [theme, state, dividerStyle]
51
+ )
52
+
53
+ return (
54
+ <View
55
+ {...props}
56
+ ref={ref}
57
+ style={[resolvedDividerStyle, style]}
58
+ />
59
+ )
60
+ })
@@ -0,0 +1 @@
1
+ export * from './Divider'