UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

214 lines (202 loc) 7.21 kB
import { html } from 'lit' import type { TFileComment, TQueueItemOperation, TQueueOperationContext } from './fileupload-types' const COMMENTS_ATTRIBUTE = 'comments' const formatTimestamp = (iso: string): string => { const date = new Date(iso) if (Number.isNaN(date.getTime())) return iso const day = String(date.getDate()).padStart(2, '0') const month = String(date.getMonth() + 1).padStart(2, '0') const year = date.getFullYear() const hours = String(date.getHours()).padStart(2, '0') const minutes = String(date.getMinutes()).padStart(2, '0') return `${day}.${month}.${year} kl. ${hours}:${minutes}` } const handleRenameKeydown = (event: KeyboardEvent, save: () => void, cancel: () => void) => { if (event.key === 'Enter') { event.preventDefault() event.stopPropagation() save() } if (event.key === 'Escape') { event.preventDefault() event.stopPropagation() cancel() } } const handleCommentTextareaKeydown = (event: KeyboardEvent, save: () => void, cancel: () => void) => { if (event.key === 'Escape') { event.preventDefault() event.stopPropagation() cancel() } if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') { event.preventDefault() event.stopPropagation() save() } } export const createRemoveOperation = (removeFile: (fileId: string) => void): TQueueItemOperation => ({ id: 'remove', title: 'Slett', ariaLabel: 'Slett fil', onClick: ({ file }) => removeFile(file.fileId), }) export const createRenameOperation = (): TQueueItemOperation => ({ id: 'rename', title: 'Rediger', ariaLabel: 'Rediger filnavn', renderInlineUI: (context: TQueueOperationContext) => { const currentName = context.getAttribute<string>('targetFilename') || context.file.attributes?.targetFilename || context.file.file?.name || '' const inputId = `pkt-fileupload-rename-${context.file.fileId}` const save = () => { const input = document.getElementById(inputId) as HTMLInputElement | null const nextName = input?.value?.trim() if (nextName) { context.setAttribute('targetFilename', nextName) } context.close() } return html` <label for=${inputId} class="pkt-sr-only">Endre filnavn</label> <input id=${inputId} type="text" class="pkt-fileupload__queue-display__item__rename-input" ?disabled=${context.disabled} .value=${currentName} @keydown=${(event: KeyboardEvent) => handleRenameKeydown(event, save, context.close)} /> <button type="button" class="pkt-btn pkt-btn--secondary pkt-btn--small" ?disabled=${context.disabled} @click=${save} > Lagre </button> <button type="button" class="pkt-btn pkt-btn--tertiary pkt-btn--small" ?disabled=${context.disabled} @click=${context.close} > Avbryt </button> ` }, renderHidden: (context: TQueueOperationContext) => { const targetFilename = context.getAttribute<string>('targetFilename') || context.file.attributes?.targetFilename || context.file.file?.name || '' return html`<input type="hidden" name=${`${context.inputName}-targetFilename`} value=${targetFilename} />` }, }) export const createCommentOperation = (): TQueueItemOperation => ({ id: 'comment', title: (file) => { const comments = (file.attributes?.[COMMENTS_ATTRIBUTE] as TFileComment[] | undefined) ?? [] return comments.length > 0 ? '' : 'Legg til kommentar' }, ariaLabel: 'Legg til kommentar', renderExtendedUI: (context: TQueueOperationContext) => { const comments = context.getAttribute<TFileComment[]>(COMMENTS_ATTRIBUTE) ?? [] const existingComment = comments[0] const textareaId = `pkt-fileupload-comment-${context.file.fileId}` const save = () => { const textarea = document.getElementById(textareaId) as HTMLTextAreaElement | null const text = textarea?.value?.trim() if (text) { context.setAttribute(COMMENTS_ATTRIBUTE, [{ text, timestamp: new Date().toISOString() } satisfies TFileComment]) } context.close() } return html` <label for=${textareaId} class="pkt-fileupload__queue-display__item__comment-label"> ${existingComment ? 'Rediger kommentar' : 'Legg til kommentar'} </label> <textarea id=${textareaId} class="pkt-fileupload__queue-display__item__comment-input" ?disabled=${context.disabled} .value=${existingComment?.text ?? ''} rows="2" placeholder="Skriv inn kommentar" @keydown=${(event: KeyboardEvent) => handleCommentTextareaKeydown(event, save, context.close)} ></textarea> <button type="button" class="pkt-btn pkt-btn--secondary pkt-btn--small" ?disabled=${context.disabled} @click=${save} > ${existingComment ? 'Lagre kommentar' : 'Legg til kommentar'} </button> <button type="button" class="pkt-btn pkt-btn--tertiary pkt-btn--small" ?disabled=${context.disabled} @click=${context.close} > Avbryt </button> ` }, renderContent: (context: TQueueOperationContext) => { if (context.isActive) return null const comments = context.getAttribute<TFileComment[]>(COMMENTS_ATTRIBUTE) ?? [] if (comments.length === 0) return null const comment = comments[0] return html` <div class="pkt-fileupload__queue-display__item__comments"> <div class="pkt-fileupload__queue-display__item__comment"> <div class="pkt-fileupload__queue-display__item__comment__content"> <span class="pkt-fileupload__queue-display__item__comment__text" aria-label="Kommentar tekst"> ${comment.text} </span> <time class="pkt-fileupload__queue-display__item__comment__time"> ${formatTimestamp(comment.timestamp)} </time> </div> <div class="pkt-fileupload__queue-display__item__comment__actions"> <button type="button" class="pkt-fileupload__queue-display__item__comment__action" aria-label="Rediger kommentar" ?disabled=${context.disabled} @click=${context.activate} > <pkt-icon name="edit"></pkt-icon> </button> <button type="button" class="pkt-fileupload__queue-display__item__comment__action" aria-label="Slett kommentar" ?disabled=${context.disabled} @click=${() => context.setAttribute(COMMENTS_ATTRIBUTE, undefined)} > <pkt-icon name="trash-can"></pkt-icon> </button> </div> </div> </div> ` }, renderHidden: (context: TQueueOperationContext) => { const comments = context.getAttribute<TFileComment[]>(COMMENTS_ATTRIBUTE) return html`<input type="hidden" name=${`${context.inputName}-comments`} value=${comments ? JSON.stringify(comments) : ''} />` }, })