@helpwave/hightide-native 0.0.1 → 0.0.5

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 (89) hide show
  1. package/README.md +56 -0
  2. package/package.json +3 -3
  3. package/src/components/chat/ChatAttachmentCard.tsx +110 -0
  4. package/src/components/chat/ChatConversationList.tsx +72 -0
  5. package/src/components/chat/ChatConversationRow.tsx +153 -0
  6. package/src/components/chat/ChatDateDivider.tsx +55 -0
  7. package/src/components/chat/ChatMessageBubble.tsx +112 -0
  8. package/src/components/chat/ChatMessageCard.tsx +118 -0
  9. package/src/components/chat/ChatMessageComposer.tsx +115 -0
  10. package/src/components/chat/ChatMessageList.tsx +66 -0
  11. package/src/components/chat/ChatQuickReplyChip.tsx +72 -0
  12. package/src/components/chat/ChatSystemLine.tsx +68 -0
  13. package/src/components/chat/ChatThreadHeader.tsx +90 -0
  14. package/src/components/chat/index.ts +11 -0
  15. package/src/components/index.ts +4 -7
  16. package/src/components/menu/Menu.tsx +61 -0
  17. package/src/components/menu/MenuActionItem.tsx +90 -0
  18. package/src/components/menu/MenuItem.tsx +73 -0
  19. package/src/components/menu/MenuNavigationItem.tsx +90 -0
  20. package/src/components/menu/index.ts +4 -0
  21. package/src/components/user-interaction/Button.tsx +101 -0
  22. package/src/components/{Checkbox → user-interaction}/Checkbox.tsx +38 -16
  23. package/src/components/user-interaction/IconButton.tsx +95 -0
  24. package/src/components/{Input → user-interaction}/Input.tsx +35 -14
  25. package/src/components/{MultiSelect → user-interaction}/MultiSelect.tsx +47 -15
  26. package/src/components/{Select → user-interaction}/Select.tsx +44 -12
  27. package/src/components/user-interaction/index.ts +6 -0
  28. package/src/components/{Chip → visualization-and-display}/Chip.tsx +36 -20
  29. package/src/components/visualization-and-display/Icon.tsx +27 -0
  30. package/src/components/{Chip → visualization-and-display}/index.ts +1 -0
  31. package/src/global-contexts/HightideContext.ts +4 -1
  32. package/src/global-contexts/HightideProvider.tsx +22 -10
  33. package/src/global-contexts/hightide-config/HightideConfigUtils.ts +15 -12
  34. package/src/global-contexts/localization/LocalizationProvider.tsx +4 -2
  35. package/src/global-contexts/localization/forward-exports.ts +1 -0
  36. package/src/global-contexts/theme/ThemeContext.ts +11 -6
  37. package/src/global-contexts/theme/ThemeProvider.tsx +35 -38
  38. package/src/hooks/useMultiSelect.ts +1 -0
  39. package/src/hooks/useNativeKeyValueStore.ts +7 -1
  40. package/src/hooks/useSelect.ts +1 -0
  41. package/src/theme/resolvers/button.ts +38 -23
  42. package/src/theme/resolvers/chat.ts +418 -0
  43. package/src/theme/resolvers/checkbox.ts +26 -21
  44. package/src/theme/resolvers/chip.ts +32 -22
  45. package/src/theme/resolvers/coloring.ts +21 -17
  46. package/src/theme/resolvers/iconButton.ts +28 -18
  47. package/src/theme/resolvers/index.ts +2 -0
  48. package/src/theme/resolvers/input.ts +28 -19
  49. package/src/theme/resolvers/menu.ts +120 -0
  50. package/src/theme/resolvers/multiSelect.ts +39 -34
  51. package/src/theme/resolvers/select.ts +35 -30
  52. package/src/theme/themes/createTheme.ts +44 -15
  53. package/src/theme/themes/nativeThemes.ts +7 -6
  54. package/src/theme/types/color.ts +60 -0
  55. package/src/theme/types/components/button.ts +30 -0
  56. package/src/theme/types/components/chat.ts +198 -0
  57. package/src/theme/types/components/checkbox.ts +33 -0
  58. package/src/theme/types/components/chip.ts +30 -0
  59. package/src/theme/types/components/hightide.ts +42 -0
  60. package/src/theme/types/components/iconButton.ts +30 -0
  61. package/src/theme/types/components/index.ts +10 -0
  62. package/src/theme/types/components/input.ts +19 -0
  63. package/src/theme/types/components/menu.ts +57 -0
  64. package/src/theme/types/components/multiSelect.ts +47 -0
  65. package/src/theme/types/components/select.ts +47 -0
  66. package/src/theme/types/decoration.ts +11 -0
  67. package/src/theme/types/index.ts +4 -7
  68. package/src/theme/types/layout.ts +46 -0
  69. package/src/theme/types/resolver.ts +43 -1
  70. package/src/theme/types/theme.ts +14 -10
  71. package/src/theme/types/typography.ts +18 -0
  72. package/src/components/Button/Button.tsx +0 -101
  73. package/src/components/Button/index.ts +0 -1
  74. package/src/components/Checkbox/index.ts +0 -1
  75. package/src/components/IconButton/IconButton.tsx +0 -89
  76. package/src/components/IconButton/index.ts +0 -1
  77. package/src/components/Input/index.ts +0 -1
  78. package/src/components/MultiSelect/index.ts +0 -1
  79. package/src/components/Select/index.ts +0 -1
  80. package/src/icons/Icon.tsx +0 -35
  81. package/src/icons/index.ts +0 -1
  82. package/src/theme/types/button.ts +0 -41
  83. package/src/theme/types/checkbox.ts +0 -36
  84. package/src/theme/types/chip.ts +0 -41
  85. package/src/theme/types/components.ts +0 -17
  86. package/src/theme/types/iconButton.ts +0 -34
  87. package/src/theme/types/input.ts +0 -25
  88. package/src/theme/types/multiSelect.ts +0 -65
  89. package/src/theme/types/select.ts +0 -77
@@ -1,16 +1,26 @@
1
+ import type { ViewStyle } from 'react-native'
2
+
3
+ import { componentLayouts } from '@helpwave/hightide-design/tokens'
4
+ import type { HightideDesignTokens as DesignTokensTheme } from '@helpwave/hightide-design/types'
5
+
6
+ import {
7
+ isOutlineColoringStyle,
8
+ resolveColoringStyles
9
+ } from '@/src/theme/resolvers/coloring'
10
+ import type { HightideSemanticColors } from '@/src/theme/types/color'
11
+ import type { HightideComponentThemes } from '@/src/theme/types/components/hightide'
12
+ import type {
13
+ IconButtonState,
14
+ IconButtonTheme
15
+ } from '@/src/theme/types/components/iconButton'
1
16
  import {
2
- componentLayouts,
3
- toPx,
4
- type ColoringTokensDefinitions,
5
- type DesignTheme as DesignTokensTheme,
6
- type SemanticColors
7
- } from '@helpwave/hightide-design'
8
- import type { IconButtonState, IconButtonStyle, IconButtonTheme } from '../types'
9
- import { isOutlineColoringStyle, resolveColoringStyles } from './coloring'
17
+ createStyleResolver,
18
+ createValueResolver
19
+ } from '@/src/theme/types/resolver'
10
20
 
11
21
  export type CreateIconButtonThemeOptions = {
12
- semantic: SemanticColors,
13
- coloring: ColoringTokensDefinitions,
22
+ semantic: HightideSemanticColors,
23
+ coloring: HightideComponentThemes['coloring'],
14
24
  }
15
25
 
16
26
  export const createIconButtonTheme = ({
@@ -24,13 +34,13 @@ export const createIconButtonTheme = ({
24
34
  const tokens = coloring[color]
25
35
  const resolved = resolveColoringStyles(tokens, coloringStyle, semantic, state)
26
36
  const sizing = componentLayouts.element[size]
27
- const outlineWidth = toPx(componentLayouts.shared.coloringOutlineWidth)
28
- const dimension = toPx(sizing.height)
37
+ const outlineWidth = componentLayouts.shared.coloringOutlineWidth
38
+ const dimension = sizing.height
29
39
  const borderWidth = resolved.borderWidth > 0
30
40
  ? resolved.borderWidth
31
41
  : (isOutlineColoringStyle(coloringStyle) ? outlineWidth : 0)
32
42
 
33
- const button: IconButtonStyle = {
43
+ const button: ViewStyle = {
34
44
  alignItems: 'center',
35
45
  justifyContent: 'center',
36
46
  backgroundColor: resolved.backgroundColor,
@@ -38,7 +48,7 @@ export const createIconButtonTheme = ({
38
48
  borderWidth,
39
49
  width: dimension,
40
50
  height: dimension,
41
- borderRadius: toPx(componentLayouts.button[size].borderRadius),
51
+ borderRadius: componentLayouts.button[size].borderRadius,
42
52
  opacity: state.isDisabled ? 0.6 : 1,
43
53
  }
44
54
 
@@ -49,14 +59,14 @@ export const createIconButtonTheme = ({
49
59
  }
50
60
 
51
61
  return {
52
- button: (state) => resolveState(state).button,
53
- icon: (state) => resolveState(state).icon,
62
+ button: createStyleResolver((state) => resolveState(state).button),
63
+ icon: createValueResolver((state) => resolveState(state).icon),
54
64
  }
55
65
  }
56
66
 
57
67
  export const createIconButtonThemeFromDesign = (theme: DesignTokensTheme): IconButtonTheme => {
58
68
  return createIconButtonTheme({
59
- semantic: theme.semantic,
60
- coloring: theme.coloring,
69
+ semantic: theme.semanticColors,
70
+ coloring: theme.coloring as HightideComponentThemes['coloring'],
61
71
  })
62
72
  }
@@ -1,8 +1,10 @@
1
1
  export * from './button'
2
+ export * from './chat'
2
3
  export * from './checkbox'
3
4
  export * from './chip'
4
5
  export * from './coloring'
5
6
  export * from './iconButton'
6
7
  export * from './input'
8
+ export * from './menu'
7
9
  export * from './multiSelect'
8
10
  export * from './select'
@@ -1,30 +1,39 @@
1
+ import type { TextStyle } from 'react-native'
2
+
3
+ import { componentLayouts } from '@helpwave/hightide-design/tokens'
4
+ import type {
5
+ ComponentColorTokens,
6
+ HightideDesignTokens as DesignTokensTheme
7
+ } from '@helpwave/hightide-design/types'
8
+
9
+ import type { HightideSemanticColors } from '@/src/theme/types/color'
10
+ import type {
11
+ InputState,
12
+ InputTheme
13
+ } from '@/src/theme/types/components/input'
1
14
  import {
2
- inputElementSizes,
3
- remToPx,
4
- type ComponentColors,
5
- type DesignTheme as DesignTokensTheme,
6
- type SemanticColors
7
- } from '@helpwave/hightide-design'
8
- import type { InputState, InputStyle, InputTheme } from '../types'
15
+ createStyleResolver,
16
+ createValueResolver
17
+ } from '@/src/theme/types/resolver'
9
18
 
10
19
  export type CreateInputThemeOptions = {
11
- semantic: SemanticColors,
12
- component: ComponentColors,
20
+ semantic: HightideSemanticColors,
21
+ component: ComponentColorTokens,
13
22
  }
14
23
 
15
24
  export const createInputTheme = ({
16
25
  semantic,
17
26
  component,
18
27
  }: CreateInputThemeOptions): InputTheme => {
19
- const resolveInput = (state: InputState): InputStyle => {
20
- const sizing = inputElementSizes.md
28
+ const resolveInput = (state: InputState): TextStyle => {
29
+ const sizing = componentLayouts.input.md
21
30
  const borderColor = state.isInvalid ? semantic.negative : component.border
22
31
 
23
32
  return {
24
- minHeight: remToPx(sizing.height),
25
- paddingHorizontal: remToPx(sizing.paddingX),
26
- paddingVertical: remToPx(sizing.paddingY),
27
- borderRadius: remToPx(sizing.borderRadius),
33
+ minHeight: sizing.height,
34
+ paddingHorizontal: sizing.paddingX,
35
+ paddingVertical: sizing.paddingY,
36
+ borderRadius: sizing.borderRadius,
28
37
  borderWidth: 1,
29
38
  borderColor,
30
39
  backgroundColor: state.isDisabled ? semantic.disabled : component.input.background,
@@ -35,14 +44,14 @@ export const createInputTheme = ({
35
44
  }
36
45
 
37
46
  return {
38
- input: resolveInput,
39
- placeholderColor: () => semantic.placeholder,
47
+ input: createStyleResolver(resolveInput),
48
+ placeholderColor: createValueResolver(() => semantic.placeholder),
40
49
  }
41
50
  }
42
51
 
43
52
  export const createInputThemeFromDesign = (theme: DesignTokensTheme): InputTheme => {
44
53
  return createInputTheme({
45
- semantic: theme.semantic,
46
- component: theme.component,
54
+ semantic: theme.semanticColors,
55
+ component: theme.componentColors,
47
56
  })
48
57
  }
@@ -0,0 +1,120 @@
1
+ import { StyleSheet } from 'react-native'
2
+
3
+ import { fontWeights } from '@helpwave/hightide-design/tokens'
4
+ import type {
5
+ ComponentColorTokens,
6
+ HightideDesignTokens as DesignTokensTheme
7
+ } from '@helpwave/hightide-design/types'
8
+
9
+ import type { HightideSemanticColors } from '@/src/theme/types/color'
10
+ import type {
11
+ MenuActionItemState,
12
+ MenuTheme
13
+ } from '@/src/theme/types/components/menu'
14
+ import {
15
+ createStyleResolver,
16
+ createValueResolver
17
+ } from '@/src/theme/types/resolver'
18
+
19
+ export type CreateMenuThemeOptions = {
20
+ semantic: HightideSemanticColors,
21
+ component: ComponentColorTokens,
22
+ }
23
+
24
+ export const createMenuTheme = ({
25
+ semantic,
26
+ component,
27
+ }: CreateMenuThemeOptions): MenuTheme => {
28
+ const resolveActionItem = (state: MenuActionItemState) => {
29
+ const pressed = !!state.isPressed && !state.isDisabled
30
+
31
+ return {
32
+ flexDirection: 'row' as const,
33
+ alignItems: 'center' as const,
34
+ minHeight: 64,
35
+ gap: 12,
36
+ paddingHorizontal: 16,
37
+ paddingVertical: 8,
38
+ borderBottomWidth: StyleSheet.hairlineWidth,
39
+ borderBottomColor: component.divider,
40
+ backgroundColor: pressed ? semantic.surfaceHover : ('transparent' as const),
41
+ opacity: state.isDisabled ? 0.6 : 1,
42
+ }
43
+ }
44
+
45
+ const resolveItemContent = () => ({
46
+ flex: 1,
47
+ gap: 4,
48
+ justifyContent: 'center' as const,
49
+ })
50
+
51
+ const resolveActionLabel = (state: MenuActionItemState) => ({
52
+ color: state.isDanger ? semantic.negative : semantic.onSurface,
53
+ fontSize: 15,
54
+ fontWeight: fontWeights.medium,
55
+ })
56
+
57
+ const resolveActionIcon = (state: MenuActionItemState) => ({
58
+ color: state.isDanger ? semantic.negative : semantic.primary,
59
+ })
60
+
61
+ return {
62
+ section: createStyleResolver(() => ({
63
+ marginBottom: 20,
64
+ gap: 8,
65
+ })),
66
+ sectionTitle: createStyleResolver(() => ({
67
+ color: semantic.description,
68
+ fontSize: 12,
69
+ fontWeight: fontWeights.bold,
70
+ letterSpacing: 0.4,
71
+ textTransform: 'uppercase',
72
+ paddingHorizontal: 4,
73
+ })),
74
+ card: createStyleResolver(() => ({
75
+ backgroundColor: semantic.surface,
76
+ borderRadius: 12,
77
+ borderWidth: 1,
78
+ borderColor: component.border,
79
+ overflow: 'hidden',
80
+ })),
81
+ item: createStyleResolver(() => ({
82
+ flexDirection: 'row' as const,
83
+ alignItems: 'center' as const,
84
+ minHeight: 64,
85
+ paddingHorizontal: 16,
86
+ paddingVertical: 8,
87
+ borderBottomWidth: StyleSheet.hairlineWidth,
88
+ borderBottomColor: component.divider,
89
+ gap: 12,
90
+ })),
91
+ itemContent: createStyleResolver(resolveItemContent),
92
+ itemLabel: createStyleResolver(() => ({
93
+ color: semantic.description,
94
+ fontSize: 12,
95
+ })),
96
+ itemValue: createStyleResolver(() => ({
97
+ color: semantic.onSurface,
98
+ fontSize: 15,
99
+ fontWeight: fontWeights.medium,
100
+ })),
101
+ actionItem: createStyleResolver(resolveActionItem),
102
+ actionItemContent: createStyleResolver(resolveItemContent),
103
+ actionItemLabel: createStyleResolver(resolveActionLabel),
104
+ actionItemIcon: createValueResolver(resolveActionIcon),
105
+ navigationItem: createStyleResolver(resolveActionItem),
106
+ navigationItemContent: createStyleResolver(resolveItemContent),
107
+ navigationItemLabel: createStyleResolver(resolveActionLabel),
108
+ navigationItemIcon: createValueResolver(resolveActionIcon),
109
+ navigationItemTrailing: createValueResolver(() => ({
110
+ color: semantic.description,
111
+ })),
112
+ }
113
+ }
114
+
115
+ export const createMenuThemeFromDesign = (theme: DesignTokensTheme): MenuTheme => {
116
+ return createMenuTheme({
117
+ semantic: theme.semanticColors,
118
+ component: theme.componentColors,
119
+ })
120
+ }
@@ -1,18 +1,23 @@
1
- import {
2
- remToPx,
3
- type ComponentColors,
4
- type DesignTheme as DesignTokensTheme,
5
- type SemanticColors
6
- } from '@helpwave/hightide-design'
1
+ import { fontWeights } from '@helpwave/hightide-design/tokens'
2
+ import type {
3
+ ComponentColorTokens,
4
+ HightideDesignTokens as DesignTokensTheme
5
+ } from '@helpwave/hightide-design/types'
6
+
7
+ import type { HightideSemanticColors } from '@/src/theme/types/color'
7
8
  import type {
8
9
  MultiSelectOptionState,
9
10
  MultiSelectState,
10
11
  MultiSelectTheme
11
- } from '../types'
12
+ } from '@/src/theme/types/components/multiSelect'
13
+ import {
14
+ createStyleResolver,
15
+ createValueResolver
16
+ } from '@/src/theme/types/resolver'
12
17
 
13
18
  export type CreateMultiSelectThemeOptions = {
14
- semantic: SemanticColors,
15
- component: ComponentColors,
19
+ semantic: HightideSemanticColors,
20
+ component: ComponentColorTokens,
16
21
  }
17
22
 
18
23
  export const createMultiSelectTheme = ({
@@ -20,44 +25,44 @@ export const createMultiSelectTheme = ({
20
25
  component,
21
26
  }: CreateMultiSelectThemeOptions): MultiSelectTheme => {
22
27
  return {
23
- trigger: (state: MultiSelectState) => ({
28
+ trigger: createStyleResolver((state: MultiSelectState) => ({
24
29
  minHeight: 44,
25
- paddingHorizontal: remToPx('0.75rem'),
26
- paddingVertical: remToPx('0.5rem'),
27
- borderRadius: remToPx('0.375rem'),
30
+ paddingHorizontal: 12,
31
+ paddingVertical: 8,
32
+ borderRadius: 6,
28
33
  borderWidth: 1,
29
34
  borderColor: state.isInvalid ? semantic.negative : component.border,
30
35
  backgroundColor: state.isDisabled ? semantic.disabled : component.input.background,
31
36
  justifyContent: 'center',
32
37
  gap: 8,
33
38
  opacity: state.isDisabled ? 0.6 : 1,
34
- }),
35
- triggerText: () => ({
39
+ })),
40
+ triggerText: createStyleResolver(() => ({
36
41
  color: semantic.placeholder,
37
- }),
38
- overlay: () => ({
42
+ })),
43
+ overlay: createStyleResolver(() => ({
39
44
  flex: 1,
40
45
  backgroundColor: '#00000059',
41
46
  justifyContent: 'center',
42
47
  padding: 24,
43
- }),
44
- menu: () => ({
48
+ })),
49
+ menu: createStyleResolver(() => ({
45
50
  maxHeight: 360,
46
51
  borderRadius: 12,
47
52
  backgroundColor: component.menu.background,
48
53
  borderWidth: 1,
49
54
  borderColor: component.menu.border,
50
55
  overflow: 'hidden',
51
- }),
52
- search: () => ({
56
+ })),
57
+ search: createStyleResolver(() => ({
53
58
  paddingHorizontal: 16,
54
59
  paddingVertical: 12,
55
60
  borderBottomWidth: 1,
56
61
  borderBottomColor: component.menu.border,
57
62
  color: component.menu.text,
58
- }),
59
- searchPlaceholderColor: () => semantic.placeholder,
60
- option: (state: MultiSelectOptionState) => ({
63
+ })),
64
+ searchPlaceholderColor: createValueResolver(() => semantic.placeholder),
65
+ option: createStyleResolver((state: MultiSelectOptionState) => ({
61
66
  paddingHorizontal: 16,
62
67
  paddingVertical: 12,
63
68
  backgroundColor: state.isHighlighted ? component.table.rowHoverBackground : 'transparent',
@@ -65,12 +70,12 @@ export const createMultiSelectTheme = ({
65
70
  flexDirection: 'row',
66
71
  alignItems: 'center',
67
72
  gap: 10,
68
- }),
69
- optionText: (state: MultiSelectOptionState) => ({
73
+ })),
74
+ optionText: createStyleResolver((state: MultiSelectOptionState) => ({
70
75
  color: state.isSelected ? semantic.primary : component.menu.text,
71
- fontWeight: state.isSelected ? '600' : '400',
72
- }),
73
- checkbox: (state: MultiSelectOptionState) => ({
76
+ fontWeight: state.isSelected ? fontWeights.semibold : fontWeights.base,
77
+ })),
78
+ checkbox: createStyleResolver((state: MultiSelectOptionState) => ({
74
79
  width: 18,
75
80
  height: 18,
76
81
  borderRadius: 4,
@@ -79,17 +84,17 @@ export const createMultiSelectTheme = ({
79
84
  backgroundColor: state.isSelected ? semantic.primary : 'transparent',
80
85
  alignItems: 'center',
81
86
  justifyContent: 'center',
82
- }),
83
- checkboxIcon: (state: MultiSelectOptionState) => ({
87
+ })),
88
+ checkboxIcon: createValueResolver((state: MultiSelectOptionState) => ({
84
89
  color: semantic.onPrimary,
85
90
  visible: !!state.isSelected,
86
- }),
91
+ })),
87
92
  }
88
93
  }
89
94
 
90
95
  export const createMultiSelectThemeFromDesign = (theme: DesignTokensTheme): MultiSelectTheme => {
91
96
  return createMultiSelectTheme({
92
- semantic: theme.semantic,
93
- component: theme.component,
97
+ semantic: theme.semanticColors,
98
+ component: theme.componentColors,
94
99
  })
95
100
  }
@@ -1,18 +1,23 @@
1
- import {
2
- remToPx,
3
- type ComponentColors,
4
- type DesignTheme as DesignTokensTheme,
5
- type SemanticColors
6
- } from '@helpwave/hightide-design'
1
+ import { fontWeights } from '@helpwave/hightide-design/tokens'
2
+ import type {
3
+ ComponentColorTokens,
4
+ HightideDesignTokens as DesignTokensTheme
5
+ } from '@helpwave/hightide-design/types'
6
+
7
+ import type { HightideSemanticColors } from '@/src/theme/types/color'
7
8
  import type {
8
9
  SelectOptionState,
9
10
  SelectState,
10
11
  SelectTheme
11
- } from '../types'
12
+ } from '@/src/theme/types/components/select'
13
+ import {
14
+ createStyleResolver,
15
+ createValueResolver
16
+ } from '@/src/theme/types/resolver'
12
17
 
13
18
  export type CreateSelectThemeOptions = {
14
- semantic: SemanticColors,
15
- component: ComponentColors,
19
+ semantic: HightideSemanticColors,
20
+ component: ComponentColorTokens,
16
21
  }
17
22
 
18
23
  export const createSelectTheme = ({
@@ -20,58 +25,58 @@ export const createSelectTheme = ({
20
25
  component,
21
26
  }: CreateSelectThemeOptions): SelectTheme => {
22
27
  return {
23
- trigger: (state: SelectState) => ({
28
+ trigger: createStyleResolver((state: SelectState) => ({
24
29
  minHeight: 44,
25
- paddingHorizontal: remToPx('0.75rem'),
26
- paddingVertical: remToPx('0.5rem'),
27
- borderRadius: remToPx('0.375rem'),
30
+ paddingHorizontal: 12,
31
+ paddingVertical: 8,
32
+ borderRadius: 6,
28
33
  borderWidth: 1,
29
34
  borderColor: state.isInvalid ? semantic.negative : component.border,
30
35
  backgroundColor: state.isDisabled ? semantic.disabled : component.input.background,
31
36
  justifyContent: 'center',
32
37
  opacity: state.isDisabled ? 0.6 : 1,
33
- }),
34
- triggerText: (state: SelectState) => ({
38
+ })),
39
+ triggerText: createStyleResolver((state: SelectState) => ({
35
40
  color: state.hasValue ? component.input.text : semantic.placeholder,
36
- }),
37
- overlay: () => ({
41
+ })),
42
+ overlay: createStyleResolver(() => ({
38
43
  flex: 1,
39
44
  backgroundColor: '#00000059',
40
45
  justifyContent: 'center',
41
46
  padding: 24,
42
- }),
43
- menu: () => ({
47
+ })),
48
+ menu: createStyleResolver(() => ({
44
49
  maxHeight: 360,
45
50
  borderRadius: 12,
46
51
  backgroundColor: component.menu.background,
47
52
  borderWidth: 1,
48
53
  borderColor: component.menu.border,
49
54
  overflow: 'hidden',
50
- }),
51
- search: () => ({
55
+ })),
56
+ search: createStyleResolver(() => ({
52
57
  paddingHorizontal: 16,
53
58
  paddingVertical: 12,
54
59
  borderBottomWidth: 1,
55
60
  borderBottomColor: component.menu.border,
56
61
  color: component.menu.text,
57
- }),
58
- searchPlaceholderColor: () => semantic.placeholder,
59
- option: (state: SelectOptionState) => ({
62
+ })),
63
+ searchPlaceholderColor: createValueResolver(() => semantic.placeholder),
64
+ option: createStyleResolver((state: SelectOptionState) => ({
60
65
  paddingHorizontal: 16,
61
66
  paddingVertical: 12,
62
67
  backgroundColor: state.isHighlighted ? component.table.rowHoverBackground : 'transparent',
63
68
  opacity: state.isDisabled ? 0.5 : 1,
64
- }),
65
- optionText: (state: SelectOptionState) => ({
69
+ })),
70
+ optionText: createStyleResolver((state: SelectOptionState) => ({
66
71
  color: state.isSelected ? semantic.primary : component.menu.text,
67
- fontWeight: state.isSelected ? '600' : '400',
68
- }),
72
+ fontWeight: state.isSelected ? fontWeights.semibold : fontWeights.base,
73
+ })),
69
74
  }
70
75
  }
71
76
 
72
77
  export const createSelectThemeFromDesign = (theme: DesignTokensTheme): SelectTheme => {
73
78
  return createSelectTheme({
74
- semantic: theme.semantic,
75
- component: theme.component,
79
+ semantic: theme.semanticColors,
80
+ component: theme.componentColors,
76
81
  })
77
82
  }
@@ -1,20 +1,47 @@
1
- import type { DesignTheme as DesignTokensTheme } from '@helpwave/hightide-design'
2
- import {
3
- createButtonThemeFromDesign,
4
- createCheckboxThemeFromDesign,
5
- createChipThemeFromDesign,
6
- createIconButtonThemeFromDesign,
7
- createInputThemeFromDesign,
8
- createMultiSelectThemeFromDesign,
9
- createSelectThemeFromDesign
10
- } from '../resolvers'
11
- import type { DesignTheme } from '../types'
1
+ import type {
2
+ ColorPaletteToken,
3
+ HightideDesignTokens
4
+ } from '@helpwave/hightide-design/types'
12
5
 
13
- export const createDesignTheme = (tokens: DesignTokensTheme): DesignTheme => ({
14
- palettes: tokens.palettes,
15
- semantic: tokens.semantic,
16
- coloring: tokens.coloring,
6
+ import { createButtonThemeFromDesign } from '@/src/theme/resolvers/button'
7
+ import { createChatThemeFromDesign } from '@/src/theme/resolvers/chat'
8
+ import { createCheckboxThemeFromDesign } from '@/src/theme/resolvers/checkbox'
9
+ import { createChipThemeFromDesign } from '@/src/theme/resolvers/chip'
10
+ import { createIconButtonThemeFromDesign } from '@/src/theme/resolvers/iconButton'
11
+ import { createInputThemeFromDesign } from '@/src/theme/resolvers/input'
12
+ import { createMenuThemeFromDesign } from '@/src/theme/resolvers/menu'
13
+ import { createMultiSelectThemeFromDesign } from '@/src/theme/resolvers/multiSelect'
14
+ import { createSelectThemeFromDesign } from '@/src/theme/resolvers/select'
15
+ import type {
16
+ Color,
17
+ ColorPalette,
18
+ HightideColors
19
+ } from '@/src/theme/types/color'
20
+ import type { Theme } from '@/src/theme/types/theme'
21
+
22
+ const unwrapColorPaletteToken = (token: ColorPaletteToken): Color | ColorPalette => {
23
+ if (token.type === 'singleValue') {
24
+ return token.value
25
+ }
26
+ return token.value
27
+ }
28
+
29
+ const unwrapColors = (colors: HightideDesignTokens['colors']): HightideColors & Record<string, Color | ColorPalette> => {
30
+ const result: Record<string, Color | ColorPalette> = {}
31
+ for (const [key, token] of Object.entries(colors)) {
32
+ result[key] = unwrapColorPaletteToken(token)
33
+ }
34
+ return result as HightideColors & Record<string, Color | ColorPalette>
35
+ }
36
+
37
+ export const createTheme = (tokens: HightideDesignTokens): Theme => ({
38
+ colors: unwrapColors(tokens.colors),
39
+ semantic: tokens.semanticColors,
40
+ typography: tokens.typography,
41
+ layout: tokens.layout,
42
+ decoration: tokens.decorcation,
17
43
  components: {
44
+ coloring: tokens.coloring,
18
45
  button: createButtonThemeFromDesign(tokens),
19
46
  iconButton: createIconButtonThemeFromDesign(tokens),
20
47
  chip: createChipThemeFromDesign(tokens),
@@ -22,5 +49,7 @@ export const createDesignTheme = (tokens: DesignTokensTheme): DesignTheme => ({
22
49
  input: createInputThemeFromDesign(tokens),
23
50
  select: createSelectThemeFromDesign(tokens),
24
51
  multiSelect: createMultiSelectThemeFromDesign(tokens),
52
+ chat: createChatThemeFromDesign(tokens),
53
+ menu: createMenuThemeFromDesign(tokens),
25
54
  },
26
55
  })
@@ -1,15 +1,16 @@
1
- import { themes as designThemes } from '@helpwave/hightide-design'
2
- import { createDesignTheme } from './createTheme'
1
+ import { Themes as designThemes } from '@helpwave/hightide-design/tokens'
3
2
 
4
- export const lightTheme = createDesignTheme(designThemes.light)
3
+ import { createTheme } from '@/src/theme/themes/createTheme'
5
4
 
6
- export const darkTheme = createDesignTheme(designThemes.dark)
5
+ export const lightTheme = createTheme(designThemes.light)
6
+
7
+ export const darkTheme = createTheme(designThemes.dark)
7
8
 
8
9
  export const themes = {
9
10
  light: lightTheme,
10
11
  dark: darkTheme,
11
12
  } as const
12
13
 
13
- export type ThemeMode = keyof typeof themes
14
+ export type HightideThemeModes = 'dark' | 'light'
14
15
 
15
- export const getTheme = (mode: ThemeMode) => themes[mode]
16
+ export type ThemeMode = string | HightideThemeModes