Vue
The same viewer, exposed as a component and a composable for Vue 3.
The component
AperturaViewer takes the file as one prop and everything else as an options object, so viewer options stay a single value that can be built once and passed around.
Pane.vue
<script setup lang="ts">
import { AperturaViewer } from '@apertura/vue';
import { ref } from 'vue';
const file = ref<File>();
const options = { fit: 'width' } as const;
</script>
<template>
<input
type="file"
accept=".docx,.xlsx,.pptx"
@change="file = ($event.target as HTMLInputElement).files?.[0]"
/>
<AperturaViewer :file="file" :options="options" style="height: 80vh" />
</template>The composable
useApertura returns containerRef, a reactive state, the open and close calls and the underlying viewer. It mirrors the React hook exactly — both are adapters over one framework-independent class.
Reader.vue
<script setup lang="ts">
import { useApertura } from '@apertura/vue';
import { onMounted } from 'vue';
const { containerRef, state, open, viewer } = useApertura({ fit: 'width' });
onMounted(() => open('/report.docx'));
</script>
<template>
<button @click="viewer?.view?.goToPage(4)">Page 5</button>
<div ref="containerRef" style="height: 80vh" />
<progress v-if="state.status === 'loading'" :value="state.progress" />
</template>Nuxt
The renderer measures real line boxes, so it needs a layout engine and has nothing to do during server rendering. A
.client.vue suffix or a <ClientOnly> wrapper is enough.