Skip to content

Commit

Permalink
feat(video): add Video component (vexip-ui#426)
Browse files Browse the repository at this point in the history
* chore: create component

* wip: update

* wip: update

* wip: update

* wip: update

* wip: update

* wip: update

* wip: update

* wip: update

* wip: update

* wip: update

* revert:  re-adjust outline-color to outline

fix vexip-ui#433

* perf(tooltip): dynamically render popper element

* feat(ellipsis): add tip-shift prop

* chore(tooltip): effective unit tests

* fix(auto-complete): correct behavior when directly input

fix vexip-ui#434

* refactor(table): improve fixed columns implement and support column group (vexip-ui#435)

* wip: update

* feat: support column group

* docs: update demos

* docs: update apis

* chore: transfer to setup script

* wip: side padding

* fix: side padding

* chore: group no-ellipsis prop

* chore: group text-align prop

* chore: col resize

* chore: update

* chore(tooltip): effective unit tests

* chore: update

* chore: update

* release(hooks): v2.1.1

* release: v2.2.12

* fix(table): ensure tree table work with virtual

* feat(table): add formatter prop for column

* fix(select): correct composition behavior for filter input

* release: v2.2.13

* fix(table): incorrect treeExpanded initialization of rows

* chore(toast): transfer to use setup script

* feat(hooks): add watchPauseable util method

* chore(hooks): create test config

* fix(table): ensure correct row span for head cell when refresh

* feat(table): add refreshData api method

* feat(table): add data-filter prop

* chore(tree): transfer to setup script

* feat(tree): support only filter leaf nodes

* fix: normalize component inherit class name

* fix: normalize input-base components composition events

* chore: compatible composition end process

* feat(utils): flatTree add buildId option

* feat(utils): walkTree callabck add parent parameter

* refactor(tree): avoid invade data when parsing by tree structure

* feat(utils): add isIterable and mapTree methods

* feat(utils): add filterTree method

* feat(tree): add getTreeData and getFlattedData api methods

* release(utils): v2.6.0

* release(hooks): v2.2.0

* release: v2.2.14

* docs: update tree preset types

* release(scripts): v1.1.2

* feat(table): add no-transition prop

* feat(utils): async debounceMinor and debounceFrame

* fix(tree): unexcepted expanding state changed

* feat(native-scroll): async refresh and ensureInView methods

* feat(scroll): async api methods

* fix(native-scroll): no emit event when sync scroll position

* perf(scrollbar): remove overused throttle for move process

* fix(hooks): useVirtual support wrapper changed

* chore(virtual-list): using renderSlot to create items

* perf(table): improve table cell span computation

* fix(confirm): ensure api method work

* perf(table): improve performance of virtual scrolling (vexip-ui#436)

* wip: update

* wip: update

* wip: update

* wip: update

* fix(table): correct flatted structure after drop

* feat(table): support inherit provided config when using columns and summaries props

* chore(table): make unit tests pass

* feat(full-screen): provide inner place for transfer elements

* fix(tree): rename empty-tip prop to empty-text

* types: normalize transfer prop type for default config

* types: normalize MaybeRef type

* feat(message): add transferTo method

* feat(notice): add transferTo method

* feat(toast): add transferTo method

* feat(loading): add transferTo method

* feat(contextmenu): support target option

* feat(confirm): add transferTo method

* chore: ensure element be removed after destroy plugin

* release(utils): v2.7.0

* release(hooks): v2.2.1

* release(config): v1.3.1

* release: v2.2.15

* docs(table): remove non-existent prop api

* fix(table): correct tree render when using virtual (vexip-ui#437)

* wip: update

* fix: correct tree process

* ci: deploy docs when publish

* fix(table): rename helper methods by more accurate names

* feat(table): add ellipsis prop

* release: v2.2.16

* ci: extract deploy docs workflow

* chore(utils): export BITree tree array

* fix(table): correct compute and refresh cell height when using tree

* chore: transfer some components to setup script

* ci: adjust deploy docs workflow trigger

* chore: update README.md

* feat(tag): add disabled prop

* fix: correct disabled and readonly of form control components

fix vexip-ui#438

* fix(overflow): correct rest count when using suffix

* fix(select): ensure selected slot work with filter

fix vexip-ui#439

* chore: transfer some components to setup script

* feat(wheel): add no-transition prop

* release(utils): v2.7.1

* release: v2.2.17

* wip: control layout

* feat: switch to lucide

* docs: update

* docs: update

* chore: update

* chore: update

* wip: segments

* wip: update

* docs: update

* feat: add shortcuts

* docs: update

* test: update

* docs: update

* test: update

* chore: update lock file

* chore: update lock file

* chore: update
  • Loading branch information
qmhc authored Jan 12, 2024
1 parent 7a0571e commit 17f02cd
Show file tree
Hide file tree
Showing 69 changed files with 3,233 additions and 48 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ module.exports = defineConfig({
rules: {
'@typescript-eslint/no-use-before-define': 'off',
'vue/no-v-html': 'off',
'vue/no-textarea-mustache': 'off'
'vue/no-textarea-mustache': 'off',
'react/jsx-key': 'off'
},
overrides: [
{
Expand Down
35 changes: 33 additions & 2 deletions common/config/src/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
Filter,
FlipHorizontal,
FlipVertical,
Fullscreen,
GripVertical,
HelpCircle,
Image,
Expand All @@ -40,6 +41,9 @@ import {
Moon,
MoreHorizontal,
Outdent,
Pause,
PictureInPicture,
Play,
Plus,
PlusSquare,
RefreshCw,
Expand All @@ -48,11 +52,16 @@ import {
RotateCw,
Search,
Siren,
SkipBack,
SkipForward,
Sun,
Trash2,
Upload,
UploadCloud,
UserRound,
Volume1,
Volume2,
VolumeX,
X,
XCircle,
ZoomIn,
Expand Down Expand Up @@ -141,7 +150,18 @@ export interface IconsOptions {
fileImage?: IconConfig,
fileAudio?: IconConfig,
fileVideo?: IconConfig,
fileZip?: IconConfig
fileZip?: IconConfig,
volume?: IconConfig,
volumeLow?: IconConfig,
volumeMute?: IconConfig,
play?: IconConfig,
pause?: IconConfig,
fullWindow?: IconConfig,
pip?: IconConfig,
playState?: IconConfig,
pauseState?: IconConfig,
playPrev?: IconConfig,
playNext?: IconConfig
}

export type IconName = keyof IconsOptions
Expand Down Expand Up @@ -208,7 +228,18 @@ const iconMap: IconsConfig = {
fileImage: FileImage,
fileAudio: FileMusic,
fileVideo: FileVideo,
fileZip: FileArchive
fileZip: FileArchive,
volume: Volume2,
volumeLow: Volume1,
volumeMute: VolumeX,
play: Play,
pause: Pause,
fullWindow: Fullscreen,
pip: PictureInPicture,
playState: Play,
pauseState: Pause,
playPrev: SkipBack,
playNext: SkipForward
}

export const iconNames = Object.freeze(Object.keys(iconMap) as IconName[])
Expand Down
16 changes: 16 additions & 0 deletions common/config/src/locale/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,22 @@ export function enUSLocale() {
dragOrClick: 'Drag files here, or click to upload'
},

video: {
play: 'Play',
pause: 'Pause',
playPrev: 'Prev',
playNext: 'Next',
refresh: 'Refresh',
flip: 'Flip',
requestPip: 'Enter PIP',
exitPip: 'Exit PIP',
fullWindow: 'Full window',
fullWindowExit: 'Full window exit',
fullScreen: 'Full screen',
fullScreenExit: 'Full screen exit',
chapterCount: 'Chapter {n}'
},

viewer: {
rotateRight: 'Rotate right',
rotateLeft: 'Rotate left',
Expand Down
16 changes: 16 additions & 0 deletions common/config/src/locale/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,22 @@ export interface LocaleConfig {
dragOrClick: string
},

video: {
play: string,
pause: string,
playPrev: string,
playNext: string,
refresh: string,
flip: string,
requestPip: string,
exitPip: string,
fullWindow: string,
fullWindowExit: string,
fullScreen: string,
fullScreenExit: string,
chapterCount: string
},

viewer: {
rotateRight: string,
rotateLeft: string,
Expand Down
18 changes: 17 additions & 1 deletion common/config/src/locale/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,30 @@ export function zhCNLocale() {
dragOrClick: '将文件拖到此处, 或点击上传'
},

video: {
play: '播放',
pause: '暂停',
playPrev: '上一个',
playNext: '下一个',
refresh: '刷新',
flip: '镜像翻转',
requestPip: '进入画中画',
exitPip: '退出画中画',
fullWindow: '进入网页全屏',
fullWindowExit: '退出网页全屏',
fullScreen: '进入全屏',
fullScreenExit: '退出全屏',
chapterCount: '第 {n} 章'
},

viewer: {
rotateRight: '向右旋转',
rotateLeft: '向左旋转',
flipHorizontal: '横向翻转',
flipVertical: '纵向翻转',
zoomIn: '放大',
zoomOut: '缩小',
fullScreen: '全屏',
fullScreen: '进入全屏',
fullScreenExit: '退出全屏',
reset: '重置'
}
Expand Down
4 changes: 1 addition & 3 deletions common/meta/scripts/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ async function readDirectives() {
const componentRE = /import \{ (.+) \} from '@\/components\/.+'/
const directivesDir = resolve(rootDir, '../../directives')
const directives = await Promise.all(
(
await readdir(directivesDir, 'utf-8')
)
(await readdir(directivesDir, 'utf-8'))
.filter(f => statSync(resolve(directivesDir, f)).isDirectory())
.map(async directive => {
const content = await readFile(resolve(directivesDir, directive, 'index.ts'), 'utf-8')
Expand Down
6 changes: 6 additions & 0 deletions components/form/tests/form.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,9 @@ describe('Form', () => {
await nextTick()
vi.runOnlyPendingTimers()
await nextTick()
await nextTick()
vi.runAllTimers()
await nextTick()

expect(document.querySelector('.vxp-form__help-tip')).toBeTruthy()
expect(document.querySelector('.vxp-form__help-tip')!.textContent).toEqual('help')
Expand All @@ -250,6 +253,9 @@ describe('Form', () => {
await nextTick()
vi.runOnlyPendingTimers()
await nextTick()
await nextTick()
vi.runAllTimers()
await nextTick()

expect(document.querySelector('.help')).toBeTruthy()
expect(document.querySelector('.help')!.textContent).toEqual('help')
Expand Down
3 changes: 3 additions & 0 deletions components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ import { Tree } from './tree'
import { Upload } from './upload'
import { UploadFile } from './upload-file'
import { UploadList } from './upload-list'
import { Video } from './video'
import { Viewer } from './viewer'
import { VirtualList } from './virtual-list'
import { Wheel } from './wheel'
Expand Down Expand Up @@ -236,6 +237,7 @@ const components = [
Upload,
UploadFile,
UploadList,
Video,
Viewer,
VirtualList,
Wheel,
Expand Down Expand Up @@ -381,6 +383,7 @@ export * from './typography'
export * from './upload'
export * from './upload-file'
export * from './upload-list'
export * from './video'
export * from './viewer'
export * from './virtual-list'
export * from './wheel'
Expand Down
16 changes: 16 additions & 0 deletions components/select/select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,22 @@
</Tooltip>
</span>
</template>
<!-- <template v-if="!limited && previewOption" #suffix>
<Tag
inherit
:class="[
nh.be('tag'),
nh.bem('tag', 'preview'),
currentValues.includes(previewOption.value) && nh.bem('tag', 'deleted')
]"
:type="props.tagType"
closable
>
<slot name="selected" :preview="true" :option="previewOption">
{{ previewOption.label }}
</slot>
</Tag>
</template> -->
</Overflow>
<div
v-if="props.filter"
Expand Down
3 changes: 3 additions & 0 deletions components/tooltip/tests/tooltip.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ describe('Tooltip', () => {
await nextTick()
vi.runOnlyPendingTimers()
await nextTick()
await nextTick()
vi.runAllTimers()
await nextTick()
expect(document.querySelector('.vxp-tooltip__popper')).not.toBeNull()
expect(document.querySelector('.tip')).not.toBeNull()
expect(document.querySelector('.tip')!.innerHTML).toEqual(TEXT)
Expand Down
4 changes: 4 additions & 0 deletions components/video/css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import '@/components/preset/css'
import '@/components/full-screen/css'
import '@/components/option/css'
import '@/css/video.css'
24 changes: 24 additions & 0 deletions components/video/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { doubleDigits, leaveNumber } from '@vexip-ui/utils'

import type { IconOptions, IconValue } from '@vexip-ui/config'

export function formatSeconds(seconds: number) {
if (seconds <= 0) return '00:00'

const remainders = leaveNumber(Math.ceil(seconds), 60, 2)

if (remainders.length < 2) {
remainders.unshift(0)
}

return remainders.length < 3
? remainders.map(doubleDigits).join(':')
: remainders.map((r, i) => (i ? doubleDigits(r) : r)).join(':')
}

export function mergeIconScale(scale: number, icon: IconOptions & { icon: IconValue }) {
return {
...icon,
scale: +(icon.scale || 1) * scale
}
}
21 changes: 21 additions & 0 deletions components/video/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Video from './video'

import type { ComponentPublicInstance } from 'vue'

export { Video }
export { videoProps } from './props'
export { videoDefaultShortcuts, videoDefaultControlLayout } from './symbol'

export type VideoExposed = ComponentPublicInstance & InstanceType<typeof Video>

export type { VideoProps, VideoCProps } from './props'
export type {
VideoPresetControl,
VideoControlName,
VideoControlConfig,
VideoControlLayout,
VideoPlaybackRate,
VideoControlType,
VideoControlOption,
VideoSegment
} from './symbol'
70 changes: 70 additions & 0 deletions components/video/props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { booleanProp, buildProps, eventProp } from '@vexip-ui/config'

import type { ExtractPropTypes, PropType } from 'vue'
import type { FullScreenType } from '@/components/full-screen'
import type { IconEffect } from '@/components/icon'
import type { ClassType, ConfigurableProps } from '@vexip-ui/config'
import type {
VideoControlLayout,
VideoControlOption,
VideoControlType,
// VideoKernel,
VideoPlaybackRate,
VideoSegment,
VideoShortcutOptions
} from './symbol'

export const videoProps = buildProps({
src: String,
srcList: Array as PropType<string[]>,
noControls: booleanProp,
videoAttrs: Object,
time: Number,
volume: Number,
playbackRate: Number,
playbackRates: Array as PropType<(number | VideoPlaybackRate)[]>,
// kernel: Object as PropType<VideoKernel>,
controlLayout: Object as PropType<VideoControlLayout>,
poster: String,
video: Object as PropType<HTMLVideoElement>,
segments: Array as PropType<(number | VideoSegment)[]>,
loading: booleanProp,
loadingIcon: Object,
loadingEffect: String as PropType<IconEffect>,
shortcuts: Object as PropType<VideoShortcutOptions>,
onPlay: eventProp(),
onPause: eventProp(),
onEnded: eventProp(),
onTimeChange: eventProp<(time: number) => void>(),
onVolumeChange: eventProp<(volume: number) => void>(),
onRateChange: eventProp<(rate: number) => void>(),
onToggleFlip: eventProp<(flip: boolean) => void>(),
onTogglePip: eventProp<(pip: boolean) => void>(),
onToggleFull: eventProp<(full: false | FullScreenType) => void>(),
onPrev: eventProp(),
onNext: eventProp(),
onRefresh: eventProp()
})

export type VideoProps = ExtractPropTypes<typeof videoProps>
export type VideoCProps = ConfigurableProps<ExtractPropTypes<typeof videoProps>>

export const videoControlProps = buildProps({
type: String as PropType<VideoControlType>,
label: String,
tipClass: [String, Array, Object] as PropType<ClassType>,
disabled: booleanProp,
shortcut: String,
focusable: booleanProp,
value: [Number, String],
options: Array as PropType<(string | VideoControlOption)[]>,
onClick: eventProp(),
onEnter: eventProp(),
onLeave: eventProp(),
onFocus: eventProp<(event: FocusEvent) => void>(),
onBlur: eventProp<(event: FocusEvent) => void>(),
onSelect: eventProp<(option: VideoControlOption) => void>()
})

export type VideoControlProps = ExtractPropTypes<typeof videoControlProps>
export type VideoControlCProps = ConfigurableProps<ExtractPropTypes<typeof videoControlProps>>
4 changes: 4 additions & 0 deletions components/video/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import '@/components/preset/style'
import '@/components/full-screen/style'
import '@/components/option/style'
import '@/style/video.scss'
Loading

0 comments on commit 17f02cd

Please sign in to comment.