@helpwave/hightide-native 0.0.7 → 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 +207 -0
  29. package/src/components/user-interaction/ThemedPressable.tsx +136 -0
  30. package/src/components/user-interaction/index.ts +3 -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 +8 -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 +71 -0
  81. package/src/theme/resolvers/themedPressable.ts +54 -0
  82. package/src/theme/themes/createHightideTheme.ts +214 -49
  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 -40
  93. package/src/theme/types/components/iconButton.ts +19 -14
  94. package/src/theme/types/components/index.ts +6 -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 +22 -0
  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
@@ -1,3 +1,4 @@
1
1
  export * from './Avatar'
2
2
  export * from './Chip'
3
- export * from './Icon'
3
+ export * from './ThemedIcon'
4
+ export * from './ThemedText'
@@ -8,6 +8,10 @@ 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'
11
15
  import {
12
16
  LocalizationProvider,
13
17
  type LocalizationProviderProps
@@ -21,11 +25,13 @@ import {
21
25
  TranslationProvider,
22
26
  type TranslationProviderProps
23
27
  } from './translation/forward-exports'
28
+ import type { HightideTheme } from '../theme'
24
29
 
25
30
  export type HightideProviderProps = PropsWithChildren & {
26
- theme?: Omit<ThemeProviderProps, 'children'>,
31
+ theme?: Omit<ThemeProviderProps<HightideTheme>, 'children'>,
27
32
  locale?: Omit<LocalizationProviderProps, 'children'>,
28
33
  translation?: Omit<TranslationProviderProps, 'children' | 'locale'>,
34
+ debug?: Omit<DebugProviderProps, 'children'>,
29
35
  }
30
36
 
31
37
  const HightideContextBridge = ({ children }: PropsWithChildren) => {
@@ -49,6 +55,7 @@ export const HightideProvider = ({
49
55
  theme,
50
56
  locale,
51
57
  translation,
58
+ debug,
52
59
  }: HightideProviderProps) => {
53
60
  const resolvedTranslations = useMemo(() => [
54
61
  ...ArrayUtil.resolveSingleOrArray(translation?.translation ?? []),
@@ -56,14 +63,16 @@ export const HightideProvider = ({
56
63
  ], [translation?.translation])
57
64
 
58
65
  return (
59
- <LocalizationProvider {...locale}>
60
- <TranslationProvider {...translation} translation={resolvedTranslations}>
61
- <ThemeProvider {...theme}>
62
- <HightideContextBridge>
63
- {children}
64
- </HightideContextBridge>
65
- </ThemeProvider>
66
- </TranslationProvider>
67
- </LocalizationProvider>
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>
68
77
  )
69
78
  }
@@ -0,0 +1,22 @@
1
+ import {
2
+ createContext,
3
+ useContext
4
+ } from 'react'
5
+ import type { ColorValue, TextStyle } from 'react-native'
6
+
7
+ export type ContentThemeContextValue = {
8
+ foregroundColor: ColorValue,
9
+ textStyle: TextStyle,
10
+ }
11
+
12
+ export const ContentThemeContext = createContext<ContentThemeContextValue | null>(null)
13
+
14
+ export const useContentTheme = (): ContentThemeContextValue => {
15
+ const context = useContext(ContentThemeContext)
16
+ if (!context) {
17
+ throw new Error(
18
+ 'useContentTheme must be used within ContentThemeProvider. Try adding a ContentThemeProvider around your app.'
19
+ )
20
+ }
21
+ return context
22
+ }
@@ -0,0 +1,32 @@
1
+ import {
2
+ useMemo,
3
+ type PropsWithChildren
4
+ } from 'react'
5
+ import type { TextStyle, ColorValue } from 'react-native'
6
+
7
+ import {
8
+ ContentThemeContext,
9
+ type ContentThemeContextValue
10
+ } from './ContentThemeContext'
11
+
12
+ export type ContentThemeProviderProps = PropsWithChildren & {
13
+ foregroundColor: ColorValue,
14
+ textStyle: TextStyle,
15
+ }
16
+
17
+ export const ContentThemeProvider = ({
18
+ children,
19
+ foregroundColor,
20
+ textStyle,
21
+ }: ContentThemeProviderProps) => {
22
+ const value = useMemo((): ContentThemeContextValue => ({
23
+ foregroundColor,
24
+ textStyle,
25
+ }), [foregroundColor, textStyle])
26
+
27
+ return (
28
+ <ContentThemeContext.Provider value={value}>
29
+ {children}
30
+ </ContentThemeContext.Provider>
31
+ )
32
+ }
@@ -0,0 +1,2 @@
1
+ export * from './ContentThemeContext'
2
+ export * from './ContentThemeProvider'
@@ -0,0 +1,10 @@
1
+ export {
2
+ DebugContext,
3
+ DebugProvider,
4
+ useDebugContext,
5
+ DEFAULT_HIT_BOX_COLOR,
6
+ defaultDebugContextValue,
7
+ type DebugContextValue,
8
+ type DebugHitBox,
9
+ type DebugProviderProps,
10
+ } from '@helpwave/hightide-utils/context/debug'
@@ -0,0 +1 @@
1
+ export * from './forward-exports'
@@ -1,5 +1,7 @@
1
1
  export * from './HightideContext'
2
2
  export * from './HightideProvider'
3
+ export * from './content-theme'
4
+ export * from './debug'
3
5
  export * from './hightide-config'
4
6
  export * from './localization'
5
7
  export * from './theme'
@@ -21,6 +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
25
 
25
26
  export type ThemeProviderProps<T> = PropsWithChildren & {
26
27
  theme?: ThemeMode | null,
@@ -92,7 +93,12 @@ export const ThemeProvider = ({
92
93
 
93
94
  return (
94
95
  <ThemeContext.Provider value={contextValue}>
95
- {children}
96
+ <ContentThemeProvider
97
+ foregroundColor={contextValue.theme.colors.surface.onColor}
98
+ textStyle={contextValue.theme.typography.body.md}
99
+ >
100
+ {children}
101
+ </ContentThemeProvider>
96
102
  </ThemeContext.Provider>
97
103
  )
98
104
  }
@@ -0,0 +1,33 @@
1
+ import {
2
+ Check,
3
+ CheckCheck,
4
+ ChevronDown,
5
+ ChevronRight,
6
+ Download,
7
+ FileText,
8
+ Minus,
9
+ Plus,
10
+ Search,
11
+ SendHorizontal,
12
+ User,
13
+ X
14
+ } from 'lucide-react-native'
15
+
16
+ import type { IconComponent } from './types'
17
+
18
+ export const HightideIconRegistry = {
19
+ Check: Check,
20
+ CheckCheck: CheckCheck,
21
+ ChevronDown: ChevronDown,
22
+ ChevronRight: ChevronRight,
23
+ Download: Download,
24
+ FileText: FileText,
25
+ Minus: Minus,
26
+ Plus: Plus,
27
+ Search: Search,
28
+ SendHorizontal: SendHorizontal,
29
+ User: User,
30
+ X: X,
31
+ } as const satisfies Record<string, IconComponent>
32
+
33
+ export type HightideIconName = keyof typeof HightideIconRegistry
@@ -0,0 +1,2 @@
1
+ export * from './HightideIconRegistry'
2
+ export * from './types'
@@ -0,0 +1,11 @@
1
+ import type { ComponentType } from 'react'
2
+
3
+ export type IconStyle = {
4
+ size?: number,
5
+ color?: string,
6
+ strokeWidth?: number,
7
+ }
8
+
9
+ export type IconComponentProps = IconStyle
10
+
11
+ export type IconComponent = ComponentType<IconComponentProps>
@@ -0,0 +1,323 @@
1
+ import type { ViewStyle } from 'react-native'
2
+
3
+ import type {
4
+ AlignSelfToken,
5
+ AxisAligmentToken,
6
+ BorderRadiusToken,
7
+ BorderToken,
8
+ ContainerTokens,
9
+ DirectionalToken,
10
+ LayoutDirectionToken,
11
+ MarginToken,
12
+ PaddingToken
13
+ } from '@helpwave/hightide-design/component-token-resolvers'
14
+ import {
15
+ defaultWritingMode,
16
+ resolveDirectionalTokens
17
+ } from '@helpwave/hightide-design/component-token-resolvers'
18
+ import type { ColorToken, HexColorToken } from '@helpwave/hightide-design/primitive-tokens'
19
+ import type { ShadowToken } from '@helpwave/hightide-design/theme-tokens'
20
+ import { HexColorUtils } from '@helpwave/hightide-design/utils'
21
+
22
+ import { defined } from './defined'
23
+
24
+ export const toShadowStyle = (shadow: ShadowToken): ViewStyle => defined({
25
+ boxShadow: [{
26
+ color: shadow.color,
27
+ offsetX: shadow.x,
28
+ offsetY: shadow.y,
29
+ blurRadius: shadow.blur,
30
+ spreadDistance: shadow.spread,
31
+ }],
32
+ })
33
+
34
+ const toFlexDirection = (
35
+ direction?: LayoutDirectionToken
36
+ ): ViewStyle['flexDirection'] => {
37
+ if (direction === undefined) {
38
+ return undefined
39
+ }
40
+
41
+ return direction === 'horizontal' ? 'row' : 'column'
42
+ }
43
+
44
+ const toJustifyContent = (
45
+ alignment?: AxisAligmentToken
46
+ ): ViewStyle['justifyContent'] => {
47
+ if (alignment === undefined) {
48
+ return undefined
49
+ }
50
+
51
+ if (alignment === 'start') {
52
+ return 'flex-start'
53
+ }
54
+
55
+ if (alignment === 'end') {
56
+ return 'flex-end'
57
+ }
58
+
59
+ return 'center'
60
+ }
61
+
62
+ const toAlignItems = (
63
+ alignment?: AxisAligmentToken
64
+ ): ViewStyle['alignItems'] => {
65
+ if (alignment === undefined) {
66
+ return undefined
67
+ }
68
+
69
+ if (alignment === 'start') {
70
+ return 'flex-start'
71
+ }
72
+
73
+ if (alignment === 'end') {
74
+ return 'flex-end'
75
+ }
76
+
77
+ return 'center'
78
+ }
79
+
80
+ const toAlignSelf = (
81
+ alignment?: AlignSelfToken
82
+ ): ViewStyle['alignSelf'] => {
83
+ if (alignment === undefined) {
84
+ return undefined
85
+ }
86
+
87
+ if (alignment === 'start') {
88
+ return 'flex-start'
89
+ }
90
+
91
+ if (alignment === 'end') {
92
+ return 'flex-end'
93
+ }
94
+
95
+ return alignment
96
+ }
97
+
98
+ const toAlignContent = (
99
+ alignment?: AlignSelfToken
100
+ ): ViewStyle['alignContent'] => {
101
+ if (alignment === undefined) {
102
+ return undefined
103
+ }
104
+
105
+ if (alignment === 'start') {
106
+ return 'flex-start'
107
+ }
108
+
109
+ if (alignment === 'end') {
110
+ return 'flex-end'
111
+ }
112
+
113
+ return alignment
114
+ }
115
+
116
+ const toBorderRadiusStyle = (
117
+ borderRadius?: BorderRadiusToken
118
+ ): ViewStyle => {
119
+ if (borderRadius === undefined) {
120
+ return {}
121
+ }
122
+
123
+ if (borderRadius.type === 'all') {
124
+ return defined({ borderRadius: borderRadius.value })
125
+ }
126
+
127
+ return defined({
128
+ borderTopLeftRadius: borderRadius.topLeft,
129
+ borderTopRightRadius: borderRadius.topRight,
130
+ borderBottomLeftRadius: borderRadius.bottomLeft,
131
+ borderBottomRightRadius: borderRadius.bottomRight,
132
+ })
133
+ }
134
+
135
+ const toDirectionalBorderWidths = (
136
+ width?: DirectionalToken<number>
137
+ ): ViewStyle => {
138
+ if (width === undefined) {
139
+ return {}
140
+ }
141
+
142
+ switch (width.type) {
143
+ case 'all':
144
+ return defined({
145
+ borderWidth: width.value,
146
+ })
147
+ case 'physicalAxis':
148
+ return defined({
149
+ borderTopWidth: width.vertical,
150
+ borderBottomWidth: width.vertical,
151
+ borderLeftWidth: width.horizontal,
152
+ borderRightWidth: width.horizontal,
153
+ })
154
+ case 'physicalSide':
155
+ return defined({
156
+ borderTopWidth: width.top,
157
+ borderRightWidth: width.right,
158
+ borderBottomWidth: width.bottom,
159
+ borderLeftWidth: width.left,
160
+ })
161
+ case 'logicalAxis':
162
+ return defined({
163
+ borderTopWidth: width.block,
164
+ borderBottomWidth: width.block,
165
+ borderStartWidth: width.inline,
166
+ borderEndWidth: width.inline,
167
+ })
168
+ case 'logicalSide':
169
+ return defined({
170
+ borderStartWidth: width.inlineStart,
171
+ borderEndWidth: width.inlineEnd,
172
+ borderTopWidth: width.blockStart,
173
+ borderBottomWidth: width.blockEnd,
174
+ })
175
+ }
176
+ }
177
+
178
+ const toDirectionalBorderColors = (
179
+ color?: NonNullable<BorderToken['color']>
180
+ ): ViewStyle => {
181
+ if (color === undefined) {
182
+ return {}
183
+ }
184
+
185
+ switch (color.type) {
186
+ case 'all':
187
+ return defined({
188
+ borderColor: color.value,
189
+ })
190
+ case 'physicalAxis':
191
+ return defined({
192
+ borderTopColor: color.vertical,
193
+ borderBottomColor: color.vertical,
194
+ borderLeftColor: color.horizontal,
195
+ borderRightColor: color.horizontal,
196
+ })
197
+ case 'physicalSide':
198
+ return defined({
199
+ borderTopColor: color.top,
200
+ borderRightColor: color.right,
201
+ borderBottomColor: color.bottom,
202
+ borderLeftColor: color.left,
203
+ })
204
+ case 'logicalAxis':
205
+ return defined({
206
+ borderTopColor: color.block,
207
+ borderBottomColor: color.block,
208
+ borderStartColor: color.inline,
209
+ borderEndColor: color.inline,
210
+ })
211
+ case 'logicalSide':
212
+ return defined({
213
+ borderStartColor: color.inlineStart,
214
+ borderEndColor: color.inlineEnd,
215
+ borderTopColor: color.blockStart,
216
+ borderBottomColor: color.blockEnd,
217
+ })
218
+ }
219
+ }
220
+
221
+ const toBorderStyle = (border?: BorderToken): ViewStyle => {
222
+ if (border === undefined) {
223
+ return {}
224
+ }
225
+
226
+ return defined({
227
+ ...toDirectionalBorderWidths(border.width),
228
+ ...toDirectionalBorderColors(border.color),
229
+ borderStyle: border.style,
230
+ })
231
+ }
232
+
233
+ const toPaddingStyle = (padding?: PaddingToken): ViewStyle => {
234
+ if (padding === undefined) {
235
+ return {}
236
+ }
237
+
238
+ const sides = resolveDirectionalTokens([padding], defaultWritingMode)
239
+
240
+ return defined({
241
+ paddingTop: sides.top,
242
+ paddingRight: sides.right,
243
+ paddingBottom: sides.bottom,
244
+ paddingLeft: sides.left,
245
+ })
246
+ }
247
+
248
+ const toMarginStyle = (margin?: MarginToken): ViewStyle => {
249
+ if (margin === undefined) {
250
+ return {}
251
+ }
252
+
253
+ const sides = resolveDirectionalTokens([margin], defaultWritingMode)
254
+
255
+ return defined({
256
+ marginTop: sides.top,
257
+ marginRight: sides.right,
258
+ marginBottom: sides.bottom,
259
+ marginLeft: sides.left,
260
+ })
261
+ }
262
+
263
+ export const toContainerStyle = (tokens: ContainerTokens): ViewStyle => defined({
264
+ display: 'flex',
265
+ overflow: tokens.overflow,
266
+ flexWrap: tokens.layout?.flexWrap,
267
+ flexDirection: toFlexDirection(tokens.layout?.direction),
268
+ justifyContent: toJustifyContent(tokens.layout?.mainAxisAlignment),
269
+ alignItems: toAlignItems(tokens.layout?.crossAxisAligment),
270
+ alignContent: toAlignContent(tokens.layout?.alignContent),
271
+ alignSelf: toAlignSelf(tokens.layout?.alignSelf),
272
+ backgroundColor: tokens.backgroundColor,
273
+ opacity: tokens.opacity,
274
+ ...toBorderStyle(tokens.border),
275
+ height: tokens.size?.height,
276
+ width: tokens.size?.width,
277
+ minHeight: tokens.size?.minHeight,
278
+ minWidth: tokens.size?.minWidth,
279
+ maxHeight: tokens.size?.maxHeight,
280
+ maxWidth: tokens.size?.maxWidth,
281
+ ...toBorderRadiusStyle(tokens.shape?.borderRadius),
282
+ ...toPaddingStyle(tokens.padding),
283
+ ...toMarginStyle(tokens.margin),
284
+ gap: tokens.layout?.gap,
285
+ outlineColor: tokens.outline?.color,
286
+ outlineOffset: tokens.outline?.offset,
287
+ outlineWidth: tokens.outline?.width,
288
+ outlineStyle: tokens.outline?.style,
289
+ ...(tokens.decoration?.shadow ? toShadowStyle(tokens.decoration.shadow) : {}),
290
+ })
291
+
292
+ const blendWithStateLayer = (
293
+ base: ColorToken | undefined,
294
+ tint: ColorToken
295
+ ): ColorToken | undefined => {
296
+ if (base === undefined || tint === 'transparent' || base === 'transparent') {
297
+ return base
298
+ }
299
+
300
+ return HexColorUtils.blend(base as HexColorToken, tint as HexColorToken)
301
+ }
302
+
303
+ export const toContainerStyleWithStateLayer = (
304
+ container: ContainerTokens,
305
+ stateLayer?: ContainerTokens
306
+ ): ViewStyle => {
307
+ const tint = stateLayer?.backgroundColor ?? 'transparent'
308
+ const borderColor = container.border?.color
309
+
310
+ return toContainerStyle({
311
+ ...container,
312
+ backgroundColor: blendWithStateLayer(container.backgroundColor, tint),
313
+ border: container.border === undefined ? undefined : {
314
+ ...container.border,
315
+ color: borderColor?.type === 'all'
316
+ ? {
317
+ type: 'all',
318
+ value: blendWithStateLayer(borderColor.value, tint) ?? borderColor.value,
319
+ }
320
+ : borderColor,
321
+ },
322
+ })
323
+ }
@@ -0,0 +1,11 @@
1
+ export const defined = <T extends object>(style: T): T => {
2
+ const result = {} as T
3
+
4
+ for (const key of Object.keys(style) as (keyof T)[]) {
5
+ if (style[key] !== undefined) {
6
+ result[key] = style[key]
7
+ }
8
+ }
9
+
10
+ return result
11
+ }
@@ -0,0 +1,10 @@
1
+ import type { IconTokens } from '@helpwave/hightide-design/component-token-resolvers'
2
+
3
+ import type { IconStyle } from '../../icons'
4
+ import { defined } from './defined'
5
+
6
+ export const toIconStyle = (tokens: IconTokens): IconStyle => defined({
7
+ color: tokens.color,
8
+ size: tokens.size,
9
+ strokeWidth: tokens.strokeWidth,
10
+ })
@@ -0,0 +1,4 @@
1
+ export * from './container-adapter'
2
+ export * from './defined'
3
+ export * from './icon-style-adapter'
4
+ export * from './text-style-adapter'
@@ -0,0 +1,16 @@
1
+ import type { TextStyle } from 'react-native'
2
+
3
+ import type { TextStyleTokens } from '@helpwave/hightide-design/component-token-resolvers'
4
+
5
+ import { defined } from './defined'
6
+
7
+ export const toTextStyle = (tokens: TextStyleTokens): TextStyle => defined({
8
+ color: tokens.color,
9
+ fontSize: tokens.fontSize,
10
+ fontWeight: tokens.fontWeight,
11
+ fontFamily: tokens.fontFamily,
12
+ lineHeight: tokens.lineHeight,
13
+ textAlign: tokens.textAlign,
14
+ flex: tokens.flex,
15
+ flexShrink: tokens.flexShrink,
16
+ })
@@ -1,3 +1,4 @@
1
+ export * from './adapters'
1
2
  export * from './resolvers'
2
3
  export * from './themes'
3
4
  export * from './types'