Skip to content

Commit 42f6383

Browse files
authored
feat: ProgressBar component (vue-terminal#14)
feat: `ProgressBar` component
1 parent 4297f5f commit 42f6383

File tree

8 files changed

+103
-2
lines changed

8 files changed

+103
-2
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import {
2+
defineComponent,
3+
h,
4+
inject,
5+
onMounted,
6+
onUpdated,
7+
onUnmounted,
8+
computed,
9+
} from '@vue/runtime-core'
10+
import type { PropType } from '@vue/runtime-core'
11+
import { colorize } from '../renderer/textColor'
12+
import type { ForegroundColorProp } from '../renderer/textColor'
13+
import { scheduleUpdateSymbol } from '../injectionSymbols'
14+
15+
const FIGURES = {
16+
basic: '█',
17+
shade: '▓',
18+
} as const
19+
20+
type FigureType = keyof typeof FIGURES
21+
22+
export const TuiProgressBar = defineComponent({
23+
name: 'TuiProgressBar',
24+
25+
props: {
26+
color: {
27+
required: false,
28+
default: 'blue',
29+
type: String as PropType<ForegroundColorProp>,
30+
},
31+
bgColor: {
32+
required: false,
33+
default: 'white',
34+
type: String as PropType<ForegroundColorProp>,
35+
},
36+
width: {
37+
required: false,
38+
default: 25,
39+
type: Number,
40+
},
41+
value: {
42+
required: true,
43+
type: Number,
44+
},
45+
type: {
46+
required: false,
47+
type: String as PropType<FigureType>,
48+
default: 'basic',
49+
},
50+
},
51+
52+
setup(props) {
53+
const scheduleUpdate = inject(scheduleUpdateSymbol)!
54+
55+
onMounted(scheduleUpdate)
56+
57+
onUpdated(scheduleUpdate)
58+
59+
onUnmounted(scheduleUpdate)
60+
61+
const content = computed(() => {
62+
const type = FIGURES[props.type]
63+
const w = Math.floor(props.value * (props.width / 100))
64+
const bg = colorize(type, props.bgColor, 'foreground')
65+
const fg = colorize(type, props.color, 'foreground')
66+
return fg.repeat(w) + bg.repeat(props.width - w)
67+
})
68+
69+
return () => {
70+
return h('tui:text', content.value)
71+
}
72+
},
73+
})

packages/core/src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export { TuiTextTransform } from './TextTransform'
33
export { TuiNewline } from './Newline'
44
export { TuiApp } from './App'
55
export { TuiBox } from './Box'
6+
export { TuiProgressBar } from './ProgressBar'
67

78
export { TuiLink } from './Link'
89
// export { default as TuiInput } from './Input.vue'

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export {
77
TuiNewline,
88
TuiLink,
99
TuiTextTransform,
10+
TuiProgressBar,
1011
} from './components'
1112

1213
export { render } from './renderer'

packages/core/src/renderer/textColor.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import chalk from 'chalk'
2-
2+
import type { ForegroundColor } from 'chalk'
33
type ColorType = 'foreground' | 'background'
4+
import type { LiteralUnion } from '../utils'
5+
6+
export type ForegroundColorProp = LiteralUnion<ForegroundColor, string>
47

58
const RGB_LIKE_REGEX = /^(rgb|hsl|hsv|hwb)\(\s?(\d+),\s?(\d+),\s?(\d+)\s?\)$/
69
const ANSI_REGEX = /^(ansi|ansi256)\(\s?(\d+)\s?\)$/

packages/playground/components.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ declare module '@vue/runtime-core' {
1111
Br: typeof import('vue-termui')['TuiNewline']
1212
Div: typeof import('vue-termui')['TuiBox']
1313
Link: typeof import('vue-termui')['TuiLink']
14+
Newline: typeof import('vue-termui')['TuiNewline']
15+
Progressbar: typeof import('vue-termui')['TuiProgressBar']
1416
Span: typeof import('vue-termui')['TuiText']
1517
Text: typeof import('vue-termui')['TuiText']
1618
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<script setup lang="ts">
2+
const progress = ref(50)
3+
useInterval(() => {
4+
progress.value < 100 && progress.value++
5+
}, 0)
6+
</script>
7+
8+
<template>
9+
<Text>
10+
<Newline :n="2" />
11+
<ProgressBar :value="progress" color="green" :width="12" />
12+
<Newline :n="2" />
13+
<ProgressBar :value="progress" color="yellow" />
14+
<Newline :n="2" />
15+
<ProgressBar :value="progress" color="blue" :width="50" />
16+
<Newline :n="2" />
17+
</Text>
18+
</template>

packages/playground/src/main.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
// import devtools from '@vue/devtools'
22
// import devtools from '@vue/devtools/node'
33
import { createApp } from 'vue-termui'
4-
import App from './Focusables.vue'
4+
// import App from './Focusables.vue'
55
// import App from './Fragments.vue'
66
// import App from './CenteredDemo.vue'
77
// import App from './App.vue'
88
// import App from './Counter.vue'
99
// import App from './Borders.vue'
10+
import App from './ProgressBarDemo.vue'
1011

1112
createApp(App, {
1213
// swapScreens: true,

packages/vite-plugin-vue-termui/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ export const VueTuiComponents = new Map<string, ModuleExports>([
174174

175175
['transform', 'TuiTextTransform'],
176176
['text-transform', 'TuiTextTransform'],
177+
178+
['progressbar', 'TuiProgressBar'],
177179
])
178180

179181
// copied from auto import plugin source code

0 commit comments

Comments
 (0)