@oslokommune/punkt-elements 16.13.2 → 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.
Files changed (157) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/dist/calendar-Ch1dgnBo.js +656 -0
  3. package/dist/calendar-DkjXla0I.cjs +90 -0
  4. package/dist/{card-CQYxrtL0.cjs → card-C3POnP3O.cjs} +1 -1
  5. package/dist/{card-Bir3-pl2.js → card-CEDbo1t7.js} +2 -2
  6. package/dist/{checkbox-Cspxcvt_.js → checkbox-Bjp43NxA.js} +1 -1
  7. package/dist/{checkbox-BARDb9iV.cjs → checkbox-nTbihMxW.cjs} +1 -1
  8. package/dist/{combobox-CGbFTWq_.cjs → combobox-C4Q6kQEs.cjs} +1 -1
  9. package/dist/{combobox-BcdLZRDU.js → combobox-CL9BLuxt.js} +6 -6
  10. package/dist/components/fileupload/fileupload-base.d.ts +116 -0
  11. package/dist/components/fileupload/fileupload-operations.d.ts +4 -0
  12. package/dist/components/fileupload/fileupload-renderers.d.ts +28 -0
  13. package/dist/components/fileupload/fileupload-types.d.ts +70 -0
  14. package/dist/components/fileupload/fileupload.d.ts +25 -0
  15. package/dist/components/fileupload/fileupload.test.d.ts +0 -0
  16. package/dist/components/fileupload/index.d.ts +4 -0
  17. package/dist/components/index.d.ts +2 -0
  18. package/dist/components/input-wrapper/input-wrapper.d.ts +2 -0
  19. package/dist/controllers/focus-modality-controller.d.ts +31 -0
  20. package/dist/converters-Bffq_YDm.cjs +1 -0
  21. package/dist/converters-jauYkvNh.js +1378 -0
  22. package/dist/{datepicker-OVd8pmnZ.js → datepicker-BUK1Qanw.js} +22 -21
  23. package/dist/{datepicker-DpmlsnH_.cjs → datepicker-DYd3JCs_.cjs} +10 -10
  24. package/dist/docs/components/fileupload.d.ts +27 -0
  25. package/dist/fileupload-BRqioKSY.cjs +396 -0
  26. package/dist/fileupload-Bnl303X0.js +1372 -0
  27. package/dist/fileupload.d.ts +1 -0
  28. package/dist/{header-DWgPgGfS.cjs → header-Dps8o-ZY.cjs} +1 -1
  29. package/dist/{header-a6ztVNp3.js → header-T5O6sfCN.js} +3 -3
  30. package/dist/{helptext-CCBKKLus.js → helptext-C5rG4VkA.js} +2 -2
  31. package/dist/{helptext-D-3QfZv5.cjs → helptext-DQgStO4D.cjs} +1 -1
  32. package/dist/{input-element-Bw1s6NlF.js → input-element-CjebcQd1.js} +3 -3
  33. package/dist/{input-element-B1yxcfz4.cjs → input-element-FGcr5hGd.cjs} +1 -1
  34. package/dist/input-wrapper-B_XFi211.cjs +55 -0
  35. package/dist/{input-wrapper-YfTmpSSY.js → input-wrapper-DBpMVSxt.js} +41 -15
  36. package/dist/{listbox-DuBgTFvH.js → listbox-0NHJvNjz.js} +2 -2
  37. package/dist/{listbox-DCA2JoPV.cjs → listbox-CcThiNBY.cjs} +1 -1
  38. package/dist/{modal-CBEWrAi2.cjs → modal-B6591sWa.cjs} +1 -1
  39. package/dist/{modal-pPp8nia6.js → modal-DyIC3uhs.js} +1 -1
  40. package/dist/pkt-calendar.cjs +1 -1
  41. package/dist/pkt-calendar.js +1 -1
  42. package/dist/pkt-card.cjs +1 -1
  43. package/dist/pkt-card.js +1 -1
  44. package/dist/pkt-checkbox.cjs +1 -1
  45. package/dist/pkt-checkbox.js +1 -1
  46. package/dist/pkt-combobox.cjs +1 -1
  47. package/dist/pkt-combobox.js +1 -1
  48. package/dist/pkt-consent.cjs +1 -1
  49. package/dist/pkt-consent.js +1 -1
  50. package/dist/pkt-datepicker.cjs +1 -1
  51. package/dist/pkt-datepicker.js +1 -1
  52. package/dist/pkt-fileupload.cjs +1 -0
  53. package/dist/pkt-fileupload.js +2 -0
  54. package/dist/pkt-header.cjs +1 -1
  55. package/dist/pkt-header.js +1 -1
  56. package/dist/pkt-heading.cjs +1 -1
  57. package/dist/pkt-heading.js +1 -1
  58. package/dist/pkt-helptext.cjs +1 -1
  59. package/dist/pkt-helptext.js +1 -1
  60. package/dist/pkt-index.cjs +1 -1
  61. package/dist/pkt-index.js +25 -24
  62. package/dist/pkt-input-wrapper.cjs +1 -1
  63. package/dist/pkt-input-wrapper.js +1 -1
  64. package/dist/pkt-link.cjs +1 -1
  65. package/dist/pkt-link.js +1 -1
  66. package/dist/pkt-linkcard.cjs +1 -1
  67. package/dist/pkt-linkcard.js +1 -1
  68. package/dist/pkt-listbox.cjs +1 -1
  69. package/dist/pkt-listbox.js +1 -1
  70. package/dist/pkt-loader.cjs +1 -1
  71. package/dist/pkt-loader.js +1 -1
  72. package/dist/pkt-messagebox.cjs +1 -1
  73. package/dist/pkt-messagebox.js +1 -1
  74. package/dist/pkt-modal.cjs +1 -1
  75. package/dist/pkt-modal.js +1 -1
  76. package/dist/pkt-progressbar.cjs +1 -1
  77. package/dist/pkt-progressbar.js +1 -1
  78. package/dist/pkt-radiobutton.cjs +1 -1
  79. package/dist/pkt-radiobutton.js +1 -1
  80. package/dist/pkt-select.cjs +1 -1
  81. package/dist/pkt-select.js +1 -1
  82. package/dist/pkt-tabs.cjs +1 -1
  83. package/dist/pkt-tabs.js +1 -1
  84. package/dist/pkt-tag.cjs +1 -1
  85. package/dist/pkt-tag.js +1 -1
  86. package/dist/pkt-textarea.cjs +1 -1
  87. package/dist/pkt-textarea.js +1 -1
  88. package/dist/pkt-textinput.cjs +1 -1
  89. package/dist/pkt-textinput.js +1 -1
  90. package/dist/pkt-timepicker.cjs +1 -1
  91. package/dist/pkt-timepicker.js +1 -1
  92. package/dist/{progressbar-CdXtmOBb.cjs → progressbar-CrwpnIkv.cjs} +1 -1
  93. package/dist/{progressbar-Dy9AiYQz.js → progressbar-uC-0W6o4.js} +1 -1
  94. package/dist/{radiobutton-V_KPbup_.js → radiobutton-B-8-wWFf.js} +1 -1
  95. package/dist/{radiobutton-GOnpUbCW.cjs → radiobutton-DvXr7tDk.cjs} +1 -1
  96. package/dist/{select-C2i8sOk5.cjs → select-B75wzvyz.cjs} +1 -1
  97. package/dist/{select-BSAFd8Wa.js → select-D9B8Ighz.js} +3 -3
  98. package/dist/shared-types/fileupload.d.ts +73 -0
  99. package/dist/shared-types/index.d.ts +2 -0
  100. package/dist/shared-utils/fileupload/announcements.d.ts +11 -0
  101. package/dist/shared-utils/fileupload/filename.d.ts +13 -0
  102. package/dist/shared-utils/fileupload/focus-trap.d.ts +12 -0
  103. package/dist/shared-utils/fileupload/formats.d.ts +30 -0
  104. package/dist/shared-utils/fileupload/index.d.ts +15 -0
  105. package/dist/shared-utils/fileupload/navigation.d.ts +5 -0
  106. package/dist/shared-utils/fileupload/size.d.ts +12 -0
  107. package/dist/shared-utils/fileupload/transfers.d.ts +17 -0
  108. package/dist/shared-utils/fileupload/truncate.d.ts +13 -0
  109. package/dist/shared-utils/fileupload/validation.d.ts +24 -0
  110. package/dist/tests/component-registry.d.ts +2 -0
  111. package/dist/{textarea-DYOBhJrN.js → textarea-CIWXMaAD.js} +2 -2
  112. package/dist/{textarea-D7aGOyDf.cjs → textarea-CjqprL6Y.cjs} +1 -1
  113. package/dist/{textinput-DFh8_9cx.cjs → textinput-B0VWmVIF.cjs} +1 -1
  114. package/dist/{textinput-BUgntXnM.js → textinput-CxzAxM8E.js} +2 -2
  115. package/dist/{timepicker-BIfE7KKJ.cjs → timepicker-Cv9juQeB.cjs} +1 -1
  116. package/dist/{timepicker-DaSwn1FA.js → timepicker-DXrpg5C7.js} +2 -2
  117. package/package.json +2 -2
  118. package/src/components/fileupload/fileupload-base.ts +557 -0
  119. package/src/components/fileupload/fileupload-operations.ts +213 -0
  120. package/src/components/fileupload/fileupload-renderers.ts +769 -0
  121. package/src/components/fileupload/fileupload-types.ts +88 -0
  122. package/src/components/fileupload/fileupload.test.ts +949 -0
  123. package/src/components/fileupload/fileupload.ts +469 -0
  124. package/src/components/fileupload/index.ts +34 -0
  125. package/src/components/index.ts +16 -0
  126. package/src/components/input-wrapper/input-wrapper.ts +10 -3
  127. package/dist/calendar-BzEtOJla.js +0 -2031
  128. package/dist/calendar-E5jJLt8D.cjs +0 -90
  129. package/dist/input-wrapper-BRuVELpK.cjs +0 -54
  130. /package/dist/{booleanish-jJLlnr6-.cjs → booleanish-B5EFqFpJ.cjs} +0 -0
  131. /package/dist/{booleanish-BmcOU-43.js → booleanish-CRaKZ75t.js} +0 -0
  132. /package/dist/{consent-DeB_5sWH.js → consent-f_IGyHss.js} +0 -0
  133. /package/dist/{consent-hwu7pp3S.cjs → consent-zh2npq2K.cjs} +0 -0
  134. /package/dist/{dialog-polyfill.esm-1hPr0gl9.js → dialog-polyfill.esm-BmVHGRTX.js} +0 -0
  135. /package/dist/{dialog-polyfill.esm-D3Oinvk0.cjs → dialog-polyfill.esm-CXDsb3l-.cjs} +0 -0
  136. /package/dist/{heading-DiQLPxdf.js → heading-BxvE80bb.js} +0 -0
  137. /package/dist/{heading-BgSWIRii.cjs → heading-DRJTS27k.cjs} +0 -0
  138. /package/dist/{input-wrapper-Dwd-_sKm.cjs → input-wrapper-CYCCx8MP.cjs} +0 -0
  139. /package/dist/{input-wrapper-CDyHTR1V.js → input-wrapper-kw2y6Jp_.js} +0 -0
  140. /package/dist/{link-CyTCpI0k.cjs → link-B8zYc5WK.cjs} +0 -0
  141. /package/dist/{link-CKAFMz9j.js → link-CjJcwcxR.js} +0 -0
  142. /package/dist/{linkcard-BE4-FewK.cjs → linkcard-C4x-NJMi.cjs} +0 -0
  143. /package/dist/{linkcard-B0KOGaGj.js → linkcard-Ddh5R_L-.js} +0 -0
  144. /package/dist/{loader-CX2rsC01.cjs → loader-CGQXAuyM.cjs} +0 -0
  145. /package/dist/{loader-6kFZUErT.js → loader-DeizpX45.js} +0 -0
  146. /package/dist/{messagebox-Din9X53b.cjs → messagebox-Ccu29rDv.cjs} +0 -0
  147. /package/dist/{messagebox-Cwlg5sOr.js → messagebox-DqoPqo4K.js} +0 -0
  148. /package/dist/{pkt-options-controller-CXUGx134.cjs → pkt-options-controller-BPBb_O2K.cjs} +0 -0
  149. /package/dist/{pkt-options-controller-CRrI6WMk.js → pkt-options-controller-DbLrdRwH.js} +0 -0
  150. /package/dist/{repeat-Cepr3469.js → repeat-DV1O43YU.js} +0 -0
  151. /package/dist/{repeat-CqcDYBxr.cjs → repeat-DaDFvx86.cjs} +0 -0
  152. /package/dist/{tabs-Rc9N9HWa.js → tabs-4eWA7CsK.js} +0 -0
  153. /package/dist/{tabs-BfurI6C3.cjs → tabs-RnDtIFv3.cjs} +0 -0
  154. /package/dist/{tag-DLthw5b4.cjs → tag-DWtajZk6.cjs} +0 -0
  155. /package/dist/{tag-VwykmuQR.js → tag-hl59gziI.js} +0 -0
  156. /package/dist/{utils-CUqCKGvp.js → utils-BOOZ0ppt.js} +0 -0
  157. /package/dist/{utils-CjAbIttF.cjs → utils-CM67Oudc.cjs} +0 -0
@@ -0,0 +1,213 @@
1
+ import { html } from 'lit'
2
+
3
+ import type { TFileComment, TQueueItemOperation, TQueueOperationContext } from './fileupload-types'
4
+
5
+ const COMMENTS_ATTRIBUTE = 'comments'
6
+
7
+ const formatTimestamp = (iso: string): string => {
8
+ const date = new Date(iso)
9
+ if (Number.isNaN(date.getTime())) return iso
10
+ const day = String(date.getDate()).padStart(2, '0')
11
+ const month = String(date.getMonth() + 1).padStart(2, '0')
12
+ const year = date.getFullYear()
13
+ const hours = String(date.getHours()).padStart(2, '0')
14
+ const minutes = String(date.getMinutes()).padStart(2, '0')
15
+ return `${day}.${month}.${year} kl. ${hours}:${minutes}`
16
+ }
17
+
18
+ const handleRenameKeydown = (event: KeyboardEvent, save: () => void, cancel: () => void) => {
19
+ if (event.key === 'Enter') {
20
+ event.preventDefault()
21
+ event.stopPropagation()
22
+ save()
23
+ }
24
+ if (event.key === 'Escape') {
25
+ event.preventDefault()
26
+ event.stopPropagation()
27
+ cancel()
28
+ }
29
+ }
30
+
31
+ const handleCommentTextareaKeydown = (event: KeyboardEvent, save: () => void, cancel: () => void) => {
32
+ if (event.key === 'Escape') {
33
+ event.preventDefault()
34
+ event.stopPropagation()
35
+ cancel()
36
+ }
37
+ if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {
38
+ event.preventDefault()
39
+ event.stopPropagation()
40
+ save()
41
+ }
42
+ }
43
+
44
+ export const createRemoveOperation = (removeFile: (fileId: string) => void): TQueueItemOperation => ({
45
+ id: 'remove',
46
+ title: 'Slett',
47
+ ariaLabel: 'Slett fil',
48
+ onClick: ({ file }) => removeFile(file.fileId),
49
+ })
50
+
51
+ export const createRenameOperation = (): TQueueItemOperation => ({
52
+ id: 'rename',
53
+ title: 'Rediger',
54
+ ariaLabel: 'Rediger filnavn',
55
+ renderInlineUI: (context: TQueueOperationContext) => {
56
+ const currentName =
57
+ context.getAttribute<string>('targetFilename') ||
58
+ context.file.attributes?.targetFilename ||
59
+ context.file.file?.name ||
60
+ ''
61
+
62
+ const inputId = `pkt-fileupload-rename-${context.file.fileId}`
63
+ const save = () => {
64
+ const input = document.getElementById(inputId) as HTMLInputElement | null
65
+ const nextName = input?.value?.trim()
66
+ if (nextName) {
67
+ context.setAttribute('targetFilename', nextName)
68
+ }
69
+ context.close()
70
+ }
71
+
72
+ return html`
73
+ <label for=${inputId} class="pkt-sr-only">Endre filnavn</label>
74
+ <input
75
+ id=${inputId}
76
+ type="text"
77
+ class="pkt-fileupload__queue-display__item__rename-input"
78
+ ?disabled=${context.disabled}
79
+ .value=${currentName}
80
+ @keydown=${(event: KeyboardEvent) => handleRenameKeydown(event, save, context.close)}
81
+ />
82
+ <button
83
+ type="button"
84
+ class="pkt-btn pkt-btn--secondary pkt-btn--small"
85
+ ?disabled=${context.disabled}
86
+ @click=${save}
87
+ >
88
+ Lagre
89
+ </button>
90
+ <button
91
+ type="button"
92
+ class="pkt-btn pkt-btn--tertiary pkt-btn--small"
93
+ ?disabled=${context.disabled}
94
+ @click=${context.close}
95
+ >
96
+ Avbryt
97
+ </button>
98
+ `
99
+ },
100
+ renderHidden: (context: TQueueOperationContext) => {
101
+ const targetFilename =
102
+ context.getAttribute<string>('targetFilename') ||
103
+ context.file.attributes?.targetFilename ||
104
+ context.file.file?.name ||
105
+ ''
106
+ return html`<input
107
+ type="hidden"
108
+ name=${`${context.inputName}-targetFilename`}
109
+ value=${targetFilename}
110
+ />`
111
+ },
112
+ })
113
+
114
+ export const createCommentOperation = (): TQueueItemOperation => ({
115
+ id: 'comment',
116
+ title: (file) => {
117
+ const comments = (file.attributes?.[COMMENTS_ATTRIBUTE] as TFileComment[] | undefined) ?? []
118
+ return comments.length > 0 ? '' : 'Legg til kommentar'
119
+ },
120
+ ariaLabel: 'Legg til kommentar',
121
+ renderExtendedUI: (context: TQueueOperationContext) => {
122
+ const comments = context.getAttribute<TFileComment[]>(COMMENTS_ATTRIBUTE) ?? []
123
+ const existingComment = comments[0]
124
+ const textareaId = `pkt-fileupload-comment-${context.file.fileId}`
125
+ const save = () => {
126
+ const textarea = document.getElementById(textareaId) as HTMLTextAreaElement | null
127
+ const text = textarea?.value?.trim()
128
+ if (text) {
129
+ context.setAttribute(COMMENTS_ATTRIBUTE, [{ text, timestamp: new Date().toISOString() } satisfies TFileComment])
130
+ }
131
+ context.close()
132
+ }
133
+
134
+ return html`
135
+ <label for=${textareaId} class="pkt-fileupload__queue-display__item__comment-label">
136
+ ${existingComment ? 'Rediger kommentar' : 'Legg til kommentar'}
137
+ </label>
138
+ <textarea
139
+ id=${textareaId}
140
+ class="pkt-fileupload__queue-display__item__comment-input"
141
+ ?disabled=${context.disabled}
142
+ .value=${existingComment?.text ?? ''}
143
+ rows="2"
144
+ placeholder="Skriv inn kommentar"
145
+ @keydown=${(event: KeyboardEvent) => handleCommentTextareaKeydown(event, save, context.close)}
146
+ ></textarea>
147
+ <button
148
+ type="button"
149
+ class="pkt-btn pkt-btn--secondary pkt-btn--small"
150
+ ?disabled=${context.disabled}
151
+ @click=${save}
152
+ >
153
+ ${existingComment ? 'Lagre kommentar' : 'Legg til kommentar'}
154
+ </button>
155
+ <button
156
+ type="button"
157
+ class="pkt-btn pkt-btn--tertiary pkt-btn--small"
158
+ ?disabled=${context.disabled}
159
+ @click=${context.close}
160
+ >
161
+ Avbryt
162
+ </button>
163
+ `
164
+ },
165
+ renderContent: (context: TQueueOperationContext) => {
166
+ if (context.isActive) return null
167
+ const comments = context.getAttribute<TFileComment[]>(COMMENTS_ATTRIBUTE) ?? []
168
+ if (comments.length === 0) return null
169
+ const comment = comments[0]
170
+ return html`
171
+ <div class="pkt-fileupload__queue-display__item__comments">
172
+ <div class="pkt-fileupload__queue-display__item__comment">
173
+ <div class="pkt-fileupload__queue-display__item__comment__content">
174
+ <span class="pkt-fileupload__queue-display__item__comment__text" aria-label="Kommentar tekst">
175
+ ${comment.text}
176
+ </span>
177
+ <time class="pkt-fileupload__queue-display__item__comment__time">
178
+ ${formatTimestamp(comment.timestamp)}
179
+ </time>
180
+ </div>
181
+ <div class="pkt-fileupload__queue-display__item__comment__actions">
182
+ <button
183
+ type="button"
184
+ class="pkt-fileupload__queue-display__item__comment__action"
185
+ aria-label="Rediger kommentar"
186
+ ?disabled=${context.disabled}
187
+ @click=${context.activate}
188
+ >
189
+ <pkt-icon name="edit"></pkt-icon>
190
+ </button>
191
+ <button
192
+ type="button"
193
+ class="pkt-fileupload__queue-display__item__comment__action"
194
+ aria-label="Slett kommentar"
195
+ ?disabled=${context.disabled}
196
+ @click=${() => context.setAttribute(COMMENTS_ATTRIBUTE, undefined)}
197
+ >
198
+ <pkt-icon name="trash-can"></pkt-icon>
199
+ </button>
200
+ </div>
201
+ </div>
202
+ </div>
203
+ `
204
+ },
205
+ renderHidden: (context: TQueueOperationContext) => {
206
+ const comments = context.getAttribute<TFileComment[]>(COMMENTS_ATTRIBUTE)
207
+ return html`<input
208
+ type="hidden"
209
+ name=${`${context.inputName}-comments`}
210
+ value=${comments ? JSON.stringify(comments) : ''}
211
+ />`
212
+ },
213
+ })