diff --git a/src/components/shared/RollingValue.vue b/src/components/shared/RollingValue.vue new file mode 100644 index 0000000..fc14f23 --- /dev/null +++ b/src/components/shared/RollingValue.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/src/composables/useAnimationProgress.js b/src/composables/useAnimationProgress.js new file mode 100644 index 0000000..2411de1 --- /dev/null +++ b/src/composables/useAnimationProgress.js @@ -0,0 +1,37 @@ +import { onBeforeUnmount, onMounted, ref, watch } from 'vue' + +export function useAnimationProgress(deps = [], duration = 1100) { + const progress = ref(0) + let frameId = 0 + + const easeOutCubic = (value) => 1 - Math.pow(1 - value, 3) + + function start() { + cancelAnimationFrame(frameId) + + if (window.matchMedia?.('(prefers-reduced-motion: reduce)').matches) { + progress.value = 1 + return + } + + const startedAt = performance.now() + progress.value = 0 + + function tick(now) { + const elapsed = Math.min((now - startedAt) / duration, 1) + progress.value = easeOutCubic(elapsed) + if (elapsed < 1) frameId = requestAnimationFrame(tick) + } + + frameId = requestAnimationFrame(tick) + } + + onMounted(start) + onBeforeUnmount(() => cancelAnimationFrame(frameId)) + + if (deps.length) { + watch(deps, start) + } + + return progress +} diff --git a/src/views/ApprovalCenterView.vue b/src/views/ApprovalCenterView.vue new file mode 100644 index 0000000..e487387 --- /dev/null +++ b/src/views/ApprovalCenterView.vue @@ -0,0 +1,618 @@ + + + + +