@bitrix24/b24ui-nuxt 0.1.1
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/.nuxt/b24ui/advice.ts +52 -0
- package/.nuxt/b24ui/alert.ts +118 -0
- package/.nuxt/b24ui/avatar-group.ts +52 -0
- package/.nuxt/b24ui/avatar.ts +63 -0
- package/.nuxt/b24ui/badge.ts +256 -0
- package/.nuxt/b24ui/button-group.ts +27 -0
- package/.nuxt/b24ui/button.ts +342 -0
- package/.nuxt/b24ui/checkbox.ts +128 -0
- package/.nuxt/b24ui/chip.ts +205 -0
- package/.nuxt/b24ui/container.ts +3 -0
- package/.nuxt/b24ui/content/description-list.ts +62 -0
- package/.nuxt/b24ui/countdown.ts +94 -0
- package/.nuxt/b24ui/form-field.ts +57 -0
- package/.nuxt/b24ui/form.ts +3 -0
- package/.nuxt/b24ui/index.ts +28 -0
- package/.nuxt/b24ui/input.ts +472 -0
- package/.nuxt/b24ui/kbd.ts +31 -0
- package/.nuxt/b24ui/link.ts +20 -0
- package/.nuxt/b24ui/progress.ts +303 -0
- package/.nuxt/b24ui/radio-group.ts +135 -0
- package/.nuxt/b24ui/range.ts +172 -0
- package/.nuxt/b24ui/select.ts +550 -0
- package/.nuxt/b24ui/separator.ts +176 -0
- package/.nuxt/b24ui/skeleton.ts +3 -0
- package/.nuxt/b24ui/switch.ts +134 -0
- package/.nuxt/b24ui/tabs.ts +341 -0
- package/.nuxt/b24ui/textarea.ts +332 -0
- package/.nuxt/b24ui/toast.ts +89 -0
- package/.nuxt/b24ui/toaster.ts +91 -0
- package/.nuxt/b24ui/tooltip.ts +16 -0
- package/LICENSE +21 -0
- package/README.md +101 -0
- package/cli/commands/make/component.mjs +95 -0
- package/cli/commands/make/index.mjs +14 -0
- package/cli/commands/make/locale.mjs +64 -0
- package/cli/index.mjs +15 -0
- package/cli/package.json +13 -0
- package/cli/templates.mjs +240 -0
- package/cli/utils.mjs +31 -0
- package/dist/meta.cjs +23610 -0
- package/dist/meta.d.cts +23608 -0
- package/dist/meta.d.mts +23608 -0
- package/dist/meta.d.ts +23608 -0
- package/dist/meta.mjs +23608 -0
- package/dist/module.cjs +54 -0
- package/dist/module.d.cts +14 -0
- package/dist/module.d.mts +14 -0
- package/dist/module.d.ts +14 -0
- package/dist/module.json +13 -0
- package/dist/module.mjs +51 -0
- package/dist/runtime/components/Advice.vue +115 -0
- package/dist/runtime/components/Alert.vue +136 -0
- package/dist/runtime/components/App.vue +52 -0
- package/dist/runtime/components/Avatar.vue +118 -0
- package/dist/runtime/components/AvatarGroup.vue +99 -0
- package/dist/runtime/components/Badge.vue +114 -0
- package/dist/runtime/components/Button.vue +177 -0
- package/dist/runtime/components/ButtonGroup.vue +58 -0
- package/dist/runtime/components/Checkbox.vue +110 -0
- package/dist/runtime/components/Chip.vue +81 -0
- package/dist/runtime/components/Container.vue +36 -0
- package/dist/runtime/components/Countdown.vue +498 -0
- package/dist/runtime/components/Form.vue +271 -0
- package/dist/runtime/components/FormField.vue +128 -0
- package/dist/runtime/components/Input.vue +224 -0
- package/dist/runtime/components/Kbd.vue +50 -0
- package/dist/runtime/components/Link.vue +219 -0
- package/dist/runtime/components/LinkBase.vue +63 -0
- package/dist/runtime/components/Progress.vue +182 -0
- package/dist/runtime/components/RadioGroup.vue +178 -0
- package/dist/runtime/components/Range.vue +114 -0
- package/dist/runtime/components/Select.vue +328 -0
- package/dist/runtime/components/Separator.vue +82 -0
- package/dist/runtime/components/Skeleton.vue +31 -0
- package/dist/runtime/components/Switch.vue +133 -0
- package/dist/runtime/components/Tabs.vue +127 -0
- package/dist/runtime/components/Textarea.vue +216 -0
- package/dist/runtime/components/Toast.vue +168 -0
- package/dist/runtime/components/Toaster.vue +143 -0
- package/dist/runtime/components/Tooltip.vue +94 -0
- package/dist/runtime/components/content/DescriptionList.vue +220 -0
- package/dist/runtime/composables/defineLocale.d.ts +9 -0
- package/dist/runtime/composables/defineLocale.js +4 -0
- package/dist/runtime/composables/defineShortcuts.d.ts +15 -0
- package/dist/runtime/composables/defineShortcuts.js +135 -0
- package/dist/runtime/composables/useAvatarGroup.d.ts +10 -0
- package/dist/runtime/composables/useAvatarGroup.js +10 -0
- package/dist/runtime/composables/useButtonGroup.d.ts +17 -0
- package/dist/runtime/composables/useButtonGroup.js +10 -0
- package/dist/runtime/composables/useComponentIcons.d.ts +20 -0
- package/dist/runtime/composables/useComponentIcons.js +25 -0
- package/dist/runtime/composables/useFormField.d.ts +42 -0
- package/dist/runtime/composables/useFormField.js +65 -0
- package/dist/runtime/composables/useKbd.d.ts +35 -0
- package/dist/runtime/composables/useKbd.js +52 -0
- package/dist/runtime/composables/useLocale.d.ts +4 -0
- package/dist/runtime/composables/useLocale.js +10 -0
- package/dist/runtime/composables/useToast.d.ts +12 -0
- package/dist/runtime/composables/useToast.js +62 -0
- package/dist/runtime/dictionary/icons.d.ts +20 -0
- package/dist/runtime/dictionary/icons.js +35 -0
- package/dist/runtime/index.css +1 -0
- package/dist/runtime/keyframes.css +1 -0
- package/dist/runtime/locale/en.d.ts +2 -0
- package/dist/runtime/locale/en.js +48 -0
- package/dist/runtime/locale/es.d.ts +2 -0
- package/dist/runtime/locale/es.js +48 -0
- package/dist/runtime/locale/index.d.ts +3 -0
- package/dist/runtime/locale/index.js +3 -0
- package/dist/runtime/locale/ru.d.ts +2 -0
- package/dist/runtime/locale/ru.js +48 -0
- package/dist/runtime/plugins/colors.d.ts +2 -0
- package/dist/runtime/plugins/colors.js +40 -0
- package/dist/runtime/types/app.config.d.ts +6 -0
- package/dist/runtime/types/form.d.ts +84 -0
- package/dist/runtime/types/form.js +12 -0
- package/dist/runtime/types/icons.d.ts +3 -0
- package/dist/runtime/types/icons.js +0 -0
- package/dist/runtime/types/index.d.ts +33 -0
- package/dist/runtime/types/index.js +33 -0
- package/dist/runtime/types/locale.d.ts +50 -0
- package/dist/runtime/types/locale.js +0 -0
- package/dist/runtime/types/utils.d.ts +22 -0
- package/dist/runtime/types/utils.js +0 -0
- package/dist/runtime/utils/form.d.ts +17 -0
- package/dist/runtime/utils/form.js +153 -0
- package/dist/runtime/utils/fuse.d.ts +4 -0
- package/dist/runtime/utils/fuse.js +63 -0
- package/dist/runtime/utils/index.d.ts +6 -0
- package/dist/runtime/utils/index.js +63 -0
- package/dist/runtime/utils/link.d.ts +29 -0
- package/dist/runtime/utils/link.js +4 -0
- package/dist/runtime/utils/locale.d.ts +15 -0
- package/dist/runtime/utils/locale.js +25 -0
- package/dist/runtime/utils/tv.d.ts +1 -0
- package/dist/runtime/utils/tv.js +4 -0
- package/dist/runtime/vue/components/Link.vue +203 -0
- package/dist/runtime/vue/plugins/color-mode.d.ts +4 -0
- package/dist/runtime/vue/plugins/color-mode.js +6 -0
- package/dist/runtime/vue/plugins/head.d.ts +4 -0
- package/dist/runtime/vue/plugins/head.js +6 -0
- package/dist/runtime/vue/stubs.d.ts +15 -0
- package/dist/runtime/vue/stubs.js +27 -0
- package/dist/shared/b24ui-nuxt.CNGvMe2S.mjs +4074 -0
- package/dist/shared/b24ui-nuxt.D22QQtm8.cjs +4079 -0
- package/dist/types.d.mts +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/unplugin.cjs +213 -0
- package/dist/unplugin.d.cts +22 -0
- package/dist/unplugin.d.mts +22 -0
- package/dist/unplugin.d.ts +22 -0
- package/dist/unplugin.mjs +202 -0
- package/dist/vite.cjs +21 -0
- package/dist/vite.d.cts +12 -0
- package/dist/vite.d.mts +12 -0
- package/dist/vite.d.ts +12 -0
- package/dist/vite.mjs +19 -0
- package/package.json +166 -0
- package/vue-plugin.d.ts +5 -0
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { VariantProps } from 'tailwind-variants'
|
|
3
|
+
import type { AppConfig } from '@nuxt/schema'
|
|
4
|
+
import _appConfig from '#build/app.config'
|
|
5
|
+
import theme from '#build/b24ui/countdown'
|
|
6
|
+
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
|
|
7
|
+
import { tv } from '../utils/tv'
|
|
8
|
+
import type { AvatarProps } from '../types'
|
|
9
|
+
|
|
10
|
+
const appConfigCountdown = _appConfig as AppConfig & { b24ui: { countdown: Partial<typeof theme> } }
|
|
11
|
+
|
|
12
|
+
const countdown = tv({ extend: tv(theme), ...(appConfigCountdown.b24ui?.countdown || {}) })
|
|
13
|
+
|
|
14
|
+
type CountdownVariants = VariantProps<typeof countdown>
|
|
15
|
+
|
|
16
|
+
export interface CountdownData {
|
|
17
|
+
days: number
|
|
18
|
+
hours: number
|
|
19
|
+
minutes: number
|
|
20
|
+
seconds: number
|
|
21
|
+
milliseconds: number
|
|
22
|
+
totalDays: number
|
|
23
|
+
totalHours: number
|
|
24
|
+
totalMinutes: number
|
|
25
|
+
totalSeconds: number
|
|
26
|
+
totalMilliseconds: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface CountdownProps extends Omit<UseComponentIconsProps, 'loading' | 'trailing' | 'trailingIcon'> {
|
|
30
|
+
/**
|
|
31
|
+
* The element or component this component should render as.
|
|
32
|
+
* @defaultValue 'span'
|
|
33
|
+
*/
|
|
34
|
+
as?: any
|
|
35
|
+
size?: CountdownVariants['size']
|
|
36
|
+
/** Emits the countdown events. */
|
|
37
|
+
emitEvents?: boolean
|
|
38
|
+
/** Number of seconds to countdown. */
|
|
39
|
+
seconds?: number | string
|
|
40
|
+
/** Should seconds be divided into minutes? */
|
|
41
|
+
showMinutes?: boolean
|
|
42
|
+
/** Shows a `Circle` around the countdown */
|
|
43
|
+
useCircle?: boolean
|
|
44
|
+
/** The interval time (in milliseconds) of the countdown progress. */
|
|
45
|
+
interval?: number
|
|
46
|
+
/** Starts the countdown automatically when initialized. */
|
|
47
|
+
needStartImmediately?: boolean
|
|
48
|
+
/** Generate the current time of a specific time zone. */
|
|
49
|
+
now?: () => number
|
|
50
|
+
class?: any
|
|
51
|
+
b24ui?: Partial<typeof countdown.slots>
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface CountdownEmits {
|
|
55
|
+
(e: 'start' | 'end' | 'abort'): void
|
|
56
|
+
(e: 'progress', payload: CountdownData): void
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface CountdownSlots {
|
|
60
|
+
leading(props?: {}): any
|
|
61
|
+
default(props: CountdownData & { formatTime: string }): any
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<script setup lang="ts">
|
|
66
|
+
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'
|
|
67
|
+
import { useComponentIcons } from '../composables/useComponentIcons'
|
|
68
|
+
import { Primitive } from 'reka-ui'
|
|
69
|
+
import B24Avatar from './Avatar.vue'
|
|
70
|
+
|
|
71
|
+
const MILLISECONDS_SECOND = 1000
|
|
72
|
+
const MILLISECONDS_MINUTE = 60 * MILLISECONDS_SECOND
|
|
73
|
+
const MILLISECONDS_HOUR = 60 * MILLISECONDS_MINUTE
|
|
74
|
+
const MILLISECONDS_DAY = 24 * MILLISECONDS_HOUR
|
|
75
|
+
|
|
76
|
+
defineOptions({ inheritAttrs: false })
|
|
77
|
+
|
|
78
|
+
// region data ////
|
|
79
|
+
|
|
80
|
+
const props = withDefaults(defineProps<CountdownProps>(), {
|
|
81
|
+
as: 'span',
|
|
82
|
+
needStartImmediately: true,
|
|
83
|
+
emitEvents: true,
|
|
84
|
+
interval: 1000,
|
|
85
|
+
now: () => Date.now(),
|
|
86
|
+
seconds: 0,
|
|
87
|
+
showMinutes: true,
|
|
88
|
+
useCircle: false
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
const emits = defineEmits<CountdownEmits>()
|
|
92
|
+
defineSlots<CountdownSlots>()
|
|
93
|
+
|
|
94
|
+
const { isLeading, leadingIconName } = useComponentIcons(
|
|
95
|
+
computed(() => ({ ...props, loading: false }))
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
const b24ui = computed(() => countdown({
|
|
99
|
+
size: props.size,
|
|
100
|
+
leading: Boolean(isLeading.value),
|
|
101
|
+
useCircle: Boolean(props.useCircle)
|
|
102
|
+
}))
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* It is counting down.
|
|
106
|
+
*/
|
|
107
|
+
const counting = ref<boolean>(false)
|
|
108
|
+
/**
|
|
109
|
+
* The absolute end time.
|
|
110
|
+
*/
|
|
111
|
+
const endTime = ref<number>(0)
|
|
112
|
+
/**
|
|
113
|
+
* The remaining milliseconds.
|
|
114
|
+
*/
|
|
115
|
+
const totalMilliseconds = ref<number>(0)
|
|
116
|
+
/**
|
|
117
|
+
* The request ID of the requestAnimationFrame.
|
|
118
|
+
*/
|
|
119
|
+
const requestId = ref<number>(0)
|
|
120
|
+
// endregion ////
|
|
121
|
+
|
|
122
|
+
// region events ////
|
|
123
|
+
onMounted(() => {
|
|
124
|
+
document.addEventListener('visibilitychange', handleVisibilityChange.bind(this))
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
onBeforeUnmount(() => {
|
|
128
|
+
document.removeEventListener('visibilitychange', handleVisibilityChange.bind(this))
|
|
129
|
+
pause()
|
|
130
|
+
})
|
|
131
|
+
// endregion ////
|
|
132
|
+
|
|
133
|
+
// region watch ////
|
|
134
|
+
/**
|
|
135
|
+
* Update the countdown when props changed.
|
|
136
|
+
*/
|
|
137
|
+
watch(
|
|
138
|
+
() => props,
|
|
139
|
+
() => {
|
|
140
|
+
totalMilliseconds.value = Number(props.seconds) * 1000
|
|
141
|
+
endTime.value = props.now() + Number(props.seconds) * 1000
|
|
142
|
+
|
|
143
|
+
if (props.needStartImmediately) {
|
|
144
|
+
start()
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
deep: true,
|
|
149
|
+
immediate: true
|
|
150
|
+
}
|
|
151
|
+
)
|
|
152
|
+
// endregion ////
|
|
153
|
+
|
|
154
|
+
// region computed ////
|
|
155
|
+
/**
|
|
156
|
+
* Remaining days.
|
|
157
|
+
*/
|
|
158
|
+
const days = computed((): number => {
|
|
159
|
+
return Math.floor(totalMilliseconds.value / MILLISECONDS_DAY)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Remaining hours.
|
|
164
|
+
*/
|
|
165
|
+
const hours = computed((): number => {
|
|
166
|
+
return Math.floor((totalMilliseconds.value % MILLISECONDS_DAY) / MILLISECONDS_HOUR)
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Remaining minutes.
|
|
171
|
+
*/
|
|
172
|
+
const minutes = computed((): number => {
|
|
173
|
+
return Math.floor((totalMilliseconds.value % MILLISECONDS_HOUR) / MILLISECONDS_MINUTE)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Remaining seconds.
|
|
178
|
+
*/
|
|
179
|
+
const secondsValue = computed((): number => {
|
|
180
|
+
return Math.floor((totalMilliseconds.value % MILLISECONDS_MINUTE) / MILLISECONDS_SECOND)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Remaining milliseconds.
|
|
185
|
+
*/
|
|
186
|
+
const milliseconds = computed((): number => {
|
|
187
|
+
return Math.floor(totalMilliseconds.value % MILLISECONDS_SECOND)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Total remaining days.
|
|
192
|
+
*/
|
|
193
|
+
const totalDays = computed((): number => {
|
|
194
|
+
return days.value
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Total remaining hours.
|
|
199
|
+
*/
|
|
200
|
+
const totalHours = computed((): number => {
|
|
201
|
+
return Math.floor(totalMilliseconds.value / MILLISECONDS_HOUR)
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Total remaining minutes.
|
|
206
|
+
*/
|
|
207
|
+
const totalMinutes = computed((): number => {
|
|
208
|
+
return Math.floor(totalMilliseconds.value / MILLISECONDS_MINUTE)
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Total remaining seconds.
|
|
213
|
+
*/
|
|
214
|
+
const totalSeconds = computed((): number => {
|
|
215
|
+
return Math.floor(totalMilliseconds.value / MILLISECONDS_SECOND)
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
const formatTime = computed((): string => {
|
|
219
|
+
if (props.showMinutes && !props.useCircle) {
|
|
220
|
+
return `${totalMinutes.value < 10 ? '0' : ''}${totalMinutes.value}:${secondsValue.value < 10 ? '0' : ''}${secondsValue.value}`
|
|
221
|
+
} else if (props.useCircle) {
|
|
222
|
+
return `:${totalSeconds.value}`
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return String(totalSeconds.value)
|
|
226
|
+
})
|
|
227
|
+
// endregion ////
|
|
228
|
+
|
|
229
|
+
// region actions ////
|
|
230
|
+
/**
|
|
231
|
+
* Starts to countdown.
|
|
232
|
+
*/
|
|
233
|
+
function start(): void {
|
|
234
|
+
if (counting.value) {
|
|
235
|
+
return
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
counting.value = true
|
|
239
|
+
|
|
240
|
+
if (!props.needStartImmediately) {
|
|
241
|
+
totalMilliseconds.value = Number(props.seconds) * 1000
|
|
242
|
+
endTime.value = props.now() + Number(props.seconds) * 1000
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (props.emitEvents) {
|
|
246
|
+
emits('start')
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (document?.visibilityState === 'visible') {
|
|
250
|
+
continueProcess()
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Continues the countdown.
|
|
256
|
+
*/
|
|
257
|
+
function continueProcess(): void {
|
|
258
|
+
if (!counting.value) {
|
|
259
|
+
return
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const delay = Math.min(totalMilliseconds.value, props.interval)
|
|
263
|
+
|
|
264
|
+
if (delay > 0) {
|
|
265
|
+
let init: number
|
|
266
|
+
let prev: number
|
|
267
|
+
const step = (now: number) => {
|
|
268
|
+
if (!init) {
|
|
269
|
+
init = now
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (!prev) {
|
|
273
|
+
prev = now
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const range = now - init
|
|
277
|
+
|
|
278
|
+
if (
|
|
279
|
+
range >= delay
|
|
280
|
+
// Avoid losing time about one second per minute (now - prev ≈ 16ms)
|
|
281
|
+
|| range + ((now - prev) / 2) >= delay
|
|
282
|
+
) {
|
|
283
|
+
progress()
|
|
284
|
+
} else {
|
|
285
|
+
requestId.value = requestAnimationFrame(step)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
prev = now
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
requestId.value = requestAnimationFrame(step)
|
|
292
|
+
} else {
|
|
293
|
+
stop()
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Pauses the countdown.
|
|
299
|
+
*/
|
|
300
|
+
function pause(): void {
|
|
301
|
+
cancelAnimationFrame(requestId.value)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Progresses to countdown.
|
|
306
|
+
*/
|
|
307
|
+
function progress(): void {
|
|
308
|
+
if (!counting.value) {
|
|
309
|
+
return
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
update()
|
|
313
|
+
|
|
314
|
+
if (props.emitEvents && totalMilliseconds.value > 0) {
|
|
315
|
+
/**
|
|
316
|
+
* Countdown progress event.
|
|
317
|
+
*/
|
|
318
|
+
emits('progress', {
|
|
319
|
+
days: days.value,
|
|
320
|
+
hours: hours.value,
|
|
321
|
+
minutes: minutes.value,
|
|
322
|
+
seconds: secondsValue.value,
|
|
323
|
+
milliseconds: milliseconds.value,
|
|
324
|
+
totalDays: totalDays.value,
|
|
325
|
+
totalHours: totalHours.value,
|
|
326
|
+
totalMinutes: totalMinutes.value,
|
|
327
|
+
totalSeconds: totalSeconds.value,
|
|
328
|
+
totalMilliseconds: totalMilliseconds.value
|
|
329
|
+
})
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
continueProcess()
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Aborts the countdown.
|
|
337
|
+
*/
|
|
338
|
+
function abort(): void {
|
|
339
|
+
if (!counting.value) {
|
|
340
|
+
return
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
pause()
|
|
344
|
+
counting.value = false
|
|
345
|
+
|
|
346
|
+
if (props.emitEvents) {
|
|
347
|
+
/**
|
|
348
|
+
* Countdown abort event.
|
|
349
|
+
*/
|
|
350
|
+
emits('abort')
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Stop the countdown.
|
|
356
|
+
*/
|
|
357
|
+
function stop(): void {
|
|
358
|
+
if (!counting.value) {
|
|
359
|
+
return
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
pause()
|
|
363
|
+
totalMilliseconds.value = 0
|
|
364
|
+
counting.value = false
|
|
365
|
+
|
|
366
|
+
if (props.emitEvents) {
|
|
367
|
+
/**
|
|
368
|
+
* Countdown end event.
|
|
369
|
+
*/
|
|
370
|
+
emits('end')
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Updates the count.
|
|
376
|
+
*/
|
|
377
|
+
function update(): void {
|
|
378
|
+
if (counting.value) {
|
|
379
|
+
totalMilliseconds.value = Math.max(0, endTime.value - props.now())
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Restarts the count.
|
|
385
|
+
*/
|
|
386
|
+
function restart(): void {
|
|
387
|
+
pause()
|
|
388
|
+
totalMilliseconds.value = Number(props.seconds) * 1000
|
|
389
|
+
endTime.value = props.now() + Number(props.seconds) * 1000
|
|
390
|
+
counting.value = false
|
|
391
|
+
start()
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Visibility change event handler.
|
|
396
|
+
*/
|
|
397
|
+
function handleVisibilityChange(): void {
|
|
398
|
+
switch (document?.visibilityState) {
|
|
399
|
+
case 'visible':
|
|
400
|
+
update()
|
|
401
|
+
continueProcess()
|
|
402
|
+
break
|
|
403
|
+
|
|
404
|
+
case 'hidden':
|
|
405
|
+
pause()
|
|
406
|
+
break
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
// endregion ////
|
|
410
|
+
|
|
411
|
+
// region Round ////
|
|
412
|
+
const fullDashArray = computed((): string => {
|
|
413
|
+
const fullDashArray = 283
|
|
414
|
+
|
|
415
|
+
const calculateTimeFraction = (): number => {
|
|
416
|
+
if (Number(props.seconds) < 0) {
|
|
417
|
+
return 1
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const rawTimeFraction = totalSeconds.value / Number(props.seconds)
|
|
421
|
+
return rawTimeFraction - (1 / Number(props.seconds)) * (1 - rawTimeFraction)
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return [
|
|
425
|
+
(calculateTimeFraction() * fullDashArray).toFixed(0),
|
|
426
|
+
fullDashArray
|
|
427
|
+
].join(' ')
|
|
428
|
+
})
|
|
429
|
+
// endregion ////
|
|
430
|
+
|
|
431
|
+
defineExpose({
|
|
432
|
+
start,
|
|
433
|
+
abort,
|
|
434
|
+
stop,
|
|
435
|
+
restart
|
|
436
|
+
})
|
|
437
|
+
</script>
|
|
438
|
+
|
|
439
|
+
<template>
|
|
440
|
+
<Primitive
|
|
441
|
+
:as="as"
|
|
442
|
+
v-bind="$attrs"
|
|
443
|
+
:class="b24ui.base({ class: [props.class, props.b24ui?.base] })"
|
|
444
|
+
>
|
|
445
|
+
<svg
|
|
446
|
+
v-if="props.useCircle"
|
|
447
|
+
:class="b24ui.circleBase({ class: [props.b24ui?.circleBase] })"
|
|
448
|
+
viewBox="0 0 100 100"
|
|
449
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
450
|
+
>
|
|
451
|
+
<g
|
|
452
|
+
:class="b24ui.circleGroup({ class: [props.b24ui?.circleGroup] })"
|
|
453
|
+
>
|
|
454
|
+
<circle
|
|
455
|
+
:class="b24ui.circleElement({ class: [props.b24ui?.circleElement] })"
|
|
456
|
+
cx="50"
|
|
457
|
+
cy="50"
|
|
458
|
+
r="45"
|
|
459
|
+
/>
|
|
460
|
+
<path
|
|
461
|
+
:class="b24ui.circlePath({ class: [props.b24ui?.circlePath] })"
|
|
462
|
+
:stroke-dasharray="fullDashArray"
|
|
463
|
+
d="M 50, 50 m -45, 0 a 45,45 0 1,0 90,0 a 45,45 0 1,0 -90,0"
|
|
464
|
+
/>
|
|
465
|
+
</g>
|
|
466
|
+
</svg>
|
|
467
|
+
<slot name="leading">
|
|
468
|
+
<Component
|
|
469
|
+
:is="leadingIconName"
|
|
470
|
+
v-if="isLeading && (typeof leadingIconName !== 'undefined')"
|
|
471
|
+
:class="b24ui.leadingIcon({ class: props.b24ui?.leadingIcon })"
|
|
472
|
+
/>
|
|
473
|
+
<B24Avatar
|
|
474
|
+
v-else-if="!!avatar"
|
|
475
|
+
:size="((props.b24ui?.leadingAvatarSize || b24ui.leadingAvatarSize()) as AvatarProps['size'])"
|
|
476
|
+
v-bind="avatar"
|
|
477
|
+
:class="b24ui.leadingAvatar({ class: props.b24ui?.leadingAvatar })"
|
|
478
|
+
/>
|
|
479
|
+
</slot>
|
|
480
|
+
<slot
|
|
481
|
+
:days="days"
|
|
482
|
+
:hours="hours"
|
|
483
|
+
:minutes="minutes"
|
|
484
|
+
:seconds="secondsValue"
|
|
485
|
+
:milliseconds="milliseconds"
|
|
486
|
+
:total-days="totalDays"
|
|
487
|
+
:total-hours="totalHours"
|
|
488
|
+
:total-minutes="totalMinutes"
|
|
489
|
+
:total-seconds="totalSeconds"
|
|
490
|
+
:total-milliseconds="totalMilliseconds"
|
|
491
|
+
:format-time="formatTime"
|
|
492
|
+
>
|
|
493
|
+
<span :class="b24ui.label({ class: props.b24ui?.label })">
|
|
494
|
+
{{ formatTime }}
|
|
495
|
+
</span>
|
|
496
|
+
</slot>
|
|
497
|
+
</Primitive>
|
|
498
|
+
</template>
|