vitepress 1.0.0-alpha.2 → 1.0.0-alpha.3

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 (61) hide show
  1. package/dist/client/app/data.js +5 -7
  2. package/dist/client/theme-default/Layout.vue +2 -0
  3. package/dist/client/theme-default/components/VPAlgoliaSearchBox.vue +3 -4
  4. package/dist/client/theme-default/components/VPDoc.vue +0 -20
  5. package/dist/client/theme-default/components/VPDocFooter.vue +2 -2
  6. package/dist/client/theme-default/components/VPFlyout.vue +8 -0
  7. package/dist/client/theme-default/components/VPHero.vue +8 -9
  8. package/dist/client/theme-default/components/VPImage.vue +38 -0
  9. package/dist/client/theme-default/components/VPNavBar.vue +0 -1
  10. package/dist/client/theme-default/components/VPNavBarHamburger.vue +10 -10
  11. package/dist/client/theme-default/components/VPNavBarMenuGroup.vue +17 -2
  12. package/dist/client/theme-default/components/VPNavBarMenuLink.vue +1 -1
  13. package/dist/client/theme-default/components/VPNavBarTitle.vue +3 -2
  14. package/dist/client/theme-default/components/VPNavScreenMenuGroupSection.vue +1 -1
  15. package/dist/client/theme-default/components/VPSidebarGroup.vue +6 -3
  16. package/dist/client/theme-default/components/VPSidebarLink.vue +2 -2
  17. package/dist/client/theme-default/components/VPSocialLink.vue +1 -1
  18. package/dist/client/theme-default/components/VPSocialLinks.vue +1 -1
  19. package/dist/client/theme-default/components/VPTeamMembers.vue +55 -0
  20. package/dist/client/theme-default/components/VPTeamMembersItem.vue +215 -0
  21. package/dist/client/theme-default/components/VPTeamPage.vue +53 -0
  22. package/dist/client/theme-default/components/VPTeamPageSection.vue +77 -0
  23. package/dist/client/theme-default/components/VPTeamPageTitle.vue +63 -0
  24. package/dist/client/theme-default/composables/copy-code.js +37 -1
  25. package/dist/client/theme-default/composables/sidebar.js +3 -1
  26. package/dist/client/theme-default/fonts/inter-cyrillic-ext.woff2 +0 -0
  27. package/dist/client/theme-default/fonts/inter-cyrillic.woff2 +0 -0
  28. package/dist/client/theme-default/fonts/inter-greek-ext.woff2 +0 -0
  29. package/dist/client/theme-default/fonts/inter-greek.woff2 +0 -0
  30. package/dist/client/theme-default/fonts/inter-italic-cyrillic-ext.woff2 +0 -0
  31. package/dist/client/theme-default/fonts/inter-italic-cyrillic.woff2 +0 -0
  32. package/dist/client/theme-default/fonts/inter-italic-greek-ext.woff2 +0 -0
  33. package/dist/client/theme-default/fonts/inter-italic-greek.woff2 +0 -0
  34. package/dist/client/theme-default/fonts/inter-italic-latin-ext.woff2 +0 -0
  35. package/dist/client/theme-default/fonts/inter-italic-latin.woff2 +0 -0
  36. package/dist/client/theme-default/fonts/inter-italic-vietnamese.woff2 +0 -0
  37. package/dist/client/theme-default/fonts/inter-latin-ext.woff2 +0 -0
  38. package/dist/client/theme-default/fonts/inter-latin.woff2 +0 -0
  39. package/dist/client/theme-default/fonts/inter-roman-cyrillic-ext.woff2 +0 -0
  40. package/dist/client/theme-default/fonts/inter-roman-cyrillic.woff2 +0 -0
  41. package/dist/client/theme-default/fonts/inter-roman-greek-ext.woff2 +0 -0
  42. package/dist/client/theme-default/fonts/inter-roman-greek.woff2 +0 -0
  43. package/dist/client/theme-default/fonts/inter-roman-latin-ext.woff2 +0 -0
  44. package/dist/client/theme-default/fonts/inter-roman-latin.woff2 +0 -0
  45. package/dist/client/theme-default/fonts/inter-roman-vietnamese.woff2 +0 -0
  46. package/dist/client/theme-default/fonts/inter-vietnamese.woff2 +0 -0
  47. package/dist/client/theme-default/index.js +4 -0
  48. package/dist/client/theme-default/styles/components/vp-doc.css +24 -1
  49. package/dist/client/theme-default/styles/fonts.css +185 -35
  50. package/dist/client/theme-default/styles/vars.css +2 -2
  51. package/dist/node/cli.js +2 -2
  52. package/dist/node/index.d.ts +27 -1
  53. package/dist/node/index.js +1 -1
  54. package/dist/node/{serve-42a92e2f.js → serve-05342c3d.js} +11 -3
  55. package/dist/node-cjs/cli.cjs +2 -2
  56. package/dist/node-cjs/index.cjs +1 -1
  57. package/dist/node-cjs/{serve-507b373b.cjs → serve-f2029a83.cjs} +14 -6
  58. package/package.json +1 -1
  59. package/theme.d.ts +4 -0
  60. package/types/default-theme.d.ts +25 -1
  61. package/dist/client/theme-default/config.js +0 -1
@@ -1,17 +1,15 @@
1
1
  import { shallowRef, readonly, computed, inject } from 'vue';
2
- import serializedSiteData from '@siteData';
2
+ import siteData from '@siteData';
3
3
  import { resolveSiteDataByRoute, createTitle } from '../shared';
4
4
  import { withBase } from './utils';
5
5
  export const dataSymbol = Symbol();
6
- export const siteDataRef = shallowRef(parse(serializedSiteData));
7
- function parse(data) {
8
- const parsed = JSON.parse(data);
9
- return (import.meta.env.DEV ? readonly(parsed) : parsed);
10
- }
6
+ export const siteDataRef = shallowRef(import.meta.env.PROD ? siteData : readonly(siteData));
11
7
  // hmr
12
8
  if (import.meta.hot) {
13
9
  import.meta.hot.accept('/@siteData', (m) => {
14
- siteDataRef.value = parse(m.default);
10
+ if (m) {
11
+ siteDataRef.value = m.default;
12
+ }
15
13
  });
16
14
  }
17
15
  // per-app data
@@ -22,6 +22,7 @@ provide('close-sidebar', closeSidebar)
22
22
 
23
23
  <template>
24
24
  <div class="Layout">
25
+ <slot name="layout-top" />
25
26
  <VPSkipLink />
26
27
  <VPBackdrop class="backdrop" :show="isSidebarOpen" @click="closeSidebar" />
27
28
  <VPNav />
@@ -46,6 +47,7 @@ provide('close-sidebar', closeSidebar)
46
47
  </VPContent>
47
48
 
48
49
  <VPFooter />
50
+ <slot name="layout-bottom" />
49
51
  </div>
50
52
  </template>
51
53
 
@@ -1,9 +1,8 @@
1
1
  <script setup lang="ts">
2
+ import type { DefaultTheme } from 'vitepress/theme'
2
3
  import docsearch from '@docsearch/js'
3
- import { DocSearchHit } from '@docsearch/react/dist/esm/types'
4
4
  import { onMounted } from 'vue'
5
5
  import { useRouter, useRoute, useData } from 'vitepress'
6
- import { DefaultTheme } from '../config'
7
6
 
8
7
  const router = useRouter()
9
8
  const route = useRoute()
@@ -52,7 +51,7 @@ function initialize(userOptions: DefaultTheme.AlgoliaSearchOptions) {
52
51
  }
53
52
  },
54
53
 
55
- transformItems(items: DocSearchHit[]) {
54
+ transformItems(items: any[]) {
56
55
  return items.map((item) => {
57
56
  return Object.assign({}, item, {
58
57
  url: getRelativePath(item.url)
@@ -60,7 +59,7 @@ function initialize(userOptions: DefaultTheme.AlgoliaSearchOptions) {
60
59
  })
61
60
  },
62
61
 
63
- hitComponent({ hit, children }: { hit: DocSearchHit, children: any }) {
62
+ hitComponent({ hit, children }: { hit: any; children: any }) {
64
63
  const relativeHit = hit.url.startsWith('http')
65
64
  ? getRelativePath(hit.url as string)
66
65
  : hit.url
@@ -169,24 +169,4 @@ const pageName = path.replace(/[./]+/g, '_').replace(/_html$/, '')
169
169
  margin: 0 auto;
170
170
  max-width: 688px;
171
171
  }
172
-
173
- .edit-link {
174
- margin: 0 0 32px;
175
- }
176
-
177
- .edit-link .vt-link {
178
- font-size: 14px;
179
- color: var(--vt-c-brand);
180
- font-weight: 500;
181
- }
182
-
183
- .vt-icon {
184
- width: 18px;
185
- height: 18px;
186
- color: var(--vt-c-brand);
187
- display: inline-block;
188
- margin-right: 8px;
189
- position: relative;
190
- top: -1px;
191
- }
192
172
  </style>
@@ -19,7 +19,7 @@ const hasLastUpdated = computed(() => {
19
19
  </script>
20
20
 
21
21
  <template>
22
- <footer v-if="control.prev || control.next" class="VPDocFooter">
22
+ <footer class="VPDocFooter">
23
23
  <div class="edit-info">
24
24
  <div v-if="theme.editLink && frontmatter.editLink !== false" class="edit-link">
25
25
  <VPLink class="edit-link-button" :href="editLink.url" :no-icon="true">
@@ -33,7 +33,7 @@ const hasLastUpdated = computed(() => {
33
33
  </div>
34
34
  </div>
35
35
 
36
- <div class="prev-next">
36
+ <div v-if="control.prev || control.next" class="prev-next">
37
37
  <div class="pager">
38
38
  <a v-if="control.prev" class="pager-link prev" :href="normalizeLink(control.prev.link)">
39
39
  <span class="desc">Previous page</span>
@@ -72,6 +72,14 @@ function onBlur() {
72
72
  fill: var(--vp-c-text-2);
73
73
  }
74
74
 
75
+ .VPFlyout.active .text {
76
+ color: var(--vp-c-brand);
77
+ }
78
+
79
+ .VPFlyout.active:hover .text {
80
+ color: var(--vp-c-brand-dark);
81
+ }
82
+
75
83
  .VPFlyout:hover .menu,
76
84
  .button[aria-expanded="true"] + .menu {
77
85
  opacity: 1;
@@ -1,5 +1,7 @@
1
1
  <script setup lang="ts">
2
+ import type { DefaultTheme } from 'vitepress/theme'
2
3
  import VPButton from './VPButton.vue'
4
+ import VPImage from './VPImage.vue'
3
5
 
4
6
  export interface HeroAction {
5
7
  theme?: 'brand' | 'alt'
@@ -7,16 +9,11 @@ export interface HeroAction {
7
9
  link: string
8
10
  }
9
11
 
10
- export interface Image {
11
- src: string
12
- alt?: string
13
- }
14
-
15
12
  defineProps<{
16
13
  name?: string
17
14
  text: string
18
15
  tagline?: string
19
- image?: Image
16
+ image?: DefaultTheme.ThemeableImage
20
17
  actions?: HeroAction[]
21
18
  }>()
22
19
  </script>
@@ -25,7 +22,9 @@ defineProps<{
25
22
  <div class="VPHero" :class="{ 'has-image': image }">
26
23
  <div class="container">
27
24
  <div class="main">
28
- <h1 v-if="name" class="name"><span class="clip">{{ name }}</span></h1>
25
+ <h1 v-if="name" class="name">
26
+ <span class="clip">{{ name }}</span>
27
+ </h1>
29
28
  <p v-if="text" class="text">{{ text }}</p>
30
29
  <p v-if="tagline" class="tagline">{{ tagline }}</p>
31
30
 
@@ -45,7 +44,7 @@ defineProps<{
45
44
  <div v-if="image" class="image">
46
45
  <div class="image-container">
47
46
  <div class="image-bg" />
48
- <img class="image-src" :src="image.src" :alt="image.alt">
47
+ <VPImage class="image-src" :image="image" />
49
48
  </div>
50
49
  </div>
51
50
  </div>
@@ -293,7 +292,7 @@ defineProps<{
293
292
  }
294
293
  }
295
294
 
296
- .image-src {
295
+ :deep(.image-src) {
297
296
  position: absolute;
298
297
  top: 50%;
299
298
  left: 50%;
@@ -0,0 +1,38 @@
1
+ <script setup lang="ts">
2
+ import type { DefaultTheme } from 'vitepress/theme'
3
+ import { withBase } from 'vitepress'
4
+
5
+ defineProps<{
6
+ image: DefaultTheme.ThemeableImage
7
+ }>()
8
+ </script>
9
+
10
+ <script lang="ts">
11
+ export default {
12
+ inheritAttrs: false
13
+ }
14
+ </script>
15
+
16
+ <template>
17
+ <template v-if="image">
18
+ <img
19
+ v-if="typeof image === 'string' || 'src' in image"
20
+ class="VPImage"
21
+ v-bind="typeof image === 'string' ? $attrs : { ...image, ...$attrs }"
22
+ :src="withBase(typeof image === 'string' ? image : image.src)"
23
+ />
24
+ <template v-else>
25
+ <VPImage class="dark" :image="image.dark" v-bind="$attrs" />
26
+ <VPImage class="light" :image="image.light" v-bind="$attrs" />
27
+ </template>
28
+ </template>
29
+ </template>
30
+
31
+ <style scoped>
32
+ html:not(.dark) .VPImage.dark {
33
+ display: none;
34
+ }
35
+ .dark .VPImage.light {
36
+ display: none;
37
+ }
38
+ </style>
@@ -48,7 +48,6 @@ const { hasSidebar } = useSidebar()
48
48
  border-bottom: 1px solid var(--vp-c-divider-light);
49
49
  padding: 0 8px 0 24px;
50
50
  height: var(--vp-nav-height-mobile);
51
- background-color: var(--vt-c-bg);
52
51
  transition: border-color 0.5s, background-color 0.5s;
53
52
  }
54
53
 
@@ -48,18 +48,18 @@ defineEmits<{
48
48
  overflow: hidden;
49
49
  }
50
50
 
51
- .container:hover .top { top: 0; left: 0; transform: translateX(4px); }
52
- .container:hover .middle { top: 6; left: 0; transform: translateX(0); }
53
- .container:hover .bottom { top: 12px; left: 0; transform: translateX(8px); }
51
+ .VPNavBarHamburger:hover .top { top: 0; left: 0; transform: translateX(4px); }
52
+ .VPNavBarHamburger:hover .middle { top: 6; left: 0; transform: translateX(0); }
53
+ .VPNavBarHamburger:hover .bottom { top: 12px; left: 0; transform: translateX(8px); }
54
54
 
55
- .container.active .top { top: 6px; transform: translateX(0) rotate(225deg); }
56
- .container.active .middle { top: 6px; transform: translateX(16px); }
57
- .container.active .bottom { top: 6px; transform: translateX(0) rotate(135deg); }
55
+ .VPNavBarHamburger.active .top { top: 6px; transform: translateX(0) rotate(225deg); }
56
+ .VPNavBarHamburger.active .middle { top: 6px; transform: translateX(16px); }
57
+ .VPNavBarHamburger.active .bottom { top: 6px; transform: translateX(0) rotate(135deg); }
58
58
 
59
- .container.active:hover .top,
60
- .container.active:hover .middle,
61
- .container.active:hover .bottom {
62
- background-color: var(--vt-c-text-2);
59
+ .VPNavBarHamburger.active:hover .top,
60
+ .VPNavBarHamburger.active:hover .middle,
61
+ .VPNavBarHamburger.active:hover .bottom {
62
+ background-color: var(--vp-c-text-2);
63
63
  transition: top .25s, background-color .25s, transform .25s;
64
64
  }
65
65
 
@@ -1,12 +1,27 @@
1
1
  <script lang="ts" setup>
2
- import { DefaultTheme } from '../config'
2
+ import { useData } from 'vitepress'
3
+ import type { DefaultTheme } from 'vitepress/theme'
4
+ import { isActive } from '../support/utils'
3
5
  import VPFlyout from './VPFlyout.vue'
4
6
 
5
7
  defineProps<{
6
8
  item: DefaultTheme.NavItemWithChildren
7
9
  }>()
10
+
11
+ const { page } = useData()
8
12
  </script>
9
13
 
10
14
  <template>
11
- <VPFlyout :button="item.text" :items="item.items" />
15
+ <VPFlyout
16
+ :class="{
17
+ VPNavBarMenuGroup: true,
18
+ active: isActive(
19
+ page.relativePath,
20
+ item.activeMatch,
21
+ !!item.activeMatch
22
+ )
23
+ }"
24
+ :button="item.text"
25
+ :items="item.items"
26
+ />
12
27
  </template>
@@ -1,7 +1,7 @@
1
1
  <script lang="ts" setup>
2
+ import type { DefaultTheme } from 'vitepress/theme'
2
3
  import { useData } from 'vitepress'
3
4
  import { isActive } from '../support/utils'
4
- import { DefaultTheme } from '../config'
5
5
  import VPLink from './VPLink.vue'
6
6
 
7
7
  defineProps<{
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { useData } from 'vitepress'
3
3
  import { useSidebar } from '../composables/sidebar'
4
+ import VPImage from './VPImage.vue'
4
5
 
5
6
  const { site, theme } = useData()
6
7
  const { hasSidebar } = useSidebar()
@@ -9,7 +10,7 @@ const { hasSidebar } = useSidebar()
9
10
  <template>
10
11
  <div class="VPNavBarTitle" :class="{ 'has-sidebar': hasSidebar }">
11
12
  <a class="title" :href="site.base">
12
- <img v-if="theme.logo" class="logo" :src="theme.logo">
13
+ <VPImage class="logo" :image="theme.logo" />
13
14
  <template v-if="theme.siteTitle">{{ theme.siteTitle }}</template>
14
15
  <template v-else-if="theme.siteTitle === undefined">{{ site.title }}</template>
15
16
  </a>
@@ -52,7 +53,7 @@ const { hasSidebar } = useSidebar()
52
53
  }
53
54
  }
54
55
 
55
- .logo {
56
+ :deep(.logo) {
56
57
  margin-right: 8px;
57
58
  height: 24px;
58
59
  }
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import { DefaultTheme } from '../config'
2
+ import type { DefaultTheme } from 'vitepress/theme'
3
3
  import VPNavScreenMenuGroupLink from './VPNavScreenMenuGroupLink.vue'
4
4
 
5
5
  defineProps<{
@@ -1,6 +1,6 @@
1
1
  <script lang="ts" setup>
2
- import { ref } from 'vue'
3
- import { DefaultTheme } from '../config'
2
+ import type { DefaultTheme } from 'vitepress/theme'
3
+ import { ref, watchEffect } from 'vue'
4
4
  import VPIconPlusSquare from './icons/VPIconPlusSquare.vue'
5
5
  import VPIconMinusSquare from './icons/VPIconMinusSquare.vue'
6
6
  import VPSidebarLink from './VPSidebarLink.vue'
@@ -12,7 +12,10 @@ const props = defineProps<{
12
12
  collapsed?: boolean
13
13
  }>()
14
14
 
15
- const collapsed = ref(props.collapsible && props.collapsed)
15
+ const collapsed = ref(false)
16
+ watchEffect(() => {
17
+ collapsed.value = !!(props.collapsible && props.collapsed)
18
+ })
16
19
 
17
20
  function toggle() {
18
21
  if (props.collapsible) {
@@ -1,8 +1,8 @@
1
1
  <script lang="ts" setup>
2
+ import type { DefaultTheme } from 'vitepress/theme'
2
3
  import { inject } from 'vue'
3
4
  import { useData } from 'vitepress'
4
- import { DefaultTheme } from '../config'
5
- import { isActive, normalizeLink } from '../support/utils'
5
+ import { isActive } from '../support/utils'
6
6
  import VPLink from './VPLink.vue'
7
7
 
8
8
  defineProps<{
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import { DefaultTheme } from '../config'
2
+ import type { DefaultTheme } from 'vitepress/theme'
3
3
  import VPIconDiscord from './icons/VPIconDiscord.vue'
4
4
  import VPIconFacebook from './icons/VPIconFacebook.vue'
5
5
  import VPIconGitHub from './icons/VPIconGitHub.vue'
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import { DefaultTheme } from '../config'
2
+ import type { DefaultTheme } from 'vitepress/theme'
3
3
  import VPSocialLink from './VPSocialLink.vue'
4
4
 
5
5
  defineProps<{
@@ -0,0 +1,55 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+ import type { DefaultTheme } from '..'
4
+ import VPTeamMembersItem from './VPTeamMembersItem.vue'
5
+
6
+ const props = defineProps<{
7
+ size?: 'small' | 'medium'
8
+ members: DefaultTheme.TeamMember[]
9
+ }>()
10
+
11
+ const classes = computed(() => [
12
+ props.size ?? 'medium',
13
+ `count-${props.members.length}`
14
+ ])
15
+ </script>
16
+
17
+ <template>
18
+ <div class="VPTeamMembers" :class="classes">
19
+ <div class="container">
20
+ <div v-for="member in members" :key="member.name" class="item">
21
+ <VPTeamMembersItem :size="size" :member="member" />
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </template>
26
+
27
+ <style scoped>
28
+ .VPTeamMembers.small .container {
29
+ grid-template-columns: repeat(auto-fit, minmax(224px, 1fr));
30
+ }
31
+
32
+ .VPTeamMembers.small.count-1 .container { max-width: 276px; }
33
+ .VPTeamMembers.small.count-2 .container { max-width: calc(276px * 2 + 24px); }
34
+ .VPTeamMembers.small.count-3 .container { max-width: calc(276px * 3 + 24px * 2); }
35
+
36
+ .VPTeamMembers.medium .container {
37
+ grid-template-columns: repeat(auto-fit, minmax(256px, 1fr));
38
+ }
39
+
40
+ @media (min-width: 375px) {
41
+ .VPTeamMembers.medium .container {
42
+ grid-template-columns: repeat(auto-fit, minmax(288px, 1fr));
43
+ }
44
+ }
45
+
46
+ .VPTeamMembers.medium.count-1 .container { max-width: 368px; }
47
+ .VPTeamMembers.medium.count-2 .container { max-width: calc(368px * 2 + 24px); }
48
+
49
+ .container {
50
+ display: grid;
51
+ gap: 24px;
52
+ margin: 0 auto;
53
+ max-width: 1152px;
54
+ }
55
+ </style>
@@ -0,0 +1,215 @@
1
+ <script setup lang="ts">
2
+ import type { DefaultTheme } from '..'
3
+ import VPIconHeart from './icons/VPIconHeart.vue'
4
+ import VPLink from './VPLink.vue'
5
+ import VPSocialLinks from './VPSocialLinks.vue'
6
+
7
+ defineProps<{
8
+ size?: 'small' | 'medium'
9
+ member: DefaultTheme.TeamMember
10
+ }>()
11
+ </script>
12
+
13
+ <template>
14
+ <article class="VPTeamMembersItem" :class="[size ?? 'medium']">
15
+ <div class="profile">
16
+ <figure class="avatar">
17
+ <img class="avatar-img" :src="member.avatar" :alt="member.name">
18
+ </figure>
19
+ <div class="data">
20
+ <h1 class="name">
21
+ {{ member.name }}
22
+ </h1>
23
+ <p v-if="member.title || member.org" class="affiliation">
24
+ <span v-if="member.title" class="title">
25
+ {{ member.title }}
26
+ </span>
27
+ <span v-if="member.title && member.org" class="at">
28
+ @
29
+ </span>
30
+ <VPLink v-if="member.org" class="org" :class="{ link: member.orgLink }" :href="member.orgLink" no-icon>
31
+ {{ member.org }}
32
+ </VPLink>
33
+ </p>
34
+ <p v-if="member.desc" class="desc">
35
+ {{ member.desc }}
36
+ </p>
37
+ <div v-if="member.links" class="links">
38
+ <VPSocialLinks :links="member.links" />
39
+ </div>
40
+ </div>
41
+ </div>
42
+ <div v-if="member.sponsor" class="sponsor">
43
+ <VPLink class="sponsor-link" :href="member.sponsor" no-icon>
44
+ <VPIconHeart class="sponsor-icon" /> Sponsor
45
+ </VPLink>
46
+ </div>
47
+ </article>
48
+ </template>
49
+
50
+ <style scoped>
51
+ .VPTeamMembersItem {
52
+ display: flex;
53
+ flex-direction: column;
54
+ gap: 2px;
55
+ border-radius: 12px;
56
+ width: 100%;
57
+ height: 100%;
58
+ overflow: hidden;
59
+ }
60
+
61
+ .VPTeamMembersItem.small .profile {
62
+ padding: 32px;
63
+ }
64
+
65
+ .VPTeamMembersItem.small .data {
66
+ padding-top: 20px;
67
+ }
68
+
69
+ .VPTeamMembersItem.small .avatar {
70
+ width: 64px;
71
+ height: 64px;
72
+ }
73
+
74
+ .VPTeamMembersItem.small .name {
75
+ line-height: 24px;
76
+ font-size: 16px;
77
+ }
78
+
79
+ .VPTeamMembersItem.small .affiliation {
80
+ padding-top: 4px;
81
+ line-height: 20px;
82
+ font-size: 14px;
83
+ }
84
+
85
+ .VPTeamMembersItem.small .desc {
86
+ padding-top: 12px;
87
+ line-height: 20px;
88
+ font-size: 14px;
89
+ }
90
+
91
+ .VPTeamMembersItem.small .links {
92
+ margin: 0 -16px -20px;
93
+ padding: 10px 0 0;
94
+ }
95
+
96
+ .VPTeamMembersItem.medium .profile {
97
+ padding: 48px 32px;
98
+ }
99
+
100
+ .VPTeamMembersItem.medium .data {
101
+ padding-top: 24px;
102
+ text-align: center;
103
+ }
104
+
105
+ .VPTeamMembersItem.medium .avatar {
106
+ width: 96px;
107
+ height: 96px;
108
+ }
109
+
110
+ .VPTeamMembersItem.medium .name {
111
+ letter-spacing: 0.15px;
112
+ line-height: 28px;
113
+ font-size: 20px;
114
+ }
115
+
116
+ .VPTeamMembersItem.medium .affiliation {
117
+ padding-top: 4px;
118
+ font-size: 16px;
119
+ }
120
+
121
+ .VPTeamMembersItem.medium .desc {
122
+ padding-top: 16px;
123
+ max-width: 288px;
124
+ font-size: 16px;
125
+ }
126
+
127
+ .VPTeamMembersItem.medium .links {
128
+ margin: 0 -16px -12px;
129
+ padding: 16px 12px 0;
130
+ }
131
+
132
+ .profile {
133
+ flex-grow: 1;
134
+ background-color: var(--vp-c-bg-soft);
135
+ }
136
+
137
+ .data {
138
+ text-align: center;
139
+ }
140
+
141
+ .avatar {
142
+ position: relative;
143
+ flex-shrink: 0;
144
+ margin: 0 auto;
145
+ border-radius: 50%;
146
+ box-shadow: var(--vp-shadow-3);
147
+ }
148
+
149
+ .avatar-img {
150
+ position: absolute;
151
+ top: 0;
152
+ right: 0;
153
+ bottom: 0;
154
+ left: 0;
155
+ border-radius: 50%;
156
+ object-fit: cover;
157
+ }
158
+
159
+ .name {
160
+ margin: 0;
161
+ font-weight: 600;
162
+ }
163
+
164
+ .affiliation {
165
+ margin: 0;
166
+ font-weight: 500;
167
+ color: var(--vp-c-text-2);
168
+ }
169
+
170
+ .org.link {
171
+ color: var(--vp-c-text-2);
172
+ transition: color 0.25s;
173
+ }
174
+
175
+ .org.link:hover {
176
+ color: var(--vp-c-brand);
177
+ }
178
+
179
+ .desc {
180
+ margin: 0 auto;
181
+ }
182
+
183
+ .links {
184
+ display: flex;
185
+ justify-content: center;
186
+ height: 56px;
187
+ }
188
+
189
+ .sponsor-link {
190
+ display: flex;
191
+ justify-content: center;
192
+ align-items: center;
193
+ text-align: center;
194
+ padding: 16px;
195
+ font-size: 14px;
196
+ font-weight: 500;
197
+ color: var(--vp-c-sponsor);
198
+ background-color: var(--vp-c-bg-soft);
199
+ transition: color 0.25s, background-color 0.25s;
200
+ }
201
+
202
+ .sponsor-link:hover,
203
+ .sponsor-link:focus {
204
+ outline: none;
205
+ color: var(--vp-c-text-dark-1);
206
+ background-color: var(--vp-c-sponsor);
207
+ }
208
+
209
+ .sponsor-icon {
210
+ margin-right: 8px;
211
+ width: 16px;
212
+ height: 16px;
213
+ fill: currentColor;
214
+ }
215
+ </style>