@limetech/lime-elements 39.0.4 → 39.1.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 (253) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/index-nxo2UO7I.js +20355 -0
  3. package/dist/cjs/lime-elements.cjs.js +1 -1
  4. package/dist/cjs/limel-action-bar_2.cjs.entry.js +4 -4
  5. package/dist/cjs/limel-ai-avatar.cjs.entry.js +1 -1
  6. package/dist/cjs/limel-breadcrumbs_7.cjs.entry.js +6 -6
  7. package/dist/cjs/limel-callout.cjs.entry.js +1 -1
  8. package/dist/cjs/limel-chart.cjs.entry.js +1 -1
  9. package/dist/cjs/limel-chip_2.cjs.entry.js +1 -1
  10. package/dist/cjs/limel-code-editor.cjs.entry.js +1 -1
  11. package/dist/cjs/limel-collapsible-section.cjs.entry.js +1 -1
  12. package/dist/cjs/limel-drag-handle.cjs.entry.js +1 -1
  13. package/dist/cjs/limel-email-viewer.cjs.entry.js +351 -0
  14. package/dist/cjs/limel-file-dropzone_2.cjs.entry.js +2 -2
  15. package/dist/cjs/limel-file-viewer.cjs.entry.js +4967 -26
  16. package/dist/cjs/limel-file.cjs.entry.js +2 -2
  17. package/dist/cjs/limel-flatpickr-adapter.cjs.entry.js +1 -1
  18. package/dist/cjs/limel-flex-container.cjs.entry.js +1 -1
  19. package/dist/cjs/limel-form.cjs.entry.js +1 -1
  20. package/dist/cjs/limel-grid.cjs.entry.js +1 -1
  21. package/dist/cjs/limel-header.cjs.entry.js +1 -1
  22. package/dist/cjs/limel-help-content.cjs.entry.js +1 -1
  23. package/dist/cjs/limel-help.cjs.entry.js +2 -2
  24. package/dist/cjs/limel-helper-line_2.cjs.entry.js +3 -3
  25. package/dist/cjs/limel-icon-button.cjs.entry.js +1 -1
  26. package/dist/cjs/limel-icon.cjs.entry.js +1 -1
  27. package/dist/cjs/limel-info-tile.cjs.entry.js +2 -2
  28. package/dist/cjs/limel-linear-progress.cjs.entry.js +1 -1
  29. package/dist/cjs/limel-list-item.cjs.entry.js +3 -3
  30. package/dist/cjs/limel-markdown.cjs.entry.js +3 -2
  31. package/dist/cjs/limel-menu-item-meta.cjs.entry.js +1 -1
  32. package/dist/cjs/limel-picker.cjs.entry.js +1 -1
  33. package/dist/cjs/limel-popover_2.cjs.entry.js +2 -2
  34. package/dist/cjs/limel-portal_3.cjs.entry.js +4 -4
  35. package/dist/cjs/limel-profile-picture.cjs.entry.js +1 -1
  36. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +15 -14
  37. package/dist/cjs/limel-radio-button-group.cjs.entry.js +1 -1
  38. package/dist/cjs/limel-radio-button.cjs.entry.js +2 -2
  39. package/dist/cjs/limel-select.cjs.entry.js +1 -1
  40. package/dist/cjs/limel-shortcut.cjs.entry.js +1 -1
  41. package/dist/cjs/limel-slider.cjs.entry.js +1 -1
  42. package/dist/cjs/limel-snackbar.cjs.entry.js +3 -3
  43. package/dist/cjs/limel-split-button.cjs.entry.js +2 -2
  44. package/dist/cjs/limel-tab-bar.cjs.entry.js +2 -2
  45. package/dist/cjs/limel-tab-panel.cjs.entry.js +1 -1
  46. package/dist/cjs/limel-table.cjs.entry.js +4 -4
  47. package/dist/cjs/limel-text-editor.cjs.entry.js +1 -1
  48. package/dist/cjs/loader.cjs.js +1 -1
  49. package/dist/cjs/{markdown-parser-_1bsy-5h.js → markdown-parser-B66l_Zvo.js} +20342 -40680
  50. package/dist/cjs/{translations-BIHr3B9O.js → translations-B0hzD08N.js} +112 -0
  51. package/dist/collection/collection-manifest.json +1 -0
  52. package/dist/collection/components/email-viewer/email-loader.js +206 -0
  53. package/dist/collection/components/email-viewer/email-viewer.css +293 -0
  54. package/dist/collection/components/email-viewer/email-viewer.js +294 -0
  55. package/dist/collection/components/email-viewer/email-viewer.types.js +1 -0
  56. package/dist/collection/components/email-viewer/remote-images.js +50 -0
  57. package/dist/collection/components/email-viewer/sanitize-email-html.js +245 -0
  58. package/dist/collection/components/email-viewer/split-email-address-list.js +106 -0
  59. package/dist/collection/components/file/file.js +1 -1
  60. package/dist/collection/components/file-dropzone/file-dropzone.js +1 -1
  61. package/dist/collection/components/file-input/file-input.js +1 -1
  62. package/dist/collection/components/file-viewer/extension-mapping.js +1 -0
  63. package/dist/collection/components/file-viewer/file-viewer.js +54 -7
  64. package/dist/collection/components/flex-container/flex-container.js +1 -1
  65. package/dist/collection/components/form/form.js +1 -1
  66. package/dist/collection/components/grid/grid.js +1 -1
  67. package/dist/collection/components/header/header.js +1 -1
  68. package/dist/collection/components/help/help-content.js +1 -1
  69. package/dist/collection/components/help/help.js +2 -2
  70. package/dist/collection/components/helper-line/helper-line.js +2 -2
  71. package/dist/collection/components/icon/icon.js +1 -1
  72. package/dist/collection/components/icon-button/icon-button.js +1 -1
  73. package/dist/collection/components/info-tile/info-tile.js +2 -2
  74. package/dist/collection/components/input-field/input-field.js +1 -1
  75. package/dist/collection/components/list/list.js +1 -1
  76. package/dist/collection/components/list-item/list-item.js +2 -2
  77. package/dist/collection/components/list-item/menu-item-meta/menu-item-meta.js +1 -1
  78. package/dist/collection/components/markdown/markdown.js +1 -1
  79. package/dist/collection/components/menu/menu.js +1 -1
  80. package/dist/collection/components/menu-list/menu-list.js +1 -1
  81. package/dist/collection/components/menu-surface/menu-surface.js +1 -1
  82. package/dist/collection/components/notched-outline/notched-outline.js +1 -1
  83. package/dist/collection/components/picker/picker.js +1 -1
  84. package/dist/collection/components/popover/popover.js +1 -1
  85. package/dist/collection/components/popover-surface/popover-surface.js +1 -1
  86. package/dist/collection/components/portal/portal.js +1 -1
  87. package/dist/collection/components/radio-button-group/radio-button-group.js +1 -1
  88. package/dist/collection/components/radio-button-group/radio-button.js +2 -2
  89. package/dist/collection/components/select/select.js +1 -1
  90. package/dist/collection/components/shortcut/shortcut.js +1 -1
  91. package/dist/collection/components/slider/slider.js +1 -1
  92. package/dist/collection/components/snackbar/snackbar.js +2 -2
  93. package/dist/collection/components/spinner/spinner.js +1 -1
  94. package/dist/collection/components/split-button/split-button.js +2 -2
  95. package/dist/collection/components/tab-bar/tab-bar.js +2 -2
  96. package/dist/collection/components/tab-panel/tab-panel.js +1 -1
  97. package/dist/collection/components/table/table.js +3 -3
  98. package/dist/collection/components/text-editor/link-menu/editor-link-menu.js +3 -3
  99. package/dist/collection/components/text-editor/prosemirror-adapter/prosemirror-adapter.js +1 -1
  100. package/dist/collection/components/text-editor/text-editor.js +1 -1
  101. package/dist/collection/components/tooltip/tooltip-content.js +1 -1
  102. package/dist/collection/components/tooltip/tooltip.js +2 -2
  103. package/dist/collection/interface.js +1 -0
  104. package/dist/collection/translations/da.js +14 -0
  105. package/dist/collection/translations/de.js +14 -0
  106. package/dist/collection/translations/en.js +14 -0
  107. package/dist/collection/translations/fi.js +14 -0
  108. package/dist/collection/translations/fr.js +14 -0
  109. package/dist/collection/translations/nl.js +14 -0
  110. package/dist/collection/translations/no.js +14 -0
  111. package/dist/collection/translations/sv.js +14 -0
  112. package/dist/collection/util/format-bytes.js +38 -0
  113. package/dist/esm/{file-metadata-D5joHaqk.js → file-metadata-BwF9vTXN.js} +1 -1
  114. package/dist/esm/{files-CkgibGPZ.js → files-P324wLau.js} +1 -1
  115. package/dist/esm/{get-icon-props-COzG_Mhw.js → get-icon-props-CgNJbSP4.js} +1 -1
  116. package/dist/esm/index-CJ0GYrWG.js +20341 -0
  117. package/dist/esm/lime-elements.js +1 -1
  118. package/dist/esm/limel-action-bar-item_2.entry.js +1 -1
  119. package/dist/esm/limel-action-bar_2.entry.js +4 -4
  120. package/dist/esm/limel-ai-avatar.entry.js +1 -1
  121. package/dist/esm/limel-breadcrumbs_7.entry.js +7 -7
  122. package/dist/esm/limel-button.entry.js +1 -1
  123. package/dist/esm/limel-callout.entry.js +1 -1
  124. package/dist/esm/limel-card.entry.js +1 -1
  125. package/dist/esm/limel-chart.entry.js +1 -1
  126. package/dist/esm/limel-chip_2.entry.js +2 -2
  127. package/dist/esm/limel-code-editor.entry.js +1 -1
  128. package/dist/esm/limel-collapsible-section.entry.js +2 -2
  129. package/dist/esm/limel-drag-handle.entry.js +1 -1
  130. package/dist/esm/limel-dynamic-label.entry.js +1 -1
  131. package/dist/esm/limel-email-viewer.entry.js +349 -0
  132. package/dist/esm/limel-file-dropzone_2.entry.js +5 -5
  133. package/dist/esm/limel-file-viewer.entry.js +4948 -7
  134. package/dist/esm/limel-file.entry.js +4 -4
  135. package/dist/esm/limel-flatpickr-adapter.entry.js +1 -1
  136. package/dist/esm/limel-flex-container.entry.js +1 -1
  137. package/dist/esm/limel-form.entry.js +1 -1
  138. package/dist/esm/limel-grid.entry.js +1 -1
  139. package/dist/esm/limel-header.entry.js +2 -2
  140. package/dist/esm/limel-help-content.entry.js +1 -1
  141. package/dist/esm/limel-help.entry.js +2 -2
  142. package/dist/esm/limel-helper-line_2.entry.js +3 -3
  143. package/dist/esm/limel-icon-button.entry.js +2 -2
  144. package/dist/esm/limel-icon.entry.js +1 -1
  145. package/dist/esm/limel-info-tile.entry.js +2 -2
  146. package/dist/esm/limel-linear-progress.entry.js +1 -1
  147. package/dist/esm/limel-list-item.entry.js +4 -4
  148. package/dist/esm/limel-markdown.entry.js +3 -2
  149. package/dist/esm/limel-menu-item-meta.entry.js +1 -1
  150. package/dist/esm/limel-picker.entry.js +2 -2
  151. package/dist/esm/limel-popover_2.entry.js +2 -2
  152. package/dist/esm/limel-portal_3.entry.js +4 -4
  153. package/dist/esm/limel-profile-picture.entry.js +4 -4
  154. package/dist/esm/limel-progress-flow-item.entry.js +1 -1
  155. package/dist/esm/limel-progress-flow.entry.js +1 -1
  156. package/dist/esm/limel-prosemirror-adapter.entry.js +7 -6
  157. package/dist/esm/limel-radio-button-group.entry.js +1 -1
  158. package/dist/esm/limel-radio-button.entry.js +2 -2
  159. package/dist/esm/limel-select.entry.js +2 -2
  160. package/dist/esm/limel-shortcut.entry.js +1 -1
  161. package/dist/esm/limel-slider.entry.js +1 -1
  162. package/dist/esm/limel-snackbar.entry.js +3 -3
  163. package/dist/esm/limel-split-button.entry.js +2 -2
  164. package/dist/esm/limel-tab-bar.entry.js +3 -3
  165. package/dist/esm/limel-tab-panel.entry.js +1 -1
  166. package/dist/esm/limel-table.entry.js +4 -4
  167. package/dist/esm/limel-text-editor.entry.js +1 -1
  168. package/dist/esm/loader.js +1 -1
  169. package/dist/esm/{markdown-parser-DkmQCwAi.js → markdown-parser-DJi1w622.js} +20287 -40624
  170. package/dist/esm/{translations-6rJPElLH.js → translations-Cdx3I2X8.js} +112 -0
  171. package/dist/lime-elements/lime-elements.esm.js +1 -1
  172. package/dist/lime-elements/{p-927622ec.entry.js → p-00fdb26c.entry.js} +1 -1
  173. package/dist/lime-elements/{p-880b9683.entry.js → p-1244d687.entry.js} +2 -2
  174. package/dist/lime-elements/p-1d71e9c8.entry.js +1 -0
  175. package/dist/lime-elements/p-21aef7f4.entry.js +1 -0
  176. package/dist/lime-elements/{p-68f49d6f.entry.js → p-278356b3.entry.js} +1 -1
  177. package/dist/lime-elements/{p-a6fae24d.entry.js → p-28dae22e.entry.js} +1 -1
  178. package/dist/lime-elements/{p-6951136b.entry.js → p-2d31cf0d.entry.js} +1 -1
  179. package/dist/lime-elements/{p-6e3666e5.entry.js → p-2ef38dac.entry.js} +1 -1
  180. package/dist/lime-elements/{p-dd36d57b.entry.js → p-2f788e92.entry.js} +7 -7
  181. package/dist/lime-elements/p-2kcqdtMr.js +1 -0
  182. package/dist/lime-elements/{p-11f716f5.entry.js → p-3000785f.entry.js} +1 -1
  183. package/dist/lime-elements/{p-2a5b259e.entry.js → p-3130d348.entry.js} +1 -1
  184. package/dist/lime-elements/{p-feeae1e4.entry.js → p-38097fa1.entry.js} +1 -1
  185. package/dist/lime-elements/p-3b299849.entry.js +1 -0
  186. package/dist/lime-elements/{p-00859fac.entry.js → p-3e6ce4e1.entry.js} +2 -2
  187. package/dist/lime-elements/{p-23f7956e.entry.js → p-3ec31835.entry.js} +1 -1
  188. package/dist/lime-elements/{p-52edfe86.entry.js → p-44396c0d.entry.js} +1 -1
  189. package/dist/lime-elements/{p-ec42a4aa.entry.js → p-494f880b.entry.js} +1 -1
  190. package/dist/lime-elements/{p-d1fa6da3.entry.js → p-4f6e3057.entry.js} +3 -3
  191. package/dist/lime-elements/{p-e6d74062.entry.js → p-504ae59f.entry.js} +1 -1
  192. package/dist/lime-elements/{p-7d5bd4a2.entry.js → p-51565372.entry.js} +1 -1
  193. package/dist/lime-elements/{p-5ddeb498.entry.js → p-52098c47.entry.js} +1 -1
  194. package/dist/lime-elements/{p-d2123236.entry.js → p-521a0204.entry.js} +1 -1
  195. package/dist/lime-elements/{p-38fb97fe.entry.js → p-54d85ae4.entry.js} +1 -1
  196. package/dist/lime-elements/{p-88f503eb.entry.js → p-59a522ee.entry.js} +1 -1
  197. package/dist/lime-elements/{p-2c1538f0.entry.js → p-5af72e1b.entry.js} +1 -1
  198. package/dist/lime-elements/p-64cc5094.entry.js +1 -0
  199. package/dist/lime-elements/{p-045c6027.entry.js → p-67a2c7f5.entry.js} +1 -1
  200. package/dist/lime-elements/{p-8db6b7d9.entry.js → p-68b1605f.entry.js} +1 -1
  201. package/dist/lime-elements/{p-7457bc07.entry.js → p-770981e6.entry.js} +1 -1
  202. package/dist/lime-elements/{p-9ea564fe.entry.js → p-7ed97446.entry.js} +1 -1
  203. package/dist/lime-elements/{p-cbb7d624.entry.js → p-8053727c.entry.js} +1 -1
  204. package/dist/lime-elements/{p-fc3209db.entry.js → p-80f9f2d3.entry.js} +1 -1
  205. package/dist/lime-elements/{p-34ef71f2.entry.js → p-95fb9ef8.entry.js} +1 -1
  206. package/dist/lime-elements/{p-6275668f.entry.js → p-961dff13.entry.js} +1 -1
  207. package/dist/lime-elements/{p-abef62d7.entry.js → p-97952658.entry.js} +1 -1
  208. package/dist/lime-elements/{p-d6270e4a.entry.js → p-982b9f50.entry.js} +1 -1
  209. package/dist/lime-elements/p-9c4156c6.entry.js +1 -0
  210. package/dist/lime-elements/p-BRCcjfVu.js +7 -0
  211. package/dist/lime-elements/{p-DSjFzQmB.js → p-CWuGCKo1.js} +1 -1
  212. package/dist/lime-elements/p-Cdx3I2X8.js +1 -0
  213. package/dist/lime-elements/{p-COzG_Mhw.js → p-CgNJbSP4.js} +1 -1
  214. package/dist/lime-elements/{p-BQY2kAWs.js → p-DlJXKdhK.js} +1 -1
  215. package/dist/lime-elements/{p-bbaf35ce.entry.js → p-a9f3f90c.entry.js} +1 -1
  216. package/dist/lime-elements/{p-c9e934af.entry.js → p-af5f2052.entry.js} +1 -1
  217. package/dist/lime-elements/{p-f9480c52.entry.js → p-c2478225.entry.js} +1 -1
  218. package/dist/lime-elements/{p-6aebcf60.entry.js → p-c7f2e189.entry.js} +1 -1
  219. package/dist/lime-elements/{p-d424688d.entry.js → p-cb2cc243.entry.js} +1 -1
  220. package/dist/lime-elements/{p-c118eac0.entry.js → p-cce53162.entry.js} +1 -1
  221. package/dist/lime-elements/{p-6896d5c8.entry.js → p-d4fea438.entry.js} +1 -1
  222. package/dist/lime-elements/{p-534fdf9b.entry.js → p-df1fa930.entry.js} +1 -1
  223. package/dist/lime-elements/{p-52bb74b9.entry.js → p-e05ad4f8.entry.js} +1 -1
  224. package/dist/lime-elements/{p-303d01e5.entry.js → p-e6b0e0a2.entry.js} +1 -1
  225. package/dist/lime-elements/{p-80d35f8f.entry.js → p-e975cc29.entry.js} +1 -1
  226. package/dist/lime-elements/{p-9ed578ec.entry.js → p-f532b60f.entry.js} +1 -1
  227. package/dist/lime-elements/{p-4be18a57.entry.js → p-ff845f5c.entry.js} +1 -1
  228. package/dist/types/components/email-viewer/email-loader.d.ts +19 -0
  229. package/dist/types/components/email-viewer/email-viewer.d.ts +69 -0
  230. package/dist/types/components/email-viewer/email-viewer.types.d.ts +70 -0
  231. package/dist/types/components/email-viewer/remote-images.d.ts +22 -0
  232. package/dist/types/components/email-viewer/sanitize-email-html.d.ts +14 -0
  233. package/dist/types/components/email-viewer/split-email-address-list.d.ts +25 -0
  234. package/dist/types/components/file-viewer/file-viewer.d.ts +9 -0
  235. package/dist/types/components/file-viewer/file-viewer.types.d.ts +1 -1
  236. package/dist/types/components.d.ts +116 -0
  237. package/dist/types/interface.d.ts +1 -0
  238. package/dist/types/translations/da.d.ts +10 -0
  239. package/dist/types/translations/de.d.ts +10 -0
  240. package/dist/types/translations/en.d.ts +10 -0
  241. package/dist/types/translations/fi.d.ts +10 -0
  242. package/dist/types/translations/fr.d.ts +10 -0
  243. package/dist/types/translations/nl.d.ts +10 -0
  244. package/dist/types/translations/no.d.ts +10 -0
  245. package/dist/types/translations/sv.d.ts +10 -0
  246. package/dist/types/util/format-bytes.d.ts +21 -0
  247. package/package.json +4 -5
  248. package/dist/lime-elements/p-017dd326.entry.js +0 -1
  249. package/dist/lime-elements/p-4beeec39.entry.js +0 -1
  250. package/dist/lime-elements/p-55596d9a.entry.js +0 -1
  251. package/dist/lime-elements/p-6rJPElLH.js +0 -1
  252. package/dist/lime-elements/p-Df0HAtSs.js +0 -7
  253. package/dist/lime-elements/p-f395fbe3.entry.js +0 -1
@@ -40,6 +40,20 @@ var da = {
40
40
  'file-viewer.open-in-fullscreen': 'Åbn i fuld skærm',
41
41
  'file-viewer.open-in-new-tab': 'Åbn i en ny fane',
42
42
  'file-viewer.more-actions': 'Mere…',
43
+ 'file-viewer.email.subject': 'Emne',
44
+ 'file-viewer.email.from': 'Fra',
45
+ 'file-viewer.email.to': 'Til',
46
+ 'file-viewer.email.cc': 'Kopi',
47
+ 'file-viewer.email.date': 'Dato',
48
+ 'file-viewer.email.attachments': 'Vedhæftninger',
49
+ 'file-viewer.email.attachment.unnamed': 'Vedhæftning uden navn',
50
+ 'file-viewer.email.remote-images.warning': 'Billeder indlæses ikke for at beskytte dit privatliv.',
51
+ 'file-viewer.email.remote-images.warning.description': `Mange e-mails indeholder billeder, der hostes på eksterne servere.
52
+ Når billeder indlæses, anmoder din enhed dem fra afsenderens server.
53
+ Det kan afsløre for afsenderen, at du har åbnet beskeden, hvornår du åbnede den, samt metadata såsom din IP-adresse og oplysninger om enhed/browser.
54
+
55
+ Du kan fortsætte med at blokere billeder (e-mailen kan se ufuldstændig ud) eller indlæse dem, hvis du stoler på afsenderen.`,
56
+ 'file-viewer.email.remote-images.load': 'Indlæs billeder',
43
57
  'editor-menu.bold': 'Fed',
44
58
  'editor-menu.italic': 'Kursiv',
45
59
  'editor-menu.strikethrough': 'Gennemstreget',
@@ -108,6 +122,20 @@ var de = {
108
122
  'file-viewer.open-in-fullscreen': 'Im Vollbildmodus öffnen',
109
123
  'file-viewer.open-in-new-tab': 'In einem neuen Tab öffnen',
110
124
  'file-viewer.more-actions': 'Mehr…',
125
+ 'file-viewer.email.subject': 'Betreff',
126
+ 'file-viewer.email.from': 'Von',
127
+ 'file-viewer.email.to': 'An',
128
+ 'file-viewer.email.cc': 'Cc',
129
+ 'file-viewer.email.date': 'Datum',
130
+ 'file-viewer.email.attachments': 'Anhänge',
131
+ 'file-viewer.email.attachment.unnamed': 'Unbenannter Anhang',
132
+ 'file-viewer.email.remote-images.warning': 'Bilder werden nicht geladen, um Ihre Privatsphäre zu schützen.',
133
+ 'file-viewer.email.remote-images.warning.description': `Viele E-Mails enthalten Bilder, die auf externen Servern gehostet werden.
134
+ Wenn Bilder geladen werden, fordert Ihr Gerät sie vom Server des Absenders an.
135
+ Dadurch kann der Absender erfahren, dass Sie die Nachricht geöffnet haben, wann Sie sie geöffnet haben, sowie Metadaten wie Ihre IP-Adresse und Informationen zu Gerät/Browser.
136
+
137
+ Sie können Bilder weiterhin blockieren (die E-Mail kann unvollständig aussehen) oder sie laden, wenn Sie dem Absender vertrauen.`,
138
+ 'file-viewer.email.remote-images.load': 'Bilder laden',
111
139
  'editor-menu.bold': 'Fett',
112
140
  'editor-menu.italic': 'Kursiv',
113
141
  'editor-menu.strikethrough': 'Durchgestrichen',
@@ -176,6 +204,20 @@ var en = {
176
204
  'file-viewer.open-in-fullscreen': 'Open in fullscreen',
177
205
  'file-viewer.open-in-new-tab': 'Open in a new tab',
178
206
  'file-viewer.more-actions': 'More…',
207
+ 'file-viewer.email.subject': 'Subject',
208
+ 'file-viewer.email.from': 'From',
209
+ 'file-viewer.email.to': 'To',
210
+ 'file-viewer.email.cc': 'Cc',
211
+ 'file-viewer.email.date': 'Date',
212
+ 'file-viewer.email.attachments': 'Attachments',
213
+ 'file-viewer.email.attachment.unnamed': 'Unnamed attachment',
214
+ 'file-viewer.email.remote-images.warning': "Images aren't loaded to protect your privacy.",
215
+ 'file-viewer.email.remote-images.warning.description': `Many emails include images hosted on external servers.
216
+ When images are loaded, your device requests them from the sender’s server.
217
+ This may reveal to the sender that you opened the message, when you opened it, and metadata such as your IP address and device/browser information.
218
+
219
+ You can keep images blocked (the email may look incomplete), or load them if you trust the sender.`,
220
+ 'file-viewer.email.remote-images.load': 'Load images',
179
221
  'editor-menu.bold': 'Bold',
180
222
  'editor-menu.italic': 'Italic',
181
223
  'editor-menu.strikethrough': 'Strikethrough',
@@ -244,6 +286,20 @@ var fi = {
244
286
  'file-viewer.open-in-fullscreen': 'Avaa koko näytössä',
245
287
  'file-viewer.open-in-new-tab': 'Avaa uudella välilehdellä',
246
288
  'file-viewer.more-actions': 'Lisää…',
289
+ 'file-viewer.email.subject': 'Aihe',
290
+ 'file-viewer.email.from': 'Lähettäjä',
291
+ 'file-viewer.email.to': 'Vastaanottaja',
292
+ 'file-viewer.email.cc': 'Kopio',
293
+ 'file-viewer.email.date': 'Päiväys',
294
+ 'file-viewer.email.attachments': 'Liitteet',
295
+ 'file-viewer.email.attachment.unnamed': 'Nimetön liite',
296
+ 'file-viewer.email.remote-images.warning': 'Kuvia ei ladata yksityisyytesi suojaamiseksi.',
297
+ 'file-viewer.email.remote-images.warning.description': `Monet sähköpostit sisältävät kuvia, jotka sijaitsevat ulkoisilla palvelimilla.
298
+ Kun kuvat ladataan, laitteesi pyytää ne lähettäjän palvelimelta.
299
+ Tämä voi paljastaa lähettäjälle, että avasit viestin, milloin avasit sen, sekä metatietoja, kuten IP-osoitteesi ja tiedot laitteesta/selaimesta.
300
+
301
+ Voit pitää kuvat estettyinä (sähköposti voi näyttää puutteelliselta) tai ladata ne, jos luotat lähettäjään.`,
302
+ 'file-viewer.email.remote-images.load': 'Lataa kuvat',
247
303
  'editor-menu.bold': 'Lihavoitu',
248
304
  'editor-menu.italic': 'Kursivoitu',
249
305
  'editor-menu.strikethrough': 'Yliviivaus',
@@ -312,6 +368,20 @@ var fr = {
312
368
  'file-viewer.open-in-fullscreen': 'Ouvrir en plein écran',
313
369
  'file-viewer.open-in-new-tab': 'Ouvrir dans un nouvel onglet',
314
370
  'file-viewer.more-actions': 'Plus…',
371
+ 'file-viewer.email.subject': 'Objet',
372
+ 'file-viewer.email.from': 'De',
373
+ 'file-viewer.email.to': 'À',
374
+ 'file-viewer.email.cc': 'Cc',
375
+ 'file-viewer.email.date': 'Date',
376
+ 'file-viewer.email.attachments': 'Pièces jointes',
377
+ 'file-viewer.email.attachment.unnamed': 'Pièce jointe sans nom',
378
+ 'file-viewer.email.remote-images.warning': 'Les images ne sont pas chargées afin de protéger votre vie privée.',
379
+ 'file-viewer.email.remote-images.warning.description': `De nombreux e-mails contiennent des images hébergées sur des serveurs externes.
380
+ Lorsque les images sont chargées, votre appareil les demande au serveur de l’expéditeur.
381
+ Cela peut révéler à l’expéditeur que vous avez ouvert le message, quand vous l’avez ouvert, ainsi que des métadonnées telles que votre adresse IP et des informations sur votre appareil/navigateur.
382
+
383
+ Vous pouvez laisser les images bloquées (l’e-mail peut sembler incomplet) ou les charger si vous faites confiance à l’expéditeur.`,
384
+ 'file-viewer.email.remote-images.load': 'Charger les images',
315
385
  'editor-menu.bold': 'Gras',
316
386
  'editor-menu.italic': 'Italique',
317
387
  'editor-menu.strikethrough': 'Barré',
@@ -380,6 +450,20 @@ var nl = {
380
450
  'file-viewer.open-in-fullscreen': 'Open in volledig scherm',
381
451
  'file-viewer.open-in-new-tab': 'Openen op een nieuw tabblad',
382
452
  'file-viewer.more-actions': 'Meer…',
453
+ 'file-viewer.email.subject': 'Onderwerp',
454
+ 'file-viewer.email.from': 'Van',
455
+ 'file-viewer.email.to': 'Aan',
456
+ 'file-viewer.email.cc': 'Cc',
457
+ 'file-viewer.email.date': 'Datum',
458
+ 'file-viewer.email.attachments': 'Bijlagen',
459
+ 'file-viewer.email.attachment.unnamed': 'Bijlage zonder naam',
460
+ 'file-viewer.email.remote-images.warning': 'Afbeeldingen worden niet geladen om je privacy te beschermen.',
461
+ 'file-viewer.email.remote-images.warning.description': `Veel e-mails bevatten afbeeldingen die op externe servers worden gehost.
462
+ Wanneer afbeeldingen worden geladen, vraagt je apparaat ze op bij de server van de afzender.
463
+ Dit kan aan de afzender onthullen dat je het bericht hebt geopend, wanneer je het hebt geopend, en metadata zoals je IP-adres en informatie over apparaat/browser.
464
+
465
+ Je kunt afbeeldingen geblokkeerd houden (de e-mail kan er onvolledig uitzien) of ze laden als je de afzender vertrouwt.`,
466
+ 'file-viewer.email.remote-images.load': 'Afbeeldingen laden',
383
467
  'editor-menu.bold': 'Vet',
384
468
  'editor-menu.italic': 'Cursief',
385
469
  'editor-menu.strikethrough': 'Doorhalen',
@@ -447,6 +531,20 @@ var no = {
447
531
  'file-viewer.open-in-fullscreen': 'Åpne i fullskjerm',
448
532
  'file-viewer.open-in-new-tab': 'Åpne i en ny fane',
449
533
  'file-viewer.more-actions': 'Mer…',
534
+ 'file-viewer.email.subject': 'Emne',
535
+ 'file-viewer.email.from': 'Fra',
536
+ 'file-viewer.email.to': 'Til',
537
+ 'file-viewer.email.cc': 'Kopi',
538
+ 'file-viewer.email.date': 'Dato',
539
+ 'file-viewer.email.attachments': 'Vedlegg',
540
+ 'file-viewer.email.attachment.unnamed': 'Vedlegg uten navn',
541
+ 'file-viewer.email.remote-images.warning': 'Bilder lastes ikke inn for å beskytte personvernet ditt.',
542
+ 'file-viewer.email.remote-images.warning.description': `Mange e-poster inneholder bilder som ligger på eksterne servere.
543
+ Når bilder lastes inn, henter enheten din dem fra avsenderens server.
544
+ Dette kan avsløre for avsenderen at du åpnet meldingen, når du åpnet den, og metadata som IP-adressen din og informasjon om enhet/nettleser.
545
+
546
+ Du kan fortsette å blokkere bilder (e-posten kan se ufullstendig ut), eller laste dem inn hvis du stoler på avsenderen.`,
547
+ 'file-viewer.email.remote-images.load': 'Last inn bilder',
450
548
  'editor-menu.bold': 'Fet',
451
549
  'editor-menu.italic': 'Kursiv',
452
550
  'editor-menu.strikethrough': 'Gjennomstreking',
@@ -516,6 +614,20 @@ var sv = {
516
614
  'file-viewer.open-in-fullscreen': 'Öppna i fullskärmsläge',
517
615
  'file-viewer.open-in-new-tab': 'Öppna i ny flik',
518
616
  'file-viewer.more-actions': 'Mer…',
617
+ 'file-viewer.email.subject': 'Ämne',
618
+ 'file-viewer.email.from': 'Från',
619
+ 'file-viewer.email.to': 'Till',
620
+ 'file-viewer.email.cc': 'Kopia',
621
+ 'file-viewer.email.date': 'Datum',
622
+ 'file-viewer.email.attachments': 'Bilagor',
623
+ 'file-viewer.email.attachment.unnamed': 'Namnlös bilaga',
624
+ 'file-viewer.email.remote-images.warning': 'Bilder laddas inte för att skydda din integritet.',
625
+ 'file-viewer.email.remote-images.warning.description': `Många e-postmeddelanden innehåller bilder som finns på externa servrar.
626
+ När bilder laddas hämtar din enhet dem från avsändarens server.
627
+ Det kan avslöja för avsändaren att du öppnade meddelandet, när du öppnade det och metadata som din IP-adress samt information om enhet/webbläsare.
628
+
629
+ Du kan fortsätta blockera bilder (e-posten kan se ofullständig ut) eller ladda dem om du litar på avsändaren.`,
630
+ 'file-viewer.email.remote-images.load': 'Ladda bilder',
519
631
  'editor-menu.bold': 'Fet',
520
632
  'editor-menu.italic': 'Kursiv',
521
633
  'editor-menu.strikethrough': 'Genomstruken',
@@ -29,6 +29,7 @@
29
29
  "components/dock/dock-button/dock-button.js",
30
30
  "components/drag-handle/drag-handle.js",
31
31
  "components/dynamic-label/dynamic-label.js",
32
+ "components/email-viewer/email-viewer.js",
32
33
  "components/file/file.js",
33
34
  "components/file-dropzone/file-dropzone.js",
34
35
  "components/file-input/file-input.js",
@@ -0,0 +1,206 @@
1
+ import PostalMime from "postal-mime";
2
+ import { sanitizeEmailHTML } from "./sanitize-email-html";
3
+ /**
4
+ * Email loading/parsing helpers for `limel-file-viewer`.
5
+ *
6
+ * Parses an RFC 5322 / MIME email message (commonly stored as a `.eml` file)
7
+ * and returns a simplified `Email` view-model.
8
+ */
9
+ /**
10
+ * Fetches and parses an email message.
11
+ *
12
+ * - Prefers `email.html` if present, otherwise falls back to `email.text`.
13
+ * - Attempts to resolve inline images referenced via `cid:` by replacing
14
+ * `<img src="cid:...">` with `data:` URLs generated from inline attachments.
15
+ *
16
+ * @param url - URL to an email message, usually ending in `.eml`.
17
+ * @returns A simplified `Email` object for rendering.
18
+ */
19
+ export async function loadEmail(url) {
20
+ const buffer = await fetchEmailBuffer(url);
21
+ const email = await parseEmail(url, buffer);
22
+ const parsedEmail = {
23
+ subject: email.subject || undefined,
24
+ from: formatAddress(email.from),
25
+ to: formatAddresses(email.to),
26
+ cc: formatAddresses(email.cc),
27
+ date: email.date || undefined,
28
+ };
29
+ const { attachments, cidUrlById } = extractAttachments(email);
30
+ if (attachments.length > 0) {
31
+ parsedEmail.attachments = attachments;
32
+ }
33
+ await applyBody(parsedEmail, email, cidUrlById);
34
+ return parsedEmail;
35
+ }
36
+ async function fetchEmailBuffer(url) {
37
+ try {
38
+ const response = await fetch(url);
39
+ if (!response.ok) {
40
+ throw new Error(`Failed to fetch email (${response.status} ${response.statusText})`);
41
+ }
42
+ return await response.arrayBuffer();
43
+ }
44
+ catch (error) {
45
+ const message = error instanceof Error ? error.message : String(error);
46
+ throw new Error(`Failed to load email from ${url}: ${message}`);
47
+ }
48
+ }
49
+ async function parseEmail(url, buffer) {
50
+ try {
51
+ return await PostalMime.parse(buffer, {
52
+ attachmentEncoding: 'arraybuffer',
53
+ });
54
+ }
55
+ catch (error) {
56
+ const message = error instanceof Error ? error.message : String(error);
57
+ throw new Error(`Failed to parse email from ${url}: ${message}`);
58
+ }
59
+ }
60
+ function extractAttachments(email) {
61
+ const attachments = [];
62
+ const cidUrlById = new Map();
63
+ for (const attachment of email.attachments || []) {
64
+ const contentId = normalizeContentId(attachment.contentId);
65
+ const isInline = attachment.related || attachment.disposition === 'inline';
66
+ if (!isInline) {
67
+ const size = attachment.content instanceof ArrayBuffer
68
+ ? attachment.content.byteLength
69
+ : undefined;
70
+ attachments.push({
71
+ filename: attachment.filename || undefined,
72
+ mimeType: attachment.mimeType || undefined,
73
+ size,
74
+ });
75
+ continue;
76
+ }
77
+ const hasArrayBufferContent = attachment.content instanceof ArrayBuffer;
78
+ if (!contentId || !hasArrayBufferContent) {
79
+ const size = hasArrayBufferContent
80
+ ? attachment.content.byteLength
81
+ : undefined;
82
+ attachments.push({
83
+ filename: attachment.filename || undefined,
84
+ mimeType: attachment.mimeType || 'application/octet-stream',
85
+ size,
86
+ });
87
+ continue;
88
+ }
89
+ const mimeType = attachment.mimeType || 'application/octet-stream';
90
+ const base64 = arrayBufferToBase64(attachment.content);
91
+ const dataUrl = `data:${mimeType};base64,${base64}`;
92
+ cidUrlById.set(contentId, dataUrl);
93
+ }
94
+ return { attachments, cidUrlById };
95
+ }
96
+ async function applyBody(parsedEmail, email, cidUrlById) {
97
+ const html = (email.html || '').trim();
98
+ if (html) {
99
+ const withCidsResolved = replaceCidReferences(html, cidUrlById);
100
+ parsedEmail.bodyHtml = await sanitizeEmailHTML(withCidsResolved);
101
+ return;
102
+ }
103
+ parsedEmail.bodyText = (email.text || '').trim() || undefined;
104
+ }
105
+ /**
106
+ * Normalizes a Content-ID by removing surrounding angle brackets.
107
+ *
108
+ * Example: `<image@id>` -> `image@id`
109
+ *
110
+ * @param contentId - The Content-ID to normalize, optionally surrounded by angle brackets.
111
+ */
112
+ function normalizeContentId(contentId) {
113
+ if (!contentId) {
114
+ return '';
115
+ }
116
+ let normalized = contentId.trim();
117
+ if (normalized.startsWith('<')) {
118
+ normalized = normalized.slice(1);
119
+ }
120
+ if (normalized.endsWith('>')) {
121
+ normalized = normalized.slice(0, -1);
122
+ }
123
+ return normalized.trim();
124
+ }
125
+ function replaceCidReferences(html, cidUrlById) {
126
+ if (cidUrlById.size === 0) {
127
+ return html;
128
+ }
129
+ return html.replaceAll(/(src\s*=\s*["']?)cid:([^"'\s>]+)(["']?)/gi, (match, prefix, cid, suffix) => {
130
+ const normalized = normalizeContentId(cid);
131
+ const replacement = cidUrlById.get(normalized);
132
+ if (!replacement) {
133
+ return match;
134
+ }
135
+ return `${prefix}${replacement}${suffix}`;
136
+ });
137
+ }
138
+ function arrayBufferToBase64(buffer) {
139
+ const bytes = new Uint8Array(buffer);
140
+ if (typeof btoa === 'function') {
141
+ let binary = '';
142
+ for (const byte of bytes) {
143
+ binary += String['fromCharCode'](byte);
144
+ }
145
+ return btoa(binary);
146
+ }
147
+ // Jest/Node fallback
148
+ return globalThis.Buffer.from(bytes).toString('base64');
149
+ }
150
+ function isNonEmptyString(value) {
151
+ return typeof value === 'string' && value.length > 0;
152
+ }
153
+ /**
154
+ * Formats one or many address objects returned by PostalMime.
155
+ *
156
+ * @param addresses - Address object(s) to format.
157
+ * @returns Formatted address string, or undefined if no valid addresses.
158
+ */
159
+ function formatAddresses(addresses) {
160
+ if (!addresses) {
161
+ return undefined;
162
+ }
163
+ const list = Array.isArray(addresses) ? addresses : [addresses];
164
+ const parts = list
165
+ .map((addr) => formatAddress(addr))
166
+ .filter(isNonEmptyString);
167
+ return parts.length > 0 ? parts.join(', ') : undefined;
168
+ }
169
+ function formatAddress(address) {
170
+ if (!address) {
171
+ return undefined;
172
+ }
173
+ if (Array.isArray(address)) {
174
+ return formatAddresses(address);
175
+ }
176
+ if (address.group && Array.isArray(address.group)) {
177
+ const groupName = (address.name || '').trim();
178
+ const groupMembers = address.group
179
+ .map((m) => formatAddress(m))
180
+ .filter(isNonEmptyString)
181
+ .join(', ');
182
+ if (groupName && groupMembers) {
183
+ return `${groupName}: ${groupMembers}`;
184
+ }
185
+ return groupName || groupMembers || undefined;
186
+ }
187
+ const name = (address.name || '').trim();
188
+ const email = (address.address || '').trim();
189
+ if (name && email) {
190
+ const displayName = quoteDisplayNameIfNeeded(name);
191
+ return `${displayName} <${email}>`;
192
+ }
193
+ return name || email || undefined;
194
+ }
195
+ function quoteDisplayNameIfNeeded(name) {
196
+ if (!name) {
197
+ return '';
198
+ }
199
+ // If the display name contains a comma, it must be quoted for safe parsing
200
+ // of comma-separated address lists.
201
+ if (!name.includes(',') && !name.includes('"')) {
202
+ return name;
203
+ }
204
+ const escaped = name.replaceAll('\\', '\\\\').replaceAll('"', '\\' + '"');
205
+ return `"${escaped}"`;
206
+ }
@@ -0,0 +1,293 @@
1
+ @charset "UTF-8";
2
+ /**
3
+ * Note! This file is exported to `dist/scss/` in the published
4
+ * node module, for consumer projects to import.
5
+ * That means this file cannot import from any file that isn't
6
+ * also exported, keeping the same relative path.
7
+ *
8
+ * Or, just don't import anything, that works too.
9
+ */
10
+ /**
11
+ * This can be used on a trigger element that opens a dropdown menu or a popover.
12
+ */
13
+ /**
14
+ * This mixin will mask out the content that is close to
15
+ * the edges of a scrollable area.
16
+ * - If the scrollable content has `overflow-y`, use `vertically`
17
+ * as an argument for `$direction`.
18
+ - If the scrollable content has `overflow-x`, use `horizontally`
19
+ * as an argument for `$direction`.
20
+ *
21
+ * For the visual effect to work smoothly, we need to make sure that
22
+ * the size of the fade-out edge effect is the same as the
23
+ * internal paddings of the scrollable area. Otherwise, content of a
24
+ * scrollable area that does not have a padding will fade out before
25
+ * any scrolling has been done.
26
+ * This is why this mixin already adds paddings, which automatically
27
+ * default to the size of the fade-out effect.
28
+ * This size defaults to `1rem`, but to override the size use
29
+ * `--limel-top-edge-fade-height` & `--limel-bottom-edge-fade-height`
30
+ * when `vertically` argument is set, and use
31
+ * `--limel-left-edge-fade-width` & `--limel-right-edge-fade-width`
32
+ * when `horizontally` argument is set.
33
+ * Of course you can also programmatically increase and decrease the
34
+ * size of these variables for each edge, based on the amount of
35
+ * scrolling that has been done by the user. In this case, make sure
36
+ * to add a custom padding where the mixin is used, to override
37
+ * the paddings that are automatically added by the mixin in the
38
+ * compiled CSS code.
39
+ */
40
+ /**
41
+ * This mixin will add an animated underline to the bottom of an `a` elements.
42
+ * Note that you may need to add `all: unset;` –depending on your use case–
43
+ * before using this mixin.
44
+ */
45
+ /**
46
+ * This mixin creates a cross-browser font stack.
47
+ * - `sans-serif` can be used for the UI of the components.
48
+ * - `monospace` can be used for code.
49
+ *
50
+ * ⚠️ If we change the font stacks, we need to update
51
+ * 1. the consumer documentation in `README.md`, and
52
+ * 2. the CSS variables of `--kompendium-example-font-family`
53
+ * in the `<style>` tag of `index.html`.
54
+ */
55
+ /**
56
+ * This mixin is a hack, using old CSS syntax
57
+ * to enable you to truncate a piece of text,
58
+ * after a certain number of lines.
59
+ */
60
+ /**
61
+ * This mixin will add a chessboard background pattern,
62
+ * typically used to visualize transparency.
63
+ */
64
+ /**
65
+ * Make a container resizable by the user.
66
+ * This is used in the documentations and examples
67
+ * of some components, to demonstrate how the component
68
+ * behaves in a resizable container.
69
+ */
70
+ /**
71
+ * Drag to reorder mixins
72
+ */
73
+ /**
74
+ * The breakpoints below are used to create responsive designs
75
+ * in Lime's products. Therefore, they are here to get distributed
76
+ * to all components in other private repos, which rely on this `mixins`
77
+ * file, to create consistent styles.
78
+ *
79
+ * :::important
80
+ * In very rare cases you should used media queries!
81
+ * Nowadays, there are many better ways of achieving responsive design
82
+ * without media queries. For example, using CSS Grid, Flexbox, and their features.
83
+ * :::
84
+ */
85
+ /**
86
+ * Media query mixins for responsive design based on screen width.
87
+ * Note that these mixins do not detect the device type!
88
+ */
89
+ :host(limel-email-viewer) {
90
+ display: block;
91
+ width: 100%;
92
+ height: 100%;
93
+ box-sizing: border-box;
94
+ }
95
+
96
+ *,
97
+ *::before,
98
+ *::after {
99
+ box-sizing: border-box;
100
+ min-width: 0;
101
+ min-height: 0;
102
+ }
103
+
104
+ .email {
105
+ display: flex;
106
+ flex-direction: column;
107
+ width: 100%;
108
+ height: 100%;
109
+ padding-bottom: 0.5rem;
110
+ box-shadow: var(--shadow-depth-8);
111
+ }
112
+
113
+ .email-headers {
114
+ position: relative;
115
+ flex-shrink: 0;
116
+ display: flex;
117
+ flex-direction: column;
118
+ }
119
+ .email-headers dl,
120
+ .email-headers dt,
121
+ .email-headers dd {
122
+ margin: 0;
123
+ }
124
+ .email-headers dl {
125
+ display: flex;
126
+ flex-wrap: wrap;
127
+ gap: 0 0.5rem;
128
+ padding: 0.5rem 0.75rem;
129
+ font-size: 0.75rem;
130
+ }
131
+ .email-headers dl:nth-child(even) {
132
+ background-color: rgb(var(--contrast-800), 0.1);
133
+ }
134
+ .email-headers dl dt {
135
+ opacity: 0.6;
136
+ min-width: 3rem;
137
+ }
138
+ .email-headers dl dt::after {
139
+ content: ":";
140
+ }
141
+ .email-headers dl dd:not(:last-child)::after {
142
+ content: ",";
143
+ opacity: 0.6;
144
+ }
145
+ .email-headers dl.subject dd {
146
+ font-weight: bold;
147
+ }
148
+ .email-headers dl.date {
149
+ position: absolute;
150
+ right: 0.25rem;
151
+ transform: translateY(-50%);
152
+ font-size: 0.625rem;
153
+ border-radius: 9rem;
154
+ padding: 0.25rem 0.5rem;
155
+ background-color: rgb(var(--contrast-100), 0.3);
156
+ }
157
+ .email-headers dl.date dt {
158
+ position: absolute;
159
+ width: 0;
160
+ height: 0;
161
+ margin: -1px;
162
+ padding: 0;
163
+ border: 0;
164
+ overflow: hidden;
165
+ clip: rect(0, 0, 0, 0);
166
+ clip-path: inset(50%);
167
+ white-space: nowrap;
168
+ }
169
+
170
+ .attachments {
171
+ flex-shrink: 0;
172
+ padding: 0.5rem;
173
+ border-bottom: 1px dashed rgba(var(--contrast-700));
174
+ }
175
+ .attachments span {
176
+ padding-left: 0.25rem;
177
+ font-size: 0.75rem;
178
+ opacity: 0.6;
179
+ }
180
+ .attachments span:first-child::after {
181
+ content: ":";
182
+ }
183
+ .attachments ul {
184
+ all: unset;
185
+ display: grid;
186
+ grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
187
+ gap: 0.5rem;
188
+ padding: 0.5rem 0;
189
+ }
190
+ .attachments li {
191
+ all: unset;
192
+ position: relative;
193
+ display: flex;
194
+ flex-direction: column;
195
+ gap: 0.25rem;
196
+ font-size: 0.6875rem;
197
+ line-height: normal;
198
+ padding: 0.5rem 0.5rem 1rem 0.5rem;
199
+ border-radius: 0.5rem;
200
+ border: 1px solid rgba(var(--contrast-600));
201
+ background-color: rgba(var(--contrast-400));
202
+ }
203
+ .attachments .attachment-filename {
204
+ font-weight: 500;
205
+ }
206
+ .attachments .attachment-mime-type {
207
+ opacity: 0.7;
208
+ }
209
+ .attachments limel-badge {
210
+ --badge-max-width: auto;
211
+ --badge-background-color: rgb(var(--contrast-1000), 0.7);
212
+ --badge-text-color: rgb(var(--color-white));
213
+ position: absolute;
214
+ bottom: 0.125rem;
215
+ right: 0.125rem;
216
+ box-shadow: var(--shadow-brighten-edges-outside);
217
+ }
218
+
219
+ section {
220
+ flex-grow: 1;
221
+ display: flex;
222
+ flex-direction: column;
223
+ border-top: 1px dashed rgba(var(--contrast-700));
224
+ min-height: 2rem;
225
+ overflow-y: auto;
226
+ }
227
+
228
+ limel-collapsible-section {
229
+ --closed-header-background-color: var(
230
+ --lime-elevated-surface-background-color
231
+ );
232
+ flex-grow: 1;
233
+ flex-shrink: 0;
234
+ margin: 0.5rem;
235
+ border-radius: 0.75rem;
236
+ box-shadow: var(--shadow-depth-8);
237
+ }
238
+ limel-collapsible-section button {
239
+ all: unset;
240
+ flex-shrink: 0;
241
+ border-radius: 0.375rem;
242
+ padding: 0.25rem 0.5rem;
243
+ font-size: var(--limel-theme-small-font-size);
244
+ margin: 0 0.5rem;
245
+ }
246
+ limel-collapsible-section button.load-images {
247
+ transition: color var(--limel-clickable-transition-speed, 0.4s) ease, background-color var(--limel-clickable-transition-speed, 0.4s) ease, box-shadow var(--limel-clickable-transform-speed, 0.4s) ease, transform var(--limel-clickable-transform-speed, 0.4s) var(--limel-clickable-transform-timing-function, ease);
248
+ cursor: pointer;
249
+ color: var(--lime-primary-color, var(--limel-theme-primary-color));
250
+ background-color: var(--lime-elevated-surface-background-color);
251
+ box-shadow: var(--button-shadow-normal);
252
+ }
253
+ limel-collapsible-section button.load-images:hover, limel-collapsible-section button.load-images:focus, limel-collapsible-section button.load-images:focus-visible {
254
+ will-change: color, background-color, box-shadow, transform;
255
+ }
256
+ limel-collapsible-section button.load-images:hover, limel-collapsible-section button.load-images:focus-visible {
257
+ transform: translate3d(0, -0.04rem, 0);
258
+ color: var(--limel-theme-on-surface-color);
259
+ background-color: var(--lime-elevated-surface-background-color);
260
+ box-shadow: var(--button-shadow-hovered);
261
+ }
262
+ limel-collapsible-section button.load-images:active {
263
+ --limel-clickable-transform-timing-function: cubic-bezier(
264
+ 0.83,
265
+ -0.15,
266
+ 0.49,
267
+ 1.16
268
+ );
269
+ transform: translate3d(0, 0.05rem, 0);
270
+ box-shadow: var(--button-shadow-pressed);
271
+ }
272
+ limel-collapsible-section button.load-images:hover, limel-collapsible-section button.load-images:active {
273
+ --limel-clickable-transition-speed: 0.2s;
274
+ --limel-clickable-transform-speed: 0.16s;
275
+ }
276
+ limel-collapsible-section limel-markdown {
277
+ padding: 0.5rem;
278
+ }
279
+
280
+ .body {
281
+ flex-grow: 1;
282
+ max-width: 100%;
283
+ padding: 0.75rem;
284
+ }
285
+ .body.plain-text {
286
+ white-space: pre-wrap;
287
+ overflow-wrap: anywhere;
288
+ margin: 0;
289
+ font-family: inherit;
290
+ }
291
+ .body img {
292
+ max-width: 100% !important;
293
+ }