@helpwave/hightide-native 0.0.6 → 0.0.7
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.
- package/package.json +3 -3
- package/src/components/chat/ChatMessageCard.tsx +1 -1
- package/src/components/chat/ChatSystemLine.tsx +1 -1
- package/src/components/user-interaction/Button.tsx +1 -1
- package/src/components/user-interaction/IconButton.tsx +1 -1
- package/src/components/visualization-and-display/Avatar.tsx +286 -0
- package/src/components/visualization-and-display/Chip.tsx +1 -1
- package/src/components/visualization-and-display/index.ts +1 -0
- package/src/global-contexts/hightide-config/HightideConfigUtils.ts +3 -3
- package/src/global-contexts/theme/ThemeContext.ts +2 -2
- package/src/global-contexts/theme/ThemeProvider.tsx +3 -3
- package/src/theme/resolvers/avatar.ts +231 -0
- package/src/theme/resolvers/button.ts +1 -1
- package/src/theme/resolvers/chat.ts +2 -2
- package/src/theme/resolvers/checkbox.ts +1 -1
- package/src/theme/resolvers/chip.ts +1 -1
- package/src/theme/resolvers/coloring.ts +1 -1
- package/src/theme/resolvers/iconButton.ts +1 -1
- package/src/theme/resolvers/index.ts +1 -0
- package/src/theme/resolvers/input.ts +1 -1
- package/src/theme/resolvers/menu.ts +1 -1
- package/src/theme/resolvers/multiSelect.ts +1 -1
- package/src/theme/resolvers/select.ts +1 -1
- package/src/theme/themes/{createTheme.ts → createHightideTheme.ts} +6 -4
- package/src/theme/themes/hightideThemes.ts +14 -0
- package/src/theme/themes/index.ts +2 -2
- package/src/theme/types/components/avatar.ts +77 -0
- package/src/theme/types/components/button.ts +1 -1
- package/src/theme/types/components/chat.ts +1 -1
- package/src/theme/types/components/chip.ts +1 -1
- package/src/theme/types/components/hightide.ts +2 -0
- package/src/theme/types/components/iconButton.ts +1 -1
- package/src/theme/types/components/index.ts +1 -0
- package/src/theme/types/layout.ts +12 -0
- package/src/theme/types/theme.ts +15 -6
- package/src/theme/themes/nativeThemes.ts +0 -16
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"access": "public"
|
|
11
11
|
},
|
|
12
12
|
"license": "AGPL-3.0-only",
|
|
13
|
-
"version": "0.0.
|
|
13
|
+
"version": "0.0.7",
|
|
14
14
|
"type": "module",
|
|
15
15
|
"files": [
|
|
16
16
|
"src"
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"lucide-react-native": "0.561.0",
|
|
46
|
-
"@helpwave/hightide-design": "0.0.
|
|
47
|
-
"@helpwave/hightide-utils": "0.0.
|
|
46
|
+
"@helpwave/hightide-design": "0.0.5",
|
|
47
|
+
"@helpwave/hightide-utils": "0.0.5"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@react-native-async-storage/async-storage": ">=2.0.0",
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
type ViewStyle
|
|
11
11
|
} from 'react-native'
|
|
12
12
|
|
|
13
|
-
import type { ColoringType } from '@helpwave/hightide-design/
|
|
13
|
+
import type { ColoringType } from '@helpwave/hightide-design/utils'
|
|
14
14
|
|
|
15
15
|
import { useTheme } from '../../global-contexts/theme/ThemeContext'
|
|
16
16
|
import type {
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from 'react-native'
|
|
12
12
|
import { CheckCheck } from 'lucide-react-native'
|
|
13
13
|
|
|
14
|
-
import type { ColoringType } from '@helpwave/hightide-design/
|
|
14
|
+
import type { ColoringType } from '@helpwave/hightide-design/utils'
|
|
15
15
|
|
|
16
16
|
import { useTheme } from '../../global-contexts/theme/ThemeContext'
|
|
17
17
|
import type {
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from 'react-native'
|
|
11
11
|
import type { LucideIcon } from 'lucide-react-native'
|
|
12
12
|
|
|
13
|
-
import type { ColoringType } from '@helpwave/hightide-design/
|
|
13
|
+
import type { ColoringType } from '@helpwave/hightide-design/utils'
|
|
14
14
|
import type {
|
|
15
15
|
ButtonColoringStyle,
|
|
16
16
|
ElementSize
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useEffect,
|
|
3
|
+
useMemo,
|
|
4
|
+
useState,
|
|
5
|
+
type ComponentType,
|
|
6
|
+
type ReactNode
|
|
7
|
+
} from 'react'
|
|
8
|
+
import {
|
|
9
|
+
Image,
|
|
10
|
+
Text,
|
|
11
|
+
View,
|
|
12
|
+
type ImageProps,
|
|
13
|
+
type StyleProp,
|
|
14
|
+
type ViewProps,
|
|
15
|
+
type ViewStyle
|
|
16
|
+
} from 'react-native'
|
|
17
|
+
import { User } from 'lucide-react-native'
|
|
18
|
+
|
|
19
|
+
import type { ElementSize } from '@helpwave/hightide-design/types'
|
|
20
|
+
|
|
21
|
+
import { useTheme } from '../../global-contexts/theme/ThemeContext'
|
|
22
|
+
import type {
|
|
23
|
+
AvatarGroupMoreStyle,
|
|
24
|
+
AvatarGroupStackStyle,
|
|
25
|
+
AvatarImageStyle,
|
|
26
|
+
AvatarIconStyle,
|
|
27
|
+
AvatarStatus,
|
|
28
|
+
AvatarStyle,
|
|
29
|
+
AvatarTextStyle,
|
|
30
|
+
AvatarWithLabelContainerStyle,
|
|
31
|
+
AvatarWithLabelTextStyle,
|
|
32
|
+
AvatarWithStatusContainerStyle,
|
|
33
|
+
AvatarStatusDotStyle
|
|
34
|
+
} from '../../theme/types/components/avatar'
|
|
35
|
+
import type { StyleOverwrite } from '../../theme/types/resolver'
|
|
36
|
+
|
|
37
|
+
export type AvatarSize = ElementSize
|
|
38
|
+
|
|
39
|
+
type ImageConfig = {
|
|
40
|
+
avatarUrl: string,
|
|
41
|
+
alt: string,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type AvatarImageProps = Omit<ImageProps, 'source'> & {
|
|
45
|
+
source: { uri: string },
|
|
46
|
+
alt?: string,
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const DefaultAvatarImage: ComponentType<AvatarImageProps> = ({ alt, ...props }) => (
|
|
50
|
+
<Image
|
|
51
|
+
{...props}
|
|
52
|
+
accessibilityLabel={alt}
|
|
53
|
+
/>
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
export const AvatarUtil = {
|
|
57
|
+
sizes: ['xs', 'sm', 'md', 'lg'] as const satisfies readonly ElementSize[],
|
|
58
|
+
statuses: ['online', 'offline', 'away', 'busy', 'unknown'] as const satisfies readonly AvatarStatus[],
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type AvatarProps = Omit<ViewProps, 'children' | 'style'> & {
|
|
62
|
+
image?: ImageConfig,
|
|
63
|
+
name?: string,
|
|
64
|
+
size?: AvatarSize,
|
|
65
|
+
ImageComponent?: ComponentType<AvatarImageProps>,
|
|
66
|
+
style?: StyleProp<ViewStyle>,
|
|
67
|
+
avatarStyle?: StyleOverwrite<{ size?: ElementSize, isGrouped?: boolean, groupIndex?: number }, AvatarStyle>,
|
|
68
|
+
imageStyle?: StyleOverwrite<{ size?: ElementSize, isGrouped?: boolean, groupIndex?: number }, AvatarImageStyle>,
|
|
69
|
+
textStyle?: StyleOverwrite<{ size?: ElementSize, isGrouped?: boolean, groupIndex?: number }, AvatarTextStyle>,
|
|
70
|
+
iconStyle?: StyleOverwrite<{ size?: ElementSize, isGrouped?: boolean, groupIndex?: number }, AvatarIconStyle>,
|
|
71
|
+
isGrouped?: boolean,
|
|
72
|
+
groupIndex?: number,
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const Avatar = ({
|
|
76
|
+
image: initialImage,
|
|
77
|
+
name,
|
|
78
|
+
size = 'md',
|
|
79
|
+
ImageComponent = DefaultAvatarImage,
|
|
80
|
+
style,
|
|
81
|
+
avatarStyle,
|
|
82
|
+
imageStyle,
|
|
83
|
+
textStyle,
|
|
84
|
+
iconStyle,
|
|
85
|
+
isGrouped = false,
|
|
86
|
+
groupIndex,
|
|
87
|
+
...props
|
|
88
|
+
}: AvatarProps) => {
|
|
89
|
+
const { theme } = useTheme()
|
|
90
|
+
const [hasError, setHasError] = useState(false)
|
|
91
|
+
const [hasLoaded, setHasLoaded] = useState(false)
|
|
92
|
+
const [image, setImage] = useState(initialImage)
|
|
93
|
+
const ImageElement = ImageComponent
|
|
94
|
+
|
|
95
|
+
const state = useMemo(() => ({
|
|
96
|
+
size,
|
|
97
|
+
isGrouped,
|
|
98
|
+
groupIndex,
|
|
99
|
+
}), [size, isGrouped, groupIndex])
|
|
100
|
+
|
|
101
|
+
const displayName = useMemo(() => {
|
|
102
|
+
const maxLetters = size === 'sm' ? 1 : 2
|
|
103
|
+
return (name ?? '')
|
|
104
|
+
.split(' ')
|
|
105
|
+
.filter((_, index) => index < maxLetters)
|
|
106
|
+
.map(value => value[0])
|
|
107
|
+
.join('')
|
|
108
|
+
.toUpperCase()
|
|
109
|
+
}, [name, size])
|
|
110
|
+
|
|
111
|
+
const isShowingImage = !!image && (!hasError || !hasLoaded)
|
|
112
|
+
const isShowingFallback = !hasLoaded || hasError
|
|
113
|
+
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
if (initialImage?.avatarUrl !== image?.avatarUrl) {
|
|
116
|
+
setHasError(false)
|
|
117
|
+
setHasLoaded(false)
|
|
118
|
+
}
|
|
119
|
+
setImage(initialImage)
|
|
120
|
+
}, [image?.avatarUrl, initialImage])
|
|
121
|
+
|
|
122
|
+
const resolvedAvatar = theme.components.avatar.avatar(state, avatarStyle)
|
|
123
|
+
const resolvedImage = theme.components.avatar.image(state, imageStyle)
|
|
124
|
+
const resolvedText = theme.components.avatar.text(state, textStyle)
|
|
125
|
+
const resolvedIcon = theme.components.avatar.icon(state, iconStyle)
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<View
|
|
129
|
+
{...props}
|
|
130
|
+
style={[resolvedAvatar, style]}
|
|
131
|
+
>
|
|
132
|
+
{isShowingImage && (
|
|
133
|
+
<ImageElement
|
|
134
|
+
key={image?.avatarUrl}
|
|
135
|
+
source={{ uri: image?.avatarUrl ?? '' }}
|
|
136
|
+
alt={image?.alt}
|
|
137
|
+
style={[resolvedImage, { opacity: hasLoaded && !hasError ? 1 : 0 }]}
|
|
138
|
+
onLoad={() => setHasLoaded(true)}
|
|
139
|
+
onError={() => setHasError(true)}
|
|
140
|
+
/>
|
|
141
|
+
)}
|
|
142
|
+
{isShowingFallback && (
|
|
143
|
+
name ? (
|
|
144
|
+
<Text style={resolvedText}>{displayName}</Text>
|
|
145
|
+
) : (
|
|
146
|
+
<User
|
|
147
|
+
size={resolvedIcon.size}
|
|
148
|
+
strokeWidth={resolvedIcon.strokeWidth}
|
|
149
|
+
color={resolvedIcon.color}
|
|
150
|
+
/>
|
|
151
|
+
)
|
|
152
|
+
)}
|
|
153
|
+
</View>
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export type AvatarGroupProps = Omit<ViewProps, 'children' | 'style'> & {
|
|
158
|
+
avatars: Omit<AvatarProps, 'size' | 'isGrouped' | 'groupIndex'>[],
|
|
159
|
+
showTotalNumber?: boolean,
|
|
160
|
+
size?: AvatarSize,
|
|
161
|
+
ImageComponent?: ComponentType<AvatarImageProps>,
|
|
162
|
+
style?: StyleProp<ViewStyle>,
|
|
163
|
+
stackStyle?: StyleOverwrite<{ size?: ElementSize, count?: number }, AvatarGroupStackStyle>,
|
|
164
|
+
moreStyle?: StyleOverwrite<{ size?: ElementSize, count?: number }, AvatarGroupMoreStyle>,
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export const AvatarGroup = ({
|
|
168
|
+
avatars,
|
|
169
|
+
showTotalNumber = true,
|
|
170
|
+
size = 'md',
|
|
171
|
+
ImageComponent,
|
|
172
|
+
style,
|
|
173
|
+
stackStyle,
|
|
174
|
+
moreStyle,
|
|
175
|
+
...props
|
|
176
|
+
}: AvatarGroupProps) => {
|
|
177
|
+
const { theme } = useTheme()
|
|
178
|
+
const maxShownProfiles = theme.layout.avatarGroup.maxShown
|
|
179
|
+
const displayedProfiles = avatars.length < maxShownProfiles ? avatars : avatars.slice(0, maxShownProfiles)
|
|
180
|
+
const notDisplayedProfiles = avatars.length - maxShownProfiles
|
|
181
|
+
|
|
182
|
+
const state = useMemo(() => ({
|
|
183
|
+
size,
|
|
184
|
+
count: displayedProfiles.length,
|
|
185
|
+
}), [size, displayedProfiles.length])
|
|
186
|
+
|
|
187
|
+
const resolvedContainer = theme.components.avatar.group.container(state)
|
|
188
|
+
const resolvedStack = theme.components.avatar.group.stack(state, stackStyle)
|
|
189
|
+
const resolvedMore = theme.components.avatar.group.more(state, moreStyle)
|
|
190
|
+
|
|
191
|
+
return (
|
|
192
|
+
<View
|
|
193
|
+
{...props}
|
|
194
|
+
style={[resolvedContainer, style]}
|
|
195
|
+
>
|
|
196
|
+
<View style={resolvedStack}>
|
|
197
|
+
{displayedProfiles.map((avatar, index) => (
|
|
198
|
+
<Avatar
|
|
199
|
+
{...avatar}
|
|
200
|
+
key={index}
|
|
201
|
+
size={size}
|
|
202
|
+
isGrouped
|
|
203
|
+
groupIndex={index}
|
|
204
|
+
ImageComponent={avatar.ImageComponent ?? ImageComponent}
|
|
205
|
+
/>
|
|
206
|
+
))}
|
|
207
|
+
</View>
|
|
208
|
+
{showTotalNumber && notDisplayedProfiles > 0 && (
|
|
209
|
+
<Text style={resolvedMore}>
|
|
210
|
+
{`+ ${notDisplayedProfiles}`}
|
|
211
|
+
</Text>
|
|
212
|
+
)}
|
|
213
|
+
</View>
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export type { AvatarStatus }
|
|
218
|
+
|
|
219
|
+
export type AvatarWithStatusProps = AvatarProps & {
|
|
220
|
+
status?: AvatarStatus,
|
|
221
|
+
containerStyle?: StyleOverwrite<{ size?: ElementSize, status?: AvatarStatus }, AvatarWithStatusContainerStyle>,
|
|
222
|
+
statusDotStyle?: StyleOverwrite<{ size?: ElementSize, status?: AvatarStatus }, AvatarStatusDotStyle>,
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export const AvatarWithStatus = ({
|
|
226
|
+
status = 'unknown',
|
|
227
|
+
size = 'md',
|
|
228
|
+
style,
|
|
229
|
+
containerStyle,
|
|
230
|
+
statusDotStyle,
|
|
231
|
+
...avatarProps
|
|
232
|
+
}: AvatarWithStatusProps) => {
|
|
233
|
+
const { theme } = useTheme()
|
|
234
|
+
|
|
235
|
+
const state = useMemo(() => ({
|
|
236
|
+
size,
|
|
237
|
+
status,
|
|
238
|
+
}), [size, status])
|
|
239
|
+
|
|
240
|
+
const resolvedContainer = theme.components.avatar.withStatus.container(state, containerStyle)
|
|
241
|
+
const resolvedStatusDot = theme.components.avatar.withStatus.statusDot(state, statusDotStyle)
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<View style={[resolvedContainer, style]}>
|
|
245
|
+
<Avatar {...avatarProps} size={size} />
|
|
246
|
+
<View style={resolvedStatusDot} />
|
|
247
|
+
</View>
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
type AvatarWithLabelPosition = 'left' | 'right'
|
|
252
|
+
|
|
253
|
+
export type AvatarWithLabelProps = AvatarProps & {
|
|
254
|
+
label: ReactNode,
|
|
255
|
+
labelPosition?: AvatarWithLabelPosition,
|
|
256
|
+
containerStyle?: StyleOverwrite<{ size?: ElementSize }, AvatarWithLabelContainerStyle>,
|
|
257
|
+
labelStyle?: StyleOverwrite<{ size?: ElementSize }, AvatarWithLabelTextStyle>,
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export const AvatarWithLabel = ({
|
|
261
|
+
label,
|
|
262
|
+
labelPosition = 'left',
|
|
263
|
+
size = 'md',
|
|
264
|
+
style,
|
|
265
|
+
containerStyle,
|
|
266
|
+
labelStyle,
|
|
267
|
+
...avatarProps
|
|
268
|
+
}: AvatarWithLabelProps) => {
|
|
269
|
+
const { theme } = useTheme()
|
|
270
|
+
|
|
271
|
+
const state = useMemo(() => ({ size }), [size])
|
|
272
|
+
const resolvedContainer = theme.components.avatar.withLabel.container(state, containerStyle)
|
|
273
|
+
const resolvedLabel = theme.components.avatar.withLabel.text(state, labelStyle)
|
|
274
|
+
|
|
275
|
+
const avatar = <Avatar {...avatarProps} size={size} />
|
|
276
|
+
const labelElement = typeof label === 'string' || typeof label === 'number'
|
|
277
|
+
? <Text style={resolvedLabel}>{label}</Text>
|
|
278
|
+
: label
|
|
279
|
+
|
|
280
|
+
return (
|
|
281
|
+
<View style={[resolvedContainer, style]}>
|
|
282
|
+
{labelPosition === 'left' ? labelElement : avatar}
|
|
283
|
+
{labelPosition === 'left' ? avatar : labelElement}
|
|
284
|
+
</View>
|
|
285
|
+
)
|
|
286
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { SupportedThemesConfig } from '@helpwave/hightide-utils/context'
|
|
2
2
|
|
|
3
3
|
import type { SupportedLocalesConfig } from '../localization/forward-exports'
|
|
4
|
-
import { themes } from '../../theme/themes/
|
|
5
|
-
import type {
|
|
4
|
+
import { themes } from '../../theme/themes/hightideThemes'
|
|
5
|
+
import type { HightideTheme } from '../../theme/types/theme'
|
|
6
6
|
|
|
7
7
|
export const HightideConfigUtils = {
|
|
8
8
|
defaultSupportedLocales: {
|
|
@@ -24,5 +24,5 @@ export const HightideConfigUtils = {
|
|
|
24
24
|
},
|
|
25
25
|
theme: themes.dark,
|
|
26
26
|
},
|
|
27
|
-
} as const satisfies SupportedThemesConfig<
|
|
27
|
+
} as const satisfies SupportedThemesConfig<HightideTheme>,
|
|
28
28
|
}
|
|
@@ -7,11 +7,11 @@ import type {
|
|
|
7
7
|
ThemeConfigValue,
|
|
8
8
|
ThemeInformation
|
|
9
9
|
} from './forward-exports'
|
|
10
|
-
import type {
|
|
10
|
+
import type { HightideTheme } from '../../theme/types/theme'
|
|
11
11
|
|
|
12
12
|
export type { ThemeInformation }
|
|
13
13
|
|
|
14
|
-
export type ThemeContextValue = ThemeConfigValue<
|
|
14
|
+
export type ThemeContextValue = ThemeConfigValue<HightideTheme> & {
|
|
15
15
|
isInitialized: boolean,
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -19,8 +19,8 @@ import {
|
|
|
19
19
|
type SystemTheme
|
|
20
20
|
} from './forward-exports'
|
|
21
21
|
import { useNativeKeyValueStore } from '../../hooks/useNativeKeyValueStore'
|
|
22
|
-
import type { ThemeMode } from '../../theme/themes/
|
|
23
|
-
import type {
|
|
22
|
+
import type { ThemeMode } from '../../theme/themes/hightideThemes'
|
|
23
|
+
import type { HightideTheme } from '../../theme/types/theme'
|
|
24
24
|
|
|
25
25
|
export type ThemeProviderProps<T> = PropsWithChildren & {
|
|
26
26
|
theme?: ThemeMode | null,
|
|
@@ -66,7 +66,7 @@ export const ThemeProvider = ({
|
|
|
66
66
|
fallbackTheme = 'light',
|
|
67
67
|
supportedThemes = HightideConfigUtils.defaultSupportedThemes,
|
|
68
68
|
onChangedTheme,
|
|
69
|
-
}: ThemeProviderProps<
|
|
69
|
+
}: ThemeProviderProps<HightideTheme>) => {
|
|
70
70
|
const store = useNativeKeyValueStore()
|
|
71
71
|
const systemTheme = useNativeSystemTheme()
|
|
72
72
|
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ImageStyle,
|
|
3
|
+
TextStyle,
|
|
4
|
+
ViewStyle
|
|
5
|
+
} from 'react-native'
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
componentLayouts,
|
|
9
|
+
fontWeights
|
|
10
|
+
} from '@helpwave/hightide-design/tokens'
|
|
11
|
+
import type {
|
|
12
|
+
ElementSize,
|
|
13
|
+
HightideThemeTokens as DesignTokensTheme,
|
|
14
|
+
TypographyTokens
|
|
15
|
+
} from '@helpwave/hightide-design/types'
|
|
16
|
+
|
|
17
|
+
import { resolveColoringStyles } from './coloring'
|
|
18
|
+
import type {
|
|
19
|
+
ColorPalette,
|
|
20
|
+
HightideSemanticColors
|
|
21
|
+
} from '../types/color'
|
|
22
|
+
import type {
|
|
23
|
+
AvatarGroupState,
|
|
24
|
+
AvatarIconStyle,
|
|
25
|
+
AvatarState,
|
|
26
|
+
AvatarStatus,
|
|
27
|
+
AvatarTheme,
|
|
28
|
+
AvatarWithLabelState,
|
|
29
|
+
AvatarWithStatusState
|
|
30
|
+
} from '../types/components/avatar'
|
|
31
|
+
import type { HightideComponentThemes } from '../types/components/hightide'
|
|
32
|
+
import { createStyleResolver } from '../types/resolver'
|
|
33
|
+
|
|
34
|
+
const avatarFontWeights: Record<ElementSize, string> = {
|
|
35
|
+
xs: fontWeights.semibold,
|
|
36
|
+
sm: fontWeights.semibold,
|
|
37
|
+
md: fontWeights.semibold,
|
|
38
|
+
lg: fontWeights.bold,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const statusColor = (
|
|
42
|
+
status: AvatarStatus,
|
|
43
|
+
semantic: HightideSemanticColors,
|
|
44
|
+
gray: ColorPalette
|
|
45
|
+
): string => {
|
|
46
|
+
switch (status) {
|
|
47
|
+
case 'online':
|
|
48
|
+
return semantic.positive
|
|
49
|
+
case 'busy':
|
|
50
|
+
return semantic.negative
|
|
51
|
+
case 'away':
|
|
52
|
+
return semantic.warning
|
|
53
|
+
case 'offline':
|
|
54
|
+
case 'unknown':
|
|
55
|
+
default:
|
|
56
|
+
return gray[500]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type CreateAvatarThemeOptions = {
|
|
61
|
+
semantic: HightideSemanticColors,
|
|
62
|
+
coloring: HightideComponentThemes['coloring'],
|
|
63
|
+
gray: ColorPalette,
|
|
64
|
+
typography: TypographyTokens,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const createAvatarTheme = ({
|
|
68
|
+
semantic,
|
|
69
|
+
coloring,
|
|
70
|
+
gray,
|
|
71
|
+
typography,
|
|
72
|
+
}: CreateAvatarThemeOptions): AvatarTheme => {
|
|
73
|
+
const resolveAvatar = (state: AvatarState) => {
|
|
74
|
+
const size = state.size ?? 'md'
|
|
75
|
+
const layout = componentLayouts.avatar[size]
|
|
76
|
+
const groupLayout = componentLayouts.avatarGroup
|
|
77
|
+
const resolved = resolveColoringStyles(coloring.primary, 'solid', semantic)
|
|
78
|
+
const borderRadius = layout.size / 2
|
|
79
|
+
|
|
80
|
+
const avatar: ViewStyle = {
|
|
81
|
+
position: state.isGrouped ? 'absolute' : 'relative',
|
|
82
|
+
flexDirection: 'row',
|
|
83
|
+
alignItems: 'center',
|
|
84
|
+
justifyContent: 'center',
|
|
85
|
+
width: layout.size,
|
|
86
|
+
height: layout.size,
|
|
87
|
+
padding: layout.padding,
|
|
88
|
+
borderRadius,
|
|
89
|
+
backgroundColor: resolved.backgroundColor,
|
|
90
|
+
overflow: 'hidden',
|
|
91
|
+
...(state.isGrouped ? {
|
|
92
|
+
left: (state.groupIndex ?? 0) * layout.size * groupLayout.overlap,
|
|
93
|
+
zIndex: groupLayout.maxShown - (state.groupIndex ?? 0),
|
|
94
|
+
shadowColor: '#000000',
|
|
95
|
+
shadowOffset: { width: 4, height: 0 },
|
|
96
|
+
shadowOpacity: 0.2,
|
|
97
|
+
shadowRadius: 4,
|
|
98
|
+
elevation: 4,
|
|
99
|
+
} : {}),
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const image: ImageStyle = {
|
|
103
|
+
position: 'absolute',
|
|
104
|
+
left: 0,
|
|
105
|
+
top: 0,
|
|
106
|
+
width: layout.size,
|
|
107
|
+
height: layout.size,
|
|
108
|
+
borderRadius,
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const text: TextStyle = {
|
|
112
|
+
color: resolved.color,
|
|
113
|
+
fontSize: layout.fontSize,
|
|
114
|
+
fontWeight: avatarFontWeights[size] as TextStyle['fontWeight'],
|
|
115
|
+
textAlign: 'center',
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const icon: AvatarIconStyle = {
|
|
119
|
+
size: componentLayouts.icon[size].size,
|
|
120
|
+
strokeWidth: componentLayouts.icon[size].strokeWidth,
|
|
121
|
+
color: resolved.color,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return { avatar, image, text, icon }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const resolveWithStatus = (state: AvatarWithStatusState) => {
|
|
128
|
+
const size = state.size ?? 'md'
|
|
129
|
+
const status = state.status ?? 'unknown'
|
|
130
|
+
const layout = componentLayouts.avatar[size]
|
|
131
|
+
|
|
132
|
+
const container: ViewStyle = {
|
|
133
|
+
position: 'relative',
|
|
134
|
+
alignSelf: 'flex-start',
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const statusDot: ViewStyle = {
|
|
138
|
+
position: 'absolute',
|
|
139
|
+
right: 0,
|
|
140
|
+
bottom: 0,
|
|
141
|
+
zIndex: 1,
|
|
142
|
+
width: layout.statusDotSize,
|
|
143
|
+
height: layout.statusDotSize,
|
|
144
|
+
borderRadius: layout.statusDotSize / 2,
|
|
145
|
+
borderWidth: layout.statusDotBorderWidth,
|
|
146
|
+
borderColor: semantic.background,
|
|
147
|
+
backgroundColor: statusColor(status, semantic, gray),
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return { container, statusDot }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const resolveWithLabel = (_state: AvatarWithLabelState) => {
|
|
154
|
+
const bodyMedium = typography.scales.body.medium
|
|
155
|
+
|
|
156
|
+
const container: ViewStyle = {
|
|
157
|
+
flexDirection: 'row',
|
|
158
|
+
alignItems: 'center',
|
|
159
|
+
gap: componentLayouts.avatarGroup.gap,
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const text: TextStyle = {
|
|
163
|
+
fontSize: bodyMedium.fontSize,
|
|
164
|
+
fontWeight: bodyMedium.fontWeight as TextStyle['fontWeight'],
|
|
165
|
+
lineHeight: bodyMedium.lineHeight,
|
|
166
|
+
color: semantic.onBackground,
|
|
167
|
+
flexShrink: 1,
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return { container, text }
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const resolveGroup = (state: AvatarGroupState) => {
|
|
174
|
+
const size = state.size ?? 'md'
|
|
175
|
+
const layout = componentLayouts.avatar[size]
|
|
176
|
+
const groupLayout = componentLayouts.avatarGroup
|
|
177
|
+
const visibleCount = Math.min(state.count ?? groupLayout.maxShown, groupLayout.maxShown)
|
|
178
|
+
const stackWidth = layout.size * (groupLayout.overlap * Math.max(visibleCount - 1, 0) + 1)
|
|
179
|
+
|
|
180
|
+
const container: ViewStyle = {
|
|
181
|
+
flexDirection: 'row',
|
|
182
|
+
alignItems: 'center',
|
|
183
|
+
gap: groupLayout.gap,
|
|
184
|
+
height: layout.size,
|
|
185
|
+
alignSelf: 'flex-start',
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const stack: ViewStyle = {
|
|
189
|
+
position: 'relative',
|
|
190
|
+
width: stackWidth,
|
|
191
|
+
height: layout.size,
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const more: TextStyle = {
|
|
195
|
+
fontSize: (layout.size * 2) / 3,
|
|
196
|
+
color: semantic.onBackground,
|
|
197
|
+
flexShrink: 1,
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return { container, stack, more }
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
avatar: createStyleResolver((state) => resolveAvatar(state).avatar),
|
|
205
|
+
image: createStyleResolver((state) => resolveAvatar(state).image),
|
|
206
|
+
text: createStyleResolver((state) => resolveAvatar(state).text),
|
|
207
|
+
icon: createStyleResolver((state) => resolveAvatar(state).icon),
|
|
208
|
+
withStatus: {
|
|
209
|
+
container: createStyleResolver((state) => resolveWithStatus(state).container),
|
|
210
|
+
statusDot: createStyleResolver((state) => resolveWithStatus(state).statusDot),
|
|
211
|
+
},
|
|
212
|
+
withLabel: {
|
|
213
|
+
container: createStyleResolver((state) => resolveWithLabel(state).container),
|
|
214
|
+
text: createStyleResolver((state) => resolveWithLabel(state).text),
|
|
215
|
+
},
|
|
216
|
+
group: {
|
|
217
|
+
container: createStyleResolver((state) => resolveGroup(state).container),
|
|
218
|
+
stack: createStyleResolver((state) => resolveGroup(state).stack),
|
|
219
|
+
more: createStyleResolver((state) => resolveGroup(state).more),
|
|
220
|
+
},
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export const createAvatarThemeFromDesign = (theme: DesignTokensTheme): AvatarTheme => {
|
|
225
|
+
return createAvatarTheme({
|
|
226
|
+
semantic: theme.semanticColors,
|
|
227
|
+
coloring: theme.coloring as HightideComponentThemes['coloring'],
|
|
228
|
+
gray: theme.colors.gray.value as ColorPalette,
|
|
229
|
+
typography: theme.typography,
|
|
230
|
+
})
|
|
231
|
+
}
|
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
type ViewStyle
|
|
5
5
|
} from 'react-native'
|
|
6
6
|
|
|
7
|
-
import { hexWithAlpha } from '@helpwave/hightide-design/
|
|
7
|
+
import { hexWithAlpha } from '@helpwave/hightide-design/utils'
|
|
8
8
|
import { fontWeights } from '@helpwave/hightide-design/tokens'
|
|
9
9
|
import type {
|
|
10
10
|
ComponentColorTokens,
|
|
11
|
-
|
|
11
|
+
HightideThemeTokens as DesignTokensTheme
|
|
12
12
|
} from '@helpwave/hightide-design/types'
|
|
13
13
|
|
|
14
14
|
import type {
|
|
@@ -3,7 +3,7 @@ import type { ViewStyle } from 'react-native'
|
|
|
3
3
|
import { componentLayouts } from '@helpwave/hightide-design/tokens'
|
|
4
4
|
import type {
|
|
5
5
|
ComponentColorTokens,
|
|
6
|
-
|
|
6
|
+
HightideThemeTokens as DesignTokensTheme,
|
|
7
7
|
ElementSize
|
|
8
8
|
} from '@helpwave/hightide-design/types'
|
|
9
9
|
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
componentLayouts,
|
|
8
8
|
fontWeights
|
|
9
9
|
} from '@helpwave/hightide-design/tokens'
|
|
10
|
-
import type {
|
|
10
|
+
import type { HightideThemeTokens as DesignTokensTheme } from '@helpwave/hightide-design/types'
|
|
11
11
|
|
|
12
12
|
import { resolveColoringStyles } from './coloring'
|
|
13
13
|
import type { HightideSemanticColors } from '../types/color'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ViewStyle } from 'react-native'
|
|
2
2
|
|
|
3
3
|
import { componentLayouts } from '@helpwave/hightide-design/tokens'
|
|
4
|
-
import type {
|
|
4
|
+
import type { HightideThemeTokens as DesignTokensTheme } from '@helpwave/hightide-design/types'
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
isOutlineColoringStyle,
|
|
@@ -3,7 +3,7 @@ import type { TextStyle } from 'react-native'
|
|
|
3
3
|
import { componentLayouts } from '@helpwave/hightide-design/tokens'
|
|
4
4
|
import type {
|
|
5
5
|
ComponentColorTokens,
|
|
6
|
-
|
|
6
|
+
HightideThemeTokens as DesignTokensTheme
|
|
7
7
|
} from '@helpwave/hightide-design/types'
|
|
8
8
|
|
|
9
9
|
import type { HightideSemanticColors } from '../types/color'
|
|
@@ -3,7 +3,7 @@ import { StyleSheet } from 'react-native'
|
|
|
3
3
|
import { fontWeights } from '@helpwave/hightide-design/tokens'
|
|
4
4
|
import type {
|
|
5
5
|
ComponentColorTokens,
|
|
6
|
-
|
|
6
|
+
HightideThemeTokens as DesignTokensTheme
|
|
7
7
|
} from '@helpwave/hightide-design/types'
|
|
8
8
|
|
|
9
9
|
import type { HightideSemanticColors } from '../types/color'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { fontWeights } from '@helpwave/hightide-design/tokens'
|
|
2
2
|
import type {
|
|
3
3
|
ComponentColorTokens,
|
|
4
|
-
|
|
4
|
+
HightideThemeTokens as DesignTokensTheme
|
|
5
5
|
} from '@helpwave/hightide-design/types'
|
|
6
6
|
|
|
7
7
|
import type { HightideSemanticColors } from '../types/color'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { fontWeights } from '@helpwave/hightide-design/tokens'
|
|
2
2
|
import type {
|
|
3
3
|
ComponentColorTokens,
|
|
4
|
-
|
|
4
|
+
HightideThemeTokens as DesignTokensTheme
|
|
5
5
|
} from '@helpwave/hightide-design/types'
|
|
6
6
|
|
|
7
7
|
import type { HightideSemanticColors } from '../types/color'
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
ColorPaletteToken,
|
|
3
|
-
|
|
3
|
+
HightideThemeTokens
|
|
4
4
|
} from '@helpwave/hightide-design/types'
|
|
5
5
|
|
|
6
|
+
import { createAvatarThemeFromDesign } from '../resolvers/avatar'
|
|
6
7
|
import { createButtonThemeFromDesign } from '../resolvers/button'
|
|
7
8
|
import { createChatThemeFromDesign } from '../resolvers/chat'
|
|
8
9
|
import { createCheckboxThemeFromDesign } from '../resolvers/checkbox'
|
|
@@ -17,7 +18,7 @@ import type {
|
|
|
17
18
|
ColorPalette,
|
|
18
19
|
HightideColors
|
|
19
20
|
} from '../types/color'
|
|
20
|
-
import type {
|
|
21
|
+
import type { HightideTheme } from '../types/theme'
|
|
21
22
|
|
|
22
23
|
const unwrapColorPaletteToken = (token: ColorPaletteToken): Color | ColorPalette => {
|
|
23
24
|
if (token.type === 'singleValue') {
|
|
@@ -26,7 +27,7 @@ const unwrapColorPaletteToken = (token: ColorPaletteToken): Color | ColorPalette
|
|
|
26
27
|
return token.value
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
const unwrapColors = (colors:
|
|
30
|
+
const unwrapColors = (colors: HightideThemeTokens['colors']): HightideColors & Record<string, Color | ColorPalette> => {
|
|
30
31
|
const result: Record<string, Color | ColorPalette> = {}
|
|
31
32
|
for (const [key, token] of Object.entries(colors)) {
|
|
32
33
|
result[key] = unwrapColorPaletteToken(token)
|
|
@@ -34,7 +35,7 @@ const unwrapColors = (colors: HightideDesignTokens['colors']): HightideColors &
|
|
|
34
35
|
return result as HightideColors & Record<string, Color | ColorPalette>
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
export const
|
|
38
|
+
export const createHightideTheme = (tokens: HightideThemeTokens): HightideTheme => ({
|
|
38
39
|
colors: unwrapColors(tokens.colors),
|
|
39
40
|
semantic: tokens.semanticColors,
|
|
40
41
|
typography: tokens.typography,
|
|
@@ -51,5 +52,6 @@ export const createTheme = (tokens: HightideDesignTokens): Theme => ({
|
|
|
51
52
|
multiSelect: createMultiSelectThemeFromDesign(tokens),
|
|
52
53
|
chat: createChatThemeFromDesign(tokens),
|
|
53
54
|
menu: createMenuThemeFromDesign(tokens),
|
|
55
|
+
avatar: createAvatarThemeFromDesign(tokens),
|
|
54
56
|
},
|
|
55
57
|
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ThemeTokens as designThemes } from '@helpwave/hightide-design/tokens'
|
|
2
|
+
import { createHightideTheme } from './createHightideTheme'
|
|
3
|
+
|
|
4
|
+
export const lightTheme = createHightideTheme(designThemes.light)
|
|
5
|
+
export const darkTheme = createHightideTheme(designThemes.dark)
|
|
6
|
+
|
|
7
|
+
export const themes = {
|
|
8
|
+
light: lightTheme,
|
|
9
|
+
dark: darkTheme,
|
|
10
|
+
} as const
|
|
11
|
+
|
|
12
|
+
export type HightideThemeModes = 'dark' | 'light'
|
|
13
|
+
|
|
14
|
+
export type ThemeMode = string | HightideThemeModes
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
1
|
+
export * from './createHightideTheme'
|
|
2
|
+
export * from './hightideThemes'
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ImageStyle,
|
|
3
|
+
TextStyle,
|
|
4
|
+
ViewStyle
|
|
5
|
+
} from 'react-native'
|
|
6
|
+
|
|
7
|
+
import type { ElementSize } from '@helpwave/hightide-design/types'
|
|
8
|
+
|
|
9
|
+
import type { StyleResolverFunction } from '../resolver'
|
|
10
|
+
|
|
11
|
+
export type AvatarStatus = 'online' | 'offline' | 'away' | 'busy' | 'unknown'
|
|
12
|
+
|
|
13
|
+
export type AvatarState = {
|
|
14
|
+
size?: ElementSize,
|
|
15
|
+
isGrouped?: boolean,
|
|
16
|
+
groupIndex?: number,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type AvatarWithStatusState = {
|
|
20
|
+
size?: ElementSize,
|
|
21
|
+
status?: AvatarStatus,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type AvatarWithLabelState = {
|
|
25
|
+
size?: ElementSize,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type AvatarGroupState = {
|
|
29
|
+
size?: ElementSize,
|
|
30
|
+
count?: number,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type AvatarStyle = ViewStyle
|
|
34
|
+
|
|
35
|
+
export type AvatarImageStyle = ImageStyle
|
|
36
|
+
|
|
37
|
+
export type AvatarTextStyle = TextStyle
|
|
38
|
+
|
|
39
|
+
export type AvatarIconStyle = {
|
|
40
|
+
size: number,
|
|
41
|
+
strokeWidth: number,
|
|
42
|
+
color: string,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type AvatarStatusDotStyle = ViewStyle
|
|
46
|
+
|
|
47
|
+
export type AvatarWithStatusContainerStyle = ViewStyle
|
|
48
|
+
|
|
49
|
+
export type AvatarWithLabelContainerStyle = ViewStyle
|
|
50
|
+
|
|
51
|
+
export type AvatarWithLabelTextStyle = TextStyle
|
|
52
|
+
|
|
53
|
+
export type AvatarGroupContainerStyle = ViewStyle
|
|
54
|
+
|
|
55
|
+
export type AvatarGroupStackStyle = ViewStyle
|
|
56
|
+
|
|
57
|
+
export type AvatarGroupMoreStyle = TextStyle
|
|
58
|
+
|
|
59
|
+
export type AvatarTheme = {
|
|
60
|
+
avatar: StyleResolverFunction<AvatarState, AvatarStyle>,
|
|
61
|
+
image: StyleResolverFunction<AvatarState, AvatarImageStyle>,
|
|
62
|
+
text: StyleResolverFunction<AvatarState, AvatarTextStyle>,
|
|
63
|
+
icon: StyleResolverFunction<AvatarState, AvatarIconStyle>,
|
|
64
|
+
withStatus: {
|
|
65
|
+
container: StyleResolverFunction<AvatarWithStatusState, AvatarWithStatusContainerStyle>,
|
|
66
|
+
statusDot: StyleResolverFunction<AvatarWithStatusState, AvatarStatusDotStyle>,
|
|
67
|
+
},
|
|
68
|
+
withLabel: {
|
|
69
|
+
container: StyleResolverFunction<AvatarWithLabelState, AvatarWithLabelContainerStyle>,
|
|
70
|
+
text: StyleResolverFunction<AvatarWithLabelState, AvatarWithLabelTextStyle>,
|
|
71
|
+
},
|
|
72
|
+
group: {
|
|
73
|
+
container: StyleResolverFunction<AvatarGroupState, AvatarGroupContainerStyle>,
|
|
74
|
+
stack: StyleResolverFunction<AvatarGroupState, AvatarGroupStackStyle>,
|
|
75
|
+
more: StyleResolverFunction<AvatarGroupState, AvatarGroupMoreStyle>,
|
|
76
|
+
},
|
|
77
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Color } from '../color'
|
|
2
|
+
import type { AvatarTheme } from './avatar'
|
|
2
3
|
import type { ButtonTheme } from './button'
|
|
3
4
|
import type { ChatTheme } from './chat'
|
|
4
5
|
import type { CheckboxTheme } from './checkbox'
|
|
@@ -39,4 +40,5 @@ export type HightideComponentThemes = {
|
|
|
39
40
|
multiSelect: MultiSelectTheme,
|
|
40
41
|
chat: ChatTheme,
|
|
41
42
|
menu: MenuTheme,
|
|
43
|
+
avatar: AvatarTheme,
|
|
42
44
|
}
|
|
@@ -43,4 +43,16 @@ export type HightideLayout = {
|
|
|
43
43
|
borderRadius: number,
|
|
44
44
|
fontSize: number,
|
|
45
45
|
}>,
|
|
46
|
+
avatar: Record<ElementSize, {
|
|
47
|
+
size: number,
|
|
48
|
+
padding: number,
|
|
49
|
+
fontSize: number,
|
|
50
|
+
statusDotSize: number,
|
|
51
|
+
statusDotBorderWidth: number,
|
|
52
|
+
}>,
|
|
53
|
+
avatarGroup: {
|
|
54
|
+
overlap: number,
|
|
55
|
+
maxShown: number,
|
|
56
|
+
gap: number,
|
|
57
|
+
},
|
|
46
58
|
}
|
package/src/theme/types/theme.ts
CHANGED
|
@@ -8,10 +8,19 @@ import type { HightideLayout } from './layout'
|
|
|
8
8
|
import type { HightideTypography } from './typography'
|
|
9
9
|
|
|
10
10
|
export type Theme = {
|
|
11
|
-
colors: Record<string, unknown
|
|
12
|
-
semantic: Record<string, unknown
|
|
13
|
-
components: Record<string, unknown
|
|
14
|
-
typography: Record<string, unknown
|
|
15
|
-
layout: Record<string, unknown
|
|
16
|
-
decoration: Record<string, unknown
|
|
11
|
+
colors: Record<string, unknown>,
|
|
12
|
+
semantic: Record<string, unknown>,
|
|
13
|
+
components: Record<string, unknown>,
|
|
14
|
+
typography: Record<string, unknown>,
|
|
15
|
+
layout: Record<string, unknown>,
|
|
16
|
+
decoration: Record<string, unknown>,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type HightideTheme = Theme & {
|
|
20
|
+
colors: HightideColors & Theme['colors'],
|
|
21
|
+
semantic: HightideSemanticColors & Theme['semantic'],
|
|
22
|
+
components: HightideComponentThemes & Theme['components'],
|
|
23
|
+
typography: HightideTypography & Theme['typography'],
|
|
24
|
+
layout: HightideLayout & Theme['layout'],
|
|
25
|
+
decoration: HightideDecoration & Theme['decoration'],
|
|
17
26
|
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Themes as designThemes } from '@helpwave/hightide-design/tokens'
|
|
2
|
-
|
|
3
|
-
import { createTheme } from './createTheme'
|
|
4
|
-
|
|
5
|
-
export const lightTheme = createTheme(designThemes.light)
|
|
6
|
-
|
|
7
|
-
export const darkTheme = createTheme(designThemes.dark)
|
|
8
|
-
|
|
9
|
-
export const themes = {
|
|
10
|
-
light: lightTheme,
|
|
11
|
-
dark: darkTheme,
|
|
12
|
-
} as const
|
|
13
|
-
|
|
14
|
-
export type HightideThemeModes = 'dark' | 'light'
|
|
15
|
-
|
|
16
|
-
export type ThemeMode = string | HightideThemeModes
|