@varlet/cli 1.23.5 → 1.23.12-alpha.25
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/CHANGELOG.md +30 -0
- package/generators/{sfc → base}/.gitignore +0 -0
- package/generators/{sfc → base}/.husky/commit-msg +0 -0
- package/generators/{sfc → base}/.husky/pre-commit +0 -0
- package/generators/{tsx → base}/.prettierignore +0 -1
- package/generators/{sfc → base}/.prettierrc +0 -0
- package/generators/{sfc → base}/README.md +0 -0
- package/generators/{sfc → base}/babel.config.js +0 -0
- package/generators/{sfc → base}/commitlint.config.js +0 -0
- package/generators/{sfc → base}/docs/home.zh-CN.md +0 -0
- package/generators/{sfc → base}/package.json +0 -0
- package/generators/{sfc → base}/public/highlight.css +0 -0
- package/generators/{sfc → base}/public/logo.svg +0 -0
- package/generators/{sfc → base}/shims/shims-md.d.ts +0 -0
- package/generators/{sfc → base}/shims/shims-vue.d.ts +0 -0
- package/generators/{sfc → base}/tsconfig.json +0 -0
- package/generators/{sfc → base}/types/basicComponent.d.ts +0 -0
- package/generators/{sfc → base}/types/button.d.ts +0 -0
- package/generators/{sfc → base}/types/index.d.ts +0 -0
- package/generators/{sfc → base}/varlet.config.js +0 -0
- package/lib/commands/dev.js +1 -1
- package/lib/commands/gen.js +7 -3
- package/lib/compiler/compileModule.js +1 -1
- package/lib/compiler/compileSiteEntry.js +1 -1
- package/lib/shared/fsUtils.d.ts +1 -0
- package/lib/shared/fsUtils.js +3 -1
- package/package.json +2 -2
- package/site/components/code-example/CodeExample.vue +107 -0
- package/site/components/code-example/codeExample.less +23 -0
- package/site/components/code-example/index.ts +10 -0
- package/site/components/icon/icon.less +1 -0
- package/site/components/loading/props.ts +2 -2
- package/site/components/snackbar/Snackbar.vue +38 -0
- package/site/components/snackbar/core.vue +117 -0
- package/site/components/snackbar/index.tsx +270 -0
- package/site/components/snackbar/props.ts +94 -0
- package/site/components/snackbar/snackbar.less +135 -0
- package/site/components/utils/elements.ts +9 -0
- package/site/components/utils/shared.ts +3 -0
- package/site/mobile/App.vue +6 -6
- package/site/module.d.ts +4 -0
- package/site/pc/App.vue +9 -11
- package/site/pc/components/AppHeader.vue +8 -9
- package/site/pc/components/AppSidebar.vue +5 -5
- package/site/pc/main.ts +8 -2
- package/site/tsconfig.json +1 -6
- package/site/useProgress.ts +6 -2
- package/site/utils.ts +4 -3
- package/tsconfig.json +0 -2
- package/varlet.default.config.js +13 -0
- package/generators/sfc/.prettierignore +0 -8
- package/generators/tsx/.gitignore +0 -14
- package/generators/tsx/.husky/commit-msg +0 -4
- package/generators/tsx/.husky/pre-commit +0 -4
- package/generators/tsx/.prettierrc +0 -5
- package/generators/tsx/README.md +0 -88
- package/generators/tsx/babel.config.js +0 -10
- package/generators/tsx/commitlint.config.js +0 -3
- package/generators/tsx/docs/home.zh-CN.md +0 -11
- package/generators/tsx/package.json +0 -98
- package/generators/tsx/public/highlight.css +0 -1
- package/generators/tsx/public/logo.svg +0 -1
- package/generators/tsx/shims/shims-md.d.ts +0 -4
- package/generators/tsx/shims/shims-vue.d.ts +0 -6
- package/generators/tsx/tsconfig.json +0 -13
- package/generators/tsx/types/basicComponent.d.ts +0 -7
- package/generators/tsx/types/button.d.ts +0 -12
- package/generators/tsx/types/index.d.ts +0 -6
- package/generators/tsx/varlet.config.js +0 -106
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import VarSiteSnackbarCore from './core.vue'
|
|
2
|
+
import VarSiteSnackbar from './Snackbar.vue'
|
|
3
|
+
import context from '../context'
|
|
4
|
+
import { reactive, TransitionGroup } from 'vue'
|
|
5
|
+
import { mountInstance } from '../utils/components'
|
|
6
|
+
import { isPlainObject, toNumber } from '../utils/shared'
|
|
7
|
+
import type { LoadingType, LoadingSize } from '../loading/props'
|
|
8
|
+
import type { App, Component, TeleportProps } from 'vue'
|
|
9
|
+
|
|
10
|
+
export type SnackbarType = 'success' | 'warning' | 'info' | 'error' | 'loading'
|
|
11
|
+
|
|
12
|
+
export const SNACKBAR_TYPE: Array<SnackbarType> = ['loading', 'success', 'warning', 'info', 'error']
|
|
13
|
+
|
|
14
|
+
interface SnackbarHandel {
|
|
15
|
+
clear: () => void
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface SnackbarOptions {
|
|
19
|
+
type?: SnackbarType
|
|
20
|
+
content?: string
|
|
21
|
+
position?: 'top' | 'center' | 'bottom'
|
|
22
|
+
loadingType?: LoadingType
|
|
23
|
+
loadingSize?: LoadingSize
|
|
24
|
+
lockScroll?: boolean
|
|
25
|
+
contentClass?: string
|
|
26
|
+
duration?: number
|
|
27
|
+
vertical?: boolean
|
|
28
|
+
show?: boolean
|
|
29
|
+
forbidClick?: boolean
|
|
30
|
+
onOpen?: () => void
|
|
31
|
+
onClose?: () => void
|
|
32
|
+
onOpened?: () => void
|
|
33
|
+
onClosed?: () => void
|
|
34
|
+
// internal
|
|
35
|
+
teleport?: TeleportProps['to']
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface UniqSnackbarOptions {
|
|
39
|
+
id: number
|
|
40
|
+
reactiveSnackOptions: SnackbarOptions
|
|
41
|
+
_update?: string
|
|
42
|
+
animationEnd?: boolean
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface Snackbar {
|
|
46
|
+
(options: SnackbarOptions | string): SnackbarHandel
|
|
47
|
+
|
|
48
|
+
install(app: App): void
|
|
49
|
+
|
|
50
|
+
allowMultiple(bool: boolean): void
|
|
51
|
+
|
|
52
|
+
success(options: SnackbarOptions | string): SnackbarHandel
|
|
53
|
+
|
|
54
|
+
warning(options: SnackbarOptions | string): SnackbarHandel
|
|
55
|
+
|
|
56
|
+
info(options: SnackbarOptions | string): SnackbarHandel
|
|
57
|
+
|
|
58
|
+
error(options: SnackbarOptions | string): SnackbarHandel
|
|
59
|
+
|
|
60
|
+
loading(options: SnackbarOptions | string): SnackbarHandel
|
|
61
|
+
|
|
62
|
+
clear(): void
|
|
63
|
+
|
|
64
|
+
Component: Component
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let sid = 0
|
|
68
|
+
let isMount = false
|
|
69
|
+
let unmount: () => void
|
|
70
|
+
let isAllowMultiple = false
|
|
71
|
+
let uniqSnackbarOptions: Array<UniqSnackbarOptions> = reactive<UniqSnackbarOptions[]>([])
|
|
72
|
+
|
|
73
|
+
const defaultOption: Partial<Record<keyof SnackbarOptions, any>> = {
|
|
74
|
+
type: undefined,
|
|
75
|
+
content: '',
|
|
76
|
+
position: 'top',
|
|
77
|
+
duration: 3000,
|
|
78
|
+
vertical: false,
|
|
79
|
+
contentClass: undefined,
|
|
80
|
+
loadingType: 'circle',
|
|
81
|
+
loadingSize: 'normal',
|
|
82
|
+
lockScroll: false,
|
|
83
|
+
teleport: 'body',
|
|
84
|
+
forbidClick: false,
|
|
85
|
+
onOpen: () => {},
|
|
86
|
+
onOpened: () => {},
|
|
87
|
+
onClose: () => {},
|
|
88
|
+
onClosed: () => {},
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const transitionGroupProps: any = {
|
|
92
|
+
name: 'var-site-snackbar-fade',
|
|
93
|
+
tag: 'div',
|
|
94
|
+
class: 'var-site-transition-group',
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const TransitionGroupHost = {
|
|
98
|
+
setup: function() {
|
|
99
|
+
return () => {
|
|
100
|
+
const snackbarList = uniqSnackbarOptions.map(({ id, reactiveSnackOptions, _update }: UniqSnackbarOptions) => {
|
|
101
|
+
const transitionGroupEl = document.querySelector('.var-site-transition-group')
|
|
102
|
+
if (reactiveSnackOptions.forbidClick || reactiveSnackOptions.type === 'loading') {
|
|
103
|
+
;(transitionGroupEl as HTMLElement).classList.add('var-site-pointer-auto')
|
|
104
|
+
} else {
|
|
105
|
+
;(transitionGroupEl as HTMLElement).classList.remove('var-site-pointer-auto')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (isAllowMultiple) reactiveSnackOptions.position = 'top'
|
|
109
|
+
|
|
110
|
+
const position = isAllowMultiple ? 'relative' : 'absolute' // avoid stylelint value-keyword-case error
|
|
111
|
+
|
|
112
|
+
const style = {
|
|
113
|
+
position,
|
|
114
|
+
...getTop(reactiveSnackOptions.position)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<VarSiteSnackbarCore
|
|
119
|
+
{...reactiveSnackOptions}
|
|
120
|
+
key={id}
|
|
121
|
+
style={style}
|
|
122
|
+
data-id={id}
|
|
123
|
+
_update={_update}
|
|
124
|
+
v-model={[reactiveSnackOptions.show, 'show']}
|
|
125
|
+
/>
|
|
126
|
+
)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const zindex = context.zIndex // avoid stylelint value-keyword-case error
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<TransitionGroup
|
|
133
|
+
{...transitionGroupProps}
|
|
134
|
+
style={{ zIndex: zindex }}
|
|
135
|
+
onAfterEnter={opened}
|
|
136
|
+
onAfterLeave={removeUniqOption}
|
|
137
|
+
>
|
|
138
|
+
{snackbarList}
|
|
139
|
+
</TransitionGroup>
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const Snackbar: Snackbar = function (options: SnackbarOptions | string): SnackbarHandel {
|
|
146
|
+
const snackOptions: SnackbarOptions = isPlainObject(options) ? options : { content: options }
|
|
147
|
+
const reactiveSnackOptions: SnackbarOptions = reactive<SnackbarOptions>({
|
|
148
|
+
...defaultOption,
|
|
149
|
+
...snackOptions,
|
|
150
|
+
})
|
|
151
|
+
reactiveSnackOptions.show = true
|
|
152
|
+
|
|
153
|
+
if (!isMount) {
|
|
154
|
+
isMount = true
|
|
155
|
+
unmount = mountInstance(TransitionGroupHost).unmountInstance
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const { length } = uniqSnackbarOptions
|
|
159
|
+
const uniqSnackbarOptionItem: UniqSnackbarOptions = {
|
|
160
|
+
id: sid++,
|
|
161
|
+
reactiveSnackOptions,
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (length === 0 || isAllowMultiple) {
|
|
165
|
+
addUniqOption(uniqSnackbarOptionItem)
|
|
166
|
+
} else {
|
|
167
|
+
const _update = `update-${sid}`
|
|
168
|
+
updateUniqOption(reactiveSnackOptions, _update)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
clear() {
|
|
173
|
+
if (!isAllowMultiple && uniqSnackbarOptions.length) {
|
|
174
|
+
uniqSnackbarOptions[0].reactiveSnackOptions.show = false
|
|
175
|
+
} else {
|
|
176
|
+
reactiveSnackOptions.show = false
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
}
|
|
180
|
+
} as Snackbar
|
|
181
|
+
|
|
182
|
+
SNACKBAR_TYPE.forEach((type) => {
|
|
183
|
+
Snackbar[type] = (options: SnackbarOptions | string): SnackbarHandel => {
|
|
184
|
+
if (isPlainObject(options)) {
|
|
185
|
+
options.type = type
|
|
186
|
+
} else {
|
|
187
|
+
options = {
|
|
188
|
+
content: options,
|
|
189
|
+
type,
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return Snackbar(options)
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
Snackbar.install = function (app: App) {
|
|
197
|
+
app.component(VarSiteSnackbar.name, VarSiteSnackbar)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
Snackbar.allowMultiple = function (bool = false) {
|
|
201
|
+
if (bool !== isAllowMultiple) {
|
|
202
|
+
uniqSnackbarOptions.forEach((option: UniqSnackbarOptions) => {
|
|
203
|
+
option.reactiveSnackOptions.show = false
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
isAllowMultiple = bool
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
Snackbar.clear = function () {
|
|
211
|
+
uniqSnackbarOptions.forEach((option: UniqSnackbarOptions) => {
|
|
212
|
+
option.reactiveSnackOptions.show = false
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
Snackbar.Component = VarSiteSnackbar
|
|
217
|
+
|
|
218
|
+
function opened(element: HTMLElement): void {
|
|
219
|
+
const id = element.getAttribute('data-id')
|
|
220
|
+
const option = uniqSnackbarOptions.find((option) => option.id === toNumber(id))
|
|
221
|
+
if (option) option.reactiveSnackOptions.onOpened?.()
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function removeUniqOption(element: HTMLElement): void {
|
|
225
|
+
element.parentElement && element.parentElement.classList.remove('var-site-pointer-auto')
|
|
226
|
+
const id = element.getAttribute('data-id')
|
|
227
|
+
|
|
228
|
+
const option = uniqSnackbarOptions.find((option) => option.id === toNumber(id))
|
|
229
|
+
if (option) {
|
|
230
|
+
option.animationEnd = true
|
|
231
|
+
option.reactiveSnackOptions.onClosed?.()
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const isAllAnimationEnd = uniqSnackbarOptions.every((option) => option.animationEnd)
|
|
235
|
+
|
|
236
|
+
if (isAllAnimationEnd) {
|
|
237
|
+
unmount?.()
|
|
238
|
+
uniqSnackbarOptions = reactive<UniqSnackbarOptions[]>([])
|
|
239
|
+
isMount = false
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function addUniqOption(uniqSnackbarOptionItem: UniqSnackbarOptions) {
|
|
244
|
+
uniqSnackbarOptions.push(uniqSnackbarOptionItem)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function updateUniqOption(reactiveSnackOptions: SnackbarOptions, _update: string) {
|
|
248
|
+
const [firstOption] = uniqSnackbarOptions
|
|
249
|
+
|
|
250
|
+
firstOption.reactiveSnackOptions = {
|
|
251
|
+
...firstOption.reactiveSnackOptions,
|
|
252
|
+
...reactiveSnackOptions,
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
firstOption._update = _update
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function getTop(position = 'top') {
|
|
259
|
+
if (position === 'bottom') return { [position]: '5%' }
|
|
260
|
+
|
|
261
|
+
return { top: position === 'top' ? '5%' : '45%' }
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
VarSiteSnackbar.install = function (app: App) {
|
|
265
|
+
app.component(VarSiteSnackbar.name, VarSiteSnackbar)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export const _SnackbarComponent = VarSiteSnackbar
|
|
269
|
+
|
|
270
|
+
export default Snackbar
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { pickProps } from '../utils/components'
|
|
2
|
+
import { props as loadingProps } from '../loading/props'
|
|
3
|
+
import { SNACKBAR_TYPE, SnackbarType } from './index'
|
|
4
|
+
import type { PropType, TeleportProps } from 'vue'
|
|
5
|
+
|
|
6
|
+
export function positionValidator(position: string): boolean {
|
|
7
|
+
const validPositions = ['top', 'center', 'bottom']
|
|
8
|
+
return validPositions.includes(position)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function typeValidator(type: SnackbarType): boolean {
|
|
12
|
+
return SNACKBAR_TYPE.includes(type)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const props = {
|
|
16
|
+
type: {
|
|
17
|
+
type: String as PropType<SnackbarType>,
|
|
18
|
+
validator: typeValidator,
|
|
19
|
+
},
|
|
20
|
+
// snackbar显示的位置
|
|
21
|
+
position: {
|
|
22
|
+
type: String,
|
|
23
|
+
default: 'top',
|
|
24
|
+
validator: positionValidator,
|
|
25
|
+
},
|
|
26
|
+
// content内容
|
|
27
|
+
content: {
|
|
28
|
+
type: String,
|
|
29
|
+
},
|
|
30
|
+
// 为snackbar content添加自定义类名
|
|
31
|
+
contentClass: {
|
|
32
|
+
type: String,
|
|
33
|
+
},
|
|
34
|
+
// snackbar 持续时间
|
|
35
|
+
duration: {
|
|
36
|
+
type: Number,
|
|
37
|
+
default: 3000,
|
|
38
|
+
},
|
|
39
|
+
// 是否将消息条内容堆叠在操作(按钮)之上
|
|
40
|
+
vertical: {
|
|
41
|
+
type: Boolean,
|
|
42
|
+
default: false,
|
|
43
|
+
},
|
|
44
|
+
// 加载动画类型
|
|
45
|
+
loadingType: pickProps(loadingProps, 'type'),
|
|
46
|
+
// 加载动画尺寸
|
|
47
|
+
loadingSize: pickProps(loadingProps, 'size'),
|
|
48
|
+
// 是否禁止滚动穿透
|
|
49
|
+
lockScroll: {
|
|
50
|
+
type: Boolean,
|
|
51
|
+
default: false,
|
|
52
|
+
},
|
|
53
|
+
// 控制组件可见还是隐藏
|
|
54
|
+
show: {
|
|
55
|
+
type: Boolean,
|
|
56
|
+
default: false,
|
|
57
|
+
},
|
|
58
|
+
// teleport
|
|
59
|
+
teleport: {
|
|
60
|
+
type: String as PropType<TeleportProps['to']>,
|
|
61
|
+
default: 'body',
|
|
62
|
+
},
|
|
63
|
+
// 是否禁止点击背景
|
|
64
|
+
forbidClick: {
|
|
65
|
+
type: Boolean,
|
|
66
|
+
default: false,
|
|
67
|
+
},
|
|
68
|
+
// 打开时的回调函数
|
|
69
|
+
onOpen: {
|
|
70
|
+
type: Function,
|
|
71
|
+
default: () => {},
|
|
72
|
+
},
|
|
73
|
+
// 打开动画结束时的回调
|
|
74
|
+
onOpened: {
|
|
75
|
+
type: Function,
|
|
76
|
+
default: () => {},
|
|
77
|
+
},
|
|
78
|
+
// 关闭时的回调函数
|
|
79
|
+
onClose: {
|
|
80
|
+
type: Function,
|
|
81
|
+
default: () => {},
|
|
82
|
+
},
|
|
83
|
+
// 关闭动画结束时的回调
|
|
84
|
+
onClosed: {
|
|
85
|
+
type: Function,
|
|
86
|
+
default: () => {},
|
|
87
|
+
},
|
|
88
|
+
'onUpdate:show': {
|
|
89
|
+
type: Function,
|
|
90
|
+
},
|
|
91
|
+
_update: {
|
|
92
|
+
type: String,
|
|
93
|
+
},
|
|
94
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
@site-snackbar-width: 256px;
|
|
2
|
+
@site-snackbar-color: rgba(255, 255, 255, 0.87);
|
|
3
|
+
@site-snackbar-border-radius: 4px;
|
|
4
|
+
@site-snackbar-background: #333;
|
|
5
|
+
@site-snackbar-font-size: var(--site-font-size-md);
|
|
6
|
+
@site-snackbar-margin: 6px 24px;
|
|
7
|
+
@site-snackbar-border-color: currentColor;
|
|
8
|
+
@site-snackbar-success-background: var(--site-color-success);
|
|
9
|
+
@site-snackbar-info-background: var(--site-color-info);
|
|
10
|
+
@site-snackbar-error-background: var(--site-color-danger);
|
|
11
|
+
@site-snackbar-warning-background: var(--site-color-warning);
|
|
12
|
+
@site-snackbar-content-padding: 14px 16px;
|
|
13
|
+
@site-snackbar-action-margin: 0 16px 0 0;
|
|
14
|
+
|
|
15
|
+
:root {
|
|
16
|
+
--site-snackbar-width: @site-snackbar-width;
|
|
17
|
+
--site-snackbar-color: @site-snackbar-color;
|
|
18
|
+
--site-snackbar-border-radius: @site-snackbar-border-radius;
|
|
19
|
+
--site-snackbar-background: @site-snackbar-background;
|
|
20
|
+
--site-snackbar-font-size: @site-snackbar-font-size;
|
|
21
|
+
--site-snackbar-margin: @site-snackbar-margin;
|
|
22
|
+
--site-snackbar-border-color: @site-snackbar-border-color;
|
|
23
|
+
--site-snackbar-success-background: @site-snackbar-success-background;
|
|
24
|
+
--site-snackbar-info-background: @site-snackbar-info-background;
|
|
25
|
+
--site-snackbar-error-background: @site-snackbar-error-background;
|
|
26
|
+
--site-snackbar-warning-background: @site-snackbar-warning-background;
|
|
27
|
+
--site-snackbar-content-padding: @site-snackbar-content-padding;
|
|
28
|
+
--site-snackbar-action-margin: @site-snackbar-action-margin;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.var-site-transition-group {
|
|
32
|
+
position: fixed;
|
|
33
|
+
left: 0;
|
|
34
|
+
right: 0;
|
|
35
|
+
top: 0;
|
|
36
|
+
bottom: 0;
|
|
37
|
+
pointer-events: none;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.var-site-pointer-auto {
|
|
41
|
+
pointer-events: auto;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.var-site {
|
|
45
|
+
&-snackbar {
|
|
46
|
+
display: flex;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
align-items: baseline;
|
|
49
|
+
left: 0;
|
|
50
|
+
right: 0;
|
|
51
|
+
bottom: 0;
|
|
52
|
+
transition: all 0.15s var(--site-cubic-bezier);
|
|
53
|
+
|
|
54
|
+
&__wrapper {
|
|
55
|
+
width: var(--site-snackbar-width);
|
|
56
|
+
display: flex;
|
|
57
|
+
border-radius: var(--site-snackbar-border-radius);
|
|
58
|
+
color: var(--site-snackbar-color);
|
|
59
|
+
background: var(--site-snackbar-background);
|
|
60
|
+
font-size: var(--site-snackbar-font-size);
|
|
61
|
+
margin: var(--site-snackbar-margin);
|
|
62
|
+
align-items: center;
|
|
63
|
+
border-color: var(--site-snackbar-border-color);
|
|
64
|
+
pointer-events: auto;
|
|
65
|
+
transition: 0.3s var(--site-cubic-bezier);
|
|
66
|
+
|
|
67
|
+
&-success {
|
|
68
|
+
background: var(--site-snackbar-success-background);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
&-info {
|
|
72
|
+
background: var(--site-snackbar-info-background);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
&-warning {
|
|
76
|
+
background: var(--site-snackbar-warning-background);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
&-error {
|
|
80
|
+
background: var(--site-snackbar-error-background);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
&__content {
|
|
85
|
+
flex-grow: 1;
|
|
86
|
+
padding: var(--site-snackbar-content-padding);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
&__action {
|
|
90
|
+
margin: var(--site-snackbar-action-margin);
|
|
91
|
+
display: flex;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
&__vertical {
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
align-items: flex-start;
|
|
97
|
+
|
|
98
|
+
.var-site-snackbar__action {
|
|
99
|
+
align-self: flex-end;
|
|
100
|
+
margin-bottom: 8px;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
&-fade-leave-active {
|
|
105
|
+
position: absolute;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
&-fade-enter-from,
|
|
109
|
+
&-fade-leave-to {
|
|
110
|
+
opacity: 0;
|
|
111
|
+
transform: translateY(-30px);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
&-snackbar-transition {
|
|
116
|
+
top: 0;
|
|
117
|
+
position: fixed;
|
|
118
|
+
|
|
119
|
+
.var-site-snackbar__wrapper {
|
|
120
|
+
position: absolute;
|
|
121
|
+
|
|
122
|
+
&-top {
|
|
123
|
+
top: 5%;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
&-center {
|
|
127
|
+
top: 45%;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
&-bottom {
|
|
131
|
+
bottom: 5%;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isNumber, isString, toNumber, kebabCase } from './shared'
|
|
2
2
|
import type { StyleVars } from '../../utils'
|
|
3
|
+
import { requestAnimationFrame } from '@varlet/ui/src/utils/elements'
|
|
3
4
|
|
|
4
5
|
export function getLeft(element: HTMLElement): number {
|
|
5
6
|
const { left } = element.getBoundingClientRect()
|
|
@@ -81,3 +82,11 @@ export function formatStyleVars(styleVars: StyleVars | null) {
|
|
|
81
82
|
return styles
|
|
82
83
|
}, {} as StyleVars)
|
|
83
84
|
}
|
|
85
|
+
|
|
86
|
+
export function doubleRaf() {
|
|
87
|
+
return new Promise((resolve) => {
|
|
88
|
+
requestAnimationFrame(() => {
|
|
89
|
+
requestAnimationFrame(resolve)
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
}
|
|
@@ -12,6 +12,9 @@ export const toNumber = (val: number | string | boolean | undefined | null): num
|
|
|
12
12
|
return val
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
export const isPlainObject = (val: unknown): val is Record<string, any> =>
|
|
16
|
+
Object.prototype.toString.call(val) === '[object Object]'
|
|
17
|
+
|
|
15
18
|
export function kebabCase(str: string): string {
|
|
16
19
|
const reg = /([^-])([A-Z])/g
|
|
17
20
|
|
package/site/mobile/App.vue
CHANGED
|
@@ -86,7 +86,6 @@
|
|
|
86
86
|
</template>
|
|
87
87
|
|
|
88
88
|
<script lang="ts">
|
|
89
|
-
// @ts-ignore
|
|
90
89
|
import config from '@config'
|
|
91
90
|
import { computed, ComputedRef, defineComponent, ref, Ref, watch } from 'vue'
|
|
92
91
|
import { useRoute } from 'vue-router'
|
|
@@ -98,7 +97,7 @@ import {
|
|
|
98
97
|
removeEmpty,
|
|
99
98
|
setThemes,
|
|
100
99
|
watchLang,
|
|
101
|
-
watchThemes
|
|
100
|
+
watchThemes,
|
|
102
101
|
} from '../utils'
|
|
103
102
|
import { get } from 'lodash-es'
|
|
104
103
|
|
|
@@ -112,11 +111,12 @@ export default defineComponent({
|
|
|
112
111
|
const languages: Ref<Record<string, string>> = ref(get(config, 'mobile.header.i18n'))
|
|
113
112
|
const nonEmptyLanguages: ComputedRef<Record<string, string>> = computed(() => removeEmpty(languages.value))
|
|
114
113
|
const redirect = get(config, 'mobile.redirect', '')
|
|
114
|
+
const themesKey = get(config, 'themesKey')
|
|
115
115
|
const github: Ref<string> = ref(get(config, 'mobile.header.github'))
|
|
116
116
|
const darkMode: Ref<string> = ref(get(config, 'mobile.header.darkMode'))
|
|
117
|
-
const currentThemes = ref(getBrowserThemes())
|
|
117
|
+
const currentThemes = ref(getBrowserThemes(themesKey))
|
|
118
118
|
|
|
119
|
-
const changeLanguage = (lang) => {
|
|
119
|
+
const changeLanguage = (lang: string) => {
|
|
120
120
|
language.value = lang
|
|
121
121
|
showMenu.value = false
|
|
122
122
|
window.location.href = `./mobile.html#${route.path}?language=${language.value}&replace=${route.query.replace}`
|
|
@@ -136,7 +136,7 @@ export default defineComponent({
|
|
|
136
136
|
|
|
137
137
|
const toGithub = () => {
|
|
138
138
|
if (inIframe() && !isPhone()) {
|
|
139
|
-
window.top
|
|
139
|
+
window.top!.open(github.value)
|
|
140
140
|
} else {
|
|
141
141
|
window.location.href = github.value
|
|
142
142
|
}
|
|
@@ -161,7 +161,7 @@ export default defineComponent({
|
|
|
161
161
|
const setCurrentThemes = (themes: 'themes' | 'darkThemes') => {
|
|
162
162
|
currentThemes.value = themes
|
|
163
163
|
setThemes(config, currentThemes.value)
|
|
164
|
-
window.localStorage.setItem(
|
|
164
|
+
window.localStorage.setItem(themesKey, currentThemes.value)
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
const toggleTheme = () => {
|
package/site/module.d.ts
ADDED
package/site/pc/App.vue
CHANGED
|
@@ -29,15 +29,14 @@
|
|
|
29
29
|
</template>
|
|
30
30
|
|
|
31
31
|
<script lang="ts">
|
|
32
|
-
// @ts-ignore
|
|
33
32
|
import config from '@config'
|
|
34
|
-
import AppMobile from './components/AppMobile'
|
|
35
|
-
import AppHeader from './components/AppHeader'
|
|
36
|
-
import AppSidebar from './components/AppSidebar'
|
|
33
|
+
import AppMobile from './components/AppMobile.vue'
|
|
34
|
+
import AppHeader from './components/AppHeader.vue'
|
|
35
|
+
import AppSidebar from './components/AppSidebar.vue'
|
|
37
36
|
import { defineComponent, nextTick, onMounted, ref, Ref, watch } from 'vue'
|
|
38
37
|
import { useRoute } from 'vue-router'
|
|
39
38
|
import { get } from 'lodash-es'
|
|
40
|
-
import { getPCLocationInfo, isPhone, MenuTypes
|
|
39
|
+
import { getPCLocationInfo, isPhone, MenuTypes } from '../utils'
|
|
41
40
|
|
|
42
41
|
export interface Menu {
|
|
43
42
|
doc: string
|
|
@@ -52,7 +51,6 @@ export default defineComponent({
|
|
|
52
51
|
AppSidebar
|
|
53
52
|
},
|
|
54
53
|
setup() {
|
|
55
|
-
// config
|
|
56
54
|
const defaultLanguage = get(config, 'defaultLanguage')
|
|
57
55
|
const menu: Ref<Menu[]> = ref(get(config, 'pc.menu', []))
|
|
58
56
|
const useMobile = ref(get(config, 'useMobile'))
|
|
@@ -79,7 +77,7 @@ export default defineComponent({
|
|
|
79
77
|
|
|
80
78
|
nextTick(() => {
|
|
81
79
|
const children = document
|
|
82
|
-
.querySelector('.varlet-site-sidebar')
|
|
80
|
+
.querySelector('.varlet-site-sidebar')!
|
|
83
81
|
.getElementsByClassName('var-site-cell')
|
|
84
82
|
const index = menu.value.findIndex((item) => item.doc === menuName)
|
|
85
83
|
|
|
@@ -93,7 +91,7 @@ export default defineComponent({
|
|
|
93
91
|
}
|
|
94
92
|
|
|
95
93
|
const handleSidebarChange = (menu: Menu) => {
|
|
96
|
-
doc.value
|
|
94
|
+
doc.value!.scrollTop = 0
|
|
97
95
|
componentName.value = getComponentNameByMenuName(menu.doc)
|
|
98
96
|
menuName.value = menu.doc
|
|
99
97
|
}
|
|
@@ -287,17 +285,17 @@ iframe {
|
|
|
287
285
|
}
|
|
288
286
|
|
|
289
287
|
pre {
|
|
290
|
-
margin:
|
|
288
|
+
margin: 10px 0 0;
|
|
291
289
|
}
|
|
292
290
|
|
|
293
291
|
code {
|
|
294
292
|
position: relative;
|
|
295
293
|
display: block;
|
|
296
|
-
padding: 16px;
|
|
294
|
+
padding: 10px 16px;
|
|
297
295
|
overflow-x: auto;
|
|
298
296
|
font-size: 13px;
|
|
299
297
|
font-family: Consolas, Monaco, monospace;
|
|
300
|
-
line-height:
|
|
298
|
+
line-height: 31px;
|
|
301
299
|
white-space: pre-wrap;
|
|
302
300
|
word-wrap: break-word;
|
|
303
301
|
color: #fff;
|