valaxy-theme-hairy 0.2.2 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. package/client/index.ts +1 -0
  2. package/components/HairyBody.vue +15 -17
  3. package/components/HairyComment.vue +33 -0
  4. package/components/HairyContainer.vue +17 -0
  5. package/components/{HairyUserPopup.vue → HairyDrawer.vue} +16 -16
  6. package/components/HairyFooter.vue +12 -9
  7. package/components/HairyHeader.vue +10 -9
  8. package/components/HairyImage.vue +3 -2
  9. package/components/HairyImageGroup.vue +12 -16
  10. package/components/HairyNavbar.vue +56 -0
  11. package/components/HairyPageArchives.vue +59 -0
  12. package/components/HairyPageTags.vue +48 -0
  13. package/components/{HairyPostList.vue → HairyPosts.vue} +3 -3
  14. package/components/{HairyNavSearch.vue → HairySearch.vue} +23 -87
  15. package/components/{HairyUserCard.vue → HairySidebar.vue} +4 -4
  16. package/components/HairyTabbar.vue +56 -0
  17. package/components/PageTags.vue +48 -0
  18. package/components/ValaxyMain.vue +3 -3
  19. package/components/navbar/HairyNav.vue +16 -0
  20. package/components/navbar/HairyNavExpand.vue +12 -0
  21. package/components/navbar/HairyNavItem.vue +35 -0
  22. package/components/navbar/HairyNavbarBackground.vue +7 -0
  23. package/components/navbar/HairyNavbarSearch.vue +8 -0
  24. package/components/{HairyNavTitle.vue → navbar/HairyNavbarTitle.vue} +5 -3
  25. package/components/navbar/HairyNavbarToggleDark.vue +22 -0
  26. package/components/{HairyBreadcrumb.vue → parts/HairyBreadcrumb.vue} +2 -2
  27. package/components/{HairyBreadcrumbItem.vue → parts/HairyBreadcrumbItem.vue} +1 -4
  28. package/components/{lib/fish.js → parts/HairyFootFish.js} +5 -7
  29. package/components/parts/HairyFootFish.vue +38 -0
  30. package/components/{HairyPostTitle.vue → parts/HairyHeadHero.vue} +6 -5
  31. package/components/{HairyWaves.vue → parts/HairyHeadWaves.vue} +5 -5
  32. package/components/parts/HairyImageGlobal.vue +51 -0
  33. package/components/{HairyImageViewer.vue → parts/HairyImageViewer.vue} +5 -4
  34. package/components/parts/HairyLink.vue +21 -0
  35. package/components/{HairyMenu.vue → parts/HairyMenu.vue} +2 -1
  36. package/components/{HairyMenuItem.vue → parts/HairyMenuItem.vue} +11 -4
  37. package/components/parts/HairyOutline.vue +99 -0
  38. package/components/parts/HairyOutlineItem.vue +48 -0
  39. package/components/{HairySocialLinks.vue → parts/HairySocialLinks.vue} +2 -2
  40. package/components/{HairyTimelinePostItem.vue → parts/HairyTimelineContent.vue} +7 -8
  41. package/components/parts/HairyUserNav.vue +95 -0
  42. package/components/{article-layout → posts}/HairyArticleImage.vue +18 -19
  43. package/components/{article-layout → posts}/HairyArticleSeries.vue +8 -5
  44. package/components/{article-layout → posts}/HairyArticleText.vue +11 -4
  45. package/components/posts/HairyPostFooter.vue +15 -0
  46. package/components/{article-layout → posts}/HairyPostImageList.vue +4 -5
  47. package/components/{article-layout → posts}/HairyPostTextsList.vue +0 -1
  48. package/components/posts/HairyPostToggleLayout.vue +36 -0
  49. package/components/third/HairyAlgoliaSearch.vue +17 -0
  50. package/components/third/HairyFuseSearch.vue +10 -0
  51. package/components/third/HairyFuseSearchDialog.vue +32 -0
  52. package/components/third/HairyFuseSearchDropdown.vue +77 -0
  53. package/components/third/HairyFuseSearchFooter.vue +28 -0
  54. package/components/third/HairyFuseSearchHeader.vue +30 -0
  55. package/components/third/HairyFuseSearchHit.vue +52 -0
  56. package/components/third/HairySearchBtnDisplay.vue +29 -0
  57. package/components/third/HairySearchBtnInput.vue +20 -0
  58. package/components/third/HairySearchBtnKeys.vue +19 -0
  59. package/components/{HairyCarousel.vue → third/HairySwiperCarousel.vue} +6 -6
  60. package/{hooks/useYearArchives.ts → composables/archives.ts} +4 -3
  61. package/composables/category.ts +43 -0
  62. package/composables/config.ts +11 -0
  63. package/composables/dark.ts +13 -0
  64. package/composables/fuse.ts +60 -0
  65. package/composables/index.ts +8 -0
  66. package/composables/layout.ts +16 -0
  67. package/composables/outline.ts +49 -0
  68. package/composables/tags.ts +36 -0
  69. package/layouts/archive-month.vue +13 -0
  70. package/layouts/archive-year.vue +13 -0
  71. package/layouts/archives.vue +9 -9
  72. package/layouts/categories.vue +11 -4
  73. package/layouts/default.vue +9 -3
  74. package/layouts/home.vue +28 -18
  75. package/layouts/post.vue +42 -36
  76. package/layouts/tag.vue +8 -4
  77. package/layouts/tags.vue +12 -4
  78. package/{modules → library}/loading.ts +18 -6
  79. package/{modules → library}/scroll.ts +3 -2
  80. package/locales/zh-CN.yml +0 -2
  81. package/node/images/default.json +139 -0
  82. package/node/images/index.ts +46 -0
  83. package/node/index.ts +2 -0
  84. package/node/theme/index.ts +78 -0
  85. package/package.json +22 -28
  86. package/pages/archives/[year]/[month]/index.vue +15 -18
  87. package/pages/archives/[year]/index.vue +20 -20
  88. package/pages/archives/index.vue +1 -54
  89. package/pages/categories/{[...categories].vue → [...its].vue} +29 -36
  90. package/pages/index.vue +1 -1
  91. package/pages/page/[page].vue +2 -2
  92. package/pages/tags/[tag]/index.vue +38 -0
  93. package/pages/tags/index.vue +1 -36
  94. package/setup/main.ts +1 -1
  95. package/store/index.ts +1 -0
  96. package/store/modules/global.ts +12 -0
  97. package/styles/components/index.scss +4 -0
  98. package/styles/{markdown.scss → components/markdown.scss} +2 -1
  99. package/styles/components/nprogress.scss +16 -0
  100. package/styles/css-vars.scss +11 -0
  101. package/styles/element-plus/tabs.scss +1 -1
  102. package/styles/element-plus/timeline.scss +1 -1
  103. package/styles/global.scss +39 -0
  104. package/styles/index.scss +4 -73
  105. package/tsconfig.json +27 -0
  106. package/types/index.d.ts +163 -0
  107. package/unocss.config.ts +5 -1
  108. package/utils/index.ts +21 -39
  109. package/valaxy.config.ts +21 -24
  110. package/@types/markdown-it.d.ts +0 -1
  111. package/@types/markdown-toc.d.ts +0 -1
  112. package/@types/types.d.ts +0 -1
  113. package/@types/valaxy.d.ts +0 -10
  114. package/components/HairyAlgoliaSearchBox.vue +0 -118
  115. package/components/HairyBackToTop.vue +0 -72
  116. package/components/HairyDivider.vue +0 -0
  117. package/components/HairyFooterFish.vue +0 -29
  118. package/components/HairyLayout.vue +0 -28
  119. package/components/HairyLink.vue +0 -10
  120. package/components/HairyLinks.vue +0 -69
  121. package/components/HairyMeting.vue +0 -19
  122. package/components/HairyNav.vue +0 -42
  123. package/components/HairyNavBackground.vue +0 -7
  124. package/components/HairyNavMenu.vue +0 -11
  125. package/components/HairyNavToggleDark.vue +0 -16
  126. package/components/HairyPostToggleLayout.vue +0 -33
  127. package/components/HairyToc.vue +0 -135
  128. package/components/HairyUserNav.vue +0 -64
  129. package/components/HairyUserTab.vue +0 -40
  130. package/components/HairyWaline.vue +0 -44
  131. package/hooks/setupDefaultDark.ts +0 -11
  132. package/hooks/useCategory.ts +0 -18
  133. package/hooks/useCategoryPost.ts +0 -21
  134. package/hooks/useContext.ts +0 -13
  135. package/hooks/useHeaderHeight.ts +0 -9
  136. package/hooks/usePostLayout.ts +0 -16
  137. package/images.json +0 -140
  138. package/index.d.ts +0 -100
  139. package/layouts/hairy.vue +0 -36
  140. package/layouts/month.vue +0 -6
  141. package/layouts/year.vue +0 -6
  142. package/node/addon-hairy.ts +0 -36
  143. package/node/addon-images.ts +0 -61
  144. package/node/addon-meting.ts +0 -13
  145. package/node/addon-statistics.ts +0 -19
  146. package/node/addon-toc.ts +0 -20
  147. package/node/utils.ts +0 -20
  148. package/pages/tags/[tag].vue +0 -40
  149. package/utils/createContext.ts +0 -40
  150. package/utils/fonts.ts +0 -15
  151. /package/components/{HairyUserStats.vue → parts/HairyUserStats.vue} +0 -0
  152. /package/components/{article-layout → posts}/HairyArticleTop.vue +0 -0
  153. /package/{modules → library}/loading.scss +0 -0
  154. /package/{shims.d.ts → node/images/shims.d.ts} +0 -0
  155. /package/styles/{aplayer.scss → components/aplayer.scss} +0 -0
  156. /package/styles/{scrollbar.scss → components/scrollbar.scss} +0 -0
package/tsconfig.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ // we need tsconfig.json to compile without
3
+ // error: This is likely not portable. A type annotation is necessary.
4
+ "compilerOptions": {
5
+ "target": "ESNext",
6
+ "jsx": "preserve",
7
+ "lib": ["DOM", "ESNext"],
8
+ "baseUrl": ".",
9
+ "module": "ESNext",
10
+ "moduleResolution": "node",
11
+ "resolveJsonModule": true,
12
+ "types": [
13
+ "vite/client",
14
+ "vue/ref-macros",
15
+ "vite-plugin-pages/client",
16
+ "vite-plugin-vue-layouts/client"
17
+ ],
18
+ "allowJs": true,
19
+ "strict": true,
20
+ "strictNullChecks": true,
21
+ "noUnusedLocals": true,
22
+ "esModuleInterop": true,
23
+ "forceConsistentCasingInFileNames": true,
24
+ "skipLibCheck": true
25
+ },
26
+ "exclude": ["**/dist/**", "node_modules"]
27
+ }
@@ -0,0 +1,163 @@
1
+ /* eslint-disable ts/no-use-before-define */
2
+ export namespace HairyTheme {
3
+ export type Config = ThemeConfig
4
+ export type Sidebar = any
5
+ export type { Layout }
6
+ }
7
+
8
+ /**
9
+ * Theme Config
10
+ */
11
+ export interface ThemeConfig {
12
+ /**
13
+ * default theme mode
14
+ *
15
+ * @default 'light'
16
+ */
17
+ theme?: 'dark' | 'light'
18
+
19
+ home?: Home
20
+
21
+ user?: User
22
+
23
+ post?: Post
24
+
25
+ /**
26
+ * colors
27
+ */
28
+ colors?: Colors
29
+
30
+ /**
31
+ * layout
32
+ */
33
+ layout?: Partial<Layout>
34
+
35
+ /**
36
+ * footer
37
+ */
38
+ footer?: Partial<Footer>
39
+
40
+ /**
41
+ * navbar
42
+ */
43
+ nav?: NavItem[]
44
+
45
+ /**
46
+ * meting
47
+ */
48
+ meting?: Partial<Meting>
49
+
50
+ /**
51
+ * Custom header levels of outline in the aside component.
52
+ *
53
+ * @default 2
54
+ */
55
+ outline?: number | [number, number] | 'deep' | false
56
+ }
57
+
58
+ export interface NavItem {
59
+ text: string
60
+ link: string
61
+ icon?: string
62
+ }
63
+ /**
64
+ * meting options
65
+ * @see https://github.com/metowolf/MetingJS#option
66
+ */
67
+ export interface Meting {
68
+ id: string
69
+ server: string
70
+ type: string
71
+ auto: string
72
+ fixed: boolean
73
+ mini: boolean
74
+ autoplay: boolean
75
+ theme: string
76
+ loop: string
77
+ order: string
78
+ preload: string
79
+ volume: number
80
+ work: string
81
+ mutex: boolean
82
+ start: string
83
+ 'lrc-type': number
84
+ 'list-folded': boolean
85
+ 'list-max-height': string
86
+ 'storage-name': string
87
+ [key: string]: any
88
+ }
89
+
90
+ export interface Layout {
91
+ post:
92
+ | 'text'
93
+ | 'markdown'
94
+ | 'image'
95
+ | 'image:slice'
96
+ | 'image:slice:reverse'
97
+ categories: 'timeline' | 'post'
98
+ }
99
+
100
+ export interface Footer {
101
+ /**
102
+ * 建站于
103
+ */
104
+ since: number
105
+
106
+ /**
107
+ * Icon between year and copyright info.
108
+ */
109
+ icon: {
110
+ /**
111
+ * icon name, i-xxx
112
+ */
113
+ name: string
114
+ animated: boolean
115
+ color: string
116
+ url: string
117
+ title: string
118
+ }
119
+
120
+ /**
121
+ * Powered by valaxy & valaxy-theme-${name}, default is yun
122
+ */
123
+ powered: boolean
124
+
125
+ /**
126
+ * Chinese Users | 中国用户
127
+ * 备案 ICP
128
+ * 国内用户需要在网站页脚展示备案 ICP 号
129
+ * https://beian.miit.gov.cn/
130
+ */
131
+ beian: {
132
+ enable: boolean
133
+ /**
134
+ * 苏ICP备xxxxxxxx号
135
+ */
136
+ icp: string
137
+ }
138
+ }
139
+
140
+ export interface Colors {
141
+ /**
142
+ * primary color
143
+ * @default '#0078E7'
144
+ */
145
+ primary: string
146
+ }
147
+ export interface Home {
148
+ headline: string
149
+ title: string
150
+ description: string
151
+ images: string[]
152
+ }
153
+
154
+ export interface Post {
155
+ images: string[]
156
+ }
157
+
158
+ export interface User {
159
+ name?: string
160
+ description?: string
161
+ }
162
+
163
+ export type ThemeUserConfig = Partial<ThemeConfig>
package/unocss.config.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { defineConfig } from 'unocss'
2
+
2
3
  const safelist = [
3
- 'i-ri:home-2-fill',
4
+ 'i-ri-home-2-fill',
4
5
  'i-ri-list-check-2',
5
6
  'i-ri-flow-chart',
6
7
  'i-ri-user-line',
@@ -11,6 +12,7 @@ const safelist = [
11
12
  'i-fluent-markdown-20-filled',
12
13
  'i-fluent-code-text-16-filled',
13
14
  ]
15
+
14
16
  export default defineConfig({
15
17
  theme: {
16
18
  breakpoints: {
@@ -28,6 +30,8 @@ export default defineConfig({
28
30
  ['font-christmas', { 'font-family': 'var(--hy-font-family-christmas)' }],
29
31
  ['font-frederick', { 'font-family': 'var(--hy-font-family-frederick)' }],
30
32
  ['text-primary', { color: 'var(--hy-c-primary)' }],
33
+ ['text-primary-dark', { color: 'var(--hy-c-primary-dark)' }],
34
+ ['text-primary-light', { color: 'var(--hy-c-primary-light)' }],
31
35
  ['border-primary', { 'border-color': 'var(--hy-c-primary)' }],
32
36
  ['bg-primary', { background: 'var(--hy-c-primary)' }],
33
37
  ],
package/utils/index.ts CHANGED
@@ -1,10 +1,4 @@
1
- import { isNumber, isString } from 'lodash-es'
2
-
3
- /**
4
- * 跳转到新的页面
5
- * @param url 跳转url
6
- */
7
- export const ejectWindow = (url: string) => {
1
+ export function ejectWindow(url: string) {
8
2
  const link = document.createElement('a')
9
3
  link.href = url
10
4
  link.target = '_blank'
@@ -12,7 +6,26 @@ export const ejectWindow = (url: string) => {
12
6
  link.remove()
13
7
  }
14
8
 
15
- export const getArchiveLink = (year?: string, month?: string) => {
9
+ export function riposte<T>(...args: [cond: boolean, value: T][]) {
10
+ for (const [cond, value] of args) {
11
+ if (cond)
12
+ return value
13
+ }
14
+ }
15
+
16
+ export function toArray<T>(value: T | T[]): T[] {
17
+ if (Array.isArray(value))
18
+ return value as any
19
+ else return [value].filter(Boolean) as any
20
+ }
21
+
22
+ export function removeTags(content = '') {
23
+ return content
24
+ .replace(/<\/?[^>]*>/g, '')
25
+ .replace(/[|]*\n/, '')
26
+ }
27
+
28
+ export function getArchiveLink(year?: string, month?: string) {
16
29
  if (!year)
17
30
  return '/archives/'
18
31
  if (!month)
@@ -22,34 +35,3 @@ export const getArchiveLink = (year?: string, month?: string) => {
22
35
 
23
36
  return ''
24
37
  }
25
-
26
- export const toArr = <T>(arr: T[] | T): T[] => {
27
- if (Array.isArray(arr))
28
- return arr as any
29
- else return [arr].filter(Boolean) as any
30
- }
31
-
32
- export type AtWillNumber = string | number
33
-
34
- export const atWillToUnit = (value: AtWillNumber, unit = 'px') => {
35
- if (!(isString(value) || isNumber(value)))
36
- return ''
37
- return isString(value) && /\D/g.test(value) ? value : value + unit
38
- }
39
-
40
- export interface PromiseResolver<T = void> extends Promise<T> {
41
- resolve: (value: T) => void
42
- reject: Function
43
- }
44
- export function createPromise<T>(): PromiseResolver<T> {
45
- let resolve
46
- let reject
47
- // eslint-disable-next-line promise/param-names
48
- const promise: any = new Promise((_r, _j) => {
49
- resolve = _r
50
- reject = _j
51
- })
52
- promise.resolve = resolve
53
- promise.reject = reject
54
- return promise as PromiseResolver<T>
55
- }
package/valaxy.config.ts CHANGED
@@ -1,29 +1,26 @@
1
- import { defineTheme } from 'valaxy'
2
- import type { HairyTheme } from 'valaxy-theme-hairy'
3
- import markdownFurigana from 'furigana-markdown-it'
4
- import addonHairy from './node/addon-hairy'
5
- import addonImages from './node/addon-images'
6
- import addonStatistics from './node/addon-statistics'
7
- import addonToc from './node/addon-toc'
8
- export default defineTheme<HairyTheme>((options) => {
9
- const images = addonImages(options)
10
- const hairy = addonHairy(options)
1
+ import type { DefaultTheme, ValaxyTheme } from 'valaxy'
2
+ import { defineTheme, mergeValaxyConfig } from 'valaxy'
3
+ import { addonAlgolia } from 'valaxy-addon-algolia'
4
+ import { withImageConfig, withThemeConfig } from './node'
5
+ import type { ThemeConfig } from './types'
11
6
 
12
- return {
13
- vite: images.vite,
14
- pages: hairy.pages,
15
- unocss: hairy.unocss,
16
- extendMd(ctx) {
17
- hairy.extendMd?.(ctx)
18
- images.extendMd?.(ctx)
19
- addonStatistics().extendMd?.(ctx)
20
- addonToc().extendMd?.(ctx)
21
- },
22
- markdown: {
23
- config(md) {
24
- md.use(markdownFurigana())
7
+ export default defineTheme<ThemeConfig>((options) => {
8
+ let config: ValaxyTheme<ThemeConfig & DefaultTheme.Config> = {
9
+ addons: [
10
+ addonAlgolia(),
11
+ ],
12
+ themeConfig: {
13
+ valaxyDarkOptions: {
14
+ useDarkOptions: { disableTransition: false },
15
+ circleTransition: true,
25
16
  },
17
+ outline: 2,
18
+ theme: 'dark',
26
19
  },
27
20
  }
28
- })
29
21
 
22
+ config = mergeValaxyConfig(config, withImageConfig(options))
23
+ config = mergeValaxyConfig(config, withThemeConfig(options))
24
+
25
+ return config
26
+ })
@@ -1 +0,0 @@
1
- declare module "*-markdown-it"
@@ -1 +0,0 @@
1
- declare module "markdown-toc"
package/@types/types.d.ts DELETED
@@ -1 +0,0 @@
1
- declare const __ALGOLIA__: boolean
@@ -1,10 +0,0 @@
1
- declare module 'valaxy' {
2
- export interface Post {
3
- image: string
4
- durations: Omit<import('reading-time').ReadTimeResults, 'text'>
5
- length: number
6
- }
7
- }
8
-
9
-
10
- export {}
@@ -1,118 +0,0 @@
1
- <script setup lang="ts">
2
- import docsearch from '@docsearch/js'
3
- import type { DocSearchHit } from '@docsearch/react/dist/esm/types'
4
- import { onMounted } from 'vue'
5
- import type { AlgoliaSearchOptions } from 'valaxy'
6
- import { useConfig } from 'valaxy'
7
- import { useRoute, useRouter } from 'vue-router'
8
-
9
- const router = useRouter()
10
- const route = useRoute()
11
- const config = useConfig()
12
-
13
- onMounted(() => {
14
- initialize(config.value.search.algolia)
15
- setTimeout(poll, 16)
16
- })
17
-
18
- /**
19
- * poll until open
20
- */
21
- function poll() {
22
- // programmatically open the search box after initialize
23
- const e = new Event('keydown') as any
24
-
25
- e.key = 'k'
26
- e.metaKey = true
27
-
28
- window.dispatchEvent(e)
29
-
30
- setTimeout(() => {
31
- if (!document.querySelector('.DocSearch-Modal'))
32
- poll()
33
- }, 16)
34
- }
35
-
36
- function initialize(userOptions: AlgoliaSearchOptions) {
37
- // note: multi-lang search support is removed since the theme
38
- // doesn't support multiple locales as of now.
39
- const options = Object.assign({}, userOptions, {
40
- container: '#docsearch',
41
- navigator: {
42
- navigate({ itemUrl }: { itemUrl: string }) {
43
- const { pathname: hitPathname } = new URL(
44
- window.location.origin + itemUrl,
45
- )
46
- // router doesn't handle same-page navigation so we use the native
47
- // browser location API for anchor navigation
48
- if (route.path === hitPathname)
49
- window.location.assign(window.location.origin + itemUrl)
50
-
51
- else
52
- router.push(itemUrl)
53
- },
54
- },
55
- transformItems(items: DocSearchHit[]) {
56
- return items.map((item) => {
57
- return Object.assign({}, item, {
58
- url: getRelativePath(item.url),
59
- })
60
- })
61
- },
62
- hitComponent({ hit, children }: { hit: DocSearchHit; children: any }) {
63
- const relativeHit = hit.url.startsWith('http')
64
- ? getRelativePath(hit.url as string)
65
- : hit.url
66
- return {
67
- __v: null,
68
- type: 'a',
69
- ref: undefined,
70
- constructor: undefined,
71
- key: undefined,
72
- props: {
73
- href: hit.url,
74
- onClick(event: MouseEvent) {
75
- if (isSpecialClick(event))
76
- return
77
-
78
- // we rely on the native link scrolling when user is already on
79
- // the right anchor because Router doesn't support duplicated
80
- // history entries.
81
- if (route.path === relativeHit)
82
- return
83
-
84
- // if the hits goes to another page, we prevent the native link
85
- // behavior to leverage the Router loading feature.
86
- if (route.path !== relativeHit)
87
- event.preventDefault()
88
-
89
- router.push(relativeHit)
90
- },
91
- children,
92
- },
93
- }
94
- },
95
- })
96
- docsearch(options as any)
97
- }
98
-
99
- function isSpecialClick(event: MouseEvent) {
100
- return (
101
- event.button === 1
102
- || event.altKey
103
- || event.ctrlKey
104
- || event.metaKey
105
- || event.shiftKey
106
- )
107
- }
108
-
109
- function getRelativePath(absoluteUrl: string) {
110
- const { pathname, hash } = new URL(absoluteUrl)
111
- return pathname + hash
112
- }
113
- </script>
114
-
115
- <template>
116
- <div id="docsearch" />
117
- </template>
118
-
@@ -1,72 +0,0 @@
1
- <script lang="ts" setup>
2
- import { computed } from 'vue'
3
- import { useBackToTop } from 'valaxy'
4
-
5
- const { show, percentage } = useBackToTop({ offset: 100 })
6
-
7
- const radius = 48
8
- const circumference = 2 * radius * Math.PI
9
-
10
- const strokeOffset = computed(() => {
11
- // 周长
12
- const val = (1 - percentage.value) * circumference
13
- return val < 0 ? 0 : val
14
- })
15
-
16
- function toTop() {
17
- window.scrollTo({ top: 0, behavior: 'smooth' })
18
- }
19
- </script>
20
-
21
- <template>
22
- <a class="back-to-top cursor-pointer" :class="show && 'show'" @click="toTop">
23
- <div w="8" h="8" i-ri-arrow-up-s-line />
24
- <svg class="progress-circle-container" viewBox="0 0 100 100">
25
- <circle :stroke-dasharray="`${circumference} ${circumference}`" :stroke-dashoffset="strokeOffset" class="progress-circle" cx="50" cy="50" :r="radius" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
26
- </svg>
27
- </a>
28
- </template>
29
-
30
- <style lang="scss">
31
- @use "sass:map";
32
-
33
- .back-to-top {
34
- position: fixed;
35
- width: 32px;
36
- height: 32px;
37
- right: 0rem;
38
- bottom: 1.5rem;
39
- z-index: 10;
40
- opacity: 0;
41
- pointer-events: none;
42
-
43
- color: var(--hy-c-primary);
44
- transform: translateX(0) rotate(270deg);
45
- // override yun-icon-btn transition
46
- transition: transform var(--va-transition-duration), opacity var(--va-transition-duration-fast) !important;
47
-
48
- &.show {
49
- transform: translateX(-32px) rotate(360deg);
50
- opacity: 1;
51
- pointer-events: fill;
52
- }
53
-
54
- .icon {
55
- width: 2.5rem;
56
- height: 2.5rem;
57
- }
58
- > div {
59
- margin-bottom: -2em;
60
- }
61
- }
62
-
63
- .progress-circle {
64
- transition: 0.3s stroke-dashoffset;
65
- transform: rotate(-90deg);
66
- transform-origin: 50% 50%;
67
-
68
- &-container {
69
- position: absolute;
70
- }
71
- }
72
- </style>
File without changes
@@ -1,29 +0,0 @@
1
- <!-- eslint-disable no-new -->
2
- <script lang="ts" setup>
3
- import { onMounted, ref } from 'vue'
4
- import { useScriptTag } from '@vueuse/core'
5
- import { RENDERER } from './lib/fish'
6
-
7
- const fishContainer = ref()
8
-
9
- const tag = useScriptTag('https://cdn.bootcdn.net/ajax/libs/zepto/1.2.0/zepto.min.js')
10
-
11
- let renderer: RENDERER
12
-
13
- function reset() {
14
- const color = 'hsl(0, 0%, 95%)'
15
- if (!renderer)
16
- renderer = new RENDERER(color)
17
- else
18
- renderer.setColor(color)
19
- }
20
-
21
- onMounted(() => {
22
- tag.load()
23
- .then(reset)
24
- })
25
- </script>
26
-
27
- <template>
28
- <div id="jsi-flying-fish-container" ref="fishContainer" style="margin-top: -60px;"></div>
29
- </template>
@@ -1,28 +0,0 @@
1
- <script lang="ts" setup>
2
- defineProps<{
3
- header?: {
4
- title?: string
5
- headline?: string
6
- description?: string
7
- }
8
- }>()
9
- </script>
10
-
11
- <template>
12
- <div class="HairyLayout min-h-80vh">
13
- <HairyNav />
14
- <HairyHeader v-bind="header">
15
- <template #description>
16
- <slot name="header-description" />
17
- </template>
18
- </HairyHeader>
19
- <HairyBody>
20
- <slot />
21
-
22
- <template v-if="$slots['body-slide']" #slide>
23
- <slot name="body-slide" />
24
- </template>
25
- </HairyBody>
26
- <HairyFooter class="z-1 relative" />
27
- </div>
28
- </template>
@@ -1,10 +0,0 @@
1
- <script lang="ts" setup>
2
- </script>
3
-
4
- <template>
5
- <span class="HairyLink cursor-pointer border-b border-dashed hover:border-primary hover:text-primary transition-all">
6
- <slot />
7
- </span>
8
- </template>
9
-
10
- <style lang="scss" scoped></style>
@@ -1,69 +0,0 @@
1
- <script lang="ts" setup>
2
- import { defineProps } from 'vue'
3
- defineProps<{
4
- links?: {
5
- name: string
6
- url: string
7
- image: string
8
- color: string
9
- desc?: string
10
- }[]
11
- }>()
12
- </script>
13
-
14
- <template>
15
- <div class="min-h-30vh">
16
- <div class="links">
17
- <div
18
- v-for="(item, index) in links" :key="index" class="link-block flex items-center py-0.5rem px-1rem rounded-lg"
19
- :style="{ '--block-color': item.color }"
20
- >
21
- <a :href="item.url" class="w-4rem h-4rem">
22
- <HairyImage class="w-full h-full rounded-xl" :src="item.image" />
23
- </a>
24
- <div class="pl-1rem flex-1">
25
- <a :href="item.url" class="font-bold text-lg title">
26
- {{ item.name }}
27
- </a>
28
- <div class="max-w-180px text-sm my-0.5rem truncate desc">
29
- {{ item.desc }}
30
- </div>
31
- </div>
32
- </div>
33
- </div>
34
- </div>
35
- </template>
36
-
37
- <style lang="scss" scoped>
38
- .link-block {
39
- border: 0.0625rem solid #f7f7f7;
40
- box-shadow: 0 0.625rem 1.875rem -0.9375rem rgba(0, 0, 0, 0.1);
41
- --bg-color: var(--block-color, #666);
42
- @apply transition-all;
43
-
44
- .title {
45
- color: var(--block-color);
46
- }
47
- }
48
-
49
- .dark .link-block {
50
- background: rgba($color: #989898, $alpha: 0.1);
51
- }
52
-
53
- .links .link-block:hover {
54
- background-color: var(--bg-color);
55
- box-shadow: 0 0.125rem 1.25rem var(--bg-color);
56
- border-color: var(--bg-color);
57
-
58
- .title,
59
- .desc {
60
- color: #fff;
61
- }
62
- }
63
-
64
- .links {
65
- display: grid;
66
- grid-template-columns: repeat(auto-fill, 300px);
67
- gap: 24px;
68
- }
69
- </style>