[READ-ONLY] Mirror of https://github.com/graphieros/vue-data-ui. An open source user-empowering data visualization Vue 3 components library for eloquent data storytelling vue-data-ui.graphieros.com/
charts components-library dashboard data-storytelling data-visualization donut gauge heatmap quadrant radar rating-stars scatter screenshot skeleton-loader sparkline table vue-data-ui vue3 vuejs vuejs3
3

Configure Feed

Select the types of activity you want to include in your feed.

feat(VueUiTimer): add slot props

graphieros (Apr 25, 2026, 5:10 PM +0200) 2161354f e1a28fe8

+294 -10
+2 -2
manual-testing/backend/database.json
··· 1233 1233 "VueUiTable": true, 1234 1234 "VueUiTableSparkline": true, 1235 1235 "VueUiThermometer": true, 1236 - "VueUiTimer": false, 1236 + "VueUiTimer": true, 1237 1237 "VueUiTiremarks": false, 1238 1238 "VueUiTreemap": false, 1239 1239 "VueUiWaffle": false, ··· 1247 1247 "customCheckList": {}, 1248 1248 "id": "3846f04c-685f-4509-8042-87b9c0b7ec33", 1249 1249 "createdAt": 1775989842046, 1250 - "updatedAt": 1777119233210 1250 + "updatedAt": 1777129688737 1251 1251 }, 1252 1252 { 1253 1253 "title": "Expose more methods",
+5 -1
src/components/vue-ui-timer.vue
··· 430 430 width="0.1" 431 431 style="overflow: visible" 432 432 > 433 - <slot name="time" v-bind="{ ...currentTime }" /> 433 + <slot name="time" v-bind="{ ...currentTime, ...svg }" /> 434 434 </foreignObject> 435 + 436 + <g v-else-if="$slots.timeSvg"> 437 + <slot name="timeSvg" v-bind="{ ...currentTime, ...svg }" /> 438 + </g> 435 439 436 440 <!-- TIME LABEL - DEFAULT --> 437 441 <text
+5
ts-playground/src/App.vue
··· 147 147 const TsVueUiThermometer = defineAsyncComponent( 148 148 () => import('./components/charts/ts-vue-ui-thermometer.vue'), 149 149 ); 150 + const TsVueUiTimer = defineAsyncComponent( 151 + () => import('./components/charts/ts-vue-ui-timer.vue'), 152 + ); 150 153 151 154 const components = shallowRef([ 152 155 { name: 'VueUiXy' }, ··· 198 201 { name: 'VueUiStripPlot' }, 199 202 { name: 'VueUiTableSparkline' }, 200 203 { name: 'VueUiThermometer' }, 204 + { name: 'VueUiTimer' }, 201 205 ]); 202 206 203 207 const selectedComponent = shallowRef(components.value[0]); ··· 292 296 <TsVueUiThermometer 293 297 v-if="selectedComponent?.name === 'VueUiThermometer'" 294 298 /> 299 + <TsVueUiTimer v-if="selectedComponent?.name === 'VueUiTimer'" /> 295 300 </div> 296 301 </template> 297 302
+188
ts-playground/src/components/charts/ts-vue-ui-timer.vue
··· 1 + <script setup lang="ts"> 2 + /** 3 + * This playground showcases all the slots and their implementations for <VueUiTimer> 4 + */ 5 + import { computed } from 'vue'; 6 + import { VueUiTimer, type VueUiTimerConfig } from 'vue-data-ui/vue-ui-timer'; 7 + import 'vue-data-ui/style.css'; 8 + 9 + const config = computed<VueUiTimerConfig>(() => { 10 + return { 11 + type: 'stopwatch', 12 + responsive: false, 13 + responsiveProportionalSizing: true, 14 + useCursorPointer: false, 15 + style: { 16 + fontFamily: 'inherit', 17 + backgroundColor: '#FFFFFF', 18 + height: 300, 19 + width: 300, 20 + title: { 21 + text: '', 22 + color: '#2D353C', 23 + fontSize: 20, 24 + bold: true, 25 + textAlign: 'center', 26 + paddingLeft: 0, 27 + paddingRight: 0, 28 + subtitle: { 29 + color: '#A1A1A1', 30 + text: '', 31 + fontSize: 16, 32 + bold: false, 33 + }, 34 + }, 35 + }, 36 + stopwatch: { 37 + showHours: false, 38 + showHundredth: true, 39 + cycleSeconds: 5, 40 + track: { 41 + radiusRatio: 1, 42 + stroke: '#e1e5e8', 43 + fill: '#FFFFFF', 44 + strokeWidth: 2, 45 + }, 46 + tracker: { 47 + radiusRatio: 1, 48 + stroke: '#FFFFFF', 49 + strokeWidth: 1, 50 + fill: '#2D353C', 51 + gradient: { 52 + show: true, 53 + color: '#FFFFFF', 54 + }, 55 + aura: { 56 + show: true, 57 + radiusRatio: 1, 58 + fill: '#2D353C', 59 + stroke: '#FFFFFF', 60 + strokeWidth: 0, 61 + }, 62 + }, 63 + cycleTrack: { 64 + show: true, 65 + stroke: '#2D353C', 66 + strokeWidth: 3, 67 + }, 68 + label: { 69 + fontSize: 24, 70 + color: '#2D353C', 71 + bold: false, 72 + }, 73 + legend: { 74 + backgroundColor: '#FFFFFF', 75 + buttons: { 76 + start: true, 77 + pause: true, 78 + reset: true, 79 + restart: true, 80 + lap: true, 81 + iconColor: '#2D353C', 82 + }, 83 + buttonTitles: { 84 + start: 'Start', 85 + pause: 'Pause', 86 + resume: 'Resume', 87 + reset: 'Reset', 88 + restart: 'Restart', 89 + lap: 'Lap', 90 + }, 91 + }, 92 + }, 93 + } 94 + }); 95 + 96 + function log(n: unknown) { 97 + console.log(n); 98 + } 99 + </script> 100 + 101 + <template> 102 + <div style="max-width: 500px"> 103 + <VueUiTimer :config> 104 + <template #chart-background> 105 + <div 106 + style=" 107 + width: 100%; 108 + height: 100%; 109 + background: linear-gradient( 110 + to bottom, 111 + #cccccc00, 112 + #cccccc90 113 + ); 114 + " 115 + > 116 + <code style="color: chocolate"> #chart-background </code> 117 + </div> 118 + </template> 119 + 120 + <!-- <template #time="{ elapsed, timestamp, formatted }"> 121 + <div 122 + style=" 123 + display: flex; 124 + flex-direction: column; 125 + font-size: 0.7rem; 126 + line-height: 0.7rem; 127 + width: 100%; 128 + border: 1px solid red; 129 + " 130 + > 131 + <code style="color: chocolate">#time</code> 132 + <span>elapsed: {{ elapsed }}</span> 133 + <span>timestamp: {{ timestamp }}</span> 134 + <span>formatted: {{ formatted }}</span> 135 + </div> 136 + </template> --> 137 + 138 + <template #timeSvg="{ formatted, width, height }"> 139 + <text 140 + :x="width / 2" 141 + :y="height / 2" 142 + fill="chocolate" 143 + font-size="12" 144 + text-anchor="middle" 145 + dominant-baseline="middle" 146 + > 147 + #time: {{ formatted }} 148 + </text> 149 + </template> 150 + 151 + <template 152 + #controls="{ 153 + start, 154 + pause, 155 + lap, 156 + restart, 157 + reset, 158 + laps, 159 + isRunning, 160 + isPaused, 161 + ...currentTime 162 + }" 163 + > 164 + <code style="color: chocolate">#controls</code> 165 + <button @click="start">START</button> 166 + <button @click="pause">PAUSE</button> 167 + <button @click="lap">LAP</button> 168 + <button @click="restart">RESTART</button> 169 + <button @click="reset">RESET</button> 170 + <div>isRunning: {{ isRunning }}</div> 171 + <div>isPaused: {{ isPaused }}</div> 172 + <div>laps: {{ laps }}</div> 173 + <div>currentTime: {{ currentTime }}</div> 174 + </template> 175 + 176 + <template 177 + #laps="{ lap, laps, isRunning, isPaused, ...currentTime }" 178 + > 179 + <code style="color: chocolate">#laps</code> 180 + <button @click="lap">LAP</button> 181 + <div>isRunning: {{ isRunning }}</div> 182 + <div>isPaused: {{ isPaused }}</div> 183 + <div>laps: {{ laps }}</div> 184 + <div>currentTime: {{ currentTime }}</div> 185 + </template> 186 + </VueUiTimer> 187 + </div> 188 + </template>
+63 -2
types/vue-data-ui.d.ts
··· 11087 11087 }; 11088 11088 }; 11089 11089 11090 - export const VueUiTimer: DefineComponent<{ 11090 + export type VueUiTimerProps = { 11091 11091 config?: VueUiTimerConfig; 11092 - }>; 11092 + }; 11093 + 11094 + export type VueUiTimerExpose = { 11095 + start(): void; 11096 + pause(): void; 11097 + reset(): void; 11098 + restart(): void; 11099 + lap(): void; 11100 + }; 11101 + 11102 + export type VueUiTimerTimeSlotProps = { 11103 + elapsed?: number; 11104 + timestamp?: number; 11105 + formatted?: string; 11106 + height: number; 11107 + label: number; 11108 + tracker: { core: number; aura: number }; 11109 + width: number; 11110 + }; 11111 + 11112 + export type VueUiTimerControlsSlotProps = { 11113 + isPaused: boolean; 11114 + isRunning: boolean; 11115 + start: () => void; 11116 + pause: () => void; 11117 + reset: () => void; 11118 + restart: () => void; 11119 + lap: () => void; 11120 + laps: Array<{ 11121 + timestamp: number; 11122 + elapsed: number; 11123 + formatted: string; 11124 + }>; 11125 + elapsed?: number; 11126 + timestamp?: number; 11127 + formatted?: string; 11128 + }; 11129 + 11130 + export type VueUiTimerLapsSlotProps = Pick< 11131 + VueUiTimerControlsSlotProps, 11132 + | 'laps' 11133 + | 'lap' 11134 + | 'isRunning' 11135 + | 'isPaused' 11136 + | 'elapsed' 11137 + | 'timestamp' 11138 + | 'formatted' 11139 + >; 11140 + 11141 + const VueUiTimerBase: DefineComponent<VueUiTimerProps>; 11142 + 11143 + export const VueUiTimer: typeof VueUiTimerBase & { 11144 + new (): VueUiTimerExpose & { 11145 + $slots: { 11146 + ['chart-background']?: () => VNodeChild; 11147 + time?: (props: VueUiTimerTimeSlotProps) => VNodeChild; 11148 + timeSvg?: (props: VueUiTimerTimeSlotProps) => VNodeChild; 11149 + controls?: (props: VueUiTimerControlsSlotProps) => VNodeChild; 11150 + laps?: (props: VueUiTimerLapsSlotProps) => VNodeChild; 11151 + }; 11152 + }; 11153 + }; 11093 11154 11094 11155 export type VueUiCarouselTableDataset = { 11095 11156 head: string[];
+31 -5
types/vue-ui-timer.d.ts
··· 1 - import type { DefineComponent } from 'vue'; 1 + import type { DefineComponent, VNodeChild } from 'vue'; 2 2 3 - export type { VueUiTimerConfig } from 'vue-data-ui'; 3 + import type { 4 + VueUiTimerConfig, 5 + VueUiTimerProps, 6 + VueUiTimerExpose, 7 + VueUiTimerTimeSlotProps, 8 + VueUiTimerControlsSlotProps, 9 + VueUiTimerLapsSlotProps, 10 + } from 'vue-data-ui'; 4 11 5 - declare const VueUiTimer: DefineComponent<{ 6 - config?: VueUiTimerConfig; 7 - }>; 12 + export type { 13 + VueUiTimerConfig, 14 + VueUiTimerProps, 15 + VueUiTimerExpose, 16 + VueUiTimerTimeSlotProps, 17 + VueUiTimerControlsSlotProps, 18 + VueUiTimerLapsSlotProps, 19 + }; 20 + 21 + declare const VueUiTimerBase: DefineComponent<VueUiTimerProps>; 22 + 23 + export const VueUiTimer: typeof VueUiTimerBase & { 24 + new (): VueUiTimerExpose & { 25 + $slots: { 26 + ['chart-background']?: () => VNodeChild; 27 + time?: (props: VueUiTimerTimeSlotProps) => VNodeChild; 28 + timeSvg?: (props: VueUiTimerTimeSlotProps) => VNodeChild; 29 + controls?: (props: VueUiTimerControlsSlotProps) => VNodeChild; 30 + laps?: (props: VueUiTimerLapsSlotProps) => VNodeChild; 31 + }; 32 + }; 33 + }; 8 34 9 35 export default VueUiTimer; 10 36 export { VueUiTimer };