@helpwave/hightide-native 0.1.1 → 0.3.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 (65) hide show
  1. package/package.json +2 -2
  2. package/src/components/chat/ChatAttachmentMessageBubble.tsx +3 -0
  3. package/src/components/chat/ChatConversationRow.tsx +127 -27
  4. package/src/components/chat/ChatQuickReplyChip.tsx +7 -1
  5. package/src/components/chat/ChatThreadHeader.tsx +88 -48
  6. package/src/components/list/ListActionItem.tsx +60 -11
  7. package/src/components/list/ListItem.tsx +47 -21
  8. package/src/components/list/ListItemAccessory.tsx +34 -0
  9. package/src/components/list/ListItemTextContent.tsx +53 -0
  10. package/src/components/list/ListNavigationItem.tsx +60 -16
  11. package/src/components/list/index.ts +2 -0
  12. package/src/components/user-interaction/Button.tsx +6 -15
  13. package/src/components/user-interaction/IconButton.tsx +5 -7
  14. package/src/components/user-interaction/MultiSelect.tsx +72 -46
  15. package/src/components/user-interaction/Select.tsx +5 -1
  16. package/src/components/user-interaction/ThemedPressable.tsx +9 -4
  17. package/src/components/visualization-and-display/Chip.tsx +12 -5
  18. package/src/components/visualization-and-display/ThemedIcon.tsx +12 -8
  19. package/src/components/visualization-and-display/ThemedText.tsx +6 -2
  20. package/src/global-contexts/HightideProvider.tsx +9 -17
  21. package/src/global-contexts/content-theme/ContentThemeContext.ts +5 -2
  22. package/src/global-contexts/content-theme/ContentThemeProvider.tsx +64 -10
  23. package/src/global-contexts/theme/ThemeProvider.tsx +9 -4
  24. package/src/theme/adapters/index.ts +1 -4
  25. package/src/theme/adapters/style-adapter-utils.ts +433 -0
  26. package/src/theme/resolvers/avatar.ts +9 -10
  27. package/src/theme/resolvers/button.ts +6 -7
  28. package/src/theme/resolvers/card.ts +3 -2
  29. package/src/theme/resolvers/chat/attachment-message-bubble.ts +25 -37
  30. package/src/theme/resolvers/chat/conversation-list.ts +5 -4
  31. package/src/theme/resolvers/chat/conversation-row.ts +114 -14
  32. package/src/theme/resolvers/chat/date-divider.ts +4 -4
  33. package/src/theme/resolvers/chat/message-bubble.ts +9 -10
  34. package/src/theme/resolvers/chat/message-composer.ts +5 -6
  35. package/src/theme/resolvers/chat/message-list.ts +3 -2
  36. package/src/theme/resolvers/chat/quick-reply-chip.ts +12 -20
  37. package/src/theme/resolvers/chat/system-line.ts +5 -6
  38. package/src/theme/resolvers/chat/thread-header.ts +60 -12
  39. package/src/theme/resolvers/checkbox.ts +6 -6
  40. package/src/theme/resolvers/chip.ts +9 -4
  41. package/src/theme/resolvers/divider.ts +3 -3
  42. package/src/theme/resolvers/iconButton.ts +5 -10
  43. package/src/theme/resolvers/input.ts +12 -7
  44. package/src/theme/resolvers/listItem.ts +19 -16
  45. package/src/theme/resolvers/multiSelect.ts +23 -16
  46. package/src/theme/resolvers/searchBar.ts +14 -7
  47. package/src/theme/resolvers/select.ts +22 -15
  48. package/src/theme/resolvers/switch.ts +5 -4
  49. package/src/theme/resolvers/themedPressable.ts +10 -5
  50. package/src/theme/themes/createHightideTheme.ts +13 -4
  51. package/src/theme/types/components/chat.ts +63 -3
  52. package/src/theme/types/components/chip.ts +4 -0
  53. package/src/theme/types/components/iconButton.ts +1 -7
  54. package/src/theme/types/components/listItem.ts +5 -0
  55. package/src/theme/types/components/multiSelect.ts +1 -0
  56. package/src/theme/types/components/select.ts +1 -0
  57. package/src/theme/types/components/themedPressable.ts +4 -0
  58. package/src/theme/types/layout.ts +13 -7
  59. package/src/theme/types/semantics.ts +2 -1
  60. package/src/theme/types/theme.ts +40 -12
  61. package/src/theme/types/typography.ts +9 -4
  62. package/src/theme/adapters/container-adapter.ts +0 -323
  63. package/src/theme/adapters/defined.ts +0 -11
  64. package/src/theme/adapters/icon-style-adapter.ts +0 -10
  65. package/src/theme/adapters/text-style-adapter.ts +0 -16
@@ -12,15 +12,15 @@ import {
12
12
  import type { ColorPairToken } from '@helpwave/hightide-design/theme-tokens'
13
13
  import type { ChipVariant, ComponentSize } from '@helpwave/hightide-design/semantic-token-resolvers'
14
14
 
15
- import { ContentThemeProvider } from '../../global-contexts/content-theme/ContentThemeProvider'
15
+ import { ContentThemeOverrideProvider } from '../../global-contexts/content-theme/ContentThemeProvider'
16
16
  import { useTheme } from '../../global-contexts/theme/ThemeContext'
17
17
  import type {
18
+ ChipIconStyle,
18
19
  ChipState,
19
20
  ChipStyle,
20
21
  ChipTextStyle
21
22
  } from '../../theme/types/components/chip'
22
23
  import type { StyleOverwrite } from '../../theme/types/resolver'
23
- import type { Color } from '../../theme/types/color'
24
24
  import { ThemedText } from './ThemedText'
25
25
 
26
26
  export type ChipSize = ComponentSize
@@ -39,6 +39,7 @@ export type ChipProps = Omit<ViewProps, 'children' | 'style'> & {
39
39
  children?: ReactNode,
40
40
  style?: StyleProp<ViewStyle>,
41
41
  chipStyle?: StyleOverwrite<ChipState, ChipStyle>,
42
+ iconStyle?: StyleOverwrite<ChipState, ChipIconStyle>,
42
43
  textStyle?: StyleOverwrite<ChipState, ChipTextStyle>,
43
44
  }
44
45
 
@@ -49,6 +50,7 @@ export const Chip = ({
49
50
  size = 'md',
50
51
  style,
51
52
  chipStyle,
53
+ iconStyle,
52
54
  textStyle,
53
55
  ...props
54
56
  }: ChipProps) => {
@@ -64,6 +66,10 @@ export const Chip = ({
64
66
  () => theme.components.chip.chip(state, chipStyle),
65
67
  [theme, state, chipStyle]
66
68
  )
69
+ const resolvedIconStyle = useMemo(
70
+ () => theme.components.chip.icon(state, iconStyle),
71
+ [theme, state, iconStyle]
72
+ )
67
73
  const resolvedTextStyle = useMemo(
68
74
  () => theme.components.chip.text(state, textStyle),
69
75
  [theme, state, textStyle]
@@ -74,14 +80,15 @@ export const Chip = ({
74
80
  {...props}
75
81
  style={[resolvedChipStyle, style]}
76
82
  >
77
- <ContentThemeProvider
78
- foregroundColor={resolvedTextStyle.color as Color}
83
+ <ContentThemeOverrideProvider
84
+ foreground={resolvedTextStyle.color}
79
85
  textStyle={resolvedTextStyle}
86
+ iconStyle={resolvedIconStyle}
80
87
  >
81
88
  {typeof children === 'string' || typeof children === 'number'
82
89
  ? <ThemedText>{children}</ThemedText>
83
90
  : children}
84
- </ContentThemeProvider>
91
+ </ContentThemeOverrideProvider>
85
92
  </View>
86
93
  )
87
94
  }
@@ -23,7 +23,7 @@ export type ThemedIconProps = Omit<ViewProps, 'children'> & {
23
23
 
24
24
  export const ThemedIcon = ({
25
25
  icon: Glyph,
26
- size = 'md',
26
+ size,
27
27
  color,
28
28
  strokeWidth,
29
29
  appearance = 'normal',
@@ -31,15 +31,19 @@ export const ThemedIcon = ({
31
31
  ...props
32
32
  }: ThemedIconProps) => {
33
33
  const { theme } = useTheme()
34
- const { foregroundColor } = useContentTheme()
35
- const iconToken = typeof size === 'number'
34
+ const { foreground, iconStyle } = useContentTheme()
35
+ const resolvedSize = size ?? iconStyle.size ?? 'md'
36
+ const iconToken = typeof resolvedSize === 'number'
36
37
  ? {
37
- size,
38
- strokeWidth: strokeWidth ?? theme.components.icon.md.strokeWidth,
38
+ size: resolvedSize,
39
+ strokeWidth: strokeWidth ?? iconStyle.strokeWidth ?? theme.components.icon.md.strokeWidth,
39
40
  }
40
- : theme.components.icon[size]
41
+ : theme.components.icon[resolvedSize]
41
42
 
42
- const baseColor = (color ?? foregroundColor) as HexColorToken
43
+ // TODO fix this by using a hex color parser
44
+ const baseColor = (color
45
+ ?? iconStyle.color
46
+ ?? foreground) as HexColorToken
43
47
  const resolvedColor = appearance === 'normal'
44
48
  ? baseColor
45
49
  : theme.semantics.withAppearance({ color: baseColor, appearance })
@@ -64,7 +68,7 @@ export const ThemedIcon = ({
64
68
  >
65
69
  <Glyph
66
70
  size={iconToken.size}
67
- strokeWidth={strokeWidth ?? iconToken.strokeWidth}
71
+ strokeWidth={strokeWidth ?? iconStyle.strokeWidth ?? iconToken.strokeWidth}
68
72
  color={resolvedColor}
69
73
  />
70
74
  </View>
@@ -23,9 +23,13 @@ export const ThemedText = forwardRef<React.ComponentRef<typeof RNText>, ThemedTe
23
23
  ...props
24
24
  }, ref) {
25
25
  const { theme } = useTheme()
26
- const { foregroundColor, textStyle } = useContentTheme()
26
+ const { foreground, textStyle } = useContentTheme()
27
+ // TODO use a hex color parser
28
+ const foregroundColor = (typeof textStyle.color === 'string'
29
+ ? textStyle.color
30
+ : foreground) as HexColorToken
27
31
  const color = appearance === 'description'
28
- ? theme.semantics.asDescription({ color: foregroundColor as HexColorToken })
32
+ ? theme.semantics.asDescription({ color: foregroundColor })
29
33
  : foregroundColor
30
34
 
31
35
  return (
@@ -8,10 +8,6 @@ import { hightideTranslation } from '@helpwave/hightide-utils/i18n'
8
8
  import { ArrayUtil } from '@helpwave/hightide-utils/utils'
9
9
 
10
10
  import { HightideContext } from './HightideContext'
11
- import {
12
- DebugProvider,
13
- type DebugProviderProps
14
- } from './debug'
15
11
  import {
16
12
  LocalizationProvider,
17
13
  type LocalizationProviderProps
@@ -31,7 +27,6 @@ export type HightideProviderProps = PropsWithChildren & {
31
27
  theme?: Omit<ThemeProviderProps<HightideTheme>, 'children'>,
32
28
  locale?: Omit<LocalizationProviderProps, 'children'>,
33
29
  translation?: Omit<TranslationProviderProps, 'children' | 'locale'>,
34
- debug?: Omit<DebugProviderProps, 'children'>,
35
30
  }
36
31
 
37
32
  const HightideContextBridge = ({ children }: PropsWithChildren) => {
@@ -55,7 +50,6 @@ export const HightideProvider = ({
55
50
  theme,
56
51
  locale,
57
52
  translation,
58
- debug,
59
53
  }: HightideProviderProps) => {
60
54
  const resolvedTranslations = useMemo(() => [
61
55
  ...ArrayUtil.resolveSingleOrArray(translation?.translation ?? []),
@@ -63,16 +57,14 @@ export const HightideProvider = ({
63
57
  ], [translation?.translation])
64
58
 
65
59
  return (
66
- <DebugProvider {...debug}>
67
- <LocalizationProvider {...locale}>
68
- <TranslationProvider {...translation} translation={resolvedTranslations}>
69
- <ThemeProvider {...theme}>
70
- <HightideContextBridge>
71
- {children}
72
- </HightideContextBridge>
73
- </ThemeProvider>
74
- </TranslationProvider>
75
- </LocalizationProvider>
76
- </DebugProvider>
60
+ <LocalizationProvider {...locale}>
61
+ <TranslationProvider {...translation} translation={resolvedTranslations}>
62
+ <ThemeProvider {...theme}>
63
+ <HightideContextBridge>
64
+ {children}
65
+ </HightideContextBridge>
66
+ </ThemeProvider>
67
+ </TranslationProvider>
68
+ </LocalizationProvider>
77
69
  )
78
70
  }
@@ -4,9 +4,12 @@ import {
4
4
  } from 'react'
5
5
  import type { ColorValue, TextStyle } from 'react-native'
6
6
 
7
+ import type { IconStyle } from '../../icons'
8
+
7
9
  export type ContentThemeContextValue = {
8
- foregroundColor: ColorValue,
10
+ foreground: ColorValue,
9
11
  textStyle: TextStyle,
12
+ iconStyle: IconStyle,
10
13
  }
11
14
 
12
15
  export const ContentThemeContext = createContext<ContentThemeContextValue | null>(null)
@@ -15,7 +18,7 @@ export const useContentTheme = (): ContentThemeContextValue => {
15
18
  const context = useContext(ContentThemeContext)
16
19
  if (!context) {
17
20
  throw new Error(
18
- 'useContentTheme must be used within ContentThemeProvider. Try adding a ContentThemeProvider around your app.'
21
+ 'useContentTheme must be used within ContentThemeRootProvider. Try adding a ContentThemeRootProvider around your app.'
19
22
  )
20
23
  }
21
24
  return context
@@ -2,27 +2,81 @@ import {
2
2
  useMemo,
3
3
  type PropsWithChildren
4
4
  } from 'react'
5
- import type { TextStyle, ColorValue } from 'react-native'
5
+ import type { ColorValue, TextStyle } from 'react-native'
6
6
 
7
+ import type { IconStyle } from '../../icons'
7
8
  import {
8
9
  ContentThemeContext,
10
+ useContentTheme,
9
11
  type ContentThemeContextValue
10
12
  } from './ContentThemeContext'
11
13
 
12
- export type ContentThemeProviderProps = PropsWithChildren & {
13
- foregroundColor: ColorValue,
14
- textStyle: TextStyle,
15
- }
14
+ export type ContentThemeRootProviderProps = PropsWithChildren & ContentThemeContextValue
16
15
 
17
- export const ContentThemeProvider = ({
16
+ export const ContentThemeRootProvider = ({
18
17
  children,
19
- foregroundColor,
18
+ foreground,
20
19
  textStyle,
21
- }: ContentThemeProviderProps) => {
20
+ iconStyle,
21
+ }: ContentThemeRootProviderProps) => {
22
22
  const value = useMemo((): ContentThemeContextValue => ({
23
- foregroundColor,
23
+ foreground,
24
24
  textStyle,
25
- }), [foregroundColor, textStyle])
25
+ iconStyle,
26
+ }), [foreground, textStyle, iconStyle])
27
+
28
+ return (
29
+ <ContentThemeContext.Provider value={value}>
30
+ {children}
31
+ </ContentThemeContext.Provider>
32
+ )
33
+ }
34
+
35
+ type ForegroundOverride =
36
+ | ColorValue
37
+ | ((prev: ColorValue) => ColorValue)
38
+
39
+ type TextStyleOverride =
40
+ | TextStyle
41
+ | ((prev: TextStyle, foreground: ColorValue) => TextStyle)
42
+
43
+ type IconStyleOverride =
44
+ | IconStyle
45
+ | ((prev: IconStyle, foreground: ColorValue) => IconStyle)
46
+
47
+ export type ContentThemeOverrideProviderProps = PropsWithChildren & {
48
+ foreground?: ForegroundOverride,
49
+ textStyle?: TextStyleOverride,
50
+ iconStyle?: IconStyleOverride,
51
+ }
52
+
53
+ export const ContentThemeOverrideProvider = ({
54
+ children,
55
+ foreground: foregroundOverride,
56
+ textStyle: textStyleOverride,
57
+ iconStyle: iconStyleOverride,
58
+ }: ContentThemeOverrideProviderProps) => {
59
+ const parent = useContentTheme()
60
+
61
+ const value = useMemo((): ContentThemeContextValue => {
62
+ const foreground = typeof foregroundOverride === 'function'
63
+ ? foregroundOverride(parent.foreground)
64
+ : foregroundOverride ?? parent.foreground
65
+
66
+ const textStyle = typeof textStyleOverride === 'function'
67
+ ? textStyleOverride(parent.textStyle, foreground)
68
+ : textStyleOverride ?? parent.textStyle
69
+
70
+ const iconStyle = typeof iconStyleOverride === 'function'
71
+ ? iconStyleOverride(parent.iconStyle, foreground)
72
+ : iconStyleOverride ?? parent.iconStyle
73
+
74
+ return {
75
+ foreground,
76
+ textStyle,
77
+ iconStyle,
78
+ }
79
+ }, [parent, foregroundOverride, textStyleOverride, iconStyleOverride])
26
80
 
27
81
  return (
28
82
  <ContentThemeContext.Provider value={value}>
@@ -21,7 +21,7 @@ import {
21
21
  import { useNativeKeyValueStore } from '../../hooks/useNativeKeyValueStore'
22
22
  import type { ThemeMode } from '../../theme/themes/hightideThemes'
23
23
  import type { HightideTheme } from '../../theme/types/theme'
24
- import { ContentThemeProvider } from '../content-theme'
24
+ import { ContentThemeRootProvider } from '../content-theme'
25
25
 
26
26
  export type ThemeProviderProps<T> = PropsWithChildren & {
27
27
  theme?: ThemeMode | null,
@@ -93,12 +93,17 @@ export const ThemeProvider = ({
93
93
 
94
94
  return (
95
95
  <ThemeContext.Provider value={contextValue}>
96
- <ContentThemeProvider
97
- foregroundColor={contextValue.theme.colors.surface.onColor}
96
+ <ContentThemeRootProvider
97
+ foreground={contextValue.theme.colors.surface.onColor}
98
98
  textStyle={contextValue.theme.typography.body.md}
99
+ iconStyle={{
100
+ size: contextValue.theme.icongraphy.sizes.md,
101
+ strokeWidth: contextValue.theme.icongraphy.strokeWidth,
102
+ color: contextValue.theme.colors.surface.onColor,
103
+ }}
99
104
  >
100
105
  {children}
101
- </ContentThemeProvider>
106
+ </ContentThemeRootProvider>
102
107
  </ThemeContext.Provider>
103
108
  )
104
109
  }
@@ -1,4 +1 @@
1
- export * from './container-adapter'
2
- export * from './defined'
3
- export * from './icon-style-adapter'
4
- export * from './text-style-adapter'
1
+ export * from './style-adapter-utils'