@oslokommune/punkt-react 16.13.3 → 16.15.0
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/CHANGELOG.md +35 -0
- package/dist/{dialog-polyfill.esm-1hPr0gl9-EorOF9Wq.js → dialog-polyfill.esm-BmVHGRTX-CuhXqEqJ.js} +1 -1
- package/dist/index.d.ts +50 -47
- package/dist/punkt-react.es.js +4560 -3038
- package/dist/punkt-react.umd.js +670 -274
- package/dist/shared-types/fileupload.d.ts +73 -0
- package/dist/shared-types/index.d.ts +2 -0
- package/dist/shared-utils/fileupload/announcements.d.ts +11 -0
- package/dist/shared-utils/fileupload/filename.d.ts +13 -0
- package/dist/shared-utils/fileupload/focus-trap.d.ts +12 -0
- package/dist/shared-utils/fileupload/formats.d.ts +30 -0
- package/dist/shared-utils/fileupload/index.d.ts +15 -0
- package/dist/shared-utils/fileupload/navigation.d.ts +5 -0
- package/dist/shared-utils/fileupload/size.d.ts +12 -0
- package/dist/shared-utils/fileupload/transfers.d.ts +17 -0
- package/dist/shared-utils/fileupload/truncate.d.ts +13 -0
- package/dist/shared-utils/fileupload/validation.d.ts +24 -0
- package/package.json +4 -4
- package/src/components/fileupload/DropZone.tsx +35 -22
- package/src/components/fileupload/FileUpload.test.tsx +165 -10
- package/src/components/fileupload/FileUpload.tsx +116 -184
- package/src/components/fileupload/QueueDisplay.test.tsx +51 -8
- package/src/components/fileupload/QueueDisplay.tsx +71 -99
- package/src/components/fileupload/QueueItemContent.tsx +120 -135
- package/src/components/fileupload/Subcomponents.tsx +175 -144
- package/src/components/fileupload/Truncate.test.tsx +65 -207
- package/src/components/fileupload/Truncate.tsx +24 -120
- package/src/components/fileupload/extensions/Comments.tsx +94 -106
- package/src/components/fileupload/extensions/Remove.tsx +3 -5
- package/src/components/fileupload/extensions/Rename.tsx +45 -42
- package/src/components/fileupload/hooks/index.ts +1 -0
- package/src/components/fileupload/hooks/useFileAttributes.ts +37 -29
- package/src/components/fileupload/hooks/useImagePreview.ts +3 -7
- package/src/components/fileupload/hooks/useOperationState.ts +29 -8
- package/src/components/fileupload/hooks/useRequiredFormValidation.ts +43 -0
- package/src/components/fileupload/hooks.ts +1 -0
- package/src/components/fileupload/types.ts +49 -32
- package/src/components/fileupload/utils.ts +3 -54
- package/src/components/inputwrapper/InputWrapper.tsx +4 -1
- package/src/components/modal/Modal.tsx +27 -15
- package/src/components/searchinput/SearchInput.tsx +14 -13
- package/src/components/types.ts +1 -1
- package/src/components/fileupload/texts.ts +0 -20
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RefObject, useEffect, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
import { getDisplayFilename, trapTabInside } from 'shared-utils/fileupload'
|
|
2
4
|
|
|
3
5
|
import { PktButton, PktIcon, PktProgressbar } from '..'
|
|
4
6
|
import { PktModal } from '../modal/Modal'
|
|
5
7
|
import { Truncate } from './Truncate'
|
|
6
|
-
import { TFileAndTransfer,
|
|
8
|
+
import { TFileAndTransfer, TQueueItemOperation, TQueueOperationContext, TTransferItemInProgress } from './types'
|
|
7
9
|
import { formatFileSize } from './utils'
|
|
8
10
|
|
|
9
|
-
const CancelTransferButton = (props: {
|
|
11
|
+
const CancelTransferButton = (props: {
|
|
12
|
+
onClick: () => void
|
|
13
|
+
label?: string
|
|
14
|
+
ariaLabel?: string
|
|
15
|
+
disabled?: boolean
|
|
16
|
+
}) => (
|
|
10
17
|
<button
|
|
18
|
+
type="button"
|
|
11
19
|
onClick={props.onClick}
|
|
20
|
+
disabled={props.disabled}
|
|
12
21
|
className="pkt-fileupload__queue-display__item__cancel-button"
|
|
13
22
|
aria-label={props.ariaLabel || 'Avbryt opplasting'}
|
|
14
23
|
>
|
|
@@ -16,30 +25,20 @@ const CancelTransferButton = (props: { onClick: () => void; label?: string; aria
|
|
|
16
25
|
</button>
|
|
17
26
|
)
|
|
18
27
|
|
|
19
|
-
const LoadingText = () =>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
setDotCount((prev) => (prev >= 3 ? 1 : prev + 1))
|
|
25
|
-
}, 400)
|
|
26
|
-
|
|
27
|
-
return () => clearInterval(interval)
|
|
28
|
-
}, [])
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<span className="pkt-fileupload__queue-display__item__loading-text" aria-label="Laster opp fil">
|
|
32
|
-
Laster opp{'.'.repeat(dotCount)}
|
|
33
|
-
</span>
|
|
34
|
-
)
|
|
35
|
-
}
|
|
28
|
+
const LoadingText = () => (
|
|
29
|
+
<span className="pkt-fileupload__queue-display__item__loading-text" aria-label="Laster opp fil">
|
|
30
|
+
Laster opp
|
|
31
|
+
</span>
|
|
32
|
+
)
|
|
36
33
|
|
|
37
34
|
export const TransferInProgress = ({
|
|
38
35
|
cancelTransfer,
|
|
39
36
|
transferItem,
|
|
37
|
+
disabled = false,
|
|
40
38
|
}: {
|
|
41
39
|
transferItem: TTransferItemInProgress
|
|
42
40
|
cancelTransfer: () => void
|
|
41
|
+
disabled?: boolean
|
|
43
42
|
}) => {
|
|
44
43
|
const showProgressBar = transferItem.showProgress ?? transferItem.progress !== 0
|
|
45
44
|
|
|
@@ -51,9 +50,13 @@ export const TransferInProgress = ({
|
|
|
51
50
|
aria-hidden="true"
|
|
52
51
|
/>
|
|
53
52
|
<p className="pkt-fileupload__queue-display__item__title" aria-label="Filnavn">
|
|
54
|
-
<Truncate>{transferItem
|
|
53
|
+
<Truncate>{getDisplayFilename(transferItem)}</Truncate>
|
|
54
|
+
<span className="pkt-fileupload__queue-display__item__filesize">
|
|
55
|
+
{' '}
|
|
56
|
+
({formatFileSize(transferItem.file.size)})
|
|
57
|
+
</span>
|
|
55
58
|
</p>
|
|
56
|
-
<CancelTransferButton onClick={cancelTransfer} />
|
|
59
|
+
<CancelTransferButton onClick={cancelTransfer} disabled={disabled} />
|
|
57
60
|
{showProgressBar ? (
|
|
58
61
|
<>
|
|
59
62
|
<PktProgressbar
|
|
@@ -63,9 +66,6 @@ export const TransferInProgress = ({
|
|
|
63
66
|
statusPlacement={'following'}
|
|
64
67
|
className="pkt-fileupload__queue-display__item__progress"
|
|
65
68
|
/>
|
|
66
|
-
<span className="pkt-fileupload__queue-display__item__filesize">
|
|
67
|
-
{formatFileSize(transferItem.file.size)}
|
|
68
|
-
</span>
|
|
69
69
|
<span className="pkt-fileupload__queue-display__item__percentage" aria-hidden="true">
|
|
70
70
|
{`${Math.round(transferItem.progress * 100)}%`}
|
|
71
71
|
</span>
|
|
@@ -77,13 +77,27 @@ export const TransferInProgress = ({
|
|
|
77
77
|
)
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
const TitleWithSize = ({ transferItem }: { transferItem: TFileAndTransfer }) => (
|
|
81
|
+
<p className="pkt-fileupload__queue-display__item__title">
|
|
82
|
+
<Truncate>{getDisplayFilename(transferItem)}</Truncate>
|
|
83
|
+
{transferItem.file && (
|
|
84
|
+
<span className="pkt-fileupload__queue-display__item__filesize">
|
|
85
|
+
{' '}
|
|
86
|
+
({formatFileSize(transferItem.file.size)})
|
|
87
|
+
</span>
|
|
88
|
+
)}
|
|
89
|
+
</p>
|
|
90
|
+
)
|
|
91
|
+
|
|
80
92
|
// Error state with progress bar (when showProgress was true during upload)
|
|
81
93
|
const TransferErrorWithProgress = ({
|
|
82
94
|
transferItem,
|
|
83
95
|
onRemove,
|
|
96
|
+
disabled,
|
|
84
97
|
}: {
|
|
85
98
|
transferItem: TFileAndTransfer
|
|
86
99
|
onRemove: () => void
|
|
100
|
+
disabled?: boolean
|
|
87
101
|
}) => {
|
|
88
102
|
// Use lastProgress to show where the upload failed (default to 100% if not available)
|
|
89
103
|
const progressValue = (transferItem.lastProgress ?? 1) * 100
|
|
@@ -95,10 +109,13 @@ const TransferErrorWithProgress = ({
|
|
|
95
109
|
name="alert-error"
|
|
96
110
|
aria-hidden="true"
|
|
97
111
|
/>
|
|
98
|
-
<
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
112
|
+
<TitleWithSize transferItem={transferItem} />
|
|
113
|
+
<CancelTransferButton
|
|
114
|
+
onClick={onRemove}
|
|
115
|
+
label="Fjern"
|
|
116
|
+
ariaLabel="Fjern fil som feilet under opplasting"
|
|
117
|
+
disabled={disabled}
|
|
118
|
+
/>
|
|
102
119
|
<PktProgressbar
|
|
103
120
|
valueCurrent={progressValue}
|
|
104
121
|
statusType={'none'}
|
|
@@ -106,7 +123,6 @@ const TransferErrorWithProgress = ({
|
|
|
106
123
|
statusPlacement={'following'}
|
|
107
124
|
className="pkt-fileupload__queue-display__item__progress pkt-fileupload__queue-display__item__progress--error"
|
|
108
125
|
/>
|
|
109
|
-
<span className="pkt-fileupload__queue-display__item__filesize">{formatFileSize(transferItem.file.size)}</span>
|
|
110
126
|
{transferItem.errorMessage && (
|
|
111
127
|
<span className="pkt-fileupload__queue-display__item__error-message">{transferItem.errorMessage}</span>
|
|
112
128
|
)}
|
|
@@ -118,9 +134,11 @@ const TransferErrorWithProgress = ({
|
|
|
118
134
|
const TransferErrorIndeterminate = ({
|
|
119
135
|
transferItem,
|
|
120
136
|
onRemove,
|
|
137
|
+
disabled,
|
|
121
138
|
}: {
|
|
122
139
|
transferItem: TFileAndTransfer
|
|
123
140
|
onRemove: () => void
|
|
141
|
+
disabled?: boolean
|
|
124
142
|
}) => (
|
|
125
143
|
<>
|
|
126
144
|
<PktIcon
|
|
@@ -128,10 +146,13 @@ const TransferErrorIndeterminate = ({
|
|
|
128
146
|
name="alert-error"
|
|
129
147
|
aria-hidden="true"
|
|
130
148
|
/>
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
149
|
+
<TitleWithSize transferItem={transferItem} />
|
|
150
|
+
<CancelTransferButton
|
|
151
|
+
onClick={onRemove}
|
|
152
|
+
label="Fjern"
|
|
153
|
+
ariaLabel="Fjern fil som feilet under opplasting"
|
|
154
|
+
disabled={disabled}
|
|
155
|
+
/>
|
|
135
156
|
{transferItem.errorMessage && (
|
|
136
157
|
<span className="pkt-fileupload__queue-display__item__error-message">{transferItem.errorMessage}</span>
|
|
137
158
|
)}
|
|
@@ -139,41 +160,46 @@ const TransferErrorIndeterminate = ({
|
|
|
139
160
|
)
|
|
140
161
|
|
|
141
162
|
// Main error component - chooses display based on showProgress
|
|
142
|
-
export const TransferError = ({
|
|
163
|
+
export const TransferError = ({
|
|
164
|
+
transferItem,
|
|
165
|
+
onRemove,
|
|
166
|
+
disabled,
|
|
167
|
+
}: {
|
|
168
|
+
transferItem: TFileAndTransfer
|
|
169
|
+
onRemove: () => void
|
|
170
|
+
disabled?: boolean
|
|
171
|
+
}) => {
|
|
143
172
|
// If showProgress was true, show error with progress bar, otherwise show indeterminate error
|
|
144
173
|
if (transferItem.showProgress) {
|
|
145
|
-
return <TransferErrorWithProgress transferItem={transferItem} onRemove={onRemove} />
|
|
174
|
+
return <TransferErrorWithProgress transferItem={transferItem} onRemove={onRemove} disabled={disabled} />
|
|
146
175
|
}
|
|
147
|
-
return <TransferErrorIndeterminate transferItem={transferItem} onRemove={onRemove} />
|
|
176
|
+
return <TransferErrorIndeterminate transferItem={transferItem} onRemove={onRemove} disabled={disabled} />
|
|
148
177
|
}
|
|
149
178
|
export const OperationButton = ({
|
|
150
179
|
operation,
|
|
151
|
-
|
|
152
|
-
transferItem,
|
|
180
|
+
context,
|
|
153
181
|
}: {
|
|
154
182
|
operation: TQueueItemOperation
|
|
155
|
-
|
|
156
|
-
transferItem: TFileAndTransfer
|
|
183
|
+
context: TQueueOperationContext
|
|
157
184
|
}) => {
|
|
158
|
-
const title = typeof operation.title === 'function' ? operation.title(
|
|
185
|
+
const title = typeof operation.title === 'function' ? operation.title(context.file) : operation.title
|
|
159
186
|
|
|
160
187
|
// Don't render button if title is empty (e.g., comment exists, show icons instead)
|
|
161
188
|
if (!title) return null
|
|
162
189
|
|
|
163
190
|
const onClick = () => {
|
|
164
191
|
if (operation.renderInlineUI || operation.renderExtendedUI) {
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
if (operation.onClick) {
|
|
168
|
-
operation.onClick(transferItem)
|
|
192
|
+
context.activate()
|
|
169
193
|
}
|
|
194
|
+
operation.onClick?.(context)
|
|
170
195
|
}
|
|
171
196
|
return (
|
|
172
197
|
<button
|
|
173
198
|
type="button"
|
|
174
199
|
className={'pkt-fileupload__queue-display__item__operation'}
|
|
175
200
|
onClick={onClick}
|
|
176
|
-
|
|
201
|
+
disabled={context.disabled}
|
|
202
|
+
aria-label={typeof operation.ariaLabel === 'function' ? operation.ariaLabel(context.file) : operation.ariaLabel}
|
|
177
203
|
>
|
|
178
204
|
{title}
|
|
179
205
|
</button>
|
|
@@ -192,10 +218,7 @@ export const FilenameRenderer = ({
|
|
|
192
218
|
className="pkt-fileupload__queue-display__item__icon pkt-icon--medium"
|
|
193
219
|
aria-hidden="true"
|
|
194
220
|
/>
|
|
195
|
-
<
|
|
196
|
-
<Truncate>{transferItem.attributes['targetFilename']}</Truncate>
|
|
197
|
-
</p>
|
|
198
|
-
<span className="pkt-fileupload__queue-display__item__filesize">{formatFileSize(transferItem.file.size)}</span>
|
|
221
|
+
<TitleWithSize transferItem={transferItem} />
|
|
199
222
|
</>
|
|
200
223
|
)
|
|
201
224
|
|
|
@@ -262,9 +285,9 @@ export const ThumbnailRenderer = ({
|
|
|
262
285
|
)}
|
|
263
286
|
{img}
|
|
264
287
|
</PktButton>
|
|
265
|
-
<
|
|
266
|
-
{transferItem.attributes['targetFilename']}
|
|
267
|
-
</
|
|
288
|
+
<span className="pkt-fileupload__queue-display__item__thumbnail__title">
|
|
289
|
+
<Truncate>{transferItem.attributes['targetFilename']}</Truncate>
|
|
290
|
+
</span>
|
|
268
291
|
</div>
|
|
269
292
|
)
|
|
270
293
|
}
|
|
@@ -277,107 +300,115 @@ interface IImagePreviewModal {
|
|
|
277
300
|
currentIndex: number
|
|
278
301
|
onClose: () => void
|
|
279
302
|
onNavigate: (direction: 'prev' | 'next') => void
|
|
303
|
+
modalRef: RefObject<HTMLDialogElement>
|
|
280
304
|
}
|
|
281
305
|
|
|
282
|
-
export const ImagePreviewModal =
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
306
|
+
export const ImagePreviewModal = ({
|
|
307
|
+
isOpen,
|
|
308
|
+
images,
|
|
309
|
+
currentIndex,
|
|
310
|
+
onClose,
|
|
311
|
+
onNavigate,
|
|
312
|
+
modalRef,
|
|
313
|
+
}: IImagePreviewModal) => {
|
|
314
|
+
const [imageUrl, setImageUrl] = useState<string | null>(null)
|
|
315
|
+
const [imageLoadFailed, setImageLoadFailed] = useState(false)
|
|
316
|
+
const currentImage = images[currentIndex]
|
|
317
|
+
const hasMultipleImages = images.length > 1
|
|
288
318
|
|
|
289
|
-
|
|
290
|
-
|
|
319
|
+
useEffect(() => {
|
|
320
|
+
setImageLoadFailed(false)
|
|
291
321
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
322
|
+
if (currentImage && currentImage.file.type.startsWith('image/')) {
|
|
323
|
+
const url = URL.createObjectURL(currentImage.file)
|
|
324
|
+
setImageUrl(url)
|
|
325
|
+
return () => URL.revokeObjectURL(url)
|
|
326
|
+
}
|
|
327
|
+
setImageUrl(null)
|
|
328
|
+
}, [currentImage])
|
|
329
|
+
|
|
330
|
+
useEffect(() => {
|
|
331
|
+
if (!isOpen) return
|
|
332
|
+
|
|
333
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
334
|
+
if (event.key === 'Tab') {
|
|
335
|
+
trapTabInside(event, modalRef.current)
|
|
336
|
+
return
|
|
296
337
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
case 'ArrowRight':
|
|
311
|
-
e.preventDefault()
|
|
312
|
-
onNavigate('next')
|
|
313
|
-
break
|
|
314
|
-
case 'Escape':
|
|
315
|
-
e.preventDefault()
|
|
316
|
-
onClose()
|
|
317
|
-
break
|
|
318
|
-
}
|
|
338
|
+
switch (event.key) {
|
|
339
|
+
case 'ArrowLeft':
|
|
340
|
+
event.preventDefault()
|
|
341
|
+
onNavigate('prev')
|
|
342
|
+
break
|
|
343
|
+
case 'ArrowRight':
|
|
344
|
+
event.preventDefault()
|
|
345
|
+
onNavigate('next')
|
|
346
|
+
break
|
|
347
|
+
case 'Escape':
|
|
348
|
+
event.preventDefault()
|
|
349
|
+
onClose()
|
|
350
|
+
break
|
|
319
351
|
}
|
|
352
|
+
}
|
|
320
353
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
if (!currentImage) return null
|
|
354
|
+
window.addEventListener('keydown', handleKeyDown)
|
|
355
|
+
return () => window.removeEventListener('keydown', handleKeyDown)
|
|
356
|
+
}, [isOpen, onNavigate, onClose, modalRef])
|
|
326
357
|
|
|
327
|
-
|
|
328
|
-
<PktModal
|
|
329
|
-
ref={ref}
|
|
330
|
-
headingText={currentImage.attributes['targetFilename']}
|
|
331
|
-
closeOnBackdropClick
|
|
332
|
-
className="pkt-fileupload__image-preview-modal"
|
|
333
|
-
>
|
|
334
|
-
<div className="pkt-fileupload__image-preview">
|
|
335
|
-
{hasMultipleImages && (
|
|
336
|
-
<PktButton
|
|
337
|
-
variant="icon-only"
|
|
338
|
-
iconName="chevron-thin-left"
|
|
339
|
-
skin="secondary"
|
|
340
|
-
size="small"
|
|
341
|
-
className="pkt-fileupload__image-preview__nav pkt-fileupload__image-preview__nav--prev"
|
|
342
|
-
onClick={() => onNavigate('prev')}
|
|
343
|
-
aria-label={`Forrige bilde ${currentIndex} / ${images.length}`}
|
|
344
|
-
/>
|
|
345
|
-
)}
|
|
358
|
+
if (!currentImage) return null
|
|
346
359
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
360
|
+
return (
|
|
361
|
+
<PktModal
|
|
362
|
+
ref={modalRef}
|
|
363
|
+
headingText={currentImage.attributes['targetFilename']}
|
|
364
|
+
closeOnBackdropClick
|
|
365
|
+
className="pkt-fileupload__image-preview-modal"
|
|
366
|
+
onClose={onClose}
|
|
367
|
+
>
|
|
368
|
+
<div className="pkt-fileupload__image-preview">
|
|
369
|
+
{hasMultipleImages && (
|
|
370
|
+
<PktButton
|
|
371
|
+
variant="icon-only"
|
|
372
|
+
iconName="chevron-thin-left"
|
|
373
|
+
skin="secondary"
|
|
374
|
+
size="medium"
|
|
375
|
+
className="pkt-fileupload__image-preview__nav pkt-fileupload__image-preview__nav--prev"
|
|
376
|
+
onClick={() => onNavigate('prev')}
|
|
377
|
+
aria-label={`Forrige bilde ${currentIndex} / ${images.length}`}
|
|
378
|
+
/>
|
|
379
|
+
)}
|
|
365
380
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
onClick={() => onNavigate('next')}
|
|
374
|
-
aria-label={`Neste bilde ${currentIndex + 2} / ${images.length}`}
|
|
381
|
+
<div className="pkt-fileupload__image-preview__content">
|
|
382
|
+
{imageUrl && !imageLoadFailed ? (
|
|
383
|
+
<img
|
|
384
|
+
src={imageUrl}
|
|
385
|
+
alt={`${currentImage.attributes['targetFilename']} - ${currentIndex + 1} av ${images.length}`}
|
|
386
|
+
className="pkt-fileupload__image-preview__image"
|
|
387
|
+
onError={() => setImageLoadFailed(true)}
|
|
375
388
|
/>
|
|
389
|
+
) : (
|
|
390
|
+
<PktIcon name="picture" className="pkt-fileupload__queue-display__item__icon pkt-icon--medium" />
|
|
376
391
|
)}
|
|
377
392
|
</div>
|
|
378
|
-
</PktModal>
|
|
379
|
-
)
|
|
380
|
-
},
|
|
381
|
-
)
|
|
382
393
|
|
|
383
|
-
|
|
394
|
+
{hasMultipleImages && (
|
|
395
|
+
<span className="pkt-fileupload__image-preview__counter">
|
|
396
|
+
{currentIndex + 1} / {images.length}
|
|
397
|
+
</span>
|
|
398
|
+
)}
|
|
399
|
+
|
|
400
|
+
{hasMultipleImages && (
|
|
401
|
+
<PktButton
|
|
402
|
+
variant="icon-only"
|
|
403
|
+
iconName="chevron-thin-right"
|
|
404
|
+
skin="secondary"
|
|
405
|
+
size="medium"
|
|
406
|
+
className="pkt-fileupload__image-preview__nav pkt-fileupload__image-preview__nav--next"
|
|
407
|
+
onClick={() => onNavigate('next')}
|
|
408
|
+
aria-label={`Neste bilde ${currentIndex + 2} / ${images.length}`}
|
|
409
|
+
/>
|
|
410
|
+
)}
|
|
411
|
+
</div>
|
|
412
|
+
</PktModal>
|
|
413
|
+
)
|
|
414
|
+
}
|