Skip to content

Commit 89a585e

Browse files
committed
feat(pdf-navigation): add first, last button & label props
1 parent 01d7deb commit 89a585e

File tree

7 files changed

+160
-13
lines changed

7 files changed

+160
-13
lines changed

src/components/pdf-viewer/PdfNavigation.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,18 @@ it('should changed page value if page selection was selected', async () => {
123123

124124
expect(context.page.value).toBe(3)
125125
})
126+
127+
it('should be able to change num-of-pages, first and last navigation label via props "num-of-pages-nav-label", "first-nav-label" and "last-nav-label"', () => {
128+
const screen = render({
129+
components: { PdfNavigation },
130+
template : '<PdfNavigation first-nav-label="Awal" last-nav-label="Akhir" num-of-pages-nav-label="dari" />',
131+
})
132+
133+
const firstNavLabel = screen.queryByText('Awal')
134+
const lastNavLabel = screen.queryByText('Akhir')
135+
const numOfPagesLabel = screen.queryByText(/dari/i)
136+
137+
expect(firstNavLabel).toBeInTheDocument()
138+
expect(lastNavLabel).toBeInTheDocument()
139+
expect(numOfPagesLabel).toBeInTheDocument()
140+
})

src/components/pdf-viewer/PdfNavigation.vue

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,20 @@
2929
size="xs" />
3030
<span
3131
data-testid="pdf-total"
32-
class="pdf__navigation-total">of {{ totalPage }}</span>
32+
class="pdf__navigation-total">
33+
<slot name="num-of-pages-navigation">
34+
{{ numOfPagesNavLabel }}
35+
</slot> {{ totalPage }}</span>
36+
<p-button
37+
data-testid="pdf-start"
38+
variant="ghost"
39+
size="xs"
40+
icon
41+
@click="first">
42+
<slot name="first-navigation">
43+
{{ firstNavLabel }}
44+
</slot>
45+
</p-button>
3346
<p-button
3447
data-testid="pdf-prev"
3548
variant="ghost"
@@ -46,6 +59,16 @@
4659
@click="next">
4760
<IconNext />
4861
</p-button>
62+
<p-button
63+
data-testid="pdf-end"
64+
variant="ghost"
65+
size="xs"
66+
icon
67+
@click="last">
68+
<slot name="last-navigation">
69+
{{ lastNavLabel }}
70+
</slot>
71+
</p-button>
4972
</div>
5073
</div>
5174
</template>
@@ -62,6 +85,21 @@ import pDivider from '../divider/Divider.vue'
6285
import pSelect from '../select/Select.vue'
6386
import type { SelectItem } from '../select'
6487
88+
defineProps({
89+
firstNavLabel: {
90+
type : String,
91+
default: 'First',
92+
},
93+
lastNavLabel: {
94+
type : String,
95+
default: 'Last',
96+
},
97+
numOfPagesNavLabel: {
98+
type : String,
99+
default: 'of',
100+
},
101+
})
102+
65103
const {
66104
page,
67105
scale,
@@ -70,6 +108,8 @@ const {
70108
zoomOut,
71109
next,
72110
prev,
111+
first,
112+
last,
73113
} = usePdfContext()
74114
75115
const pages = computed<SelectItem[]>(() => {
@@ -85,7 +125,7 @@ const pages = computed<SelectItem[]>(() => {
85125
<style lang="postcss">
86126
.pdf {
87127
&__navigation {
88-
@apply absolute bottom-4 inset-x-0 justify-center items-center flex w-80 mx-auto z-10;
128+
@apply absolute bottom-4 inset-x-0 justify-center items-center flex w-96 mx-auto z-10;
89129
90130
&-container {
91131
@apply flex bg-inverse text-subtlest rounded p-2 space-x-1 items-center;
@@ -122,7 +162,7 @@ const pages = computed<SelectItem[]>(() => {
122162
}
123163
124164
&-total {
125-
@apply shrink-0;
165+
@apply shrink-0 mr-3 !important;
126166
}
127167
}
128168
}

src/components/pdf-viewer/PdfViewer.spec.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ it('should expose navigation in slot', async () => {
173173
src="http://sample.pdf"
174174
password="123456"
175175
>
176-
<template #header="{ zoomIn, zoomOut, next, prev }">
176+
<template #header="{ zoomIn, zoomOut, next, prev, first, last }">
177177
<button data-testid="zoom-in" @click="zoomIn">
178178
zoom in
179179
</button>
@@ -186,6 +186,12 @@ it('should expose navigation in slot', async () => {
186186
<button data-testid="prev" @click="prev">
187187
prev
188188
</button>
189+
<button data-testid="first" @click="first">
190+
first
191+
</button>
192+
<button data-testid="last" @click="last">
193+
last
194+
</button>
189195
</template>
190196
</pdf-viewer>
191197
`,
@@ -207,6 +213,8 @@ it('should expose navigation in slot', async () => {
207213
const zoomOut = screen.queryByTestId('zoom-out')
208214
const next = screen.queryByTestId('next')
209215
const prev = screen.queryByTestId('prev')
216+
const first = screen.queryByTestId('first')
217+
const last = screen.queryByTestId('last')
210218

211219
await fireEvent.click(zoomIn)
212220

@@ -225,4 +233,34 @@ it('should expose navigation in slot', async () => {
225233
await fireEvent.click(prev)
226234

227235
expect(page.value).toBe(2)
236+
237+
await fireEvent.click(first)
238+
239+
expect(page.value).toBe(1)
240+
241+
await fireEvent.click(last)
242+
243+
expect(page.value).toBe(5)
244+
})
245+
246+
it('should be able to change num-of-pages, first and last navigation label via props "num-of-pages-nav-label", "first-nav-label" and "last-nav-label"', () => {
247+
const screen = render({
248+
components: { PdfViewer },
249+
template : `
250+
<pdf-viewer
251+
src="http://sample.pdf"
252+
first-nav-label="Awal"
253+
last-nav-label="Akhir"
254+
num-of-pages-nav-label="dari"
255+
/>
256+
`,
257+
})
258+
259+
const firstNavLabel = screen.queryByText('Awal')
260+
const lastNavLabel = screen.queryByText('Akhir')
261+
const numOfPagesLabel = screen.queryByText(/dari/i)
262+
263+
expect(firstNavLabel).toBeInTheDocument()
264+
expect(lastNavLabel).toBeInTheDocument()
265+
expect(numOfPagesLabel).toBeInTheDocument()
228266
})

src/components/pdf-viewer/PdfViewer.vue

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
:zoom-out="zoomOut"
1919
:next="next"
2020
:prev="prev"
21+
:first="first"
22+
:last="last"
2123
:doc="pdfDoc" />
2224
</div>
2325

@@ -43,6 +45,8 @@
4345
:zoom-out="zoomOut"
4446
:next="next"
4547
:prev="prev"
48+
:first="first"
49+
:last="last"
4650
:doc="pdfDoc" />
4751
</div>
4852
<!-- Minimum PDFJS Viewer end -->
@@ -56,11 +60,16 @@
5660
:zoom-out="zoomOut"
5761
:next="next"
5862
:prev="prev"
63+
:first="first"
64+
:last="last"
5965
:doc="pdfDoc" />
6066

6167
<transition name="slide-up">
6268
<PdfNavigation
63-
v-show="src && !idle && !loading && !error" />
69+
v-show="src && !idle && !loading && !error"
70+
:first-nav-label="firstNavLabel"
71+
:last-nav-label="lastNavLabel"
72+
:num-of-pages-nav-label="numOfPagesNavLabel" />
6473
</transition>
6574

6675
<slot
@@ -72,6 +81,8 @@
7281
:zoom-out="zoomOut"
7382
:next="next"
7483
:prev="prev"
84+
:first="first"
85+
:last="last"
7586
:doc="pdfDoc" />
7687
</PdfObjects>
7788
<div class="pdf__footer">
@@ -84,6 +95,8 @@
8495
:zoom-out="zoomOut"
8596
:next="next"
8697
:prev="prev"
98+
:first="first"
99+
:last="last"
87100
:doc="pdfDoc" />
88101
</div>
89102
</div>
@@ -151,6 +164,18 @@ const props = defineProps({
151164
type : [Object] as PropType<OpenDocConfig>,
152165
default: () => ({}),
153166
},
167+
firstNavLabel: {
168+
type : String,
169+
default: 'First',
170+
},
171+
lastNavLabel: {
172+
type : String,
173+
default: 'Last',
174+
},
175+
numOfPagesNavLabel: {
176+
type : String,
177+
default: 'of',
178+
},
154179
})
155180
156181
const emit = defineEmits<{
@@ -246,6 +271,14 @@ function prev () {
246271
pdfPage.value--
247272
}
248273
274+
function first () {
275+
pdfPage.value = 1
276+
}
277+
278+
function last () {
279+
pdfPage.value = totalPage.value
280+
}
281+
249282
provide(PDF_VIEWER_CONTEXT, {
250283
page : pdfPage,
251284
scale: pdfScale,
@@ -254,6 +287,8 @@ provide(PDF_VIEWER_CONTEXT, {
254287
zoomOut,
255288
next,
256289
prev,
290+
first,
291+
last,
257292
})
258293
259294
syncRef(pdfPage, vPage)
@@ -273,6 +308,8 @@ defineExpose({
273308
prev,
274309
openDoc,
275310
closeDoc,
311+
first,
312+
last,
276313
})
277314
278315
interface PdfViewerSlotScope {

src/components/pdf-viewer/index.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,17 @@ Set `layout` prop to `fit` to enable layout fit mode. It will adapt the viewer h
179179

180180
### Props
181181

182-
| Props | Type | Default | Description |
183-
|-------------|:--------:|:-------:|---------------------------------------------------|
184-
| `src` | `String` | `-` | Document source URL |
185-
| `password` | `String` | `-` | Document password |
186-
| `layout` | `String` | `fixed` | Viewer layout sizing, valid value: `fixed`, `fit` |
187-
| `offsetTop` | `Number` | `0` | Margin top when using layout `fit` |
188-
| `page` | `Number` | `1` | `v-model:page` value |
189-
| `scale` | `Number` | `1` | `v-model:scale` value |
182+
| Props | Type | Default | Description |
183+
|--------------------------|:--------:|:-------:|----------------------------------------------------------------------------|
184+
| `src` | `String` | `-` | Document source URL |
185+
| `password` | `String` | `-` | Document password |
186+
| `layout` | `String` | `fixed` | Viewer layout sizing, valid value: `fixed`, `fit` |
187+
| `offsetTop` | `Number` | `0` | Margin top when using layout `fit` |
188+
| `page` | `Number` | `1` | `v-model:page` value |
189+
| `scale` | `Number` | `1` | `v-model:scale` value |
190+
| `first-nav-label` | `String` | `First` | Label to place in the first navigation button |
191+
| `last-nav-label` | `String` | `Last` | Label to place in the last navigation button |
192+
| `num-of-pages-nav-label` | `String` | `of` | Label to place on the preposition number of pages navigation button |
190193

191194
### Slots
192195

src/components/pdf-viewer/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ export interface PdfViewerContext {
1919
zoomOut: () => void,
2020
next: () => void,
2121
prev: () => void,
22+
first: () => void,
23+
last: () => void,
2224
}
2325

2426
export const PDF_VIEWER_CONTEXT: InjectionKey<PdfViewerContext> = Symbol('PdfViewer')
@@ -37,6 +39,8 @@ export function usePdfContext () {
3739
zoomOut: noop,
3840
next : noop,
3941
prev : noop,
42+
first : noop,
43+
last : noop,
4044
}
4145
}, true)
4246
}

src/components/pspdfkit/PspdfViewer.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,14 @@ function prev () {
186186
pdfPage.value--
187187
}
188188
189+
function first () {
190+
pdfPage.value = 1
191+
}
192+
193+
function last () {
194+
pdfPage.value = totalPage.value
195+
}
196+
189197
provide(PDF_VIEWER_CONTEXT, {
190198
page : pdfPage,
191199
scale: pdfScale,
@@ -194,6 +202,8 @@ provide(PDF_VIEWER_CONTEXT, {
194202
zoomOut,
195203
next,
196204
prev,
205+
first,
206+
last,
197207
})
198208
199209
syncRef(pdfPage, vPage)

0 commit comments

Comments
 (0)