@veracity/vui 2.14.8-beta.2 → 2.15.2

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 (41) hide show
  1. package/dist/cjs/avatar/avatar.d.ts.map +1 -1
  2. package/dist/cjs/avatar/avatar.js +40 -9
  3. package/dist/cjs/header/header.types.d.ts +9 -4
  4. package/dist/cjs/header/header.types.d.ts.map +1 -1
  5. package/dist/cjs/header/loggedInHeader.d.ts.map +1 -1
  6. package/dist/cjs/header/loggedInHeader.js +44 -41
  7. package/dist/cjs/header/loggedOutHeader.d.ts.map +1 -1
  8. package/dist/cjs/header/loggedOutHeader.js +17 -3
  9. package/dist/cjs/input/consts.js +2 -2
  10. package/dist/cjs/menu/menu.types.d.ts +5 -1
  11. package/dist/cjs/menu/menu.types.d.ts.map +1 -1
  12. package/dist/cjs/menu/menuList.d.ts.map +1 -1
  13. package/dist/cjs/menu/menuList.js +6 -1
  14. package/dist/cjs/utils/images.d.ts +3 -0
  15. package/dist/cjs/utils/images.d.ts.map +1 -0
  16. package/dist/cjs/utils/images.js +24 -0
  17. package/dist/esm/avatar/avatar.d.ts.map +1 -1
  18. package/dist/esm/avatar/avatar.js +17 -9
  19. package/dist/esm/header/header.types.d.ts +9 -4
  20. package/dist/esm/header/header.types.d.ts.map +1 -1
  21. package/dist/esm/header/loggedInHeader.d.ts.map +1 -1
  22. package/dist/esm/header/loggedInHeader.js +38 -35
  23. package/dist/esm/header/loggedOutHeader.d.ts.map +1 -1
  24. package/dist/esm/header/loggedOutHeader.js +18 -4
  25. package/dist/esm/input/consts.js +2 -2
  26. package/dist/esm/menu/menu.types.d.ts +5 -1
  27. package/dist/esm/menu/menu.types.d.ts.map +1 -1
  28. package/dist/esm/menu/menuList.d.ts.map +1 -1
  29. package/dist/esm/menu/menuList.js +6 -1
  30. package/dist/esm/utils/images.d.ts +3 -0
  31. package/dist/esm/utils/images.d.ts.map +1 -0
  32. package/dist/esm/utils/images.js +20 -0
  33. package/package.json +1 -1
  34. package/src/avatar/avatar.tsx +45 -18
  35. package/src/header/header.types.ts +31 -25
  36. package/src/header/loggedInHeader.tsx +115 -93
  37. package/src/header/loggedOutHeader.tsx +39 -4
  38. package/src/input/consts.ts +2 -2
  39. package/src/menu/menu.types.ts +5 -1
  40. package/src/menu/menuList.tsx +15 -1
  41. package/src/utils/images.ts +20 -0
@@ -1,6 +1,7 @@
1
1
  import React from 'react'
2
2
 
3
3
  import Box from '../box'
4
+ import Button from '../button'
4
5
  import { RenderOnScreen, useDown, useStyleConfig, vui } from '../core'
5
6
  import List from '../list'
6
7
  import { cs, isJsx } from '../utils'
@@ -20,6 +21,7 @@ export const LoggedInHeader = vui<'div', LoggedInHeaderProps>((props, ref) => {
20
21
  children,
21
22
  className,
22
23
  isApplication = false,
24
+ isCleanLayout = false,
23
25
  logo,
24
26
  mainLinks,
25
27
  services,
@@ -27,6 +29,7 @@ export const LoggedInHeader = vui<'div', LoggedInHeaderProps>((props, ref) => {
27
29
  showMainLinks = isApplication ? false : true,
28
30
  showServices = true,
29
31
  notifications,
32
+ url,
30
33
  ...rest
31
34
  } = props
32
35
 
@@ -47,7 +50,7 @@ export const LoggedInHeader = vui<'div', LoggedInHeaderProps>((props, ref) => {
47
50
 
48
51
  return (
49
52
  <Header
50
- className={cs('vui-loggedInHeader', isApplication ? 'vui-loggedInAppHeader' : '', className)}
53
+ className={cs('vui-loggedInHeader', isApplication ? 'vui-loggedInAppHeader' : undefined, className)}
51
54
  mb={isApplication && isSmallScreen ? '41px' : 'inherited'}
52
55
  ref={ref}
53
56
  {...rest}
@@ -64,106 +67,125 @@ export const LoggedInHeader = vui<'div', LoggedInHeaderProps>((props, ref) => {
64
67
  )}
65
68
  {!isApplication && <RenderOnScreen minWidth="lg">{children}</RenderOnScreen>}
66
69
  <Box ml="auto" />
67
- {isApplication && (
70
+ {isCleanLayout ? (
68
71
  <>
69
- <RenderOnScreen minWidth="lg">
70
- {showMainLinks && mainLinks !== undefined && (
71
- <>
72
- {isJsx(mainLinks) ? mainLinks : <Header.MainLinks links={mainLinks} />}
73
- <Header.Divider mx={1} />
74
- </>
75
- )}
72
+ {!!url && (
73
+ <Box>
74
+ <Button as="a" className={cs('vui-headerSignOut')} href={url} size="lg" variant="secondaryDark">
75
+ Sign out
76
+ </Button>
77
+ </Box>
78
+ )}
79
+ </>
80
+ ) : (
81
+ <>
82
+ {isApplication && (
83
+ <>
84
+ <RenderOnScreen minWidth="lg">
85
+ {showMainLinks && mainLinks !== undefined && (
86
+ <>
87
+ {isJsx(mainLinks) ? mainLinks : <Header.MainLinks links={mainLinks} />}
88
+ <Header.Divider mx={1} />
89
+ </>
90
+ )}
76
91
 
77
- {/* the main-links are folded into the hamburger menu by default */}
78
- {!showMainLinks && mainLinks && (
79
- <>
80
- <Header.MobileToggle ml={0} />
81
- <Header.MobileContent>
92
+ {/* the main-links are folded into the hamburger menu by default */}
93
+ {!showMainLinks && mainLinks && (
82
94
  <>
83
- {isJsx(mainLinks) ? (
84
- mainLinks
85
- ) : (
86
- <Box column w={1}>
87
- <List py={1}>
88
- {mainLinks?.map(({ icon, url, ...rest }, index) => (
89
- <List.Item iconLeft={icon} key={index} linkProps={{ href: url }} {...rest} />
90
- ))}
91
- </List>
92
- </Box>
93
- )}
94
-
95
- {!showServices && servicesLinks && (
96
- <Box column w={1}>
97
- <List
98
- className="vui-headerHiddenServicesLargeScreen"
99
- heading="My Services"
100
- maxH={295}
101
- right={0}
102
- w={320}
103
- {...styles.services.list}
104
- borderTop={1}
105
- borderTopColor="sandstone.main"
106
- pt={1}
107
- >
108
- {servicesLinks.length > 0 ? (
109
- servicesLinks?.map(({ url, ...rest }, index: number) => (
110
- <List.Item key={index} linkProps={{ href: url }} {...rest} />
111
- ))
112
- ) : (
113
- <HeaderServicesMessage />
114
- )}
115
- </List>
116
- </Box>
117
- )}
95
+ <Header.MobileToggle ml={0} />
96
+ <Header.MobileContent>
97
+ <>
98
+ {isJsx(mainLinks) ? (
99
+ mainLinks
100
+ ) : (
101
+ <Box column w={1}>
102
+ <List py={1}>
103
+ {mainLinks?.map(({ icon, url, ...rest }, index) => (
104
+ <List.Item iconLeft={icon} key={index} linkProps={{ href: url }} {...rest} />
105
+ ))}
106
+ </List>
107
+ </Box>
108
+ )}
109
+
110
+ {!showServices && servicesLinks && (
111
+ <Box column w={1}>
112
+ <List
113
+ className="vui-headerHiddenServicesLargeScreen"
114
+ heading="My Services"
115
+ maxH={295}
116
+ right={0}
117
+ w={320}
118
+ {...styles.services.list}
119
+ borderTop={1}
120
+ borderTopColor="sandstone.main"
121
+ pt={1}
122
+ >
123
+ {servicesLinks.length > 0 ? (
124
+ servicesLinks?.map(({ url, ...rest }, index: number) => (
125
+ <List.Item key={index} linkProps={{ href: url }} {...rest} />
126
+ ))
127
+ ) : (
128
+ <HeaderServicesMessage />
129
+ )}
130
+ </List>
131
+ </Box>
132
+ )}
133
+ </>
134
+ </Header.MobileContent>
118
135
  </>
119
- </Header.MobileContent>
136
+ )}
137
+ {showServices && services && (
138
+ <>{isJsx(services) ? services : <Header.Services isApplication={isApplication} {...services} />}</>
139
+ )}
140
+ </RenderOnScreen>
141
+
142
+ <Header.Support {...supportLinks} />
143
+ </>
144
+ )}
145
+ {!isApplication && (
146
+ <RenderOnScreen minWidth="lg">
147
+ {isJsx(mainLinks) ? mainLinks : <Header.MainLinks links={mainLinks} />}
148
+
149
+ {mainLinks !== undefined && <Header.Divider mx={1} />}
150
+
151
+ {isJsx(services) ? services : <Header.Services {...services} />}
152
+ </RenderOnScreen>
153
+ )}
154
+ {isJsx(notifications) ? notifications : <Header.Notifications {...notifications} />}
155
+ {!showMainLinks &&
156
+ showAltUserInfo &&
157
+ (isJsx(userInfo) ? (
158
+ userInfo
159
+ ) : (
160
+ <>
161
+ <Header.Divider ml={2} />
162
+ <HeaderAccountUserInfo
163
+ className="vui-altUserInfo"
164
+ color={localTextColor}
165
+ isApplication
166
+ {...userInfo}
167
+ />
120
168
  </>
121
- )}
122
- {showServices && services && (
123
- <>{isJsx(services) ? services : <Header.Services isApplication={isApplication} {...services} />}</>
124
- )}
169
+ ))}
170
+ {isJsx(account) ? account : <Header.Account {...account} />}
171
+ <RenderOnScreen maxWidth="lg">
172
+ {isApplication && <Header.Divider ml={1} />}
173
+ {!isApplication && (account !== undefined || notifications !== undefined) && <Header.Divider ml={1} />}
174
+
175
+ <Header.MobileToggle />
176
+
177
+ <Header.MobileContent>
178
+ {!isApplication && children}
179
+ {isJsx(mainLinks) ? mainLinks : <Header.MainLinks links={mainLinks} />}
180
+ {isJsx(services) ? (
181
+ services
182
+ ) : (
183
+ <Header.Services {...services} showTopBorder={mainLinks ? true : false} />
184
+ )}
185
+ </Header.MobileContent>
125
186
  </RenderOnScreen>
126
-
127
- <Header.Support {...supportLinks} />
128
187
  </>
129
188
  )}
130
- {!isApplication && (
131
- <RenderOnScreen minWidth="lg">
132
- {isJsx(mainLinks) ? mainLinks : <Header.MainLinks links={mainLinks} />}
133
-
134
- {mainLinks !== undefined && <Header.Divider mx={1} />}
135
-
136
- {isJsx(services) ? services : <Header.Services {...services} />}
137
- </RenderOnScreen>
138
- )}
139
- {isJsx(notifications) ? notifications : <Header.Notifications {...notifications} />}
140
-
141
- {!showMainLinks &&
142
- showAltUserInfo &&
143
- (isJsx(userInfo) ? (
144
- userInfo
145
- ) : (
146
- <>
147
- <Header.Divider ml={2} />
148
- <HeaderAccountUserInfo className="vui-altUserInfo" color={localTextColor} isApplication {...userInfo} />
149
- </>
150
- ))}
151
-
152
- {isJsx(account) ? account : <Header.Account {...account} />}
153
- <RenderOnScreen maxWidth="lg">
154
- {isApplication && <Header.Divider ml={1} />}
155
- {!isApplication && (account !== undefined || notifications !== undefined) && <Header.Divider ml={1} />}
156
-
157
- <Header.MobileToggle />
158
-
159
- <Header.MobileContent>
160
- {!isApplication && children}
161
-
162
- {isJsx(mainLinks) ? mainLinks : <Header.MainLinks links={mainLinks} />}
163
-
164
- {isJsx(services) ? services : <Header.Services {...services} showTopBorder={mainLinks ? true : false} />}
165
- </Header.MobileContent>
166
- </RenderOnScreen>
167
189
  </Header.Content>
168
190
  </Header>
169
191
  )
@@ -1,19 +1,54 @@
1
1
  import React from 'react'
2
2
 
3
3
  import Box from '../box'
4
- import { RenderOnScreen, vui } from '../core'
4
+ import { RenderOnScreen, useDown, vui } from '../core'
5
5
  import { cs, isJsx } from '../utils'
6
6
  import Header from './header'
7
7
  import { LoggedOutHeaderProps } from './header.types'
8
8
 
9
9
  /** Displays Header content appropriate for logged out users, such as sign in button or create account prompt. */
10
10
  export const LoggedOutHeader = vui<'div', LoggedOutHeaderProps>((props, ref) => {
11
- const { children, className, createAccount, logo, mainLinks, signIn, ...rest } = props
11
+ const {
12
+ applicationName,
13
+ applicationUrl,
14
+ children,
15
+ className,
16
+ isApplication = false,
17
+ createAccount,
18
+ logo,
19
+ mainLinks,
20
+ signIn,
21
+ ...rest
22
+ } = props
23
+
24
+ if (isApplication) {
25
+ if (!applicationName) {
26
+ console.error('Header: isApplication is true but applicationName is not set.')
27
+ }
28
+ }
29
+
30
+ const isSmallScreen = useDown('md')
31
+ const isLessThanMD = useDown('sm')
32
+
33
+ const localTextColor = rest?.variant === 'dark' ? 'white' : 'darkBlue.main'
12
34
 
13
35
  return (
14
- <Header className={cs('vui-loggedOutHeader', className)} ref={ref} {...rest}>
36
+ <Header
37
+ className={cs('vui-loggedOutHeader', isApplication ? 'vui-loggedOutAppHeader' : undefined, className)}
38
+ mb={isApplication && isSmallScreen ? '41px' : 'inherited'}
39
+ ref={ref}
40
+ {...rest}
41
+ >
15
42
  <Header.Content>
16
- {isJsx(logo) ? logo : <Header.Logo {...logo} />}
43
+ {(!isApplication || !isLessThanMD) && <> {isJsx(logo) ? logo : <Header.Logo {...logo} />}</>}
44
+ {isApplication && (
45
+ <>
46
+ <RenderOnScreen minWidth="sm">
47
+ <Header.Divider mr={2} />
48
+ </RenderOnScreen>
49
+ <Header.ApplicationName color={localTextColor} title={applicationName} url={applicationUrl || '/'} />
50
+ </>
51
+ )}
17
52
 
18
53
  <RenderOnScreen minWidth="lg">{children}</RenderOnScreen>
19
54
 
@@ -54,6 +54,6 @@ export const displayValueOnlyTextSize = {
54
54
  export const clearIconSize = {
55
55
  sm: 'sm',
56
56
  md: 'sm',
57
- lg: 'md',
58
- xl: 'lg'
57
+ lg: 'sm',
58
+ xl: 'md'
59
59
  }
@@ -1,4 +1,4 @@
1
- import { RefObject } from 'react'
1
+ import { ReactNode, RefObject } from 'react'
2
2
 
3
3
  import { ListProps } from '../list'
4
4
  import { PopoverContentProps, PopoverProps } from '../popover'
@@ -9,6 +9,10 @@ export type MenuListProps = ListProps & {
9
9
  contentProps?: PopoverContentProps
10
10
  /** Ref passed to the inner PopoverContent. */
11
11
  contentRef?: RefObject<HTMLDivElement>
12
+ /** Custom content displayed at the bottom of the panel */
13
+ slotBottom?: ReactNode
14
+ /** Custom content displayed at the top of the panel */
15
+ slotTop?: ReactNode
12
16
  }
13
17
 
14
18
  export type MenuProps = ThemingProps<'Menu'> &
@@ -1,5 +1,6 @@
1
1
  import React from 'react'
2
2
 
3
+ import { Box } from '../box'
3
4
  import { useStyleConfig, vui, VuiComponent } from '../core'
4
5
  import List from '../list'
5
6
  import { PopoverContent } from '../popover'
@@ -10,11 +11,24 @@ import { MenuListProps } from './menu.types'
10
11
  /** Displays a list of menu items in a popover content element. */
11
12
  export const MenuList = vui<'ul', MenuListProps>((props, ref) => {
12
13
  const { className, contentProps, contentRef, ...rest } = props
14
+ const { slotTop, slotBottom } = props
13
15
  const styles = useStyleConfig('Menu', useMenuContext())
14
16
 
15
17
  return (
16
18
  <PopoverContent borderRadius={0} ref={contentRef} {...contentProps}>
17
- <List className={cs('vui-menuList', className)} py={1} ref={ref} w="100%" {...styles.list} {...rest} maxH={295} />
19
+ <Box flexDirection="column">
20
+ {slotTop}
21
+ <List
22
+ className={cs('vui-menuList', className)}
23
+ py={1}
24
+ ref={ref}
25
+ w="100%"
26
+ {...styles.list}
27
+ {...rest}
28
+ maxH={295}
29
+ />
30
+ {slotBottom}
31
+ </Box>
18
32
  </PopoverContent>
19
33
  )
20
34
  }) as VuiComponent<'ul', MenuListProps> & {
@@ -0,0 +1,20 @@
1
+ const loadImagePromises = new Map<string, Promise<boolean>>()
2
+
3
+ /** Attempts to load the image and returns a boolean indicating success or not. */
4
+ export function loadImageUrl(url: string) {
5
+ let promise = loadImagePromises.get(url)
6
+ if (promise) return promise
7
+ promise = new Promise(resolve => {
8
+ const img = new Image()
9
+ img.onload = () => {
10
+ // After this event occurs, you can use the url in the DOM. The browser will not make another request for the image; there will be no delay.
11
+ resolve(true)
12
+ }
13
+ img.onerror = () => {
14
+ resolve(false)
15
+ }
16
+ img.src = url
17
+ })
18
+ loadImagePromises.set(url, promise)
19
+ return promise
20
+ }