@nextcloud/vue 8.3.0 → 8.4.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 (250) hide show
  1. package/CHANGELOG.md +44 -3
  2. package/dist/Components/NcActionButton.cjs +1 -1
  3. package/dist/Components/NcActionButton.mjs +1 -1
  4. package/dist/Components/NcActionButtonGroup.cjs +13 -9
  5. package/dist/Components/NcActionButtonGroup.cjs.map +1 -1
  6. package/dist/Components/NcActionButtonGroup.mjs +16 -11
  7. package/dist/Components/NcActionButtonGroup.mjs.map +1 -1
  8. package/dist/Components/NcActionInput.cjs +9 -8
  9. package/dist/Components/NcActionInput.cjs.map +1 -1
  10. package/dist/Components/NcActionInput.mjs +11 -10
  11. package/dist/Components/NcActionInput.mjs.map +1 -1
  12. package/dist/Components/NcActionLink.cjs +1 -1
  13. package/dist/Components/NcActionLink.mjs +1 -1
  14. package/dist/Components/NcActionRouter.cjs +1 -1
  15. package/dist/Components/NcActionRouter.mjs +1 -1
  16. package/dist/Components/NcActionText.cjs +1 -1
  17. package/dist/Components/NcActionText.mjs +1 -1
  18. package/dist/Components/NcActionTextEditable.cjs +1 -1
  19. package/dist/Components/NcActionTextEditable.mjs +1 -1
  20. package/dist/Components/NcActions.cjs +37 -37
  21. package/dist/Components/NcActions.cjs.map +1 -1
  22. package/dist/Components/NcActions.mjs +19 -19
  23. package/dist/Components/NcActions.mjs.map +1 -1
  24. package/dist/Components/NcAppContent.cjs +15 -14
  25. package/dist/Components/NcAppContent.cjs.map +1 -1
  26. package/dist/Components/NcAppContent.mjs +35 -34
  27. package/dist/Components/NcAppContent.mjs.map +1 -1
  28. package/dist/Components/NcAppNavigation.cjs +1 -1
  29. package/dist/Components/NcAppNavigation.mjs +1 -1
  30. package/dist/Components/NcAppNavigationCaption.cjs +2 -2
  31. package/dist/Components/NcAppNavigationCaption.cjs.map +1 -1
  32. package/dist/Components/NcAppNavigationCaption.mjs +2 -2
  33. package/dist/Components/NcAppNavigationCaption.mjs.map +1 -1
  34. package/dist/Components/NcAppNavigationItem.cjs +28 -24
  35. package/dist/Components/NcAppNavigationItem.cjs.map +1 -1
  36. package/dist/Components/NcAppNavigationItem.mjs +66 -63
  37. package/dist/Components/NcAppNavigationItem.mjs.map +1 -1
  38. package/dist/Components/NcAppNavigationNewItem.cjs +2 -2
  39. package/dist/Components/NcAppNavigationNewItem.mjs +2 -2
  40. package/dist/Components/NcAppNavigationSettings.cjs +7 -8
  41. package/dist/Components/NcAppNavigationSettings.cjs.map +1 -1
  42. package/dist/Components/NcAppNavigationSettings.mjs +27 -29
  43. package/dist/Components/NcAppNavigationSettings.mjs.map +1 -1
  44. package/dist/Components/NcAppNavigationToggle.cjs +1 -1
  45. package/dist/Components/NcAppNavigationToggle.mjs +1 -1
  46. package/dist/Components/NcAppSettingsDialog.cjs +19 -18
  47. package/dist/Components/NcAppSettingsDialog.cjs.map +1 -1
  48. package/dist/Components/NcAppSettingsDialog.mjs +22 -21
  49. package/dist/Components/NcAppSettingsDialog.mjs.map +1 -1
  50. package/dist/Components/NcAppSidebar.cjs +88 -45
  51. package/dist/Components/NcAppSidebar.cjs.map +1 -1
  52. package/dist/Components/NcAppSidebar.mjs +158 -112
  53. package/dist/Components/NcAppSidebar.mjs.map +1 -1
  54. package/dist/Components/NcAvatar.cjs +1 -1
  55. package/dist/Components/NcAvatar.mjs +1 -1
  56. package/dist/Components/NcBreadcrumb.cjs +4 -3
  57. package/dist/Components/NcBreadcrumb.cjs.map +1 -1
  58. package/dist/Components/NcBreadcrumb.mjs +6 -5
  59. package/dist/Components/NcBreadcrumb.mjs.map +1 -1
  60. package/dist/Components/NcBreadcrumbs.cjs +26 -19
  61. package/dist/Components/NcBreadcrumbs.cjs.map +1 -1
  62. package/dist/Components/NcBreadcrumbs.mjs +48 -41
  63. package/dist/Components/NcBreadcrumbs.mjs.map +1 -1
  64. package/dist/Components/NcCheckboxRadioSwitch.cjs +44 -34
  65. package/dist/Components/NcCheckboxRadioSwitch.cjs.map +1 -1
  66. package/dist/Components/NcCheckboxRadioSwitch.mjs +72 -62
  67. package/dist/Components/NcCheckboxRadioSwitch.mjs.map +1 -1
  68. package/dist/Components/NcColorPicker.cjs +34 -11
  69. package/dist/Components/NcColorPicker.cjs.map +1 -1
  70. package/dist/Components/NcColorPicker.mjs +48 -25
  71. package/dist/Components/NcColorPicker.mjs.map +1 -1
  72. package/dist/Components/NcDashboardWidget.cjs +7 -6
  73. package/dist/Components/NcDashboardWidget.cjs.map +1 -1
  74. package/dist/Components/NcDashboardWidget.mjs +17 -16
  75. package/dist/Components/NcDashboardWidget.mjs.map +1 -1
  76. package/dist/Components/NcDashboardWidgetItem.cjs +1 -1
  77. package/dist/Components/NcDashboardWidgetItem.mjs +1 -1
  78. package/dist/Components/NcDateTime.cjs +15 -13
  79. package/dist/Components/NcDateTime.cjs.map +1 -1
  80. package/dist/Components/NcDateTime.mjs +12 -11
  81. package/dist/Components/NcDateTime.mjs.map +1 -1
  82. package/dist/Components/NcDateTimePicker.cjs +24 -23
  83. package/dist/Components/NcDateTimePicker.cjs.map +1 -1
  84. package/dist/Components/NcDateTimePicker.mjs +36 -36
  85. package/dist/Components/NcDateTimePicker.mjs.map +1 -1
  86. package/dist/Components/NcDateTimePickerNative.cjs +3 -3
  87. package/dist/Components/NcDateTimePickerNative.cjs.map +1 -1
  88. package/dist/Components/NcDateTimePickerNative.mjs +3 -3
  89. package/dist/Components/NcDateTimePickerNative.mjs.map +1 -1
  90. package/dist/Components/NcDialog.cjs +18 -17
  91. package/dist/Components/NcDialog.cjs.map +1 -1
  92. package/dist/Components/NcDialog.mjs +26 -24
  93. package/dist/Components/NcDialog.mjs.map +1 -1
  94. package/dist/Components/NcEmojiPicker.cjs +2 -1
  95. package/dist/Components/NcEmojiPicker.cjs.map +1 -1
  96. package/dist/Components/NcEmojiPicker.mjs +18 -17
  97. package/dist/Components/NcEmojiPicker.mjs.map +1 -1
  98. package/dist/Components/NcHeaderMenu.cjs +8 -8
  99. package/dist/Components/NcHeaderMenu.cjs.map +1 -1
  100. package/dist/Components/NcHeaderMenu.mjs +6 -6
  101. package/dist/Components/NcHeaderMenu.mjs.map +1 -1
  102. package/dist/Components/NcListItem.cjs +15 -10
  103. package/dist/Components/NcListItem.cjs.map +1 -1
  104. package/dist/Components/NcListItem.mjs +22 -17
  105. package/dist/Components/NcListItem.mjs.map +1 -1
  106. package/dist/Components/NcListItemIcon.cjs +1 -1
  107. package/dist/Components/NcListItemIcon.mjs +1 -1
  108. package/dist/Components/NcModal.cjs +50 -46
  109. package/dist/Components/NcModal.cjs.map +1 -1
  110. package/dist/Components/NcModal.mjs +66 -63
  111. package/dist/Components/NcModal.mjs.map +1 -1
  112. package/dist/Components/NcPasswordField.cjs +14 -12
  113. package/dist/Components/NcPasswordField.cjs.map +1 -1
  114. package/dist/Components/NcPasswordField.mjs +25 -23
  115. package/dist/Components/NcPasswordField.mjs.map +1 -1
  116. package/dist/Components/NcRelatedResourcesPanel.cjs +6 -4
  117. package/dist/Components/NcRelatedResourcesPanel.cjs.map +1 -1
  118. package/dist/Components/NcRelatedResourcesPanel.mjs +24 -22
  119. package/dist/Components/NcRelatedResourcesPanel.mjs.map +1 -1
  120. package/dist/Components/NcRichContenteditable.cjs +113 -82
  121. package/dist/Components/NcRichContenteditable.cjs.map +1 -1
  122. package/dist/Components/NcRichContenteditable.mjs +89 -55
  123. package/dist/Components/NcRichContenteditable.mjs.map +1 -1
  124. package/dist/Components/NcRichText.cjs +1 -1
  125. package/dist/Components/NcRichText.mjs +3 -3
  126. package/dist/Components/NcSelect.cjs +22 -21
  127. package/dist/Components/NcSelect.cjs.map +1 -1
  128. package/dist/Components/NcSelect.mjs +28 -28
  129. package/dist/Components/NcSelect.mjs.map +1 -1
  130. package/dist/Components/NcSelectTags.cjs +4 -2
  131. package/dist/Components/NcSelectTags.cjs.map +1 -1
  132. package/dist/Components/NcSelectTags.mjs +46 -44
  133. package/dist/Components/NcSelectTags.mjs.map +1 -1
  134. package/dist/Components/NcSettingsInputText.cjs +5 -4
  135. package/dist/Components/NcSettingsInputText.cjs.map +1 -1
  136. package/dist/Components/NcSettingsInputText.mjs +15 -14
  137. package/dist/Components/NcSettingsInputText.mjs.map +1 -1
  138. package/dist/Components/NcSettingsSection.cjs +8 -6
  139. package/dist/Components/NcSettingsSection.cjs.map +1 -1
  140. package/dist/Components/NcSettingsSection.mjs +18 -17
  141. package/dist/Components/NcSettingsSection.mjs.map +1 -1
  142. package/dist/Components/NcSettingsSelectGroup.cjs +1 -1
  143. package/dist/Components/NcSettingsSelectGroup.mjs +1 -1
  144. package/dist/Components/NcTextArea.cjs +5 -5
  145. package/dist/Components/NcTextArea.cjs.map +1 -1
  146. package/dist/Components/NcTextArea.mjs +4 -4
  147. package/dist/Components/NcTextArea.mjs.map +1 -1
  148. package/dist/Components/NcTextField.cjs +4 -2
  149. package/dist/Components/NcTextField.cjs.map +1 -1
  150. package/dist/Components/NcTextField.mjs +19 -17
  151. package/dist/Components/NcTextField.mjs.map +1 -1
  152. package/dist/Components/NcTimezonePicker.cjs +10 -8
  153. package/dist/Components/NcTimezonePicker.cjs.map +1 -1
  154. package/dist/Components/NcTimezonePicker.mjs +35 -33
  155. package/dist/Components/NcTimezonePicker.mjs.map +1 -1
  156. package/dist/Components/NcUserBubble.cjs +1 -1
  157. package/dist/Components/NcUserBubble.mjs +1 -1
  158. package/dist/Composables/useIsMobile.cjs +13 -8
  159. package/dist/Composables/useIsMobile.cjs.map +1 -1
  160. package/dist/Composables/useIsMobile.mjs +15 -10
  161. package/dist/Composables/useIsMobile.mjs.map +1 -1
  162. package/dist/Functions/usernameToColor.cjs +1 -1
  163. package/dist/Functions/usernameToColor.cjs.map +1 -1
  164. package/dist/Functions/usernameToColor.mjs +1 -1
  165. package/dist/Functions/usernameToColor.mjs.map +1 -1
  166. package/dist/assets/{NcAppNavigationToggle-2bc73ee8.css → NcAppNavigationToggle-48c375e8.css} +4 -2
  167. package/dist/assets/{NcSettingsSelectGroup-6ddb63a6.css → NcSettingsSelectGroup-a29e2156.css} +2 -2
  168. package/dist/assets/{index-7157aefa.css → index-13720a46.css} +24 -24
  169. package/dist/assets/{index-93bc89ef.css → index-1a317434.css} +9 -12
  170. package/dist/assets/{index-3d1ccc15.css → index-2d5cf6b2.css} +45 -45
  171. package/dist/assets/index-3b654875.css +144 -0
  172. package/dist/assets/{index-e6a91529.css → index-7f77b8ae.css} +36 -36
  173. package/dist/assets/{index-9941f384.css → index-86454928.css} +13 -13
  174. package/dist/assets/{index-2d4de2fc.css → index-8b327013.css} +11 -3
  175. package/dist/assets/{index-30ca9574.css → index-97305c1f.css} +27 -40
  176. package/dist/assets/{index-73ded07b.css → index-a3c23731.css} +63 -63
  177. package/dist/assets/{index-50dc154e.css → index-a7fc7815.css} +16 -16
  178. package/dist/assets/{index-810b8984.css → index-a9999048.css} +11 -11
  179. package/dist/assets/{index-3764a447.css → index-aacb7cf8.css} +16 -16
  180. package/dist/assets/{index-b0a8a48c.css → index-b0bba2fc.css} +11 -11
  181. package/dist/assets/{index-b991895f.css → index-c20f9f7e.css} +15 -15
  182. package/dist/assets/{index-5e4bf286.css → index-d8bc189c.css} +38 -41
  183. package/dist/assets/{index-ffa6d11c.css → index-dab51681.css} +64 -31
  184. package/dist/assets/{index-4e03d941.css → index-f24e102f.css} +49 -48
  185. package/dist/assets/{index-4611417f.css → index-f5162bbd.css} +7 -7
  186. package/dist/assets/{index-34dfc54e.css → index-f78bd735.css} +13 -13
  187. package/dist/assets/{index-f72cef5d.css → index-fe84a063.css} +5 -5
  188. package/dist/chunks/GenColors-5c054042.mjs +137 -0
  189. package/dist/chunks/GenColors-5c054042.mjs.map +1 -0
  190. package/dist/chunks/GenColors-7495e6f6.cjs +136 -0
  191. package/dist/chunks/GenColors-7495e6f6.cjs.map +1 -0
  192. package/dist/chunks/{NcAppNavigationToggle-f5591773.mjs → NcAppNavigationToggle-0bc638a8.mjs} +27 -26
  193. package/dist/chunks/{NcAppNavigationToggle-6a975868.cjs.map → NcAppNavigationToggle-0bc638a8.mjs.map} +1 -1
  194. package/dist/chunks/{NcAppNavigationToggle-6a975868.cjs → NcAppNavigationToggle-6d192bea.cjs} +17 -15
  195. package/dist/chunks/{NcAppNavigationToggle-f5591773.mjs.map → NcAppNavigationToggle-6d192bea.cjs.map} +1 -1
  196. package/dist/chunks/{NcInputConfirmCancel-7837eb4d.mjs → NcInputConfirmCancel-a08c5cb4.mjs} +14 -13
  197. package/dist/chunks/{NcInputConfirmCancel-7837eb4d.mjs.map → NcInputConfirmCancel-a08c5cb4.mjs.map} +1 -1
  198. package/dist/chunks/{NcInputConfirmCancel-790f5902.cjs → NcInputConfirmCancel-b99898db.cjs} +8 -7
  199. package/dist/chunks/{NcInputConfirmCancel-790f5902.cjs.map → NcInputConfirmCancel-b99898db.cjs.map} +1 -1
  200. package/dist/chunks/{NcRichText-0db09c78.mjs → NcRichText-e4bf7767.mjs} +1 -1
  201. package/dist/chunks/{NcRichText-0db09c78.mjs.map → NcRichText-e4bf7767.mjs.map} +1 -1
  202. package/dist/chunks/{NcRichText-0dd96aac.cjs → NcRichText-f729896c.cjs} +1 -1
  203. package/dist/chunks/{NcRichText-0dd96aac.cjs.map → NcRichText-f729896c.cjs.map} +1 -1
  204. package/dist/chunks/{NcSettingsSelectGroup-532ba813.cjs → NcSettingsSelectGroup-b065ffc8.cjs} +18 -17
  205. package/dist/chunks/NcSettingsSelectGroup-b065ffc8.cjs.map +1 -0
  206. package/dist/chunks/{NcSettingsSelectGroup-cdd84895.mjs → NcSettingsSelectGroup-ecc8bc5a.mjs} +19 -19
  207. package/dist/chunks/NcSettingsSelectGroup-ecc8bc5a.mjs.map +1 -0
  208. package/dist/chunks/{ScopeComponent-92144d97.cjs → ScopeComponent-06c558d3.cjs} +1 -1
  209. package/dist/chunks/{ScopeComponent-92144d97.cjs.map → ScopeComponent-06c558d3.cjs.map} +1 -1
  210. package/dist/chunks/{ScopeComponent-ac5265f5.mjs → ScopeComponent-b039a43c.mjs} +1 -1
  211. package/dist/chunks/{ScopeComponent-ac5265f5.mjs.map → ScopeComponent-b039a43c.mjs.map} +1 -1
  212. package/dist/chunks/_l10n-72c5e29e.cjs +62 -0
  213. package/dist/chunks/_l10n-72c5e29e.cjs.map +1 -0
  214. package/dist/chunks/_l10n-f5af5269.mjs +64 -0
  215. package/dist/chunks/_l10n-f5af5269.mjs.map +1 -0
  216. package/dist/chunks/{actionText-60ff01d1.mjs → actionText-123f26b0.mjs} +3 -3
  217. package/dist/chunks/{actionText-60ff01d1.mjs.map → actionText-123f26b0.mjs.map} +1 -1
  218. package/dist/chunks/{actionText-9582810f.cjs → actionText-e450809c.cjs} +5 -5
  219. package/dist/chunks/{actionText-9582810f.cjs.map → actionText-e450809c.cjs.map} +1 -1
  220. package/dist/chunks/{index-efb07851.mjs → index-309426ff.mjs} +123 -77
  221. package/dist/chunks/index-309426ff.mjs.map +1 -0
  222. package/dist/chunks/{index-32c8b581.cjs → index-693e993c.cjs} +109 -64
  223. package/dist/chunks/index-693e993c.cjs.map +1 -0
  224. package/dist/chunks/{referencePickerModal-ded8273d.mjs → referencePickerModal-12935fb3.mjs} +175 -169
  225. package/dist/chunks/{referencePickerModal-ded8273d.mjs.map → referencePickerModal-12935fb3.mjs.map} +1 -1
  226. package/dist/chunks/{referencePickerModal-90dac0d0.cjs → referencePickerModal-12fa2ad0.cjs} +36 -30
  227. package/dist/chunks/{referencePickerModal-90dac0d0.cjs.map → referencePickerModal-12fa2ad0.cjs.map} +1 -1
  228. package/dist/index.cjs +93 -93
  229. package/dist/index.cjs.map +1 -1
  230. package/dist/index.mjs +96 -95
  231. package/dist/index.mjs.map +1 -1
  232. package/dist/utils/UserStatus.d.ts +26 -0
  233. package/package.json +10 -4
  234. package/dist/assets/index-2e5e3b55.css +0 -151
  235. package/dist/chunks/GenColors-12ec1caa.mjs +0 -56
  236. package/dist/chunks/GenColors-12ec1caa.mjs.map +0 -1
  237. package/dist/chunks/GenColors-a8d54566.cjs +0 -55
  238. package/dist/chunks/GenColors-a8d54566.cjs.map +0 -1
  239. package/dist/chunks/NcSettingsSelectGroup-532ba813.cjs.map +0 -1
  240. package/dist/chunks/NcSettingsSelectGroup-cdd84895.mjs.map +0 -1
  241. package/dist/chunks/index-32c8b581.cjs.map +0 -1
  242. package/dist/chunks/index-efb07851.mjs.map +0 -1
  243. package/dist/chunks/l10n-070da9ad.cjs +0 -29
  244. package/dist/chunks/l10n-070da9ad.cjs.map +0 -1
  245. package/dist/chunks/l10n-1b905a9a.mjs +0 -31
  246. package/dist/chunks/l10n-1b905a9a.mjs.map +0 -1
  247. package/dist/chunks/l10n-38626490.cjs +0 -8
  248. package/dist/chunks/l10n-38626490.cjs.map +0 -1
  249. package/dist/chunks/l10n-6cfc1200.mjs +0 -10
  250. package/dist/chunks/l10n-6cfc1200.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"NcRichContenteditable.mjs","sources":["../../src/components/NcRichContenteditable/NcAutoCompleteResult.vue","../../src/components/NcRichContenteditable/NcRichContenteditable.vue"],"sourcesContent":["<!--\n - @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>\n -\n - @author John Molakvoæ <skjnldsv@protonmail.com>\n -\n - @license GNU AGPL version 3 or any later version\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n-->\n\n<template>\n\t<div class=\"autocomplete-result\">\n\t\t<!-- Avatar or icon -->\n\t\t<div :class=\"[icon, `autocomplete-result__icon--${avatarUrl ? 'with-avatar' : ''}`]\"\n\t\t\t:style=\"avatarUrl ? { backgroundImage: `url(${avatarUrl})` } : null \"\n\t\t\tclass=\"autocomplete-result__icon\">\n\t\t\t<div v-if=\"haveStatus\"\n\t\t\t\t:class=\"[`autocomplete-result__status--${status && status.icon ? 'icon' : status.status}`]\"\n\t\t\t\tclass=\"autocomplete-result__status\">\n\t\t\t\t{{ status && status.icon || '' }}\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Title and subline -->\n\t\t<span class=\"autocomplete-result__content\">\n\t\t\t<span class=\"autocomplete-result__title\" :title=\"title\">\n\t\t\t\t{{ title }}\n\t\t\t</span>\n\t\t\t<span v-if=\"subline\" class=\"autocomplete-result__subline\">\n\t\t\t\t{{ subline }}\n\t\t\t</span>\n\t\t</span>\n\t</div>\n</template>\n\n<script>\nimport { generateUrl } from '@nextcloud/router'\n\nexport default {\n\tname: 'NcAutoCompleteResult',\n\n\tprops: {\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\t\tsubline: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t\tid: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t\ticon: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\t\ticonUrl: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t\tsource: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\t\tstatus: {\n\t\t\ttype: [Object, Array],\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\tcomputed: {\n\t\tavatarUrl() {\n\t\t\tif (this.iconUrl) {\n\t\t\t\treturn this.iconUrl\n\t\t\t}\n\n\t\t\treturn this.id && this.source === 'users'\n\t\t\t\t? this.getAvatarUrl(this.id, 44)\n\t\t\t\t: null\n\t\t},\n\t\thaveStatus() {\n\t\t\treturn this.status?.icon || (this.status?.status && this.status?.status !== 'offline')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tgetAvatarUrl(user, size) {\n\t\t\treturn generateUrl('/avatar/{user}/{size}', {\n\t\t\t\tuser,\n\t\t\t\tsize,\n\t\t\t})\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n$autocomplete-padding: 10px;\n\n.autocomplete-result {\n\tdisplay: flex;\n\theight: $clickable-area;\n\tpadding: $autocomplete-padding;\n\n\t.highlight & {\n\t\tcolor: var(--color-primary-element-light-text);\n\t\tbackground: var(--color-primary-element-light);\n\t\t&, * {\n\t\t\tcursor: pointer;\n\t\t}\n\t}\n\n\t&__icon {\n\t\tposition: relative;\n\t\tflex: 0 0 $clickable-area;\n\t\twidth: $clickable-area;\n\t\tmin-width: $clickable-area;\n\t\theight: $clickable-area;\n\t\tborder-radius: $clickable-area;\n\t\tbackground-color: var(--color-background-darker);\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-position: center;\n\t\tbackground-size: $clickable-area - 2 * $autocomplete-padding;\n\t\t&--with-avatar {\n\t\t\tcolor: inherit;\n\t\t\tbackground-size: cover;\n\t\t}\n\t}\n\n\t&__status {\n\t\tposition: absolute;\n\t\tright: -4px;\n\t\tbottom: -4px;\n\t\tbox-sizing: border-box;\n\t\twidth: 18px;\n\t\theight: 18px;\n\t\tborder: 2px solid var(--color-main-background);\n\t\tborder-radius: 50%;\n\t\tbackground-color: var(--color-main-background);\n\t\tfont-size: var(--default-font-size);\n\t\tline-height: 15px;\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-size: 16px;\n\t\tbackground-position: center;\n\n\t\t&--online{\n\t\t\tbackground-image: url('../../assets/status-icons/user-status-online.svg');\n\t\t}\n\t\t&--dnd{\n\t\t\tbackground-image: url('../../assets/status-icons/user-status-dnd.svg');\n\t\t\tbackground-color: #ffffff;\n\t\t}\n\t\t&--away{\n\t\t\tbackground-image: url('../../assets/status-icons/user-status-away.svg');\n\t\t}\n\t\t&--icon {\n\t\t\tborder: none;\n\t\t\tbackground-color: transparent;\n\t\t}\n\t}\n\n\t&__content {\n\t\tdisplay: flex;\n\t\tflex: 1 1 100%;\n\t\tflex-direction: column;\n\t\tjustify-content: center;\n\t\tmin-width: 0;\n\t\tpadding-left: $autocomplete-padding;\n\t}\n\n\t&__title,\n\t&__subline {\n\t\twhite-space: nowrap;\n\t\toverflow: hidden;\n\t\ttext-overflow: ellipsis;\n\t}\n\n\t&__subline {\n\t\tcolor: var(--color-text-maxcontrast);\n\t}\n}\n\n</style>\n","<!--\n - @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>\n -\n - @author John Molakvoæ <skjnldsv@protonmail.com>\n -\n - @license GNU AGPL version 3 or any later version\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n-->\n\n<docs>\n\n### General description\n\nThis component displays contenteditable div with automated `@` [at] autocompletion and `:` [colon] emoji autocompletion.\n\n### Examples\n\nTry mentioning user @Test01 or inserting emoji :smile\n\n```vue\n<template>\n\t<div>\n\t\t<NcRichContenteditable\n\t\t\t:value.sync=\"message\"\n\t\t\t:auto-complete=\"autoComplete\"\n\t\t\t:maxlength=\"100\"\n\t\t\t:user-data=\"userData\"\n\t\t\t@submit=\"onSubmit\" />\n\t\t<br>\n\n\t\t<NcRichContenteditable\n\t\t\t:value.sync=\"message\"\n\t\t\t:auto-complete=\"autoComplete\"\n\t\t\t:maxlength=\"400\"\n\t\t\t:multiline=\"true\"\n\t\t\t:user-data=\"userData\"\n\t\t\t@submit=\"onSubmit\" />\n\n\t\t<h5>Output - raw</h5>\n\t\t{{ JSON.stringify(message) }}\n\n\t\t<h5>Output - preformatted</h5>\n\t\t<p class=\"pre-line\">{{ message }}</p>\n\n\t\t<h5>Output - in NcRichText with markdown support</h5>\n\t\t<NcRichText :text=\"text\" :arguments=\"userMentions\" autolink use-markdown />\n\t</div>\n</template>\n<script>\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\tmessage: '**Lorem ipsum** dolor sit amet.',\n\t\t\t// You need to provide this for the inline mention to understand what to display or not.\n\t\t\t// Key should be a string with leading '@', like @Test02 or @\"Test Offline\"\n\t\t\tuserData: {\n\t\t\t\tTest01: {\n\t\t\t\t\ticon: 'icon-user',\n\t\t\t\t\tid: 'Test01',\n\t\t\t\t\ttitle: 'Test01',\n\t\t\t\t\tsource: 'users',\n\t\t\t\t\tprimary: true,\n\t\t\t\t},\n\t\t\t\tTest02: {\n\t\t\t\t\ticon: 'icon-user',\n\t\t\t\t\tid: 'Test02',\n\t\t\t\t\ttitle: 'Test02',\n\t\t\t\t\tsource: 'users',\n\t\t\t\t\tstatus: {\n\t\t\t\t\t\tclearAt: null,\n\t\t\t\t\t\ticon: '🎡',\n\t\t\t\t\t\tmessage: 'Visiting London',\n\t\t\t\t\t\tstatus: 'away',\n\t\t\t\t\t},\n\t\t\t\t\tsubline: 'Visiting London',\n\t\t\t\t},\n\t\t\t\t'Test@User': {\n\t\t\t\t\ticon: 'icon-user',\n\t\t\t\t\tid: 'Test@User',\n\t\t\t\t\ttitle: 'Test 03',\n\t\t\t\t\tsource: 'users',\n\t\t\t\t\tstatus: {\n\t\t\t\t\t\tclearAt: null,\n\t\t\t\t\t\ticon: '🎡',\n\t\t\t\t\t\tmessage: 'Having space in my name',\n\t\t\t\t\t\tstatus: 'online',\n\t\t\t\t\t},\n\t\t\t\t\tsubline: 'Visiting London',\n\t\t\t\t},\n\t\t\t\t'Test Offline': {\n\t\t\t\t\ticon: 'icon-user',\n\t\t\t\t\tid: 'Test Offline',\n\t\t\t\t\ttitle: 'Test Offline',\n\t\t\t\t\tsource: 'users',\n\t\t\t\t\tstatus: {\n\t\t\t\t\t\tclearAt: null,\n\t\t\t\t\t\ticon: null,\n\t\t\t\t\t\tmessage: null,\n\t\t\t\t\t\tstatus: 'offline',\n\t\t\t\t\t},\n\t\t\t\t\tsubline: null,\n\t\t\t\t},\n\t\t\t\t'Test DND': {\n\t\t\t\t\ticon: 'icon-user',\n\t\t\t\t\tid: 'Test DND',\n\t\t\t\t\ttitle: 'Test DND',\n\t\t\t\t\tsource: 'users',\n\t\t\t\t\tstatus: {\n\t\t\t\t\t\tclearAt: null,\n\t\t\t\t\t\ticon: null,\n\t\t\t\t\t\tmessage: 'Out sick',\n\t\t\t\t\t\tstatus: 'dnd',\n\t\t\t\t\t},\n\t\t\t\t\tsubline: 'Out sick',\n\t\t\t\t},\n\t\t\t},\n\t\t\t// To display user bubbles in NcRichText, special format of data should be provided:\n\t\t\t// Key should be in curly brackets without '@' and ' ' symbols, like {user-2}\n\t\t\tuserMentions: {\n\t\t\t\t'user-1': {\n\t\t\t\t\tcomponent: 'NcUserBubble',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdisplayName: 'Test01',\n\t\t\t\t\t\tuser: 'Test01',\n\t\t\t\t\t\tprimary: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t'user-2': {\n\t\t\t\t\tcomponent: 'NcUserBubble',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdisplayName: 'Test02',\n\t\t\t\t\t\tuser: 'Test02',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t'user-3': {\n\t\t\t\t\tcomponent: 'NcUserBubble',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdisplayName: 'Test 03',\n\t\t\t\t\t\tuser: 'Test@User',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t'user-4': {\n\t\t\t\t\tcomponent: 'NcUserBubble',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdisplayName: 'Test Offline',\n\t\t\t\t\t\tuser: 'Test Offline',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t'user-5': {\n\t\t\t\t\tcomponent: 'NcUserBubble',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdisplayName: 'Test DND',\n\t\t\t\t\t\tuser: 'Test DND',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t},\n\tcomputed: {\n\t\ttext() {\n\t\t\treturn this.message\n\t\t\t\t\t.replace('@Test01', '{user-1}')\n\t\t\t\t\t.replace('@Test02', '{user-2}')\n\t\t\t\t\t.replace('@Test@User', '{user-3}')\n\t\t\t\t\t.replace('@\"Test Offline\"', '{user-4}')\n\t\t\t\t\t.replace('@\"Test DND\"', '{user-5}')\n\t\t},\n\t},\n\tmethods: {\n\t\t/**\n\t\t* Do your own query to the autocompletion api.\n\t\t* The returned data bellow is a fake data example.\n\t\t* The callback expects the same format returned by the core/autocomplete/get ocs api endpoint!\n\t\t* @see userData example above\n\t\t*\n\t\t* @param {string} search the query\n\t\t* @param {Function} callback the callback to process the results with\n\t\t*/\n\t\tautoComplete(search, callback) {\n\t\t\tcallback(Object.values(this.userData))\n\t\t},\n\t\tonSubmit() {\n\t\t\talert(this.message)\n\t\t}\n\t}\n}\n</script>\n<style lang=\"scss\" scoped>\n\th5 {\n\t\tfont-weight: bold;\n\t\tmargin: 40px 0 20px 0;\n\t}\n\n\t.pre-line {\n\t\twhite-space: pre-line;\n\t}\n</style>\n```\n\n</docs>\n\n<template>\n\t<div ref=\"contenteditable\"\n\t\tv-tooltip=\"tooltipString\"\n\t\t:class=\"{\n\t\t\t'rich-contenteditable__input--empty': isEmptyValue,\n\t\t\t'rich-contenteditable__input--multiline': multiline,\n\t\t\t'rich-contenteditable__input--overflow': isOverMaxlength,\n\t\t\t'rich-contenteditable__input--disabled': disabled,\n\t\t}\"\n\t\t:contenteditable=\"canEdit\"\n\t\t:aria-placeholder=\"placeholder\"\n\t\taria-multiline=\"true\"\n\t\tclass=\"rich-contenteditable__input\"\n\t\trole=\"textbox\"\n\t\tv-on=\"listeners\"\n\t\t@input=\"onInput\"\n\t\t@compositionstart=\"isComposing = true\"\n\t\t@compositionend=\"isComposing = false\"\n\t\t@keydown.delete=\"onDelete\"\n\t\t@keydown.enter.exact=\"onEnter\"\n\t\t@keydown.ctrl.enter.exact.stop.prevent=\"onCtrlEnter\"\n\t\t@paste=\"onPaste\"\n\t\t@keyup.stop.prevent.capture=\"onKeyUp\" />\n</template>\n\n<script>\nimport { t } from '../../l10n.js'\nimport NcAutoCompleteResult from './NcAutoCompleteResult.vue'\nimport richEditor from '../../mixins/richEditor/index.js'\nimport Tooltip from '../../directives/Tooltip/index.js'\nimport { emojiSearch, emojiAddRecent } from '../../functions/emoji/index.js'\nimport { searchProvider, getLinkWithPicker } from '../NcRichText/index.js'\n\nimport Tribute from 'tributejs/dist/tribute.esm.js'\nimport debounce from 'debounce'\nimport stringLength from 'string-length'\n\nexport default {\n\tname: 'NcRichContenteditable',\n\n\tdirectives: {\n\t\ttooltip: Tooltip,\n\t},\n\n\tmixins: [richEditor],\n\n\tprops: {\n\t\tvalue: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t\trequired: true,\n\t\t},\n\n\t\tplaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: t('Write a message …'),\n\t\t},\n\n\t\tautoComplete: {\n\t\t\ttype: Function,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\tmenuContainer: {\n\t\t\ttype: Element,\n\t\t\tdefault: () => document.body,\n\t\t},\n\n\t\t/**\n\t\t * Make the contenteditable looks like a textarea or not.\n\t\t * Default looks like a single-line input.\n\t\t * This also handle the default enter/shift+enter behaviour.\n\t\t * if multiline, enter = newline; otherwise enter = submit\n\t\t * shift+enter always add a new line. ctrl+enter always submits\n\t\t */\n\t\tmultiline: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Is the content editable ?\n\t\t */\n\t\tcontenteditable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Disable the editing and show specific disabled design\n\t\t */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Max allowed length\n\t\t */\n\t\tmaxlength: {\n\t\t\ttype: Number,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Enable or disable emoji autocompletion\n\t\t */\n\t\temojiAutocomplete: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Enable or disable link autocompletion\n\t\t */\n\t\tlinkAutocomplete: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\t},\n\n\temits: [\n\t\t'submit',\n\t\t'paste',\n\t\t'update:value',\n\t\t'smart-picker-submit',\n\t],\n\n\tdata() {\n\t\treturn {\n\t\t\ttextSmiles: [],\n\t\t\ttribute: null,\n\t\t\tautocompleteOptions: {\n\t\t\t\t// Allow spaces in the middle of mentions\n\t\t\t\tallowSpaces: true,\n\t\t\t\tfillAttr: 'id',\n\t\t\t\t// Search against id and title (display name)\n\t\t\t\tlookup: result => `${result.id} ${result.title}`,\n\t\t\t\t// Where to inject the menu popup\n\t\t\t\tmenuContainer: this.menuContainer,\n\t\t\t\t// Popup mention autocompletion templates\n\t\t\t\tmenuItemTemplate: item => this.renderComponentHtml(item.original, NcAutoCompleteResult),\n\t\t\t\t// Hide if no results\n\t\t\t\tnoMatchTemplate: () => '<span class=\"hidden\"></span>',\n\t\t\t\t// Inner display of mentions\n\t\t\t\tselectTemplate: item => this.genSelectTemplate(item?.original?.id),\n\t\t\t\t// Autocompletion results\n\t\t\t\tvalues: this.debouncedAutoComplete,\n\t\t\t},\n\t\t\temojiOptions: {\n\t\t\t\ttrigger: ':',\n\t\t\t\t// Don't use the tribute search function at all\n\t\t\t\t// We pass search results as values (see below)\n\t\t\t\tlookup: (result, query) => query,\n\t\t\t\t// Where to inject the menu popup\n\t\t\t\tmenuContainer: this.menuContainer,\n\t\t\t\t// Popup mention autocompletion templates\n\t\t\t\tmenuItemTemplate: item => {\n\t\t\t\t\tif (this.textSmiles.includes(item.original)) {\n\t\t\t\t\t\t// Display the raw text string for :), :-D, … for non emoji results,\n\t\t\t\t\t\t// instead of trying to show an image and their name.\n\t\t\t\t\t\treturn item.original\n\t\t\t\t\t}\n\n\t\t\t\t\treturn `<span class=\"tribute-container-emoji__item__emoji\">${item.original.native}</span> :${item.original.short_name}`\n\t\t\t\t},\n\t\t\t\t// Hide if no results\n\t\t\t\tnoMatchTemplate: () => t('No emoji found'),\n\t\t\t\t// Display raw emoji along with its name\n\t\t\t\tselectTemplate: (item) => {\n\t\t\t\t\tif (this.textSmiles.includes(item.original)) {\n\t\t\t\t\t\t// Replace the selection with the raw text string for :), :-D, … for non emoji results\n\t\t\t\t\t\treturn item.original\n\t\t\t\t\t}\n\n\t\t\t\t\temojiAddRecent(item.original)\n\t\t\t\t\treturn item.original.native\n\t\t\t\t},\n\t\t\t\t// Pass the search results as values\n\t\t\t\tvalues: (text, cb) => {\n\t\t\t\t\tconst emojiResults = emojiSearch(text)\n\t\t\t\t\tif (this.textSmiles.includes(':' + text)) {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Prepend text smiles to the search results so that Tribute\n\t\t\t\t\t\t * is not interfering with normal writing, aka. \"Cocos Island Meme\".\n\t\t\t\t\t\t * E.g. `:)` and `:-)` got replaced by the flag of Cocos Island,\n\t\t\t\t\t\t * when submitting the input with Enter after writing them\n\t\t\t\t\t\t */\n\t\t\t\t\t\temojiResults.unshift(':' + text)\n\t\t\t\t\t}\n\t\t\t\t\tcb(emojiResults)\n\t\t\t\t},\n\t\t\t\t// Class added to the menu container\n\t\t\t\tcontainerClass: 'tribute-container-emoji',\n\t\t\t\t// Class added to each list item\n\t\t\t\titemClass: 'tribute-container-emoji__item',\n\t\t\t},\n\t\t\tlinkOptions: {\n\t\t\t\ttrigger: '/',\n\t\t\t\t// Don't use the tribute search function at all\n\t\t\t\t// We pass search results as values (see below)\n\t\t\t\tlookup: (result, query) => query,\n\t\t\t\t// Where to inject the menu popup\n\t\t\t\tmenuContainer: this.menuContainer,\n\t\t\t\t// Popup mention autocompletion templates\n\t\t\t\tmenuItemTemplate: item => `<img class=\"tribute-container-link__item__icon\" src=\"${item.original.icon_url}\"> <span class=\"tribute-container-link__item__title\">${item.original.title}</span>`,\n\t\t\t\t// Hide if no results\n\t\t\t\tnoMatchTemplate: () => t('No link provider found'),\n\t\t\t\tselectTemplate: this.getLink,\n\t\t\t\t// Pass the search results as values\n\t\t\t\tvalues: (text, cb) => cb(searchProvider(text)),\n\t\t\t\t// Class added to the menu container\n\t\t\t\tcontainerClass: 'tribute-container-link',\n\t\t\t\t// Class added to each list item\n\t\t\t\titemClass: 'tribute-container-link__item',\n\t\t\t},\n\n\t\t\t// Represent the raw untrimmed text of the contenteditable\n\t\t\t// serves no other purpose than to check whether the\n\t\t\t// content is empty or not\n\t\t\tlocalValue: this.value,\n\n\t\t\t// Is in text composition session in IME\n\t\t\tisComposing: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * Is the current trimmed value empty?\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisEmptyValue() {\n\t\t\treturn !this.localValue\n\t\t\t\t|| (this.localValue && this.localValue.trim() === '')\n\t\t},\n\n\t\t/**\n\t\t * Is this Firefox? 🙄\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisFF() {\n\t\t\treturn !!navigator.userAgent.match(/firefox/i)\n\t\t},\n\n\t\t/**\n\t\t * Is the current value over maxlength?\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisOverMaxlength() {\n\t\t\tif (this.isEmptyValue || !this.maxlength) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn stringLength(this.localValue) > this.maxlength\n\t\t},\n\n\t\t/**\n\t\t * Tooltip to show if characters count is over limit\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\ttooltipString() {\n\t\t\tif (!this.isOverMaxlength) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcontent: t('Message limit of {count} characters reached', { count: this.maxlength }),\n\t\t\t\tshown: true,\n\t\t\t\ttrigger: 'manual',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Edit is only allowed when contenteditableis true and disabled is false\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tcanEdit() {\n\t\t\treturn this.contenteditable && !this.disabled\n\t\t},\n\n\t\t/**\n\t\t * Proxied native event handlers without custom event handlers\n\t\t *\n\t\t * @return {Record<string, Function>}\n\t\t */\n\t\tlisteners() {\n\t\t\t/**\n\t\t\t * All component's event handlers are set as native event handlers with by v-on directive.\n\t\t\t * The component also raised custom events manually by $emit for corresponding events.\n\t\t\t * As a result, it triggers handlers twice.\n\t\t\t * The v-on=\"listeners\" directive should only set proxied native events handler without custom events\n\t\t\t */\n\t\t\tconst listeners = { ...this.$listeners }\n\t\t\tdelete listeners.paste\n\t\t\treturn listeners\n\t\t},\n\t},\n\n\twatch: {\n\t\t/**\n\t\t * If the parent value change, we compare the plain text rendering\n\t\t * If it's different, we render everything and update the main content\n\t\t */\n\t\tvalue() {\n\t\t\tconst html = this.$refs.contenteditable.innerHTML\n\t\t\t// Compare trimmed versions to be safe\n\t\t\tif (this.value.trim() !== this.parseContent(html).trim()) {\n\t\t\t\tthis.updateContent(this.value)\n\t\t\t}\n\t\t},\n\t},\n\n\tmounted() {\n\t\t/**\n\t\t * Populate the list of text smiles we want to offer via Tribute.\n\t\t * We add the colon `:)` and colon-dash `:-)` version for each of them.\n\t\t */\n\t\tconst smilesCharacters = ['d', 'D', 'p', 'P', 's', 'S', 'x', 'X', ')', '(', '|', '/']\n\t\tthis.textSmiles = []\n\t\tsmilesCharacters.forEach((char) => {\n\t\t\tthis.textSmiles.push(':' + char)\n\t\t\tthis.textSmiles.push(':-' + char)\n\t\t})\n\n\t\tthis.autocompleteTribute = new Tribute(this.autocompleteOptions)\n\t\tthis.autocompleteTribute.attach(this.$el)\n\n\t\tif (this.emojiAutocomplete) {\n\t\t\tthis.emojiTribute = new Tribute(this.emojiOptions)\n\t\t\tthis.emojiTribute.attach(this.$el)\n\t\t}\n\n\t\tif (this.linkAutocomplete) {\n\t\t\tthis.linkTribute = new Tribute(this.linkOptions)\n\t\t\tthis.linkTribute.attach(this.$el)\n\t\t}\n\n\t\t// Update default value\n\t\tthis.updateContent(this.value)\n\n\t\t// Removes the contenteditable attribute at first load if the prop is\n\t\t// set to false.\n\t\tthis.$refs.contenteditable.contentEditable = this.canEdit\n\t},\n\tbeforeDestroy() {\n\t\tif (this.autocompleteTribute) {\n\t\t\tthis.autocompleteTribute.detach(this.$el)\n\t\t}\n\t\tif (this.emojiTribute) {\n\t\t\tthis.emojiTribute.detach(this.$el)\n\t\t}\n\t\tif (this.linkTribute) {\n\t\t\tthis.linkTribute.detach(this.$el)\n\t\t}\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Focus the richContenteditable\n\t\t *\n\t\t * @public\n\t\t */\n\t\tfocus() {\n\t\t\tthis.$refs.contenteditable.focus()\n\t\t},\n\n\t\tgetLink(item) {\n\t\t\t// there is no way to get a tribute result asynchronously\n\t\t\t// so we immediately insert a node and replace it when the result comes\n\t\t\tgetLinkWithPicker(item.original.id)\n\t\t\t\t.then(result => {\n\t\t\t\t\t// replace dummy temp element by a text node which contains the picker result\n\t\t\t\t\tconst tmpElem = document.getElementById('tmp-smart-picker-result-node')\n\t\t\t\t\tconst eventData = {\n\t\t\t\t\t\tresult,\n\t\t\t\t\t\tinsertText: true,\n\t\t\t\t\t}\n\t\t\t\t\tthis.$emit('smart-picker-submit', eventData)\n\t\t\t\t\tif (eventData.insertText) {\n\t\t\t\t\t\tconst newElem = document.createTextNode(result)\n\t\t\t\t\t\ttmpElem.replaceWith(newElem)\n\t\t\t\t\t\tthis.setCursorAfter(newElem)\n\t\t\t\t\t\tthis.updateValue(this.$refs.contenteditable.innerHTML)\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttmpElem.remove()\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tconsole.debug('Smart picker promise rejected:', error)\n\t\t\t\t\tconst tmpElem = document.getElementById('tmp-smart-picker-result-node')\n\t\t\t\t\tthis.setCursorAfter(tmpElem)\n\t\t\t\t\ttmpElem.remove()\n\t\t\t\t})\n\t\t\treturn '<span id=\"tmp-smart-picker-result-node\"></span>'\n\t\t},\n\t\tsetCursorAfter(element) {\n\t\t\tconst range = document.createRange()\n\t\t\trange.setEndAfter(element)\n\t\t\trange.collapse()\n\t\t\tconst selection = window.getSelection()\n\t\t\tselection.removeAllRanges()\n\t\t\tselection.addRange(range)\n\t\t},\n\t\t/**\n\t\t * Re-emit the input event to the parent\n\t\t *\n\t\t * @param {Event} event the input event\n\t\t */\n\t\tonInput(event) {\n\t\t\tthis.updateValue(event.target.innerHTML)\n\t\t},\n\n\t\t/**\n\t\t * When pasting, sanitize the content, extract text\n\t\t * and render it again\n\t\t *\n\t\t * @param {Event} event the paste event\n\t\t * @fires Event paste the original paste event\n\t\t */\n\t\tonPaste(event) {\n\t\t\t// Either disabled or edit deactivated\n\t\t\tif (!this.canEdit) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tevent.preventDefault()\n\t\t\tconst clipboardData = event.clipboardData\n\n\t\t\t/** The original paste event */\n\t\t\tthis.$emit('paste', event)\n\n\t\t\t// If we have a file or if we don't have any text, ignore\n\t\t\tif (clipboardData.files.length !== 0\n\t\t\t\t|| !Object.values(clipboardData.items).find(item => item?.type.startsWith('text'))) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst text = clipboardData.getData('text')\n\t\t\tconst selection = window.getSelection()\n\n\t\t\t// If no selection, replace the whole data\n\t\t\tif (!selection.rangeCount) {\n\t\t\t\tthis.updateValue(text)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Generate text and insert\n\t\t\tconst range = selection.getRangeAt(0)\n\t\t\tselection.deleteFromDocument()\n\t\t\trange.insertNode(document.createTextNode(text))\n\n\t\t\t// Put cursor at the end of the selection\n\t\t\tconst newRange = document.createRange()\n\t\t\tnewRange.setStart(event.target, range.endOffset)\n\t\t\tnewRange.collapse(true)\n\t\t\tselection.removeAllRanges()\n\t\t\tselection.addRange(newRange)\n\n\t\t\t// Propagate data\n\t\t\tthis.updateValue(this.$refs.contenteditable.innerHTML)\n\t\t},\n\n\t\t/**\n\t\t * Update the value text from the provided html\n\t\t *\n\t\t * @param {string} htmlOrText the html content (or raw text with @mentions)\n\t\t */\n\t\tupdateValue(htmlOrText) {\n\t\t\tconst text = this.parseContent(htmlOrText)\n\t\t\tthis.localValue = text\n\t\t\tthis.$emit('update:value', text)\n\t\t},\n\n\t\t/**\n\t\t * Update content and local value\n\t\t *\n\t\t * @param {string} value the message value\n\t\t */\n\t\tupdateContent(value) {\n\t\t\tconst renderedContent = this.renderContent(value)\n\t\t\tthis.$refs.contenteditable.innerHTML = renderedContent\n\t\t\tthis.localValue = value\n\t\t},\n\n\t\t/**\n\t\t * Because FF have a decade old bug preventing contenteditable=false\n\t\t * to properly be deleted on backspace, we have to hack 👀\n\t\t * https://stackoverflow.com/a/59383394/3885878\n\t\t * https://stackoverflow.com/a/30574622\n\t\t *\n\t\t * @param {Event} event the delete keydown event\n\t\t */\n\t\tonDelete(event) {\n\t\t\tif (!this.isFF || !window.getSelection) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Either disabled or edit deactivated\n\t\t\tif (!this.canEdit) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// fix backspace bug in FF\n\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=685445\n\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=1665167\n\t\t\tconst selection = window.getSelection()\n\t\t\tconst node = event.target\n\t\t\tif (!selection.isCollapsed || !selection.rangeCount) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst curRange = selection.getRangeAt(selection.rangeCount - 1)\n\t\t\tif (curRange.commonAncestorContainer.nodeType === 3 && curRange.startOffset > 0) {\n\t\t\t\t// we are in child selection. The characters of the text node is being deleted\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst range = document.createRange()\n\t\t\tif (selection.anchorNode !== node) {\n\t\t\t\t// selection is in character mode. expand it to the whole editable field\n\t\t\t\trange.selectNodeContents(node)\n\t\t\t\trange.setEndBefore(selection.anchorNode)\n\t\t\t} else if (selection.anchorOffset > 0) {\n\t\t\t\trange.setEnd(node, selection.anchorOffset)\n\t\t\t} else {\n\t\t\t\t// reached the beginning of editable field\n\t\t\t\treturn\n\t\t\t}\n\t\t\trange.setStart(node, range.endOffset - 1)\n\n\t\t\tconst previousNode = range.cloneContents().lastChild\n\t\t\tif (previousNode && previousNode.contentEditable === 'false') {\n\t\t\t\t// this is some rich content, e.g. smile. We should help the user to delete it\n\t\t\t\trange.deleteContents()\n\t\t\t\tevent.preventDefault()\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * Enter key pressed. Submits if not multiline\n\t\t *\n\t\t * @param {Event} event the keydown event\n\t\t */\n\t\tonEnter(event) {\n\t\t\t// Prevent submitting if multiline\n\t\t\t// or length is over maxlength\n\t\t\t// or autocompletion menu is opened\n\t\t\t// or in a text composition session with IME\n\t\t\tif (this.multiline\n\t\t\t\t|| this.isOverMaxlength\n\t\t\t\t|| this.autocompleteTribute.isActive || this.emojiTribute.isActive || this.linkTribute.isActive\n\t\t\t\t|| this.isComposing) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tevent.preventDefault()\n\t\t\tevent.stopPropagation()\n\t\t\tthis.$emit('submit', event)\n\t\t},\n\n\t\t/**\n\t\t * Ctrl + Enter key pressed is used to submit\n\t\t *\n\t\t * @param {Event} event the keydown event\n\t\t */\n\t\tonCtrlEnter(event) {\n\t\t\tif (this.isOverMaxlength) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.$emit('submit', event)\n\t\t},\n\n\t\t/**\n\t\t * Debounce the autocomplete function\n\t\t */\n\t\tdebouncedAutoComplete: debounce(async function(search, callback) {\n\t\t\tthis.autoComplete(search, callback)\n\t\t}, 100),\n\n\t\tonKeyUp(event) {\n\t\t\t// prevent tribute from opening on keyup\n\t\t\tevent.stopImmediatePropagation()\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n// Standalone styling, independent from server\n.rich-contenteditable__input {\n\toverflow-y: auto;\n\twidth: auto;\n\tmargin: 0;\n\tpadding: 8px;\n\tcursor: text;\n\twhite-space: pre-wrap;\n\tword-break: break-word;\n\tcolor: var(--color-main-text);\n\tborder: 2px solid var(--color-border-dark);\n\tborder-radius: var(--border-radius-large);\n\toutline: none;\n\tbackground-color: var(--color-main-background);\n\tfont-family: var(--font-face);\n\tfont-size: inherit;\n\tmin-height: $clickable-area;\n\tmax-height: $clickable-area * 5.5;\n\n\t// Cannot use :empty because of firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=1513303\n\t&--empty:before {\n\t\tcontent: attr(aria-placeholder);\n\t\tcolor: var(--color-text-maxcontrast);\n\t\tposition: absolute;\n\t}\n\n\t&[contenteditable='false']:not(&--disabled) {\n\t\tcursor: default;\n\t\tbackground-color: transparent;\n\t\tcolor: var(--color-main-text);\n\t\tborder-color: transparent;\n\t\topacity: 1;\n\t\tborder-radius: 0;\n\t}\n\n\t&--multiline {\n\t\tmin-height: $clickable-area * 3;\n\t\t// No max for mutiline\n\t\tmax-height: none;\n\t}\n\n\t&--disabled {\n\t\topacity: $opacity_disabled;\n\t\tcolor: var(--color-text-maxcontrast);\n\t\tborder: 2px solid var(--color-background-darker);\n\t\tborder-radius: var(--border-radius);\n\t\tbackground-color: var(--color-background-dark);\n\t}\n}\n\n</style>\n\n<style lang=\"scss\">\n.tribute-container, .tribute-container-emoji, .tribute-container-link {\n\tz-index: 9000;\n\toverflow: auto;\n\tmin-width: 250px;\n\tmax-width: 300px;\n\t// Show maximum 4 entries and a half to show scroll\n\t// 44px + 10px padding\n\tmax-height: ($clickable-area + 20px) * 4.5;\n\t// Space it out a bit from the text\n\tmargin: 5px 0;\n\tcolor: var(--color-main-text);\n\tborder-radius: var(--border-radius);\n\tbackground: var(--color-main-background);\n\tbox-shadow: 0 1px 5px var(--color-box-shadow);\n}\n\n.tribute-container-emoji, .tribute-container-link {\n\tmin-width: 200px;\n\tmax-width: 200px;\n\tpadding: 4px;\n\t// Show maximum 5 entries and a half to show scroll\n\tmax-height: 35px * 5 + math.div(35px, 2) !important;\n\n\t&__item {\n\t\tborder-radius: 8px;\n\t\tpadding: 4px 8px;\n\t\tmargin-bottom: 4px;\n\t\topacity: 0.8;\n\t\tcursor: pointer;\n\n\t\t// Take care of long names\n\t\twhite-space: nowrap;\n\t\toverflow: hidden;\n\t\ttext-overflow: ellipsis;\n\n\t\t&:last-child {\n\t\t\tmargin-bottom: 0;\n\t\t}\n\n\t\t&__emoji {\n\t\t\tpadding-right: 8px;\n\t\t}\n\t}\n\n\t.highlight {\n\t\topacity: 1;\n\t\tcolor: var(--color-primary-element-light-text);\n\t\tbackground: var(--color-primary-element-light);\n\t\t&, * {\n\t\t\tcursor: pointer;\n\t\t}\n\t}\n}\n\n.tribute-container-link {\n\tmin-width: 200px;\n\tmax-width: 300px;\n\t&__item {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\t&__title {\n\t\t\twhite-space: nowrap;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t}\n\t\t&__icon {\n\t\t\tmargin: auto 0;\n\t\t\twidth: 20px;\n\t\t\theight: 20px;\n\t\t\tobject-fit: contain;\n\t\t\tpadding-right: 8px;\n\t\t\tfilter: var(--background-invert-if-dark);\n\t\t}\n\t}\n}\n\n</style>\n"],"names":["_sfc_main$1","_a","_b","_c","user","size","generateUrl","_sfc_main","VTooltip","richEditor","t","result","item","NcAutoCompleteResult","query","emojiAddRecent","text","cb","emojiResults","emojiSearch","searchProvider","stringLength","listeners","html","smilesCharacters","char","Tribute","getLinkWithPicker","tmpElem","eventData","newElem","error","element","range","selection","event","clipboardData","newRange","htmlOrText","value","renderedContent","node","curRange","previousNode","debounce","search","callback"],"mappings":"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"}
1
+ {"version":3,"file":"NcRichContenteditable.mjs","sources":["../../src/components/NcRichContenteditable/NcAutoCompleteResult.vue","../../src/components/NcRichContenteditable/NcRichContenteditable.vue"],"sourcesContent":["<!--\n - @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>\n -\n - @author John Molakvoæ <skjnldsv@protonmail.com>\n -\n - @license GNU AGPL version 3 or any later version\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n-->\n\n<template>\n\t<div class=\"autocomplete-result\">\n\t\t<!-- Avatar or icon -->\n\t\t<div :class=\"[icon, `autocomplete-result__icon--${avatarUrl ? 'with-avatar' : ''}`]\"\n\t\t\t:style=\"avatarUrl ? { backgroundImage: `url(${avatarUrl})` } : null \"\n\t\t\tclass=\"autocomplete-result__icon\">\n\t\t\t<span v-if=\"status.icon\"\n\t\t\t\tclass=\"autocomplete-result__status autocomplete-result__status--icon\">\n\t\t\t\t{{ status && status.icon || '' }}\n\t\t\t</span>\n\t\t\t<NcIconSvgWrapper v-else-if=\"status.status && status.status !== 'offline'\"\n\t\t\t\tclass=\"autocomplete-result__status\"\n\t\t\t\t:svg=\"userStatusIcon\"\n\t\t\t\t:name=\"userStatusIconName\" />\n\t\t</div>\n\n\t\t<!-- Title and subline -->\n\t\t<span class=\"autocomplete-result__content\">\n\t\t\t<span class=\"autocomplete-result__title\" :title=\"title\">\n\t\t\t\t{{ title }}\n\t\t\t</span>\n\t\t\t<span v-if=\"subline\" class=\"autocomplete-result__subline\">\n\t\t\t\t{{ subline }}\n\t\t\t</span>\n\t\t</span>\n\t</div>\n</template>\n\n<script>\nimport { generateUrl } from '@nextcloud/router'\n\nimport NcIconSvgWrapper from '../NcIconSvgWrapper/index.js'\n\nimport { getUserStatusIcon, getUserStatusIconName } from '../../utils/UserStatus.ts'\n\nexport default {\n\tname: 'NcAutoCompleteResult',\n\n\tcomponents: {\n\t\tNcIconSvgWrapper,\n\t},\n\n\tprops: {\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\t\tsubline: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t\tid: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t\ticon: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\t\ticonUrl: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\t\tsource: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\t\tstatus: {\n\t\t\ttype: [Object, Array],\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\tcomputed: {\n\t\tavatarUrl() {\n\t\t\tif (this.iconUrl) {\n\t\t\t\treturn this.iconUrl\n\t\t\t}\n\n\t\t\treturn this.id && this.source === 'users'\n\t\t\t\t? this.getAvatarUrl(this.id, 44)\n\t\t\t\t: null\n\t\t},\n\t\tuserStatusIcon() {\n\t\t\treturn getUserStatusIcon(this.status.status)\n\t\t},\n\t\tuserStatusIconName() {\n\t\t\treturn getUserStatusIconName(this.status.status)\n\t\t},\n\t},\n\n\tmethods: {\n\t\tgetAvatarUrl(user, size) {\n\t\t\treturn generateUrl('/avatar/{user}/{size}', {\n\t\t\t\tuser,\n\t\t\t\tsize,\n\t\t\t})\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n$autocomplete-padding: 10px;\n\n.autocomplete-result {\n\tdisplay: flex;\n\theight: $clickable-area;\n\tpadding: $autocomplete-padding;\n\n\t.highlight & {\n\t\tcolor: var(--color-primary-element-light-text);\n\t\tbackground: var(--color-primary-element-light);\n\t\t&, * {\n\t\t\tcursor: pointer;\n\t\t}\n\t}\n\n\t&__icon {\n\t\tposition: relative;\n\t\tflex: 0 0 $clickable-area;\n\t\twidth: $clickable-area;\n\t\tmin-width: $clickable-area;\n\t\theight: $clickable-area;\n\t\tborder-radius: $clickable-area;\n\t\tbackground-color: var(--color-background-darker);\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-position: center;\n\t\tbackground-size: $clickable-area - 2 * $autocomplete-padding;\n\t\t&--with-avatar {\n\t\t\tcolor: inherit;\n\t\t\tbackground-size: cover;\n\t\t}\n\t}\n\n\t&__status {\n\t\tbox-sizing: border-box;\n\t\tposition: absolute;\n\t\tright: -4px;\n\t\tbottom: -4px;\n\t\tmin-width: 18px;\n\t\tmin-height: 18px;\n\t\twidth: 18px;\n\t\theight: 18px;\n\t\tborder: 2px solid var(--color-main-background);\n\t\tborder-radius: 50%;\n\t\tbackground-color: var(--color-main-background);\n\t\tfont-size: var(--default-font-size);\n\t\tline-height: 15px;\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-size: 16px;\n\t\tbackground-position: center;\n\n\t\t&--icon {\n\t\t\tborder: none;\n\t\t\tbackground-color: transparent;\n\t\t}\n\t}\n\n\t&__content {\n\t\tdisplay: flex;\n\t\tflex: 1 1 100%;\n\t\tflex-direction: column;\n\t\tjustify-content: center;\n\t\tmin-width: 0;\n\t\tpadding-left: $autocomplete-padding;\n\t}\n\n\t&__title,\n\t&__subline {\n\t\twhite-space: nowrap;\n\t\toverflow: hidden;\n\t\ttext-overflow: ellipsis;\n\t}\n\n\t&__subline {\n\t\tcolor: var(--color-text-maxcontrast);\n\t}\n}\n\n</style>\n","<!--\n - @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>\n -\n - @author John Molakvoæ <skjnldsv@protonmail.com>\n -\n - @license GNU AGPL version 3 or any later version\n -\n - This program is free software: you can redistribute it and/or modify\n - it under the terms of the GNU Affero General Public License as\n - published by the Free Software Foundation, either version 3 of the\n - License, or (at your option) any later version.\n -\n - This program is distributed in the hope that it will be useful,\n - but WITHOUT ANY WARRANTY; without even the implied warranty of\n - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n - GNU Affero General Public License for more details.\n -\n - You should have received a copy of the GNU Affero General Public License\n - along with this program. If not, see <http://www.gnu.org/licenses/>.\n-->\n\n<docs>\n\n### General description\n\nThis component displays contenteditable div with automated `@` [at] autocompletion and `:` [colon] emoji autocompletion.\n\n### Examples\n\nTry mentioning user @Test01 or inserting emoji :smile\n\n```vue\n<template>\n\t<div>\n\t\t<NcRichContenteditable\n\t\t\tlabel=\"Write a comment\"\n\t\t\t:value.sync=\"message\"\n\t\t\t:auto-complete=\"autoComplete\"\n\t\t\t:maxlength=\"100\"\n\t\t\t:user-data=\"userData\"\n\t\t\t@submit=\"onSubmit\" />\n\t\t<br>\n\n\t\t<NcRichContenteditable\n\t\t\t:value.sync=\"message\"\n\t\t\t:auto-complete=\"autoComplete\"\n\t\t\t:maxlength=\"400\"\n\t\t\t:multiline=\"true\"\n\t\t\t:user-data=\"userData\"\n\t\t\t@submit=\"onSubmit\" />\n\n\t\t<h5>Output - raw</h5>\n\t\t{{ JSON.stringify(message) }}\n\n\t\t<h5>Output - preformatted</h5>\n\t\t<p class=\"pre-line\">{{ message }}</p>\n\n\t\t<h5>Output - in NcRichText with markdown support</h5>\n\t\t<NcRichText :text=\"text\" :arguments=\"userMentions\" autolink use-markdown />\n\t</div>\n</template>\n<script>\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\tmessage: '**Lorem ipsum** dolor sit amet.',\n\t\t\t// You need to provide this for the inline mention to understand what to display or not.\n\t\t\t// Key should be a string with leading '@', like @Test02 or @\"Test Offline\"\n\t\t\tuserData: {\n\t\t\t\tTest01: {\n\t\t\t\t\ticon: 'icon-user',\n\t\t\t\t\tid: 'Test01',\n\t\t\t\t\ttitle: 'Test01',\n\t\t\t\t\tsource: 'users',\n\t\t\t\t\tprimary: true,\n\t\t\t\t},\n\t\t\t\tTest02: {\n\t\t\t\t\ticon: 'icon-user',\n\t\t\t\t\tid: 'Test02',\n\t\t\t\t\ttitle: 'Test02',\n\t\t\t\t\tsource: 'users',\n\t\t\t\t\tstatus: {\n\t\t\t\t\t\tclearAt: null,\n\t\t\t\t\t\ticon: '🎡',\n\t\t\t\t\t\tmessage: 'Visiting London',\n\t\t\t\t\t\tstatus: 'away',\n\t\t\t\t\t},\n\t\t\t\t\tsubline: 'Visiting London',\n\t\t\t\t},\n\t\t\t\t'Test@User': {\n\t\t\t\t\ticon: 'icon-user',\n\t\t\t\t\tid: 'Test@User',\n\t\t\t\t\ttitle: 'Test 03',\n\t\t\t\t\tsource: 'users',\n\t\t\t\t\tstatus: {\n\t\t\t\t\t\tclearAt: null,\n\t\t\t\t\t\ticon: '🎡',\n\t\t\t\t\t\tmessage: 'Having space in my name',\n\t\t\t\t\t\tstatus: 'online',\n\t\t\t\t\t},\n\t\t\t\t\tsubline: 'Visiting London',\n\t\t\t\t},\n\t\t\t\t'Test Offline': {\n\t\t\t\t\ticon: 'icon-user',\n\t\t\t\t\tid: 'Test Offline',\n\t\t\t\t\ttitle: 'Test Offline',\n\t\t\t\t\tsource: 'users',\n\t\t\t\t\tstatus: {\n\t\t\t\t\t\tclearAt: null,\n\t\t\t\t\t\ticon: null,\n\t\t\t\t\t\tmessage: null,\n\t\t\t\t\t\tstatus: 'offline',\n\t\t\t\t\t},\n\t\t\t\t\tsubline: null,\n\t\t\t\t},\n\t\t\t\t'Test DND': {\n\t\t\t\t\ticon: 'icon-user',\n\t\t\t\t\tid: 'Test DND',\n\t\t\t\t\ttitle: 'Test DND',\n\t\t\t\t\tsource: 'users',\n\t\t\t\t\tstatus: {\n\t\t\t\t\t\tclearAt: null,\n\t\t\t\t\t\ticon: null,\n\t\t\t\t\t\tmessage: 'Out sick',\n\t\t\t\t\t\tstatus: 'dnd',\n\t\t\t\t\t},\n\t\t\t\t\tsubline: 'Out sick',\n\t\t\t\t},\n\t\t\t},\n\t\t\t// To display user bubbles in NcRichText, special format of data should be provided:\n\t\t\t// Key should be in curly brackets without '@' and ' ' symbols, like {user-2}\n\t\t\tuserMentions: {\n\t\t\t\t'user-1': {\n\t\t\t\t\tcomponent: 'NcUserBubble',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdisplayName: 'Test01',\n\t\t\t\t\t\tuser: 'Test01',\n\t\t\t\t\t\tprimary: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t'user-2': {\n\t\t\t\t\tcomponent: 'NcUserBubble',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdisplayName: 'Test02',\n\t\t\t\t\t\tuser: 'Test02',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t'user-3': {\n\t\t\t\t\tcomponent: 'NcUserBubble',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdisplayName: 'Test 03',\n\t\t\t\t\t\tuser: 'Test@User',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t'user-4': {\n\t\t\t\t\tcomponent: 'NcUserBubble',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdisplayName: 'Test Offline',\n\t\t\t\t\t\tuser: 'Test Offline',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t'user-5': {\n\t\t\t\t\tcomponent: 'NcUserBubble',\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tdisplayName: 'Test DND',\n\t\t\t\t\t\tuser: 'Test DND',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t},\n\tcomputed: {\n\t\ttext() {\n\t\t\treturn this.message\n\t\t\t\t\t.replace('@Test01', '{user-1}')\n\t\t\t\t\t.replace('@Test02', '{user-2}')\n\t\t\t\t\t.replace('@Test@User', '{user-3}')\n\t\t\t\t\t.replace('@\"Test Offline\"', '{user-4}')\n\t\t\t\t\t.replace('@\"Test DND\"', '{user-5}')\n\t\t},\n\t},\n\tmethods: {\n\t\t/**\n\t\t* Do your own query to the autocompletion api.\n\t\t* The returned data bellow is a fake data example.\n\t\t* The callback expects the same format returned by the core/autocomplete/get ocs api endpoint!\n\t\t* @see userData example above\n\t\t*\n\t\t* @param {string} search the query\n\t\t* @param {Function} callback the callback to process the results with\n\t\t*/\n\t\tautoComplete(search, callback) {\n\t\t\tcallback(Object.values(this.userData))\n\t\t},\n\t\tonSubmit() {\n\t\t\talert(this.message)\n\t\t}\n\t}\n}\n</script>\n<style lang=\"scss\" scoped>\n\th5 {\n\t\tfont-weight: bold;\n\t\tmargin: 40px 0 20px 0;\n\t}\n\n\t.pre-line {\n\t\twhite-space: pre-line;\n\t}\n</style>\n```\n\n</docs>\n\n<template>\n\t<div class=\"rich-contenteditable\">\n\t\t<div :id=\"id\"\n\t\t\tref=\"contenteditable\"\n\t\t\tv-tooltip=\"tooltipString\"\n\t\t\t:class=\"{\n\t\t\t\t'rich-contenteditable__input--empty': isEmptyValue,\n\t\t\t\t'rich-contenteditable__input--multiline': multiline,\n\t\t\t\t'rich-contenteditable__input--has-label': label,\n\t\t\t\t'rich-contenteditable__input--overflow': isOverMaxlength,\n\t\t\t\t'rich-contenteditable__input--disabled': disabled,\n\t\t\t}\"\n\t\t\t:contenteditable=\"canEdit\"\n\t\t\t:aria-labelledby=\"label ? labelId : undefined\"\n\t\t\t:aria-placeholder=\"placeholder\"\n\t\t\taria-multiline=\"true\"\n\t\t\tclass=\"rich-contenteditable__input\"\n\t\t\trole=\"textbox\"\n\t\t\tv-bind=\"$attrs\"\n\t\t\tv-on=\"listeners\"\n\t\t\t@focus=\"moveCursorToEnd\"\n\t\t\t@input=\"onInput\"\n\t\t\t@compositionstart=\"isComposing = true\"\n\t\t\t@compositionend=\"isComposing = false\"\n\t\t\t@keydown.delete=\"onDelete\"\n\t\t\t@keydown.enter.exact=\"onEnter\"\n\t\t\t@keydown.ctrl.enter.exact.stop.prevent=\"onCtrlEnter\"\n\t\t\t@paste=\"onPaste\"\n\t\t\t@keyup.stop.prevent.capture=\"onKeyUp\" />\n\t\t<div v-if=\"label\"\n\t\t\t:id=\"labelId\"\n\t\t\tclass=\"rich-contenteditable__label\">\n\t\t\t{{ label }}\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { t } from '../../l10n.js'\nimport NcAutoCompleteResult from './NcAutoCompleteResult.vue'\nimport richEditor from '../../mixins/richEditor/index.js'\nimport Tooltip from '../../directives/Tooltip/index.js'\nimport { emojiSearch, emojiAddRecent } from '../../functions/emoji/index.js'\nimport { searchProvider, getLinkWithPicker } from '../NcRichText/index.js'\n\nimport Tribute from 'tributejs/dist/tribute.esm.js'\nimport debounce from 'debounce'\nimport stringLength from 'string-length'\nimport GenRandomId from '../../utils/GenRandomId.js'\n\nexport default {\n\tname: 'NcRichContenteditable',\n\n\tdirectives: {\n\t\ttooltip: Tooltip,\n\t},\n\n\tmixins: [richEditor],\n\n\tinheritAttrs: false,\n\n\tprops: {\n\t\t/**\n\t\t * The ID attribute of the content editable\n\t\t */\n\t\tid: {\n\t\t\ttype: String,\n\t\t\tdefault: () => GenRandomId(7),\n\t\t},\n\n\t\t/**\n\t\t * Visual label of the contenteditable\n\t\t */\n\t\tlabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\tvalue: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t\trequired: true,\n\t\t},\n\n\t\tplaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: t('Write a message …'),\n\t\t},\n\n\t\tautoComplete: {\n\t\t\ttype: Function,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\tmenuContainer: {\n\t\t\ttype: Element,\n\t\t\tdefault: () => document.body,\n\t\t},\n\n\t\t/**\n\t\t * Make the contenteditable looks like a textarea or not.\n\t\t * Default looks like a single-line input.\n\t\t * This also handle the default enter/shift+enter behaviour.\n\t\t * if multiline, enter = newline; otherwise enter = submit\n\t\t * shift+enter always add a new line. ctrl+enter always submits\n\t\t */\n\t\tmultiline: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Is the content editable ?\n\t\t */\n\t\tcontenteditable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Disable the editing and show specific disabled design\n\t\t */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Max allowed length\n\t\t */\n\t\tmaxlength: {\n\t\t\ttype: Number,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Enable or disable emoji autocompletion\n\t\t */\n\t\temojiAutocomplete: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Enable or disable link autocompletion\n\t\t */\n\t\tlinkAutocomplete: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\t},\n\n\temits: [\n\t\t'submit',\n\t\t'paste',\n\t\t'update:value',\n\t\t'smart-picker-submit',\n\t],\n\n\tdata() {\n\t\treturn {\n\t\t\tlabelId: `rich-label-${GenRandomId(5)}`,\n\t\t\ttextSmiles: [],\n\t\t\ttribute: null,\n\t\t\tautocompleteOptions: {\n\t\t\t\t// Allow spaces in the middle of mentions\n\t\t\t\tallowSpaces: true,\n\t\t\t\tfillAttr: 'id',\n\t\t\t\t// Search against id and title (display name)\n\t\t\t\tlookup: result => `${result.id} ${result.title}`,\n\t\t\t\t// Where to inject the menu popup\n\t\t\t\tmenuContainer: this.menuContainer,\n\t\t\t\t// Popup mention autocompletion templates\n\t\t\t\tmenuItemTemplate: item => this.renderComponentHtml(item.original, NcAutoCompleteResult),\n\t\t\t\t// Hide if no results\n\t\t\t\tnoMatchTemplate: () => '<span class=\"hidden\"></span>',\n\t\t\t\t// Inner display of mentions\n\t\t\t\tselectTemplate: item => this.genSelectTemplate(item?.original?.id),\n\t\t\t\t// Autocompletion results\n\t\t\t\tvalues: this.debouncedAutoComplete,\n\t\t\t},\n\t\t\temojiOptions: {\n\t\t\t\ttrigger: ':',\n\t\t\t\t// Don't use the tribute search function at all\n\t\t\t\t// We pass search results as values (see below)\n\t\t\t\tlookup: (result, query) => query,\n\t\t\t\t// Where to inject the menu popup\n\t\t\t\tmenuContainer: this.menuContainer,\n\t\t\t\t// Popup mention autocompletion templates\n\t\t\t\tmenuItemTemplate: item => {\n\t\t\t\t\tif (this.textSmiles.includes(item.original)) {\n\t\t\t\t\t\t// Display the raw text string for :), :-D, … for non emoji results,\n\t\t\t\t\t\t// instead of trying to show an image and their name.\n\t\t\t\t\t\treturn item.original\n\t\t\t\t\t}\n\n\t\t\t\t\treturn `<span class=\"tribute-container-emoji__item__emoji\">${item.original.native}</span> :${item.original.short_name}`\n\t\t\t\t},\n\t\t\t\t// Hide if no results\n\t\t\t\tnoMatchTemplate: () => t('No emoji found'),\n\t\t\t\t// Display raw emoji along with its name\n\t\t\t\tselectTemplate: (item) => {\n\t\t\t\t\tif (this.textSmiles.includes(item.original)) {\n\t\t\t\t\t\t// Replace the selection with the raw text string for :), :-D, … for non emoji results\n\t\t\t\t\t\treturn item.original\n\t\t\t\t\t}\n\n\t\t\t\t\temojiAddRecent(item.original)\n\t\t\t\t\treturn item.original.native\n\t\t\t\t},\n\t\t\t\t// Pass the search results as values\n\t\t\t\tvalues: (text, cb) => {\n\t\t\t\t\tconst emojiResults = emojiSearch(text)\n\t\t\t\t\tif (this.textSmiles.includes(':' + text)) {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Prepend text smiles to the search results so that Tribute\n\t\t\t\t\t\t * is not interfering with normal writing, aka. \"Cocos Island Meme\".\n\t\t\t\t\t\t * E.g. `:)` and `:-)` got replaced by the flag of Cocos Island,\n\t\t\t\t\t\t * when submitting the input with Enter after writing them\n\t\t\t\t\t\t */\n\t\t\t\t\t\temojiResults.unshift(':' + text)\n\t\t\t\t\t}\n\t\t\t\t\tcb(emojiResults)\n\t\t\t\t},\n\t\t\t\t// Class added to the menu container\n\t\t\t\tcontainerClass: 'tribute-container-emoji',\n\t\t\t\t// Class added to each list item\n\t\t\t\titemClass: 'tribute-container-emoji__item',\n\t\t\t},\n\t\t\tlinkOptions: {\n\t\t\t\ttrigger: '/',\n\t\t\t\t// Don't use the tribute search function at all\n\t\t\t\t// We pass search results as values (see below)\n\t\t\t\tlookup: (result, query) => query,\n\t\t\t\t// Where to inject the menu popup\n\t\t\t\tmenuContainer: this.menuContainer,\n\t\t\t\t// Popup mention autocompletion templates\n\t\t\t\tmenuItemTemplate: item => `<img class=\"tribute-container-link__item__icon\" src=\"${item.original.icon_url}\"> <span class=\"tribute-container-link__item__title\">${item.original.title}</span>`,\n\t\t\t\t// Hide if no results\n\t\t\t\tnoMatchTemplate: () => t('No link provider found'),\n\t\t\t\tselectTemplate: this.getLink,\n\t\t\t\t// Pass the search results as values\n\t\t\t\tvalues: (text, cb) => cb(searchProvider(text)),\n\t\t\t\t// Class added to the menu container\n\t\t\t\tcontainerClass: 'tribute-container-link',\n\t\t\t\t// Class added to each list item\n\t\t\t\titemClass: 'tribute-container-link__item',\n\t\t\t},\n\n\t\t\t// Represent the raw untrimmed text of the contenteditable\n\t\t\t// serves no other purpose than to check whether the\n\t\t\t// content is empty or not\n\t\t\tlocalValue: this.value,\n\n\t\t\t// Is in text composition session in IME\n\t\t\tisComposing: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * Is the current trimmed value empty?\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisEmptyValue() {\n\t\t\treturn !this.localValue || this.localValue.trim() === ''\n\t\t},\n\n\t\t/**\n\t\t * Is this Firefox? 🙄\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisFF() {\n\t\t\treturn !!navigator.userAgent.match(/firefox/i)\n\t\t},\n\n\t\t/**\n\t\t * Is the current value over maxlength?\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisOverMaxlength() {\n\t\t\tif (this.isEmptyValue || !this.maxlength) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn stringLength(this.localValue) > this.maxlength\n\t\t},\n\n\t\t/**\n\t\t * Tooltip to show if characters count is over limit\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\ttooltipString() {\n\t\t\tif (!this.isOverMaxlength) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tcontent: t('Message limit of {count} characters reached', { count: this.maxlength }),\n\t\t\t\tshown: true,\n\t\t\t\ttrigger: 'manual',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Edit is only allowed when contenteditableis true and disabled is false\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tcanEdit() {\n\t\t\treturn this.contenteditable && !this.disabled\n\t\t},\n\n\t\t/**\n\t\t * Proxied native event handlers without custom event handlers\n\t\t *\n\t\t * @return {Record<string, Function>}\n\t\t */\n\t\tlisteners() {\n\t\t\t/**\n\t\t\t * All component's event handlers are set as native event handlers with by v-on directive.\n\t\t\t * The component also raised custom events manually by $emit for corresponding events.\n\t\t\t * As a result, it triggers handlers twice.\n\t\t\t * The v-on=\"listeners\" directive should only set proxied native events handler without custom events\n\t\t\t */\n\t\t\tconst listeners = { ...this.$listeners }\n\t\t\tdelete listeners.paste\n\t\t\treturn listeners\n\t\t},\n\t},\n\n\twatch: {\n\t\t/**\n\t\t * If the parent value change, we compare the plain text rendering\n\t\t * If it's different, we render everything and update the main content\n\t\t */\n\t\tvalue() {\n\t\t\tconst html = this.$refs.contenteditable.innerHTML\n\t\t\t// Compare trimmed versions to be safe\n\t\t\tif (this.value.trim() !== this.parseContent(html).trim()) {\n\t\t\t\tthis.updateContent(this.value)\n\t\t\t}\n\t\t},\n\t},\n\n\tmounted() {\n\t\t/**\n\t\t * Populate the list of text smiles we want to offer via Tribute.\n\t\t * We add the colon `:)` and colon-dash `:-)` version for each of them.\n\t\t */\n\t\tconst smilesCharacters = ['d', 'D', 'p', 'P', 's', 'S', 'x', 'X', ')', '(', '|', '/']\n\t\tthis.textSmiles = []\n\t\tsmilesCharacters.forEach((char) => {\n\t\t\tthis.textSmiles.push(':' + char)\n\t\t\tthis.textSmiles.push(':-' + char)\n\t\t})\n\n\t\tthis.autocompleteTribute = new Tribute(this.autocompleteOptions)\n\t\tthis.autocompleteTribute.attach(this.$refs.contenteditable)\n\n\t\tif (this.emojiAutocomplete) {\n\t\t\tthis.emojiTribute = new Tribute(this.emojiOptions)\n\t\t\tthis.emojiTribute.attach(this.$refs.contenteditable)\n\t\t}\n\n\t\tif (this.linkAutocomplete) {\n\t\t\tthis.linkTribute = new Tribute(this.linkOptions)\n\t\t\tthis.linkTribute.attach(this.$refs.contenteditable)\n\t\t}\n\n\t\t// Update default value\n\t\tthis.updateContent(this.value)\n\n\t\t// Removes the contenteditable attribute at first load if the prop is\n\t\t// set to false.\n\t\tthis.$refs.contenteditable.contentEditable = this.canEdit\n\t},\n\tbeforeDestroy() {\n\t\tif (this.autocompleteTribute) {\n\t\t\tthis.autocompleteTribute.detach(this.$refs.contenteditable)\n\t\t}\n\t\tif (this.emojiTribute) {\n\t\t\tthis.emojiTribute.detach(this.$refs.contenteditable)\n\t\t}\n\t\tif (this.linkTribute) {\n\t\t\tthis.linkTribute.detach(this.$refs.contenteditable)\n\t\t}\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Focus the richContenteditable\n\t\t *\n\t\t * @public\n\t\t */\n\t\tfocus() {\n\t\t\tthis.$refs.contenteditable.focus()\n\t\t},\n\n\t\tgetLink(item) {\n\t\t\t// there is no way to get a tribute result asynchronously\n\t\t\t// so we immediately insert a node and replace it when the result comes\n\t\t\tgetLinkWithPicker(item.original.id)\n\t\t\t\t.then(result => {\n\t\t\t\t\t// replace dummy temp element by a text node which contains the picker result\n\t\t\t\t\tconst tmpElem = document.getElementById('tmp-smart-picker-result-node')\n\t\t\t\t\tconst eventData = {\n\t\t\t\t\t\tresult,\n\t\t\t\t\t\tinsertText: true,\n\t\t\t\t\t}\n\t\t\t\t\tthis.$emit('smart-picker-submit', eventData)\n\t\t\t\t\tif (eventData.insertText) {\n\t\t\t\t\t\tconst newElem = document.createTextNode(result)\n\t\t\t\t\t\ttmpElem.replaceWith(newElem)\n\t\t\t\t\t\tthis.setCursorAfter(newElem)\n\t\t\t\t\t\tthis.updateValue(this.$refs.contenteditable.innerHTML)\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttmpElem.remove()\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tconsole.debug('Smart picker promise rejected:', error)\n\t\t\t\t\tconst tmpElem = document.getElementById('tmp-smart-picker-result-node')\n\t\t\t\t\tthis.setCursorAfter(tmpElem)\n\t\t\t\t\ttmpElem.remove()\n\t\t\t\t})\n\t\t\treturn '<span id=\"tmp-smart-picker-result-node\"></span>'\n\t\t},\n\t\tsetCursorAfter(element) {\n\t\t\tconst range = document.createRange()\n\t\t\trange.setEndAfter(element)\n\t\t\trange.collapse()\n\t\t\tconst selection = window.getSelection()\n\t\t\tselection.removeAllRanges()\n\t\t\tselection.addRange(range)\n\t\t},\n\t\tmoveCursorToEnd() {\n\t\t\tif (!document.createRange) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst range = document.createRange()\n\t\t\trange.selectNodeContents(this.$refs.contenteditable)\n\t\t\trange.collapse(false)\n\t\t\tconst selection = window.getSelection()\n\t\t\tselection.removeAllRanges()\n\t\t\tselection.addRange(range)\n\t\t},\n\t\t/**\n\t\t * Re-emit the input event to the parent\n\t\t *\n\t\t * @param {Event} event the input event\n\t\t */\n\t\tonInput(event) {\n\t\t\tthis.updateValue(event.target.innerHTML)\n\t\t},\n\n\t\t/**\n\t\t * When pasting, sanitize the content, extract text\n\t\t * and render it again\n\t\t *\n\t\t * @param {Event} event the paste event\n\t\t * @fires Event paste the original paste event\n\t\t */\n\t\tonPaste(event) {\n\t\t\t// Either disabled or edit deactivated\n\t\t\tif (!this.canEdit) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tevent.preventDefault()\n\t\t\tconst clipboardData = event.clipboardData\n\n\t\t\t/** The original paste event */\n\t\t\tthis.$emit('paste', event)\n\n\t\t\t// If we have a file or if we don't have any text, ignore\n\t\t\tif (clipboardData.files.length !== 0\n\t\t\t\t|| !Object.values(clipboardData.items).find(item => item?.type.startsWith('text'))) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst text = clipboardData.getData('text')\n\t\t\tconst selection = window.getSelection()\n\n\t\t\t// If no selection, replace the whole data\n\t\t\tif (!selection.rangeCount) {\n\t\t\t\tthis.updateValue(text)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Generate text and insert\n\t\t\tconst range = selection.getRangeAt(0)\n\t\t\tselection.deleteFromDocument()\n\t\t\trange.insertNode(document.createTextNode(text))\n\n\t\t\t// Put cursor at the end of the selection\n\t\t\tconst newRange = document.createRange()\n\t\t\tnewRange.setStart(event.target, range.endOffset)\n\t\t\tnewRange.collapse(true)\n\t\t\tselection.removeAllRanges()\n\t\t\tselection.addRange(newRange)\n\n\t\t\t// Propagate data\n\t\t\tthis.updateValue(this.$refs.contenteditable.innerHTML)\n\t\t},\n\n\t\t/**\n\t\t * Update the value text from the provided html\n\t\t *\n\t\t * @param {string} htmlOrText the html content (or raw text with @mentions)\n\t\t */\n\t\tupdateValue(htmlOrText) {\n\t\t\tconst text = this.parseContent(htmlOrText)\n\t\t\tthis.localValue = text\n\t\t\tthis.$emit('update:value', text)\n\t\t},\n\n\t\t/**\n\t\t * Update content and local value\n\t\t *\n\t\t * @param {string} value the message value\n\t\t */\n\t\tupdateContent(value) {\n\t\t\tconst renderedContent = this.renderContent(value)\n\t\t\tthis.$refs.contenteditable.innerHTML = renderedContent\n\t\t\tthis.localValue = value\n\t\t},\n\n\t\t/**\n\t\t * Because FF have a decade old bug preventing contenteditable=false\n\t\t * to properly be deleted on backspace, we have to hack 👀\n\t\t * https://stackoverflow.com/a/59383394/3885878\n\t\t * https://stackoverflow.com/a/30574622\n\t\t *\n\t\t * @param {Event} event the delete keydown event\n\t\t */\n\t\tonDelete(event) {\n\t\t\tif (!this.isFF || !window.getSelection) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Either disabled or edit deactivated\n\t\t\tif (!this.canEdit) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// fix backspace bug in FF\n\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=685445\n\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=1665167\n\t\t\tconst selection = window.getSelection()\n\t\t\tconst node = event.target\n\t\t\tif (!selection.isCollapsed || !selection.rangeCount) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst curRange = selection.getRangeAt(selection.rangeCount - 1)\n\t\t\tif (curRange.commonAncestorContainer.nodeType === 3 && curRange.startOffset > 0) {\n\t\t\t\t// we are in child selection. The characters of the text node is being deleted\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst range = document.createRange()\n\t\t\tif (selection.anchorNode !== node) {\n\t\t\t\t// selection is in character mode. expand it to the whole editable field\n\t\t\t\trange.selectNodeContents(node)\n\t\t\t\trange.setEndBefore(selection.anchorNode)\n\t\t\t} else if (selection.anchorOffset > 0) {\n\t\t\t\trange.setEnd(node, selection.anchorOffset)\n\t\t\t} else {\n\t\t\t\t// reached the beginning of editable field\n\t\t\t\treturn\n\t\t\t}\n\t\t\trange.setStart(node, range.endOffset - 1)\n\n\t\t\tconst previousNode = range.cloneContents().lastChild\n\t\t\tif (previousNode && previousNode.contentEditable === 'false') {\n\t\t\t\t// this is some rich content, e.g. smile. We should help the user to delete it\n\t\t\t\trange.deleteContents()\n\t\t\t\tevent.preventDefault()\n\t\t\t}\n\t\t},\n\t\t/**\n\t\t * Enter key pressed. Submits if not multiline\n\t\t *\n\t\t * @param {Event} event the keydown event\n\t\t */\n\t\tonEnter(event) {\n\t\t\t// Prevent submitting if multiline\n\t\t\t// or length is over maxlength\n\t\t\t// or autocompletion menu is opened\n\t\t\t// or in a text composition session with IME\n\t\t\tif (this.multiline\n\t\t\t\t|| this.isOverMaxlength\n\t\t\t\t|| this.autocompleteTribute.isActive || this.emojiTribute.isActive || this.linkTribute.isActive\n\t\t\t\t|| this.isComposing) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tevent.preventDefault()\n\t\t\tevent.stopPropagation()\n\t\t\tthis.$emit('submit', event)\n\t\t},\n\n\t\t/**\n\t\t * Ctrl + Enter key pressed is used to submit\n\t\t *\n\t\t * @param {Event} event the keydown event\n\t\t */\n\t\tonCtrlEnter(event) {\n\t\t\tif (this.isOverMaxlength) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.$emit('submit', event)\n\t\t},\n\n\t\t/**\n\t\t * Debounce the autocomplete function\n\t\t */\n\t\tdebouncedAutoComplete: debounce(async function(search, callback) {\n\t\t\tthis.autoComplete(search, callback)\n\t\t}, 100),\n\n\t\tonKeyUp(event) {\n\t\t\t// prevent tribute from opening on keyup\n\t\t\tevent.stopImmediatePropagation()\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n// Standalone styling, independent from server\n.rich-contenteditable {\n\tposition: relative;\n\twidth: auto;\n\n\t&__label {\n\t\tposition: absolute;\n\t\tmargin-inline: 14px 0;\n\t\tmax-width: fit-content;\n\t\tinset-block-start: 11px;\n\t\tinset-inline: 0;\n\t\t// Fix color so that users do not think the input already has content\n\t\tcolor: var(--color-text-maxcontrast);\n\t\t// only one line labels are allowed\n\t\twhite-space: nowrap;\n\t\toverflow: hidden;\n\t\ttext-overflow: ellipsis;\n\t\t// forward events to input\n\t\tpointer-events: none;\n\t\t// Position transition\n\t\ttransition: height var(--animation-quick), inset-block-start var(--animation-quick), font-size var(--animation-quick), color var(--animation-quick), background-color var(--animation-quick) var(--animation-slow);\n\t}\n\n\t&__input:focus + &__label,\n\t&__input:not(&__input--empty) + &__label {\n\t\tinset-block-start: -10px;\n\t\tfont-size: 13px; // minimum allowed font size for accessibility\n\t\tfont-weight: 500;\n\t\tborder-radius: var(--default-grid-baseline) var(--default-grid-baseline) 0 0;\n\t\tbackground-color: var(--color-main-background);\n\t\tpadding-inline: 5px;\n\t\tmargin-inline-start: 9px;\n\n\t\ttransition: height var(--animation-quick), inset-block-start var(--animation-quick), font-size var(--animation-quick), color var(--animation-quick);\n\t}\n\n\t&__input {\n\t\toverflow-y: auto;\n\t\twidth: auto;\n\t\tmargin: 0;\n\t\tpadding: 8px;\n\t\tcursor: text;\n\t\twhite-space: pre-wrap;\n\t\tword-break: break-word;\n\t\tcolor: var(--color-main-text);\n\t\tborder: 2px solid var(--color-border-maxcontrast);\n\t\tborder-radius: var(--border-radius-large);\n\t\toutline: none;\n\t\tbackground-color: var(--color-main-background);\n\t\tfont-family: var(--font-face);\n\t\tfont-size: inherit;\n\t\tmin-height: $clickable-area;\n\t\tmax-height: $clickable-area * 5.5;\n\n\t\t&--has-label {\n\t\t\tmargin-top: 10px;\n\t\t}\n\n\t\t// Cannot use :empty because of firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=1513303\n\t\t&--empty:focus:before,\n\t\t&--empty:not(&--has-label):before {\n\t\t\tcontent: attr(aria-placeholder);\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t\tposition: absolute;\n\t\t}\n\n\t\t&[contenteditable='false']:not(&--disabled) {\n\t\t\tcursor: default;\n\t\t\tbackground-color: transparent;\n\t\t\tcolor: var(--color-main-text);\n\t\t\tborder-color: transparent;\n\t\t\topacity: 1;\n\t\t\tborder-radius: 0;\n\t\t}\n\n\t\t&--multiline {\n\t\t\tmin-height: $clickable-area * 3;\n\t\t\t// No max for mutiline\n\t\t\tmax-height: none;\n\t\t}\n\n\t\t&--disabled {\n\t\t\topacity: $opacity_disabled;\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t\tborder: 2px solid var(--color-background-darker);\n\t\t\tborder-radius: var(--border-radius);\n\t\t\tbackground-color: var(--color-background-dark);\n\t\t}\n\t}\n}\n\n</style>\n\n<style lang=\"scss\">\n.tribute-container, .tribute-container-emoji, .tribute-container-link {\n\tz-index: 9000;\n\toverflow: auto;\n\tmin-width: 250px;\n\tmax-width: 300px;\n\t// Show maximum 4 entries and a half to show scroll\n\t// 44px + 10px padding\n\tmax-height: ($clickable-area + 20px) * 4.5;\n\t// Space it out a bit from the text\n\tmargin: 5px 0;\n\tcolor: var(--color-main-text);\n\tborder-radius: var(--border-radius);\n\tbackground: var(--color-main-background);\n\tbox-shadow: 0 1px 5px var(--color-box-shadow);\n}\n\n.tribute-container-emoji, .tribute-container-link {\n\tmin-width: 200px;\n\tmax-width: 200px;\n\tpadding: 4px;\n\t// Show maximum 5 entries and a half to show scroll\n\tmax-height: 35px * 5 + math.div(35px, 2) !important;\n\n\t&__item {\n\t\tborder-radius: 8px;\n\t\tpadding: 4px 8px;\n\t\tmargin-bottom: 4px;\n\t\topacity: 0.8;\n\t\tcursor: pointer;\n\n\t\t// Take care of long names\n\t\twhite-space: nowrap;\n\t\toverflow: hidden;\n\t\ttext-overflow: ellipsis;\n\n\t\t&:last-child {\n\t\t\tmargin-bottom: 0;\n\t\t}\n\n\t\t&__emoji {\n\t\t\tpadding-right: 8px;\n\t\t}\n\t}\n\n\t.highlight {\n\t\topacity: 1;\n\t\tcolor: var(--color-primary-element-light-text);\n\t\tbackground: var(--color-primary-element-light);\n\t\t&, * {\n\t\t\tcursor: pointer;\n\t\t}\n\t}\n}\n\n.tribute-container-link {\n\tmin-width: 200px;\n\tmax-width: 300px;\n\t&__item {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\t&__title {\n\t\t\twhite-space: nowrap;\n\t\t\toverflow: hidden;\n\t\t\ttext-overflow: ellipsis;\n\t\t}\n\t\t&__icon {\n\t\t\tmargin: auto 0;\n\t\t\twidth: 20px;\n\t\t\theight: 20px;\n\t\t\tobject-fit: contain;\n\t\t\tpadding-right: 8px;\n\t\t\tfilter: var(--background-invert-if-dark);\n\t\t}\n\t}\n}\n\n</style>\n"],"names":["_sfc_main$1","NcIconSvgWrapper","getUserStatusIcon","getUserStatusIconName","user","size","generateUrl","_sfc_main","VTooltip","richEditor","GenRandomId","t","result","item","NcAutoCompleteResult","_a","query","emojiAddRecent","text","cb","emojiResults","emojiSearch","searchProvider","stringLength","listeners","html","smilesCharacters","char","Tribute","getLinkWithPicker","tmpElem","eventData","newElem","error","element","range","selection","event","clipboardData","newRange","htmlOrText","value","renderedContent","node","curRange","previousNode","debounce","search","callback"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperties(exports, { __esModule: { value: !0 }, [Symbol.toStringTag]: { value: "Module" } });
3
- const r = require("../chunks/NcRichText-0dd96aac.cjs"), e = require("../chunks/referencePickerModal-90dac0d0.cjs");
3
+ const r = require("../chunks/NcRichText-f729896c.cjs"), e = require("../chunks/referencePickerModal-12fa2ad0.cjs");
4
4
  /**
5
5
  * @copyright Copyright (c) 2023 Raimund Schlüßler <raimund.schluessler@mailbox.org>
6
6
  *
@@ -1,6 +1,6 @@
1
- import { N as r } from "../chunks/NcRichText-0db09c78.mjs";
2
- import { a as t } from "../chunks/NcRichText-0db09c78.mjs";
3
- import { e as c, a as d, b as o, N as n, c as g, k as m, j as P, l as k, m as f, h as N, i as R, f as l, r as u, g as h, d as v, n as W, s as p } from "../chunks/referencePickerModal-ded8273d.mjs";
1
+ import { N as r } from "../chunks/NcRichText-e4bf7767.mjs";
2
+ import { a as t } from "../chunks/NcRichText-e4bf7767.mjs";
3
+ import { e as c, a as d, b as o, N as n, c as g, k as m, j as P, l as k, m as f, h as N, i as R, f as l, r as u, g as h, d as v, n as W, s as p } from "../chunks/referencePickerModal-12935fb3.mjs";
4
4
  /**
5
5
  * @copyright Copyright (c) 2023 Raimund Schlüßler <raimund.schluessler@mailbox.org>
6
6
  *
@@ -1,34 +1,32 @@
1
- var I = require("../assets/index-f9bfa317.css");
1
+ var N = require("../assets/index-f9bfa317.css");
2
2
  require("@nextcloud/vue-select/dist/vue-select.css");
3
- const c = require("@nextcloud/vue-select"), a = require("@floating-ui/dom"), u = require("../chunks/l10n-070da9ad.cjs"), f = require("../chunks/ChevronDown-dc32e51d.cjs"), d = require("../chunks/Close-98cb6f12.cjs"), m = require("./NcEllipsisedOption.cjs"), y = require("./NcListItemIcon.cjs"), _ = require("./NcLoadingIcon.cjs"), h = require("../chunks/l10n-38626490.cjs"), g = require("../chunks/GenRandomId-c214d235.cjs"), S = require("../chunks/_plugin-vue2_normalizer-7f9efb60.cjs");
4
- const b = {
3
+ const i = require("@nextcloud/vue-select"), a = require("@floating-ui/dom"), c = require("../chunks/_l10n-72c5e29e.cjs"), f = require("../chunks/ChevronDown-dc32e51d.cjs"), d = require("../chunks/Close-98cb6f12.cjs"), m = require("./NcEllipsisedOption.cjs"), y = require("./NcListItemIcon.cjs"), _ = require("./NcLoadingIcon.cjs"), h = require("../chunks/GenRandomId-c214d235.cjs"), g = require("../chunks/_plugin-vue2_normalizer-7f9efb60.cjs");
4
+ c.register(c.t14);
5
+ const S = {
5
6
  name: "NcSelect",
6
7
  components: {
7
8
  ChevronDown: f.ChevronDown,
8
9
  NcEllipsisedOption: m,
9
10
  NcListItemIcon: y,
10
11
  NcLoadingIcon: _,
11
- VueSelect: c.VueSelect
12
+ VueSelect: i.VueSelect
12
13
  },
13
- mixins: [
14
- h.l10n
15
- ],
16
14
  props: {
17
15
  // Add VueSelect props to $props
18
- ...c.VueSelect.props,
16
+ ...i.VueSelect.props,
19
17
  /**
20
18
  * `aria-label` for the clear input button
21
19
  */
22
20
  ariaLabelClearSelected: {
23
21
  type: String,
24
- default: u.t("Clear selected")
22
+ default: c.t("Clear selected")
25
23
  },
26
24
  /**
27
25
  * `aria-label` for the search input
28
26
  */
29
27
  ariaLabelCombobox: {
30
28
  type: String,
31
- default: u.t("Search for options")
29
+ default: c.t("Search for options")
32
30
  },
33
31
  /**
34
32
  * Allows to customize the `aria-label` for the deselect-option button
@@ -37,7 +35,7 @@ const b = {
37
35
  */
38
36
  ariaLabelDeselectOption: {
39
37
  type: Function,
40
- default: (l) => u.t("Deselect {option}", { option: l })
38
+ default: (l) => c.t("Deselect {option}", { option: l })
41
39
  },
42
40
  /**
43
41
  * Append the dropdown element to the end of the body
@@ -258,7 +256,7 @@ const b = {
258
256
  */
259
257
  uid: {
260
258
  type: String,
261
- default: () => "-" + g.GenRandomId()
259
+ default: () => "-" + h.GenRandomId()
262
260
  },
263
261
  /**
264
262
  * When `appendToBody` is true, this sets the placement of the dropdown
@@ -370,13 +368,13 @@ const b = {
370
368
  localFilterBy() {
371
369
  const l = /[^<]*<([^>]+)/;
372
370
  return this.filterBy !== null ? this.filterBy : this.userSelect ? (e, n, t) => {
373
- var r, i, s;
371
+ var r, u, s;
374
372
  const o = t.match(l);
375
- return o && ((s = (i = (r = e.subname) == null ? void 0 : r.toLocaleLowerCase) == null ? void 0 : i.call(r)) == null ? void 0 : s.indexOf(o[1].toLocaleLowerCase())) > -1 || `${n} ${e.subname}`.toLocaleLowerCase().indexOf(t.toLocaleLowerCase()) > -1;
376
- } : c.VueSelect.props.filterBy.default;
373
+ return o && ((s = (u = (r = e.subname) == null ? void 0 : r.toLocaleLowerCase) == null ? void 0 : u.call(r)) == null ? void 0 : s.indexOf(o[1].toLocaleLowerCase())) > -1 || `${n} ${e.subname}`.toLocaleLowerCase().indexOf(t.toLocaleLowerCase()) > -1;
374
+ } : i.VueSelect.props.filterBy.default;
377
375
  },
378
376
  localLabel() {
379
- return this.label !== null ? this.label : this.userSelect ? "displayName" : c.VueSelect.props.label.default;
377
+ return this.label !== null ? this.label : this.userSelect ? "displayName" : i.VueSelect.props.label.default;
380
378
  },
381
379
  propsToForward() {
382
380
  const {
@@ -396,9 +394,12 @@ const b = {
396
394
  label: this.localLabel
397
395
  };
398
396
  }
397
+ },
398
+ methods: {
399
+ t: c.t
399
400
  }
400
401
  };
401
- var C = function() {
402
+ var b = function() {
402
403
  var e = this, n = e._self._c;
403
404
  return n("VueSelect", e._g(e._b({ staticClass: "select", class: {
404
405
  "select--no-wrap": e.noWrap,
@@ -420,15 +421,15 @@ var C = function() {
420
421
  return [e._t(o, null, null, r)];
421
422
  } };
422
423
  })], null, !0) }, "VueSelect", e.propsToForward, !1), e.$listeners));
423
- }, L = [], v = /* @__PURE__ */ S.normalizeComponent(
424
+ }, C = [], L = /* @__PURE__ */ g.normalizeComponent(
425
+ S,
424
426
  b,
425
427
  C,
426
- L,
427
428
  !1,
428
429
  null,
429
430
  null,
430
431
  null,
431
432
  null
432
433
  );
433
- const N = v.exports;
434
- module.exports = N;
434
+ const v = L.exports;
435
+ module.exports = v;
@@ -1 +1 @@
1
- {"version":3,"file":"NcSelect.cjs","sources":["../../src/components/NcSelect/NcSelect.vue"],"sourcesContent":["<!--\n\t- @copyright 2022 Christopher Ng <chrng8@gmail.com>\n\t-\n\t- @author Christopher Ng <chrng8@gmail.com>\n\t-\n\t- @license AGPL-3.0-or-later\n\t-\n\t- This program is free software: you can redistribute it and/or modify\n\t- it under the terms of the GNU Affero General Public License as\n\t- published by the Free Software Foundation, either version 3 of the\n\t- License, or (at your option) any later version.\n\t-\n\t- This program is distributed in the hope that it will be useful,\n\t- but WITHOUT ANY WARRANTY; without even the implied warranty of\n\t- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\t- GNU Affero General Public License for more details.\n\t-\n\t- You should have received a copy of the GNU Affero General Public License\n\t- along with this program. If not, see <http://www.gnu.org/licenses/>.\n\t-\n-->\n\n<docs>\n### Description\n\nGeneral purpose multiselect component.\n\n### Basic examples\n\n```vue\n<template>\n\t<div class=\"grid\">\n\t\t<div v-for=\"{ name, props } in selectArray\"\n\t\t\tclass=\"container\">\n\t\t\t<label :for=\"props.inputId\">{{ name }}</label>\n\t\t\t<NcSelect v-bind=\"props\"\n\t\t\t\tv-model=\"props.value\" />\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport GenRandomId from '../../utils/GenRandomId.js'\n\nconst getRandomId = () => {\n\treturn `select-${GenRandomId()}`\n}\n\nconst selectArray = [\n\t{\n\t\tname: 'Simple',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\toptions: [\n\t\t\t\t'foo',\n\t\t\t\t'bar',\n\t\t\t\t'baz',\n\t\t\t\t'qux',\n\t\t\t\t'quux',\n\t\t\t],\n\t\t},\n\t},\n\n\t{\n\t\tname: 'Simple (top placement)',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\tplacement: 'top',\n\t\t\toptions: [\n\t\t\t\t'foo',\n\t\t\t\t'bar',\n\t\t\t\t'baz',\n\t\t\t\t'qux',\n\t\t\t\t'quux',\n\t\t\t],\n\t\t},\n\t},\n\n\t{\n\t\tname: 'Multiple (with placeholder)',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\tmultiple: true,\n\t\t\tplaceholder: 'Select multiple options',\n\t\t\toptions: [\n\t\t\t\t'foo',\n\t\t\t\t'bar',\n\t\t\t\t'baz',\n\t\t\t\t'qux',\n\t\t\t\t'quux',\n\t\t\t],\n\t\t},\n\t},\n\n\t{\n\t\tname: 'Multiple (objects, pre-selected, stay open on select)',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\tmultiple: true,\n\t\t\tcloseOnSelect: false,\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tid: 'foo',\n\t\t\t\t\tlabel: 'Foo',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'bar',\n\t\t\t\t\tlabel: 'Bar',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'baz',\n\t\t\t\t\tlabel: 'Baz',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'qux',\n\t\t\t\t\tlabel: 'Qux',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'quux',\n\t\t\t\t\tlabel: 'Quux',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'corge',\n\t\t\t\t\tlabel: 'Corge',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'grault',\n\t\t\t\t\tlabel: 'Grault',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'garply',\n\t\t\t\t\tlabel: 'Garply',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'waldo',\n\t\t\t\t\tlabel: 'Waldo',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'fred',\n\t\t\t\t\tlabel: 'Fred',\n\t\t\t\t},\n\t\t\t],\n\t\t\tvalue: [\n\t\t\t\t{\n\t\t\t\t\tid: 'foo',\n\t\t\t\t\tlabel: 'Foo',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'bar',\n\t\t\t\t\tlabel: 'Bar',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t},\n]\n\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\tselectArray,\n\t\t}\n\t},\n}\n</script>\n\n<style>\n.grid {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(2, 1fr);\n\tgap: 10px;\n}\n\n.container {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px 0;\n}\n</style>\n```\n\n### No wrap example\n\nThe `noWrap` prop is set to `true` and the `max-width` of the multiselect\nparent container is limited to `350px`\n\n```vue\n<template>\n\t<div class=\"grid\">\n\t\t<div class=\"container\">\n\t\t\t<label :for=\"data1.props.inputId\">{{ data1.name }}</label>\n\t\t\t<NcSelect :no-wrap=\"false\"\n\t\t\t\tv-bind=\"data1.props\"\n\t\t\t\tv-model=\"data1.props.value\" />\n\t\t</div>\n\t\t<div class=\"container\">\n\t\t\t<label :for=\"data2.props.inputId\">{{ data2.name }}</label>\n\t\t\t<NcSelect :no-wrap=\"true\"\n\t\t\t\tv-bind=\"data2.props\"\n\t\t\t\tv-model=\"data2.props.value\" />\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport GenRandomId from '../../utils/GenRandomId.js'\n\nconst getRandomId = () => {\n\treturn `select-${GenRandomId()}`\n}\n\nconst data1 = {\n\tname: 'Wrapped (Default)',\n\tprops: {\n\t\tinputId: getRandomId(),\n\t\tmultiple: true,\n\t\tcloseOnSelect: false,\n\t\toptions: [\n\t\t\t'foo',\n\t\t\t'bar',\n\t\t\t'baz',\n\t\t\t'qux',\n\t\t\t'quux',\n\t\t\t'corge',\n\t\t\t'grault',\n\t\t\t'garply',\n\t\t\t'waldo',\n\t\t\t'fred',\n\t\t],\n\t\tvalue: [\n\t\t\t'foo',\n\t\t\t'bar',\n\t\t\t'baz',\n\t\t\t'qux',\n\t\t\t'quux',\n\t\t\t'corge',\n\t\t\t'grault',\n\t\t\t'garply',\n\t\t\t'waldo',\n\t\t\t'fred',\n\t\t],\n\t},\n}\n\nconst data2 = {\n\tname: 'Not wrapped',\n\tprops: {\n\t\tinputId: getRandomId(),\n\t\tmultiple: true,\n\t\tcloseOnSelect: false,\n\t\toptions: [\n\t\t\t'foo',\n\t\t\t'bar',\n\t\t\t'baz',\n\t\t\t'qux',\n\t\t\t'quux',\n\t\t\t'corge',\n\t\t\t'grault',\n\t\t\t'garply',\n\t\t\t'waldo',\n\t\t\t'fred',\n\t\t],\n\t\tvalue: [\n\t\t\t'foo',\n\t\t\t'bar',\n\t\t\t'baz',\n\t\t\t'qux',\n\t\t\t'quux',\n\t\t\t'corge',\n\t\t\t'grault',\n\t\t\t'garply',\n\t\t\t'waldo',\n\t\t\t'fred',\n\t\t],\n\t},\n}\n\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\tdata1,\n\t\t\tdata2,\n\t\t}\n\t},\n}\n</script>\n\n<style>\n.grid {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(1, 1fr);\n\tgap: 10px;\n}\n\n.container {\n\tmax-width: 350px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px 0;\n}\n</style>\n```\n\n### User select examples\n\n```vue\n<template>\n\t<div class=\"grid\">\n\t\t<div v-for=\"{ name, props } in selectArray\"\n\t\t\tclass=\"container\">\n\t\t\t<label :for=\"props.inputId\">{{ name }}</label>\n\t\t\t<NcSelect v-bind=\"props\"\n\t\t\t\tv-model=\"props.value\" />\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport AccountGroup from '@mdi/svg/svg/account-group.svg?raw'\nimport Email from '@mdi/svg/svg/email.svg?raw'\n\nimport GenRandomId from '../../utils/GenRandomId.js'\n\nconst getRandomId = () => {\n\treturn `select-${GenRandomId()}`\n}\n\nconst selectArray = [\n\t{\n\t\tname: 'User select',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\tuserSelect: true,\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tid: '0-john',\n\t\t\t\t\tdisplayName: 'John',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'john@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t\t// Example of how to show the user status within the option\n\t\t\t\t\tuser: '0-john',\n\t\t\t\t\tpreloadedUserStatus: {\n\t\t\t\t\t\ticon: '',\n\t\t\t\t\t\tstatus: 'online',\n\t\t\t\t\t\tmessage: 'I am online',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-emma',\n\t\t\t\t\tdisplayName: 'Emma',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'emma@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-olivia',\n\t\t\t\t\tdisplayName: 'Olivia',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'olivia@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-noah',\n\t\t\t\t\tdisplayName: 'Noah',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'noah@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-oliver',\n\t\t\t\t\tdisplayName: 'Oliver',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'oliver@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '1-admin',\n\t\t\t\t\tdisplayName: 'Admin',\n\t\t\t\t\tisNoUser: true,\n\t\t\t\t\tsubname: null,\n\t\t\t\t\ticonSvg: AccountGroup,\n\t\t\t\t\ticonName: 'Group icon',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '2-org@example.org',\n\t\t\t\t\tdisplayName: 'Organization',\n\t\t\t\t\tisNoUser: true,\n\t\t\t\t\tsubname: 'org@example.org',\n\t\t\t\t\ticonSvg: Email,\n\t\t\t\t\ticonName: 'Email icon',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t},\n\n\t{\n\t\tname: 'Multiple user select (stay open on select)',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\tuserSelect: true,\n\t\t\tmultiple: true,\n\t\t\tcloseOnSelect: false,\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tid: '0-john',\n\t\t\t\t\tdisplayName: 'John',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'john@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-emma',\n\t\t\t\t\tdisplayName: 'Emma',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'emma@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-olivia',\n\t\t\t\t\tdisplayName: 'Olivia',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'olivia@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-noah',\n\t\t\t\t\tdisplayName: 'Noah',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'noah@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-oliver',\n\t\t\t\t\tdisplayName: 'Oliver',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'oliver@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '1-admin',\n\t\t\t\t\tdisplayName: 'Admin',\n\t\t\t\t\tisNoUser: true,\n\t\t\t\t\tsubname: null,\n\t\t\t\t\ticonSvg: AccountGroup,\n\t\t\t\t\ticonName: 'Group icon',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '2-org@example.org',\n\t\t\t\t\tdisplayName: 'Organization',\n\t\t\t\t\tisNoUser: true,\n\t\t\t\t\tsubname: 'org@example.org',\n\t\t\t\t\ticonSvg: Email,\n\t\t\t\t\ticonName: 'Email icon',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t},\n]\n\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\tselectArray,\n\t\t}\n\t},\n}\n</script>\n\n<style>\n.grid {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(1, 500px);\n\tgap: 10px;\n}\n\n.container {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px 0;\n}\n</style>\n```\n</docs>\n\n<template>\n\t<VueSelect class=\"select\"\n\t\t:class=\"{\n\t\t\t'select--no-wrap': noWrap,\n\t\t\t'user-select': userSelect,\n\t\t}\"\n\t\tv-bind=\"propsToForward\"\n\t\tv-on=\"$listeners\"\n\t\t@search=\"searchString => search = searchString\">\n\t\t<template #search=\"{ attributes, events }\">\n\t\t\t<input :class=\"['vs__search', inputClass]\"\n\t\t\t\tv-bind=\"attributes\"\n\t\t\t\tv-on=\"events\">\n\t\t</template>\n\t\t<template #open-indicator=\"{ attributes }\">\n\t\t\t<ChevronDown v-bind=\"attributes\"\n\t\t\t\tfill-color=\"var(--vs-controls-color)\"\n\t\t\t\t:size=\"26\" />\n\t\t\t\t<!-- Set size to 26 to make up for the increased padding of this icon -->\n\t\t</template>\n\t\t<template #option=\"option\">\n\t\t\t<NcListItemIcon v-if=\"userSelect\"\n\t\t\t\tv-bind=\"option\"\n\t\t\t\t:avatar-size=\"24\"\n\t\t\t\t:name=\"option[localLabel]\"\n\t\t\t\t:search=\"search\" />\n\t\t\t<NcEllipsisedOption v-else\n\t\t\t\t:name=\"String(option[localLabel])\"\n\t\t\t\t:search=\"search\" />\n\t\t</template>\n\t\t<template #selected-option=\"selectedOption\">\n\t\t\t<NcListItemIcon v-if=\"userSelect\"\n\t\t\t\tv-bind=\"selectedOption\"\n\t\t\t\t:avatar-size=\"24\"\n\t\t\t\t:name=\"selectedOption[localLabel]\"\n\t\t\t\t:search=\"search\" />\n\t\t\t<NcEllipsisedOption v-else\n\t\t\t\t:name=\"String(selectedOption[localLabel])\"\n\t\t\t\t:search=\"search\" />\n\t\t</template>\n\t\t<template #spinner=\"spinner\">\n\t\t\t<NcLoadingIcon v-if=\"spinner.loading\" />\n\t\t</template>\n\t\t<template #no-options>\n\t\t\t{{ t('No results') }}\n\t\t</template>\n\t\t<template v-for=\"(_, name) in $scopedSlots\" #[name]=\"data\">\n\t\t\t<!-- @slot Any combination of slots from https://vue-select.org/api/slots.html -->\n\t\t\t<slot :name=\"name\" v-bind=\"data\" />\n\t\t</template>\n\t</VueSelect>\n</template>\n\n<script>\nimport '@nextcloud/vue-select/dist/vue-select.css'\n\nimport { VueSelect } from '@nextcloud/vue-select'\nimport {\n\tautoUpdate,\n\tcomputePosition,\n\tflip,\n\tlimitShift,\n\toffset,\n\tshift,\n} from '@floating-ui/dom'\nimport { t } from '../../l10n.js'\n\nimport ChevronDown from 'vue-material-design-icons/ChevronDown.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\n\nimport NcEllipsisedOption from '../NcEllipsisedOption/index.js'\nimport NcListItemIcon from '../NcListItemIcon/index.js'\nimport NcLoadingIcon from '../NcLoadingIcon/index.js'\n\nimport l10n from '../../mixins/l10n.js'\nimport GenRandomId from '../../utils/GenRandomId.js'\n\nexport default {\n\tname: 'NcSelect',\n\n\tcomponents: {\n\t\tChevronDown,\n\t\tNcEllipsisedOption,\n\t\tNcListItemIcon,\n\t\tNcLoadingIcon,\n\t\tVueSelect,\n\t},\n\n\tmixins: [\n\t\tl10n,\n\t],\n\n\tprops: {\n\t\t// Add VueSelect props to $props\n\t\t...VueSelect.props,\n\n\t\t/**\n\t\t * `aria-label` for the clear input button\n\t\t */\n\t\tariaLabelClearSelected: {\n\t\t\ttype: String,\n\t\t\tdefault: t('Clear selected'),\n\t\t},\n\n\t\t/**\n\t\t * `aria-label` for the search input\n\t\t */\n\t\tariaLabelCombobox: {\n\t\t\ttype: String,\n\t\t\tdefault: t('Search for options'),\n\t\t},\n\n\t\t/**\n\t\t * Allows to customize the `aria-label` for the deselect-option button\n\t\t * The default is \"Deselect \" + optionLabel\n\t\t * @type {(optionLabel: string) => string}\n\t\t */\n\t\tariaLabelDeselectOption: {\n\t\t\ttype: Function,\n\t\t\tdefault: (optionLabel) => t('Deselect {option}', { option: optionLabel }),\n\t\t},\n\n\t\t/**\n\t\t * Append the dropdown element to the end of the body\n\t\t * and size/position it dynamically.\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#appendtobody\n\t\t */\n\t\tappendToBody: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * When `appendToBody` is true, this function is responsible for\n\t\t * positioning the drop down list.\n\t\t *\n\t\t * If a function is returned from `calculatePosition`, it will\n\t\t * be called when the drop down list is removed from the DOM.\n\t\t * This allows for any garbage collection you may need to do.\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#calculateposition\n\t\t */\n\t\tcalculatePosition: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Close the dropdown when selecting an option\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#closeonselect\n\t\t */\n\t\tcloseOnSelect: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Replace default vue-select components\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#components\n\t\t */\n\t\tcomponents: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({\n\t\t\t\tDeselect: {\n\t\t\t\t\trender: createElement => createElement(Close, {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsize: 20,\n\t\t\t\t\t\t\tfillColor: 'var(--vs-controls-color)',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t}),\n\t\t},\n\n\t\t/**\n\t\t * Sets the maximum number of options to display in the dropdown list\n\t\t */\n\t\tlimit: {\n\t\t\ttype: Number,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Disable the component\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#disabled\n\t\t */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Determines whether the dropdown should be open.\n\t\t * Receives the component instance as the only argument.\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#dropdownshouldopen\n\t\t */\n\t\tdropdownShouldOpen: {\n\t\t\ttype: Function,\n\t\t\tdefault: ({ noDrop, open }) => {\n\t\t\t\treturn noDrop ? false : open\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Callback to determine if the provided option should\n\t\t * match the current search text. Used to determine\n\t\t * if the option should be displayed.\n\t\t *\n\t\t * Defaults to the internal vue-select function documented at the link\n\t\t * below\n\t\t *\n\t\t * Enabling `userSelect` will automatically set this to filter by the\n\t\t * `displayName` and `subname` properties of the user option object\n\t\t * unless this prop is set explicitly\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#filterby\n\t\t */\n\t\tfilterBy: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Class for the `input`\n\t\t *\n\t\t * Necessary for use in NcActionInput\n\t\t */\n\t\tinputClass: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Input element id\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#inputid\n\t\t */\n\t\tinputId: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Display a visible border around dropdown options\n\t\t * which have keyboard focus\n\t\t */\n\t\tkeyboardFocusBorder: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Key of the displayed label for object options\n\t\t *\n\t\t * Defaults to the internal vue-select string documented at the link\n\t\t * below\n\t\t *\n\t\t * Enabling `userSelect` will automatically set this to `'displayName'`\n\t\t * unless this prop is set explicitly\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#label\n\t\t */\n\t\tlabel: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Show the loading icon\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#loading\n\t\t */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Allow selection of multiple options\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#multiple\n\t\t */\n\t\tmultiple: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Disable automatic wrapping when selected options overflow the width\n\t\t */\n\t\tnoWrap: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Array of options\n\t\t *\n\t\t * @type {Array<string | number | Record<string | number, any>>}\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#options\n\t\t */\n\t\toptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * Placeholder text\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#placeholder\n\t\t */\n\t\tplaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Customized component's response to keydown events while the search input has focus\n\t\t *\n\t\t * @see https://vue-select.org/guide/keydown.html#mapkeydown\n\t\t */\n\t\tmapKeydown: {\n\t\t\ttype: Function,\n\t\t\t/**\n\t\t\t * Patched Vue-Select keydown events handlers map to stop Escape propagation in open select\n\t\t\t *\n\t\t\t * @param {Record<number, Function>} map - Mapped keyCode to handlers { <keyCode>:<callback> }\n\t\t\t * @param {import('@nextcloud/vue-select').VueSelect} vm - VueSelect instance\n\t\t\t * @return {Record<number, Function>} patched keydown event handlers\n\t\t\t */\n\t\t\tdefault(map, vm) {\n\t\t\t\treturn {\n\t\t\t\t\t...map,\n\t\t\t\t\t/**\n\t\t\t\t\t * Patched Escape handler to stop propagation from open select\n\t\t\t\t\t *\n\t\t\t\t\t * @param {KeyboardEvent} event - default keydown event handler\n\t\t\t\t\t */\n\t\t\t\t\t27: (event) => {\n\t\t\t\t\t\tif (vm.open) {\n\t\t\t\t\t\t\tevent.stopPropagation()\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Default VueSelect's handler\n\t\t\t\t\t\tmap[27](event)\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * A unique identifier used to generate IDs and DOM attributes. Must be unique for every instance of the component.\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#uid\n\t\t */\n\t\tuid: {\n\t\t\ttype: String,\n\t\t\tdefault: () => '-' + GenRandomId(),\n\t\t},\n\n\t\t/**\n\t\t * When `appendToBody` is true, this sets the placement of the dropdown\n\t\t *\n\t\t * @type {'bottom' | 'top'}\n\t\t */\n\t\tplacement: {\n\t\t\ttype: String,\n\t\t\tdefault: 'bottom',\n\t\t},\n\n\t\t/**\n\t\t * If false, the focused dropdown option will not be reset when filtered\n\t\t * options change\n\t\t */\n\t\tresetFocusOnOptionsChange: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Enable the user selector with avatars\n\t\t *\n\t\t * Objects must contain the data expected by the\n\t\t * [NcListItemIcon](#/Components/NcListItemIcon) and\n\t\t * [NcAvatar](#/Components/NcAvatar) components\n\t\t */\n\t\tuserSelect: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Currently selected value\n\t\t *\n\t\t * The `v-model` directive may be used for two-way data binding\n\t\t *\n\t\t * @type {string | number | Record<string | number, any> | Array<any>}\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#value\n\t\t */\n\t\tvalue: {\n\t\t\ttype: [String, Number, Object, Array],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Any available prop\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html\n\t\t */\n\t\t// Not an actual prop but needed to show in vue-styleguidist docs\n\t\t// eslint-disable-next-line\n\t\t' ': {},\n\t},\n\n\temits: [\n\t\t/**\n\t\t * All events from https://vue-select.org/api/events.html\n\t\t */\n\t\t// Not an actual event but needed to show in vue-styleguidist docs\n\t\t' ',\n\t],\n\n\tdata() {\n\t\treturn {\n\t\t\tsearch: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tlocalCalculatePosition() {\n\t\t\tif (this.calculatePosition !== null) {\n\t\t\t\treturn this.calculatePosition\n\t\t\t}\n\n\t\t\treturn (dropdownMenu, component, { width }) => {\n\t\t\t\tdropdownMenu.style.width = width\n\n\t\t\t\tconst addClass = {\n\t\t\t\t\tname: 'addClass',\n\t\t\t\t\tfn(_middlewareArgs) {\n\t\t\t\t\t\tdropdownMenu.classList.add('vs__dropdown-menu--floating')\n\t\t\t\t\t\treturn {}\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tconst togglePlacementClass = {\n\t\t\t\t\tname: 'togglePlacementClass',\n\t\t\t\t\tfn({ placement }) {\n\t\t\t\t\t\tcomponent.$el.classList.toggle(\n\t\t\t\t\t\t\t'select--drop-up',\n\t\t\t\t\t\t\tplacement === 'top',\n\t\t\t\t\t\t)\n\t\t\t\t\t\tdropdownMenu.classList.toggle(\n\t\t\t\t\t\t\t'vs__dropdown-menu--floating-placement-top',\n\t\t\t\t\t\t\tplacement === 'top',\n\t\t\t\t\t\t)\n\t\t\t\t\t\treturn {}\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tconst updatePosition = () => {\n\t\t\t\t\tcomputePosition(component.$refs.toggle, dropdownMenu, {\n\t\t\t\t\t\tplacement: this.placement,\n\t\t\t\t\t\tmiddleware: [\n\t\t\t\t\t\t\toffset(-1),\n\t\t\t\t\t\t\taddClass,\n\t\t\t\t\t\t\ttogglePlacementClass,\n\t\t\t\t\t\t\t// Match popperjs default collision prevention behavior by appending the following middleware in order\n\t\t\t\t\t\t\tflip(),\n\t\t\t\t\t\t\tshift({ limiter: limitShift() }),\n\t\t\t\t\t\t],\n\t\t\t\t\t}).then(({ x, y }) => {\n\t\t\t\t\t\tObject.assign(dropdownMenu.style, {\n\t\t\t\t\t\t\tleft: `${x}px`,\n\t\t\t\t\t\t\ttop: `${y}px`,\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tconst cleanup = autoUpdate(\n\t\t\t\t\tcomponent.$refs.toggle,\n\t\t\t\t\tdropdownMenu,\n\t\t\t\t\tupdatePosition,\n\t\t\t\t)\n\n\t\t\t\treturn cleanup\n\t\t\t}\n\t\t},\n\n\t\tlocalFilterBy() {\n\t\t\t// Match the email notation like \"Jane <j.doe@example.com>\" with the email address as matching group\n\t\t\tconst EMAIL_NOTATION = /[^<]*<([^>]+)/\n\n\t\t\tif (this.filterBy !== null) {\n\t\t\t\treturn this.filterBy\n\t\t\t}\n\t\t\tif (this.userSelect) {\n\t\t\t\treturn (option, label, search) => {\n\t\t\t\t\tconst match = search.match(EMAIL_NOTATION)\n\t\t\t\t\treturn (match && option.subname?.toLocaleLowerCase?.()?.indexOf(match[1].toLocaleLowerCase()) > -1)\n\t\t\t\t\t\t|| (`${label} ${option.subname}`\n\t\t\t\t\t\t\t.toLocaleLowerCase()\n\t\t\t\t\t\t\t.indexOf(search.toLocaleLowerCase()) > -1)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn VueSelect.props.filterBy.default\n\t\t},\n\n\t\tlocalLabel() {\n\t\t\tif (this.label !== null) {\n\t\t\t\treturn this.label\n\t\t\t}\n\t\t\tif (this.userSelect) {\n\t\t\t\treturn 'displayName'\n\t\t\t}\n\t\t\treturn VueSelect.props.label.default\n\t\t},\n\n\t\tpropsToForward() {\n\t\t\tconst {\n\t\t\t\t// Props handled by this component\n\t\t\t\tinputClass,\n\t\t\t\tnoWrap,\n\t\t\t\tplacement,\n\t\t\t\tuserSelect,\n\t\t\t\t// Props to forward\n\t\t\t\t...initialPropsToForward\n\t\t\t} = this.$props\n\n\t\t\tconst propsToForward = {\n\t\t\t\t...initialPropsToForward,\n\t\t\t\t// Custom overrides of vue-select props\n\t\t\t\tcalculatePosition: this.localCalculatePosition,\n\t\t\t\tfilterBy: this.localFilterBy,\n\t\t\t\tlabel: this.localLabel,\n\t\t\t}\n\n\t\t\treturn propsToForward\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\">\nbody {\n\t/**\n\t * Set custom vue-select CSS variables.\n\t * Needs to be on the body (not :root) for theming to apply (see nextcloud/server#36462)\n\t */\n\n\t/* Search Input */\n\t--vs-search-input-color: var(--color-main-text);\n\t--vs-search-input-bg: var(--color-main-background);\n\t--vs-search-input-placeholder-color: var(--color-text-maxcontrast);\n\n\t/* Font */\n\t--vs-font-size: var(--default-font-size);\n\t--vs-line-height: var(--default-line-height);\n\n\t/* Disabled State */\n\t--vs-state-disabled-bg: var(--color-background-hover);\n\t--vs-state-disabled-color: var(--color-text-maxcontrast);\n\t--vs-state-disabled-controls-color: var(--color-text-maxcontrast);\n\t--vs-state-disabled-cursor: not-allowed;\n\t--vs-disabled-bg: var(--color-background-hover);\n\t--vs-disabled-color: var(--color-text-maxcontrast);\n\t--vs-disabled-cursor: not-allowed;\n\n\t/* Borders */\n\t--vs-border-color: var(--color-border-maxcontrast);\n\t--vs-border-width: 2px;\n\t--vs-border-style: solid;\n\t--vs-border-radius: var(--border-radius-large);\n\n\t/* Component Controls: Clear, Open Indicator */\n\t--vs-controls-color: var(--color-main-text);\n\n\t/* Selected */\n\t--vs-selected-bg: var(--color-background-hover);\n\t--vs-selected-color: var(--color-main-text);\n\t--vs-selected-border-color: var(--vs-border-color);\n\t--vs-selected-border-style: var(--vs-border-style);\n\t--vs-selected-border-width: var(--vs-border-width);\n\n\t/* Dropdown */\n\t--vs-dropdown-bg: var(--color-main-background);\n\t--vs-dropdown-color: var(--color-main-text);\n\t--vs-dropdown-z-index: 9999;\n\t--vs-dropdown-box-shadow: 0px 2px 2px 0px var(--color-box-shadow);\n\n\t/* Options */\n\t--vs-dropdown-option-padding: 8px 20px;\n\n\t/* Active State */\n\t--vs-dropdown-option--active-bg: var(--color-background-hover);\n\t--vs-dropdown-option--active-color: var(--color-main-text);\n\n\t/* Keyboard Focus State */\n\t--vs-dropdown-option--kb-focus-box-shadow: inset 0px 0px 0px 2px var(--vs-border-color);\n\n\t/* Deselect State */\n\t--vs-dropdown-option--deselect-bg: var(--color-error);\n\t--vs-dropdown-option--deselect-color: #fff;\n\n\t/* Transitions */\n\t--vs-transition-duration: 0ms;\n\n\t/* Actions */\n\t--vs-actions-padding: 0 8px 0 4px;\n}\n\n.v-select.select {\n\t/* Override default vue-select styles */\n\tmin-height: $clickable-area;\n\tmin-width: 260px;\n\tmargin: 0;\n\n\t.vs__selected {\n\t\theight: 32px;\n\t\tpadding: 0 8px 0 12px;\n\t\tborder-radius: 18px !important;\n\t\tbackground: var(--color-primary-element-light);\n\t\tborder: none;\n\t}\n\n\t.vs__search, .vs__search:focus {\n\t\tmargin: 2px 0 0;\n\t}\n\n\t.vs__dropdown-toggle {\n\t\tpadding: 0;\n\t}\n\n\t.vs__clear {\n\t\tmargin-right: 2px;\n\t}\n\n\t&.vs--open .vs__dropdown-toggle {\n\t\toutline: 2px solid var(--color-main-background);\n\t\tborder-color: var(--color-main-text);\n\t\tborder-bottom-color: transparent;\n\t}\n\n\t&:not(.vs--disabled, .vs--open) .vs__dropdown-toggle:hover {\n\t\toutline: 2px solid var(--color-main-background);\n\t\tborder-color: var(--color-main-text);\n\t}\n\n\t&.vs--disabled {\n\t\t.vs__search,\n\t\t.vs__selected {\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t}\n\n\t\t.vs__clear,\n\t\t.vs__deselect {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n\n\t&--no-wrap {\n\t\t.vs__selected-options {\n\t\t\tflex-wrap: nowrap;\n\t\t\toverflow: auto;\n\t\t\tmin-width: unset;\n\t\t\t.vs__selected {\n\t\t\t\tmin-width: unset;\n\t\t\t}\n\t\t}\n\t}\n\n\t&--drop-up {\n\t\t&.vs--open {\n\t\t\t.vs__dropdown-toggle {\n\t\t\t\tborder-radius: 0 0 var(--vs-border-radius) var(--vs-border-radius);\n\t\t\t\tborder-top-color: transparent;\n\t\t\t\tborder-bottom-color: var(--color-main-text);\n\t\t\t}\n\t\t}\n\t}\n\n\t.vs__selected-options {\n\t\t// If search is hidden, ensure that the height of the search is the same\n\t\tmin-height: 40px; // 36px search height + 4px search margin\n\n\t\t// Hide search from dom if unused to prevent unneeded flex wrap\n\t\t.vs__selected ~ .vs__search[readonly] {\n\t\t\tposition: absolute;\n\t\t}\n\t}\n\n\t&.vs--single {\n\t\t&.vs--loading,\n\t\t&.vs--open {\n\t\t\t.vs__selected {\n\t\t\t\t// Fix `max-width` for `position: absolute`\n\t\t\t\tmax-width: 100%;\n\t\t\t\t// Fix color to be accessible\n\t\t\t\topacity: 1;\n\t\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t\t}\n\t\t}\n\t\t.vs__selected-options {\n\t\t\tflex-wrap: nowrap;\n\t\t}\n\t\t.vs__selected {\n\t\t\tbackground: unset !important;\n\t\t}\n\t}\n}\n\n.vs__dropdown-menu {\n\tborder-color: var(--color-main-text) !important;\n\toutline: 2px solid var(--color-main-background);\n\tpadding: 4px !important;\n\tbox-shadow: none;\n\n\t&--floating {\n\t\t/* Fallback styles overidden by programmatically set inline styles */\n\t\twidth: max-content;\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\n\t\t&-placement-top {\n\t\t\tborder-radius: var(--vs-border-radius) var(--vs-border-radius) 0 0 !important;\n\t\t\tborder-top-style: var(--vs-border-style) !important;\n\t\t\tborder-bottom-style: none !important;\n\t\t}\n\t}\n\n\t.vs__dropdown-option {\n\t\tborder-radius: 6px !important;\n\t}\n\n\t.vs__no-options {\n\t\tcolor: var(--color-text-lighter) !important;\n\t}\n}\n\n// Selected users require slightly different padding\n.user-select .vs__selected {\n\tpadding: 0 2px !important;\n}\n\n</style>\n"],"names":["_sfc_main","ChevronDown","Components_NcEllipsisedOption","Components_NcListItemIcon","Components_NcLoadingIcon","vueSelect","l10n","l10n$1","optionLabel","createElement","Close","noDrop","open","map","vm","event","GenRandomId","dropdownMenu","component","width","addClass","_middlewareArgs","togglePlacementClass","placement","updatePosition","dom","x","y","EMAIL_NOTATION","option","label","search","match","_c","_b","_a","inputClass","noWrap","userSelect","initialPropsToForward"],"mappings":"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"}
1
+ {"version":3,"file":"NcSelect.cjs","sources":["../../src/components/NcSelect/NcSelect.vue"],"sourcesContent":["<!--\n\t- @copyright 2022 Christopher Ng <chrng8@gmail.com>\n\t-\n\t- @author Christopher Ng <chrng8@gmail.com>\n\t-\n\t- @license AGPL-3.0-or-later\n\t-\n\t- This program is free software: you can redistribute it and/or modify\n\t- it under the terms of the GNU Affero General Public License as\n\t- published by the Free Software Foundation, either version 3 of the\n\t- License, or (at your option) any later version.\n\t-\n\t- This program is distributed in the hope that it will be useful,\n\t- but WITHOUT ANY WARRANTY; without even the implied warranty of\n\t- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\t- GNU Affero General Public License for more details.\n\t-\n\t- You should have received a copy of the GNU Affero General Public License\n\t- along with this program. If not, see <http://www.gnu.org/licenses/>.\n\t-\n-->\n\n<docs>\n### Description\n\nGeneral purpose multiselect component.\n\n### Basic examples\n\n```vue\n<template>\n\t<div class=\"grid\">\n\t\t<div v-for=\"{ name, props } in selectArray\"\n\t\t\tclass=\"container\">\n\t\t\t<label :for=\"props.inputId\">{{ name }}</label>\n\t\t\t<NcSelect v-bind=\"props\"\n\t\t\t\tv-model=\"props.value\" />\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport GenRandomId from '../../utils/GenRandomId.js'\n\nconst getRandomId = () => {\n\treturn `select-${GenRandomId()}`\n}\n\nconst selectArray = [\n\t{\n\t\tname: 'Simple',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\toptions: [\n\t\t\t\t'foo',\n\t\t\t\t'bar',\n\t\t\t\t'baz',\n\t\t\t\t'qux',\n\t\t\t\t'quux',\n\t\t\t],\n\t\t},\n\t},\n\n\t{\n\t\tname: 'Simple (top placement)',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\tplacement: 'top',\n\t\t\toptions: [\n\t\t\t\t'foo',\n\t\t\t\t'bar',\n\t\t\t\t'baz',\n\t\t\t\t'qux',\n\t\t\t\t'quux',\n\t\t\t],\n\t\t},\n\t},\n\n\t{\n\t\tname: 'Multiple (with placeholder)',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\tmultiple: true,\n\t\t\tplaceholder: 'Select multiple options',\n\t\t\toptions: [\n\t\t\t\t'foo',\n\t\t\t\t'bar',\n\t\t\t\t'baz',\n\t\t\t\t'qux',\n\t\t\t\t'quux',\n\t\t\t],\n\t\t},\n\t},\n\n\t{\n\t\tname: 'Multiple (objects, pre-selected, stay open on select)',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\tmultiple: true,\n\t\t\tcloseOnSelect: false,\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tid: 'foo',\n\t\t\t\t\tlabel: 'Foo',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'bar',\n\t\t\t\t\tlabel: 'Bar',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'baz',\n\t\t\t\t\tlabel: 'Baz',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'qux',\n\t\t\t\t\tlabel: 'Qux',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'quux',\n\t\t\t\t\tlabel: 'Quux',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'corge',\n\t\t\t\t\tlabel: 'Corge',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'grault',\n\t\t\t\t\tlabel: 'Grault',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'garply',\n\t\t\t\t\tlabel: 'Garply',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'waldo',\n\t\t\t\t\tlabel: 'Waldo',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'fred',\n\t\t\t\t\tlabel: 'Fred',\n\t\t\t\t},\n\t\t\t],\n\t\t\tvalue: [\n\t\t\t\t{\n\t\t\t\t\tid: 'foo',\n\t\t\t\t\tlabel: 'Foo',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: 'bar',\n\t\t\t\t\tlabel: 'Bar',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t},\n]\n\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\tselectArray,\n\t\t}\n\t},\n}\n</script>\n\n<style>\n.grid {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(2, 1fr);\n\tgap: 10px;\n}\n\n.container {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px 0;\n}\n</style>\n```\n\n### No wrap example\n\nThe `noWrap` prop is set to `true` and the `max-width` of the multiselect\nparent container is limited to `350px`\n\n```vue\n<template>\n\t<div class=\"grid\">\n\t\t<div class=\"container\">\n\t\t\t<label :for=\"data1.props.inputId\">{{ data1.name }}</label>\n\t\t\t<NcSelect :no-wrap=\"false\"\n\t\t\t\tv-bind=\"data1.props\"\n\t\t\t\tv-model=\"data1.props.value\" />\n\t\t</div>\n\t\t<div class=\"container\">\n\t\t\t<label :for=\"data2.props.inputId\">{{ data2.name }}</label>\n\t\t\t<NcSelect :no-wrap=\"true\"\n\t\t\t\tv-bind=\"data2.props\"\n\t\t\t\tv-model=\"data2.props.value\" />\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport GenRandomId from '../../utils/GenRandomId.js'\n\nconst getRandomId = () => {\n\treturn `select-${GenRandomId()}`\n}\n\nconst data1 = {\n\tname: 'Wrapped (Default)',\n\tprops: {\n\t\tinputId: getRandomId(),\n\t\tmultiple: true,\n\t\tcloseOnSelect: false,\n\t\toptions: [\n\t\t\t'foo',\n\t\t\t'bar',\n\t\t\t'baz',\n\t\t\t'qux',\n\t\t\t'quux',\n\t\t\t'corge',\n\t\t\t'grault',\n\t\t\t'garply',\n\t\t\t'waldo',\n\t\t\t'fred',\n\t\t],\n\t\tvalue: [\n\t\t\t'foo',\n\t\t\t'bar',\n\t\t\t'baz',\n\t\t\t'qux',\n\t\t\t'quux',\n\t\t\t'corge',\n\t\t\t'grault',\n\t\t\t'garply',\n\t\t\t'waldo',\n\t\t\t'fred',\n\t\t],\n\t},\n}\n\nconst data2 = {\n\tname: 'Not wrapped',\n\tprops: {\n\t\tinputId: getRandomId(),\n\t\tmultiple: true,\n\t\tcloseOnSelect: false,\n\t\toptions: [\n\t\t\t'foo',\n\t\t\t'bar',\n\t\t\t'baz',\n\t\t\t'qux',\n\t\t\t'quux',\n\t\t\t'corge',\n\t\t\t'grault',\n\t\t\t'garply',\n\t\t\t'waldo',\n\t\t\t'fred',\n\t\t],\n\t\tvalue: [\n\t\t\t'foo',\n\t\t\t'bar',\n\t\t\t'baz',\n\t\t\t'qux',\n\t\t\t'quux',\n\t\t\t'corge',\n\t\t\t'grault',\n\t\t\t'garply',\n\t\t\t'waldo',\n\t\t\t'fred',\n\t\t],\n\t},\n}\n\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\tdata1,\n\t\t\tdata2,\n\t\t}\n\t},\n}\n</script>\n\n<style>\n.grid {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(1, 1fr);\n\tgap: 10px;\n}\n\n.container {\n\tmax-width: 350px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px 0;\n}\n</style>\n```\n\n### User select examples\n\n```vue\n<template>\n\t<div class=\"grid\">\n\t\t<div v-for=\"{ name, props } in selectArray\"\n\t\t\tclass=\"container\">\n\t\t\t<label :for=\"props.inputId\">{{ name }}</label>\n\t\t\t<NcSelect v-bind=\"props\"\n\t\t\t\tv-model=\"props.value\" />\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport AccountGroup from '@mdi/svg/svg/account-group.svg?raw'\nimport Email from '@mdi/svg/svg/email.svg?raw'\n\nimport GenRandomId from '../../utils/GenRandomId.js'\n\nconst getRandomId = () => {\n\treturn `select-${GenRandomId()}`\n}\n\nconst selectArray = [\n\t{\n\t\tname: 'User select',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\tuserSelect: true,\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tid: '0-john',\n\t\t\t\t\tdisplayName: 'John',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'john@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t\t// Example of how to show the user status within the option\n\t\t\t\t\tuser: '0-john',\n\t\t\t\t\tpreloadedUserStatus: {\n\t\t\t\t\t\ticon: '',\n\t\t\t\t\t\tstatus: 'online',\n\t\t\t\t\t\tmessage: 'I am online',\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-emma',\n\t\t\t\t\tdisplayName: 'Emma',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'emma@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-olivia',\n\t\t\t\t\tdisplayName: 'Olivia',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'olivia@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-noah',\n\t\t\t\t\tdisplayName: 'Noah',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'noah@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-oliver',\n\t\t\t\t\tdisplayName: 'Oliver',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'oliver@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '1-admin',\n\t\t\t\t\tdisplayName: 'Admin',\n\t\t\t\t\tisNoUser: true,\n\t\t\t\t\tsubname: null,\n\t\t\t\t\ticonSvg: AccountGroup,\n\t\t\t\t\ticonName: 'Group icon',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '2-org@example.org',\n\t\t\t\t\tdisplayName: 'Organization',\n\t\t\t\t\tisNoUser: true,\n\t\t\t\t\tsubname: 'org@example.org',\n\t\t\t\t\ticonSvg: Email,\n\t\t\t\t\ticonName: 'Email icon',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t},\n\n\t{\n\t\tname: 'Multiple user select (stay open on select)',\n\t\tprops: {\n\t\t\tinputId: getRandomId(),\n\t\t\tuserSelect: true,\n\t\t\tmultiple: true,\n\t\t\tcloseOnSelect: false,\n\t\t\toptions: [\n\t\t\t\t{\n\t\t\t\t\tid: '0-john',\n\t\t\t\t\tdisplayName: 'John',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'john@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-emma',\n\t\t\t\t\tdisplayName: 'Emma',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'emma@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-olivia',\n\t\t\t\t\tdisplayName: 'Olivia',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'olivia@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-noah',\n\t\t\t\t\tdisplayName: 'Noah',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'noah@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '0-oliver',\n\t\t\t\t\tdisplayName: 'Oliver',\n\t\t\t\t\tisNoUser: false,\n\t\t\t\t\tsubname: 'oliver@example.org',\n\t\t\t\t\ticon: '',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '1-admin',\n\t\t\t\t\tdisplayName: 'Admin',\n\t\t\t\t\tisNoUser: true,\n\t\t\t\t\tsubname: null,\n\t\t\t\t\ticonSvg: AccountGroup,\n\t\t\t\t\ticonName: 'Group icon',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: '2-org@example.org',\n\t\t\t\t\tdisplayName: 'Organization',\n\t\t\t\t\tisNoUser: true,\n\t\t\t\t\tsubname: 'org@example.org',\n\t\t\t\t\ticonSvg: Email,\n\t\t\t\t\ticonName: 'Email icon',\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t},\n]\n\nexport default {\n\tdata() {\n\t\treturn {\n\t\t\tselectArray,\n\t\t}\n\t},\n}\n</script>\n\n<style>\n.grid {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(1, 500px);\n\tgap: 10px;\n}\n\n.container {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px 0;\n}\n</style>\n```\n</docs>\n\n<template>\n\t<VueSelect class=\"select\"\n\t\t:class=\"{\n\t\t\t'select--no-wrap': noWrap,\n\t\t\t'user-select': userSelect,\n\t\t}\"\n\t\tv-bind=\"propsToForward\"\n\t\tv-on=\"$listeners\"\n\t\t@search=\"searchString => search = searchString\">\n\t\t<template #search=\"{ attributes, events }\">\n\t\t\t<input :class=\"['vs__search', inputClass]\"\n\t\t\t\tv-bind=\"attributes\"\n\t\t\t\tv-on=\"events\">\n\t\t</template>\n\t\t<template #open-indicator=\"{ attributes }\">\n\t\t\t<ChevronDown v-bind=\"attributes\"\n\t\t\t\tfill-color=\"var(--vs-controls-color)\"\n\t\t\t\t:size=\"26\" />\n\t\t\t\t<!-- Set size to 26 to make up for the increased padding of this icon -->\n\t\t</template>\n\t\t<template #option=\"option\">\n\t\t\t<NcListItemIcon v-if=\"userSelect\"\n\t\t\t\tv-bind=\"option\"\n\t\t\t\t:avatar-size=\"24\"\n\t\t\t\t:name=\"option[localLabel]\"\n\t\t\t\t:search=\"search\" />\n\t\t\t<NcEllipsisedOption v-else\n\t\t\t\t:name=\"String(option[localLabel])\"\n\t\t\t\t:search=\"search\" />\n\t\t</template>\n\t\t<template #selected-option=\"selectedOption\">\n\t\t\t<NcListItemIcon v-if=\"userSelect\"\n\t\t\t\tv-bind=\"selectedOption\"\n\t\t\t\t:avatar-size=\"24\"\n\t\t\t\t:name=\"selectedOption[localLabel]\"\n\t\t\t\t:search=\"search\" />\n\t\t\t<NcEllipsisedOption v-else\n\t\t\t\t:name=\"String(selectedOption[localLabel])\"\n\t\t\t\t:search=\"search\" />\n\t\t</template>\n\t\t<template #spinner=\"spinner\">\n\t\t\t<NcLoadingIcon v-if=\"spinner.loading\" />\n\t\t</template>\n\t\t<template #no-options>\n\t\t\t{{ t('No results') }}\n\t\t</template>\n\t\t<template v-for=\"(_, name) in $scopedSlots\" #[name]=\"data\">\n\t\t\t<!-- @slot Any combination of slots from https://vue-select.org/api/slots.html -->\n\t\t\t<slot :name=\"name\" v-bind=\"data\" />\n\t\t</template>\n\t</VueSelect>\n</template>\n\n<script>\nimport '@nextcloud/vue-select/dist/vue-select.css'\n\nimport { VueSelect } from '@nextcloud/vue-select'\nimport {\n\tautoUpdate,\n\tcomputePosition,\n\tflip,\n\tlimitShift,\n\toffset,\n\tshift,\n} from '@floating-ui/dom'\nimport { t } from '../../l10n.js'\n\nimport ChevronDown from 'vue-material-design-icons/ChevronDown.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\n\nimport NcEllipsisedOption from '../NcEllipsisedOption/index.js'\nimport NcListItemIcon from '../NcListItemIcon/index.js'\nimport NcLoadingIcon from '../NcLoadingIcon/index.js'\n\nimport GenRandomId from '../../utils/GenRandomId.js'\n\nexport default {\n\tname: 'NcSelect',\n\n\tcomponents: {\n\t\tChevronDown,\n\t\tNcEllipsisedOption,\n\t\tNcListItemIcon,\n\t\tNcLoadingIcon,\n\t\tVueSelect,\n\t},\n\n\tprops: {\n\t\t// Add VueSelect props to $props\n\t\t...VueSelect.props,\n\n\t\t/**\n\t\t * `aria-label` for the clear input button\n\t\t */\n\t\tariaLabelClearSelected: {\n\t\t\ttype: String,\n\t\t\tdefault: t('Clear selected'),\n\t\t},\n\n\t\t/**\n\t\t * `aria-label` for the search input\n\t\t */\n\t\tariaLabelCombobox: {\n\t\t\ttype: String,\n\t\t\tdefault: t('Search for options'),\n\t\t},\n\n\t\t/**\n\t\t * Allows to customize the `aria-label` for the deselect-option button\n\t\t * The default is \"Deselect \" + optionLabel\n\t\t * @type {(optionLabel: string) => string}\n\t\t */\n\t\tariaLabelDeselectOption: {\n\t\t\ttype: Function,\n\t\t\tdefault: (optionLabel) => t('Deselect {option}', { option: optionLabel }),\n\t\t},\n\n\t\t/**\n\t\t * Append the dropdown element to the end of the body\n\t\t * and size/position it dynamically.\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#appendtobody\n\t\t */\n\t\tappendToBody: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * When `appendToBody` is true, this function is responsible for\n\t\t * positioning the drop down list.\n\t\t *\n\t\t * If a function is returned from `calculatePosition`, it will\n\t\t * be called when the drop down list is removed from the DOM.\n\t\t * This allows for any garbage collection you may need to do.\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#calculateposition\n\t\t */\n\t\tcalculatePosition: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Close the dropdown when selecting an option\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#closeonselect\n\t\t */\n\t\tcloseOnSelect: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Replace default vue-select components\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#components\n\t\t */\n\t\tcomponents: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({\n\t\t\t\tDeselect: {\n\t\t\t\t\trender: createElement => createElement(Close, {\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsize: 20,\n\t\t\t\t\t\t\tfillColor: 'var(--vs-controls-color)',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tstyle: {\n\t\t\t\t\t\t\tcursor: 'pointer',\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t}),\n\t\t},\n\n\t\t/**\n\t\t * Sets the maximum number of options to display in the dropdown list\n\t\t */\n\t\tlimit: {\n\t\t\ttype: Number,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Disable the component\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#disabled\n\t\t */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Determines whether the dropdown should be open.\n\t\t * Receives the component instance as the only argument.\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#dropdownshouldopen\n\t\t */\n\t\tdropdownShouldOpen: {\n\t\t\ttype: Function,\n\t\t\tdefault: ({ noDrop, open }) => {\n\t\t\t\treturn noDrop ? false : open\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Callback to determine if the provided option should\n\t\t * match the current search text. Used to determine\n\t\t * if the option should be displayed.\n\t\t *\n\t\t * Defaults to the internal vue-select function documented at the link\n\t\t * below\n\t\t *\n\t\t * Enabling `userSelect` will automatically set this to filter by the\n\t\t * `displayName` and `subname` properties of the user option object\n\t\t * unless this prop is set explicitly\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#filterby\n\t\t */\n\t\tfilterBy: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Class for the `input`\n\t\t *\n\t\t * Necessary for use in NcActionInput\n\t\t */\n\t\tinputClass: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Input element id\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#inputid\n\t\t */\n\t\tinputId: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Display a visible border around dropdown options\n\t\t * which have keyboard focus\n\t\t */\n\t\tkeyboardFocusBorder: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Key of the displayed label for object options\n\t\t *\n\t\t * Defaults to the internal vue-select string documented at the link\n\t\t * below\n\t\t *\n\t\t * Enabling `userSelect` will automatically set this to `'displayName'`\n\t\t * unless this prop is set explicitly\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#label\n\t\t */\n\t\tlabel: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Show the loading icon\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#loading\n\t\t */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Allow selection of multiple options\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#multiple\n\t\t */\n\t\tmultiple: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Disable automatic wrapping when selected options overflow the width\n\t\t */\n\t\tnoWrap: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Array of options\n\t\t *\n\t\t * @type {Array<string | number | Record<string | number, any>>}\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#options\n\t\t */\n\t\toptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * Placeholder text\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#placeholder\n\t\t */\n\t\tplaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Customized component's response to keydown events while the search input has focus\n\t\t *\n\t\t * @see https://vue-select.org/guide/keydown.html#mapkeydown\n\t\t */\n\t\tmapKeydown: {\n\t\t\ttype: Function,\n\t\t\t/**\n\t\t\t * Patched Vue-Select keydown events handlers map to stop Escape propagation in open select\n\t\t\t *\n\t\t\t * @param {Record<number, Function>} map - Mapped keyCode to handlers { <keyCode>:<callback> }\n\t\t\t * @param {import('@nextcloud/vue-select').VueSelect} vm - VueSelect instance\n\t\t\t * @return {Record<number, Function>} patched keydown event handlers\n\t\t\t */\n\t\t\tdefault(map, vm) {\n\t\t\t\treturn {\n\t\t\t\t\t...map,\n\t\t\t\t\t/**\n\t\t\t\t\t * Patched Escape handler to stop propagation from open select\n\t\t\t\t\t *\n\t\t\t\t\t * @param {KeyboardEvent} event - default keydown event handler\n\t\t\t\t\t */\n\t\t\t\t\t27: (event) => {\n\t\t\t\t\t\tif (vm.open) {\n\t\t\t\t\t\t\tevent.stopPropagation()\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Default VueSelect's handler\n\t\t\t\t\t\tmap[27](event)\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * A unique identifier used to generate IDs and DOM attributes. Must be unique for every instance of the component.\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#uid\n\t\t */\n\t\tuid: {\n\t\t\ttype: String,\n\t\t\tdefault: () => '-' + GenRandomId(),\n\t\t},\n\n\t\t/**\n\t\t * When `appendToBody` is true, this sets the placement of the dropdown\n\t\t *\n\t\t * @type {'bottom' | 'top'}\n\t\t */\n\t\tplacement: {\n\t\t\ttype: String,\n\t\t\tdefault: 'bottom',\n\t\t},\n\n\t\t/**\n\t\t * If false, the focused dropdown option will not be reset when filtered\n\t\t * options change\n\t\t */\n\t\tresetFocusOnOptionsChange: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Enable the user selector with avatars\n\t\t *\n\t\t * Objects must contain the data expected by the\n\t\t * [NcListItemIcon](#/Components/NcListItemIcon) and\n\t\t * [NcAvatar](#/Components/NcAvatar) components\n\t\t */\n\t\tuserSelect: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Currently selected value\n\t\t *\n\t\t * The `v-model` directive may be used for two-way data binding\n\t\t *\n\t\t * @type {string | number | Record<string | number, any> | Array<any>}\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html#value\n\t\t */\n\t\tvalue: {\n\t\t\ttype: [String, Number, Object, Array],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Any available prop\n\t\t *\n\t\t * @see https://vue-select.org/api/props.html\n\t\t */\n\t\t// Not an actual prop but needed to show in vue-styleguidist docs\n\t\t// eslint-disable-next-line\n\t\t' ': {},\n\t},\n\n\temits: [\n\t\t/**\n\t\t * All events from https://vue-select.org/api/events.html\n\t\t */\n\t\t// Not an actual event but needed to show in vue-styleguidist docs\n\t\t' ',\n\t],\n\n\tdata() {\n\t\treturn {\n\t\t\tsearch: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tlocalCalculatePosition() {\n\t\t\tif (this.calculatePosition !== null) {\n\t\t\t\treturn this.calculatePosition\n\t\t\t}\n\n\t\t\treturn (dropdownMenu, component, { width }) => {\n\t\t\t\tdropdownMenu.style.width = width\n\n\t\t\t\tconst addClass = {\n\t\t\t\t\tname: 'addClass',\n\t\t\t\t\tfn(_middlewareArgs) {\n\t\t\t\t\t\tdropdownMenu.classList.add('vs__dropdown-menu--floating')\n\t\t\t\t\t\treturn {}\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tconst togglePlacementClass = {\n\t\t\t\t\tname: 'togglePlacementClass',\n\t\t\t\t\tfn({ placement }) {\n\t\t\t\t\t\tcomponent.$el.classList.toggle(\n\t\t\t\t\t\t\t'select--drop-up',\n\t\t\t\t\t\t\tplacement === 'top',\n\t\t\t\t\t\t)\n\t\t\t\t\t\tdropdownMenu.classList.toggle(\n\t\t\t\t\t\t\t'vs__dropdown-menu--floating-placement-top',\n\t\t\t\t\t\t\tplacement === 'top',\n\t\t\t\t\t\t)\n\t\t\t\t\t\treturn {}\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tconst updatePosition = () => {\n\t\t\t\t\tcomputePosition(component.$refs.toggle, dropdownMenu, {\n\t\t\t\t\t\tplacement: this.placement,\n\t\t\t\t\t\tmiddleware: [\n\t\t\t\t\t\t\toffset(-1),\n\t\t\t\t\t\t\taddClass,\n\t\t\t\t\t\t\ttogglePlacementClass,\n\t\t\t\t\t\t\t// Match popperjs default collision prevention behavior by appending the following middleware in order\n\t\t\t\t\t\t\tflip(),\n\t\t\t\t\t\t\tshift({ limiter: limitShift() }),\n\t\t\t\t\t\t],\n\t\t\t\t\t}).then(({ x, y }) => {\n\t\t\t\t\t\tObject.assign(dropdownMenu.style, {\n\t\t\t\t\t\t\tleft: `${x}px`,\n\t\t\t\t\t\t\ttop: `${y}px`,\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tconst cleanup = autoUpdate(\n\t\t\t\t\tcomponent.$refs.toggle,\n\t\t\t\t\tdropdownMenu,\n\t\t\t\t\tupdatePosition,\n\t\t\t\t)\n\n\t\t\t\treturn cleanup\n\t\t\t}\n\t\t},\n\n\t\tlocalFilterBy() {\n\t\t\t// Match the email notation like \"Jane <j.doe@example.com>\" with the email address as matching group\n\t\t\tconst EMAIL_NOTATION = /[^<]*<([^>]+)/\n\n\t\t\tif (this.filterBy !== null) {\n\t\t\t\treturn this.filterBy\n\t\t\t}\n\t\t\tif (this.userSelect) {\n\t\t\t\treturn (option, label, search) => {\n\t\t\t\t\tconst match = search.match(EMAIL_NOTATION)\n\t\t\t\t\treturn (match && option.subname?.toLocaleLowerCase?.()?.indexOf(match[1].toLocaleLowerCase()) > -1)\n\t\t\t\t\t\t|| (`${label} ${option.subname}`\n\t\t\t\t\t\t\t.toLocaleLowerCase()\n\t\t\t\t\t\t\t.indexOf(search.toLocaleLowerCase()) > -1)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn VueSelect.props.filterBy.default\n\t\t},\n\n\t\tlocalLabel() {\n\t\t\tif (this.label !== null) {\n\t\t\t\treturn this.label\n\t\t\t}\n\t\t\tif (this.userSelect) {\n\t\t\t\treturn 'displayName'\n\t\t\t}\n\t\t\treturn VueSelect.props.label.default\n\t\t},\n\n\t\tpropsToForward() {\n\t\t\tconst {\n\t\t\t\t// Props handled by this component\n\t\t\t\tinputClass,\n\t\t\t\tnoWrap,\n\t\t\t\tplacement,\n\t\t\t\tuserSelect,\n\t\t\t\t// Props to forward\n\t\t\t\t...initialPropsToForward\n\t\t\t} = this.$props\n\n\t\t\tconst propsToForward = {\n\t\t\t\t...initialPropsToForward,\n\t\t\t\t// Custom overrides of vue-select props\n\t\t\t\tcalculatePosition: this.localCalculatePosition,\n\t\t\t\tfilterBy: this.localFilterBy,\n\t\t\t\tlabel: this.localLabel,\n\t\t\t}\n\n\t\t\treturn propsToForward\n\t\t},\n\t},\n\tmethods: {\n\t\tt,\n\t},\n}\n</script>\n\n<style lang=\"scss\">\nbody {\n\t/**\n\t * Set custom vue-select CSS variables.\n\t * Needs to be on the body (not :root) for theming to apply (see nextcloud/server#36462)\n\t */\n\n\t/* Search Input */\n\t--vs-search-input-color: var(--color-main-text);\n\t--vs-search-input-bg: var(--color-main-background);\n\t--vs-search-input-placeholder-color: var(--color-text-maxcontrast);\n\n\t/* Font */\n\t--vs-font-size: var(--default-font-size);\n\t--vs-line-height: var(--default-line-height);\n\n\t/* Disabled State */\n\t--vs-state-disabled-bg: var(--color-background-hover);\n\t--vs-state-disabled-color: var(--color-text-maxcontrast);\n\t--vs-state-disabled-controls-color: var(--color-text-maxcontrast);\n\t--vs-state-disabled-cursor: not-allowed;\n\t--vs-disabled-bg: var(--color-background-hover);\n\t--vs-disabled-color: var(--color-text-maxcontrast);\n\t--vs-disabled-cursor: not-allowed;\n\n\t/* Borders */\n\t--vs-border-color: var(--color-border-maxcontrast);\n\t--vs-border-width: 2px;\n\t--vs-border-style: solid;\n\t--vs-border-radius: var(--border-radius-large);\n\n\t/* Component Controls: Clear, Open Indicator */\n\t--vs-controls-color: var(--color-main-text);\n\n\t/* Selected */\n\t--vs-selected-bg: var(--color-background-hover);\n\t--vs-selected-color: var(--color-main-text);\n\t--vs-selected-border-color: var(--vs-border-color);\n\t--vs-selected-border-style: var(--vs-border-style);\n\t--vs-selected-border-width: var(--vs-border-width);\n\n\t/* Dropdown */\n\t--vs-dropdown-bg: var(--color-main-background);\n\t--vs-dropdown-color: var(--color-main-text);\n\t--vs-dropdown-z-index: 9999;\n\t--vs-dropdown-box-shadow: 0px 2px 2px 0px var(--color-box-shadow);\n\n\t/* Options */\n\t--vs-dropdown-option-padding: 8px 20px;\n\n\t/* Active State */\n\t--vs-dropdown-option--active-bg: var(--color-background-hover);\n\t--vs-dropdown-option--active-color: var(--color-main-text);\n\n\t/* Keyboard Focus State */\n\t--vs-dropdown-option--kb-focus-box-shadow: inset 0px 0px 0px 2px var(--vs-border-color);\n\n\t/* Deselect State */\n\t--vs-dropdown-option--deselect-bg: var(--color-error);\n\t--vs-dropdown-option--deselect-color: #fff;\n\n\t/* Transitions */\n\t--vs-transition-duration: 0ms;\n\n\t/* Actions */\n\t--vs-actions-padding: 0 8px 0 4px;\n}\n\n.v-select.select {\n\t/* Override default vue-select styles */\n\tmin-height: $clickable-area;\n\tmin-width: 260px;\n\tmargin: 0;\n\n\t.vs__selected {\n\t\theight: 32px;\n\t\tpadding: 0 8px 0 12px;\n\t\tborder-radius: 18px !important;\n\t\tbackground: var(--color-primary-element-light);\n\t\tborder: none;\n\t}\n\n\t.vs__search, .vs__search:focus {\n\t\tmargin: 2px 0 0;\n\t}\n\n\t.vs__dropdown-toggle {\n\t\tpadding: 0;\n\t}\n\n\t.vs__clear {\n\t\tmargin-right: 2px;\n\t}\n\n\t&.vs--open .vs__dropdown-toggle {\n\t\toutline: 2px solid var(--color-main-background);\n\t\tborder-color: var(--color-main-text);\n\t\tborder-bottom-color: transparent;\n\t}\n\n\t&:not(.vs--disabled, .vs--open) .vs__dropdown-toggle:hover {\n\t\toutline: 2px solid var(--color-main-background);\n\t\tborder-color: var(--color-main-text);\n\t}\n\n\t&.vs--disabled {\n\t\t.vs__search,\n\t\t.vs__selected {\n\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t}\n\n\t\t.vs__clear,\n\t\t.vs__deselect {\n\t\t\tdisplay: none;\n\t\t}\n\t}\n\n\t&--no-wrap {\n\t\t.vs__selected-options {\n\t\t\tflex-wrap: nowrap;\n\t\t\toverflow: auto;\n\t\t\tmin-width: unset;\n\t\t\t.vs__selected {\n\t\t\t\tmin-width: unset;\n\t\t\t}\n\t\t}\n\t}\n\n\t&--drop-up {\n\t\t&.vs--open {\n\t\t\t.vs__dropdown-toggle {\n\t\t\t\tborder-radius: 0 0 var(--vs-border-radius) var(--vs-border-radius);\n\t\t\t\tborder-top-color: transparent;\n\t\t\t\tborder-bottom-color: var(--color-main-text);\n\t\t\t}\n\t\t}\n\t}\n\n\t.vs__selected-options {\n\t\t// If search is hidden, ensure that the height of the search is the same\n\t\tmin-height: 40px; // 36px search height + 4px search margin\n\n\t\t// Hide search from dom if unused to prevent unneeded flex wrap\n\t\t.vs__selected ~ .vs__search[readonly] {\n\t\t\tposition: absolute;\n\t\t}\n\t}\n\n\t&.vs--single {\n\t\t&.vs--loading,\n\t\t&.vs--open {\n\t\t\t.vs__selected {\n\t\t\t\t// Fix `max-width` for `position: absolute`\n\t\t\t\tmax-width: 100%;\n\t\t\t\t// Fix color to be accessible\n\t\t\t\topacity: 1;\n\t\t\t\tcolor: var(--color-text-maxcontrast);\n\t\t\t}\n\t\t}\n\t\t.vs__selected-options {\n\t\t\tflex-wrap: nowrap;\n\t\t}\n\t\t.vs__selected {\n\t\t\tbackground: unset !important;\n\t\t}\n\t}\n}\n\n.vs__dropdown-menu {\n\tborder-color: var(--color-main-text) !important;\n\toutline: 2px solid var(--color-main-background);\n\tpadding: 4px !important;\n\tbox-shadow: none;\n\n\t&--floating {\n\t\t/* Fallback styles overidden by programmatically set inline styles */\n\t\twidth: max-content;\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\n\t\t&-placement-top {\n\t\t\tborder-radius: var(--vs-border-radius) var(--vs-border-radius) 0 0 !important;\n\t\t\tborder-top-style: var(--vs-border-style) !important;\n\t\t\tborder-bottom-style: none !important;\n\t\t}\n\t}\n\n\t.vs__dropdown-option {\n\t\tborder-radius: 6px !important;\n\t}\n\n\t.vs__no-options {\n\t\tcolor: var(--color-text-lighter) !important;\n\t}\n}\n\n// Selected users require slightly different padding\n.user-select .vs__selected {\n\tpadding: 0 2px !important;\n}\n\n</style>\n"],"names":["_sfc_main","ChevronDown","Components_NcEllipsisedOption","Components_NcListItemIcon","Components_NcLoadingIcon","vueSelect","_l10n","optionLabel","createElement","Close","noDrop","open","map","vm","event","GenRandomId","dropdownMenu","component","width","addClass","_middlewareArgs","togglePlacementClass","placement","updatePosition","dom","x","y","EMAIL_NOTATION","option","label","search","match","_c","_b","_a","inputClass","noWrap","userSelect","initialPropsToForward"],"mappings":"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"}