@conduction/nextcloud-vue 2.98.0 → 2.100.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 (141) hide show
  1. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js +12 -0
  2. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js.map +1 -1
  3. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js +11 -2
  4. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js.map +1 -1
  5. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
  6. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +6 -1
  7. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
  8. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +2 -1
  9. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
  10. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue.js +1 -1
  11. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue2.js.map +1 -1
  12. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js +1 -1
  13. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js.map +1 -1
  14. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +25 -8
  15. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  16. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +7 -4
  17. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  18. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  19. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +11 -8
  20. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  21. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +13 -4
  22. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  23. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
  24. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +54 -3
  25. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  26. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +16 -2
  27. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  28. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue.js +1 -1
  29. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js +42 -7
  30. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js.map +1 -1
  31. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js +121 -57
  32. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js.map +1 -1
  33. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue2.js +10 -0
  34. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue2.js.map +1 -1
  35. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue3.js +2 -1
  36. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue3.js.map +1 -1
  37. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +136 -7
  38. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  39. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  40. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue.js +1 -1
  41. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js +26 -7
  42. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js.map +1 -1
  43. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js +78 -17
  44. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js.map +1 -1
  45. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  46. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +68 -7
  47. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  48. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +256 -240
  49. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  50. package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +9 -0
  51. package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js.map +1 -0
  52. package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js +265 -0
  53. package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -0
  54. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +191 -0
  55. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -0
  56. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue.js +9 -0
  57. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue.js.map +1 -0
  58. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue2.js +537 -0
  59. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue2.js.map +1 -0
  60. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue3.js +99 -0
  61. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue3.js.map +1 -0
  62. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue.js +1 -1
  63. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js +18 -70
  64. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js.map +1 -1
  65. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js +6 -44
  66. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js.map +1 -1
  67. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
  68. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +16 -2
  69. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
  70. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +40 -25
  71. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
  72. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
  73. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  74. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue.js +1 -1
  75. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js +7 -7
  76. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js.map +1 -1
  77. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js.map +1 -1
  78. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue.js +9 -0
  79. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue.js.map +1 -0
  80. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue2.js +472 -0
  81. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue2.js.map +1 -0
  82. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue3.js +231 -0
  83. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue3.js.map +1 -0
  84. package/dist/esm/components/CnWorkingCalendarWidget/index.js +27 -0
  85. package/dist/esm/components/CnWorkingCalendarWidget/index.js.map +1 -0
  86. package/dist/esm/composables/useFlowStore.js +2 -1
  87. package/dist/esm/composables/useFlowStore.js.map +1 -1
  88. package/dist/esm/index.js +3 -0
  89. package/dist/esm/index.js.map +1 -1
  90. package/dist/esm/l10n/en.json.js +101 -1
  91. package/dist/esm/l10n/en.json.js.map +1 -1
  92. package/dist/esm/l10n/nl.json.js +115 -1
  93. package/dist/esm/l10n/nl.json.js.map +1 -1
  94. package/dist/esm/library-style.js +1 -1
  95. package/dist/esm/nextcloud-vue.css +999 -233
  96. package/dist/esm/utils/libraryWidgetKeys.js +1 -0
  97. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  98. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  99. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  100. package/dist/esm/utils/workingCalendarMonth.js +85 -0
  101. package/dist/esm/utils/workingCalendarMonth.js.map +1 -0
  102. package/dist/nextcloud-vue.cjs.js +10314 -7778
  103. package/dist/nextcloud-vue.cjs.js.map +2 -2
  104. package/dist/nextcloud-vue.css +999 -233
  105. package/l10n/en.json +101 -1
  106. package/l10n/nl.json +115 -1
  107. package/package.json +1 -1
  108. package/src/components/CnActionsMenu/CnActionsMenu.vue +14 -1
  109. package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +7 -1
  110. package/src/components/CnBreadcrumbs/CnBreadcrumbs.vue +1 -0
  111. package/src/components/CnDetailPage/CnDetailPage.vue +29 -9
  112. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +13 -4
  113. package/src/components/CnFactsWidget/CnFactsWidget.vue +65 -3
  114. package/src/components/CnFlowsPage/CnFlowBoard.vue +77 -2
  115. package/src/components/CnFlowsPage/CnFlowEditorPage.vue +11 -0
  116. package/src/components/CnIndexPage/CnIndexPage.vue +136 -7
  117. package/src/components/CnOrderedListField/CnOrderedListField.vue +81 -9
  118. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +114 -7
  119. package/src/components/CnSettingsField/CnSettingsField.vue +449 -0
  120. package/src/components/CnSettingsField/index.js +4 -0
  121. package/src/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue +642 -0
  122. package/src/components/CnSettingsFieldsSection/index.js +4 -0
  123. package/src/components/CnSettingsPage/CnSettingsPage.vue +6 -86
  124. package/src/components/CnSetupWizard/CnSetupWizard.vue +37 -3
  125. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
  126. package/src/components/CnWizardDialog/CnWizardDialog.vue +7 -7
  127. package/src/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue +725 -0
  128. package/src/components/CnWorkingCalendarWidget/index.js +26 -0
  129. package/src/components/index.js +3 -0
  130. package/src/composables/useFlowStore.js +2 -1
  131. package/src/css/badge.css +32 -16
  132. package/src/css/detail-page.css +15 -0
  133. package/src/css/dialog.css +48 -0
  134. package/src/css/look-board-detail.css +80 -8
  135. package/src/css/look-board-index.css +52 -8
  136. package/src/css/look-board.css +301 -1
  137. package/src/index.js +3 -0
  138. package/src/schemas/app-manifest-v2.schema.json +25 -1
  139. package/src/utils/libraryWidgetKeys.js +1 -0
  140. package/src/utils/validateManifestV2.compiled.js +3 -3
  141. package/src/utils/workingCalendarMonth.js +82 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CnSettingsField.vue2.js","sources":["../../../../src/components/CnSettingsField/CnSettingsField.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-settings-field\" :data-testid=\"`cn-settings-field-${field.key}`\">\n\t\t<NcCheckboxRadioSwitch\n\t\t\tv-if=\"kind === 'switch' || kind === 'boolean'\"\n\t\t\t:type=\"kind === 'switch' ? 'switch' : 'checkbox'\"\n\t\t\t:modelValue=\"!!modelValue\"\n\t\t\t:disabled=\"field.readOnly\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue($event)\">\n\t\t\t{{ label }}\n\t\t</NcCheckboxRadioSwitch>\n\t\t<div v-else-if=\"kind === 'image'\"\n\t\t\tclass=\"cn-settings-field__image\"\n\t\t\trole=\"group\"\n\t\t\t:aria-labelledby=\"`${inputId}-label`\">\n\t\t\t<span :id=\"`${inputId}-label`\" class=\"cn-settings-field__image-label\">{{ label }}</span>\n\t\t\t<div class=\"cn-settings-field__image-row\">\n\t\t\t\t<span class=\"cn-settings-field__image-tile\" :data-testid=\"`cn-settings-field-image-${field.key}`\">\n\t\t\t\t\t<img v-if=\"stringValue\" :src=\"stringValue\" :alt=\"t('nextcloud-vue', 'Current {name}', { name: label })\">\n\t\t\t\t\t<span v-else class=\"cn-settings-field__image-initials\" aria-hidden=\"true\">{{ field.initials || '' }}</span>\n\t\t\t\t</span>\n\t\t\t\t<input\n\t\t\t\t\t:id=\"inputId\"\n\t\t\t\t\tref=\"file\"\n\t\t\t\t\tclass=\"hidden-visually\"\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\t:accept=\"field.accept || 'image/*'\"\n\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\t:aria-labelledby=\"`${inputId}-label`\"\n\t\t\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t\t\t@change=\"upload($event.target.files && $event.target.files[0])\">\n\t\t\t\t<NcButton\n\t\t\t\t\tv-if=\"!field.readOnly && field.uploadUrl\"\n\t\t\t\t\t:disabled=\"uploading\"\n\t\t\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t\t\t:data-testid=\"`cn-settings-field-upload-${field.key}`\"\n\t\t\t\t\t@click=\"$refs.file && $refs.file.click()\">\n\t\t\t\t\t<template v-if=\"uploading\" #icon>\n\t\t\t\t\t\t<NcLoadingIcon :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ field.uploadLabel || t('nextcloud-vue', 'Upload {name}', { name: label }) }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\t\t<NcSelect\n\t\t\tv-else-if=\"kind === 'select'\"\n\t\t\t:inputId=\"inputId\"\n\t\t\t:modelValue=\"selectedOption\"\n\t\t\t:options=\"normalizedOptions\"\n\t\t\t:inputLabel=\"label\"\n\t\t\t:placeholder=\"field.placeholder || ''\"\n\t\t\t:loading=\"optionsLoading\"\n\t\t\t:disabled=\"field.readOnly\"\n\t\t\t:clearable=\"!field.required\"\n\t\t\tlabel=\"label\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue(optionValue($event))\" />\n\t\t<NcTextArea\n\t\t\tv-else-if=\"kind === 'textarea'\"\n\t\t\t:id=\"inputId\"\n\t\t\t:label=\"label\"\n\t\t\t:modelValue=\"stringValue\"\n\t\t\t:rows=\"field.rows || 4\"\n\t\t\t:placeholder=\"field.placeholder || ''\"\n\t\t\t:readonly=\"field.readOnly\"\n\t\t\t:error=\"!!error\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue($event)\" />\n\t\t<NcTextField\n\t\t\tv-else-if=\"kind === 'secret'\"\n\t\t\t:id=\"inputId\"\n\t\t\t:label=\"label\"\n\t\t\ttype=\"password\"\n\t\t\tautocomplete=\"new-password\"\n\t\t\t:modelValue=\"stringValue\"\n\t\t\t:placeholder=\"field.secretSet ? secretSetPlaceholder : (field.placeholder || '')\"\n\t\t\t:readonly=\"field.readOnly\"\n\t\t\t:error=\"!!error\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue($event)\" />\n\t\t<NcTextField\n\t\t\tv-else-if=\"kind === 'number'\"\n\t\t\t:id=\"inputId\"\n\t\t\t:label=\"label\"\n\t\t\ttype=\"number\"\n\t\t\t:min=\"field.min\"\n\t\t\t:max=\"field.max\"\n\t\t\t:modelValue=\"stringValue\"\n\t\t\t:readonly=\"field.readOnly\"\n\t\t\t:error=\"!!error\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue($event === '' ? null : Number($event))\" />\n\t\t<NcTextField\n\t\t\tv-else\n\t\t\t:id=\"inputId\"\n\t\t\t:label=\"label\"\n\t\t\t:type=\"kind === 'password' ? 'password' : 'text'\"\n\t\t\t:modelValue=\"stringValue\"\n\t\t\t:placeholder=\"field.placeholder || ''\"\n\t\t\t:readonly=\"field.readOnly\"\n\t\t\t:error=\"!!error\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue($event)\" />\n\t\t<p v-if=\"shownError\"\n\t\t\t:id=\"`${inputId}-error`\"\n\t\t\tclass=\"cn-settings-field__error\"\n\t\t\t:data-testid=\"`cn-settings-field-error-${field.key}`\">\n\t\t\t{{ shownError }}\n\t\t</p>\n\t\t<p v-else-if=\"hint\" :id=\"`${inputId}-hint`\" class=\"cn-settings-field__hint\">\n\t\t\t{{ hint }}\n\t\t</p>\n\t</div>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon, NcSelect, NcTextArea, NcTextField } from '@nextcloud/vue'\nimport { buildHeaders, prefixUrl } from '../../utils/headers.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { serverErrorMessage } from '../../utils/serverErrorMessage.js'\n\nlet fieldUid = 0\n\n/** Field types and the names CnSettingsPage's manifest uses for them. */\nconst KIND_ALIASES = { enum: 'select', string: 'text' }\n\n/**\n * CnSettingsField - one settings field: the control for its type with its\n * label, and under it an error or a hint. Shared by CnSettingsPage and\n * CnSettingsFieldsSection.\n *\n * Types: `text` (default), `textarea`, `number`, `switch`, `boolean` (a checkbox),\n * `select` (`enum`) with static `options` or options read from `optionsUrl`,\n * `password` (a masked input that shows its value back) and `secret`\n * (replace-only: the input stays empty, and with `secretSet` says a value is\n * stored; the host sends it only when something is typed), and `image` (a\n * preview tile, the initials without an image, and an upload button that\n * posts the file to `uploadUrl` at once and emits `uploaded`).\n *\n * ```vue\n * <CnSettingsField\n * :field=\"{ key: 'apiKey', label: 'API key', type: 'secret', secretSet: true }\"\n * v-model=\"form.apiKey\" />\n * ```\n */\nexport default {\n\tname: 'CnSettingsField',\n\n\tcomponents: { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon, NcSelect, NcTextArea, NcTextField },\n\n\tprops: {\n\t\t/**\n\t\t * The field: `{ key, label, type?, options?, optionsUrl?, optionsPath?,\n\t\t * optionLabel?, optionValue?, placeholder?, rows?, min?, max?, required?,\n\t\t * readOnly?, secretSet? }`. `label` arrives translated.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tfield: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/**\n\t\t * The value: text, a number, a boolean or a select value. Any type,\n\t\t * because a Boolean in a type list would read an empty string as true.\n\t\t */\n\t\tmodelValue: {\n\t\t\ttype: null,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** A validation message, drawn under the control and tied to it. */\n\t\terror: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** A hint under the control (not drawn while there is an error). */\n\t\thint: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['update:modelValue', 'uploaded'],\n\n\tdata() {\n\t\tfieldUid += 1\n\t\treturn {\n\t\t\tuid: fieldUid,\n\t\t\tfetchedOptions: null,\n\t\t\toptionsLoading: false,\n\t\t\tuploading: false,\n\t\t\tuploadError: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} The control kind. */\n\t\tkind() {\n\t\t\tconst type = String(this.field.type || 'text')\n\t\t\treturn KIND_ALIASES[type] || type\n\t\t},\n\n\t\t/** @return {string} The label. */\n\t\tlabel() {\n\t\t\treturn String(this.field.label || this.field.key || '')\n\t\t},\n\n\t\t/** @return {string} The control's id. */\n\t\tinputId() {\n\t\t\treturn `cn-settings-field-${this.uid}-${String(this.field.key).replace(/[^A-Za-z0-9_-]/g, '-')}`\n\t\t},\n\n\t\t/** @return {string} The message shown under the control: an upload failure, else `error`. */\n\t\tshownError() {\n\t\t\treturn this.uploadError || this.error\n\t\t},\n\n\t\t/** @return {string|null} The id of the error or hint the control is described by. */\n\t\tdescribedBy() {\n\t\t\tif (this.shownError) {\n\t\t\t\treturn `${this.inputId}-error`\n\t\t\t}\n\t\t\treturn this.hint ? `${this.inputId}-hint` : null\n\t\t},\n\n\t\t/** @return {string} The value as text for a text control. */\n\t\tstringValue() {\n\t\t\treturn this.modelValue === null || this.modelValue === undefined ? '' : String(this.modelValue)\n\t\t},\n\n\t\t/** @return {string} The placeholder of a secret that is stored. */\n\t\tsecretSetPlaceholder() {\n\t\t\treturn t('nextcloud-vue', 'Stored. Type a new value to replace it.')\n\t\t},\n\n\t\t/**\n\t\t * The select options as `{ label, value }`: the static `options` (strings,\n\t\t * numbers or objects), or those read from `optionsUrl`.\n\t\t *\n\t\t * @return {Array<{label: string, value: (string|number|boolean)}>}\n\t\t */\n\t\tnormalizedOptions() {\n\t\t\tconst raw = Array.isArray(this.field.options) ? this.field.options : (this.fetchedOptions || [])\n\t\t\treturn raw.map((option) => (option && typeof option === 'object'\n\t\t\t\t? { ...option, label: String(option.label ?? option.value ?? ''), value: option.value }\n\t\t\t\t: { label: String(option), value: option }))\n\t\t},\n\n\t\t/** @return {object|null} The option the value selects, for NcSelect. */\n\t\tselectedOption() {\n\t\t\tif (this.modelValue === null || this.modelValue === undefined || this.modelValue === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.normalizedOptions.find((option) => option.value === this.modelValue)\n\t\t\t\t|| { label: String(this.modelValue), value: this.modelValue }\n\t\t},\n\t},\n\n\twatch: {\n\t\t'field.optionsUrl': {\n\t\t\thandler() {\n\t\t\t\tthis.loadOptions()\n\t\t\t},\n\n\t\t\timmediate: true,\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Upload a chosen image to `uploadUrl` as multipart form data (the\n\t\t * file under `uploadField`, default `image`, plus `uploadParams`), then\n\t\t * take the new image url from the answer at `uploadValuePath` (or a\n\t\t * cache-busted `previewUrl`).\n\t\t *\n\t\t * @param {File|undefined} file The chosen file.\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/settings-fields-section/specs/settings-fields-section/spec.md#requirement-an-image-field-uploads-at-once\n\t\t */\n\t\tasync upload(file) {\n\t\t\tif (!file || !this.field.uploadUrl) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst form = new FormData()\n\t\t\tfor (const [name, value] of Object.entries(this.field.uploadParams || {})) {\n\t\t\t\tform.append(name, value)\n\t\t\t}\n\t\t\tform.append(this.field.uploadField || 'image', file)\n\t\t\tthis.uploading = true\n\t\t\tthis.uploadError = ''\n\t\t\ttry {\n\t\t\t\tconst response = await axios.post(prefixUrl(this.field.uploadUrl), form)\n\t\t\t\tconst fromAnswer = this.field.uploadValuePath ? readPath(response?.data, this.field.uploadValuePath) : ''\n\t\t\t\tconst next = fromAnswer || (this.field.previewUrl ? `${prefixUrl(this.field.previewUrl)}${this.field.previewUrl.includes('?') ? '&' : '?'}v=${Date.now()}` : '')\n\t\t\t\t/**\n\t\t\t\t * @event uploaded An image was uploaded. Payload: its new url.\n\t\t\t\t */\n\t\t\t\tthis.$emit('uploaded', next)\n\t\t\t} catch (error) {\n\t\t\t\tthis.uploadError = t('nextcloud-vue', 'The image could not be uploaded: {reason}', { reason: serverErrorMessage(error) })\n\t\t\t} finally {\n\t\t\t\tthis.uploading = false\n\t\t\t\tif (this.$refs.file) {\n\t\t\t\t\tthis.$refs.file.value = ''\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Report a new value.\n\t\t *\n\t\t * @param {unknown} value The value.\n\t\t * @return {void}\n\t\t */\n\t\temitValue(value) {\n\t\t\t/**\n\t\t\t * @event update:modelValue The value changed. Payload: the new value.\n\t\t\t */\n\t\t\tthis.$emit('update:modelValue', value)\n\t\t},\n\n\t\t/**\n\t\t * The storable value of what NcSelect emits.\n\t\t *\n\t\t * @param {object|string|number|null} emitted An option, or null on clear.\n\t\t * @return {string|number|boolean|null}\n\t\t */\n\t\toptionValue(emitted) {\n\t\t\tif (emitted === null || emitted === undefined) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn typeof emitted === 'object' && 'value' in emitted ? emitted.value : emitted\n\t\t},\n\n\t\t/**\n\t\t * Read a sourced select's options: a list (or the list at\n\t\t * `optionsPath`, or under `results`) mapped through `optionLabel` and\n\t\t * `optionValue` (dotted paths; default `label`/`title`/`name` and `value`/`id`).\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadOptions() {\n\t\t\tconst url = this.kind === 'select' && !Array.isArray(this.field.options) ? this.field.optionsUrl : ''\n\t\t\tif (!url) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.optionsLoading = true\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(url), { headers: buildHeaders() })\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthis.fetchedOptions = []\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst data = await response.json()\n\t\t\t\tconst list = this.field.optionsPath ? readPath(data, this.field.optionsPath) : (Array.isArray(data) ? data : data?.results)\n\t\t\t\tthis.fetchedOptions = (Array.isArray(list) ? list : []).map((item) => {\n\t\t\t\t\tif (!item || typeof item !== 'object') {\n\t\t\t\t\t\treturn { label: String(item), value: item }\n\t\t\t\t\t}\n\t\t\t\t\tconst value = this.field.optionValue ? readPath(item, this.field.optionValue) : (item.value ?? item.id)\n\t\t\t\t\tconst label = this.field.optionLabel ? readPath(item, this.field.optionLabel) : (item.label ?? item.title ?? item.name ?? value)\n\t\t\t\t\treturn { label: String(label ?? ''), value }\n\t\t\t\t})\n\t\t\t} catch {\n\t\t\t\tthis.fetchedOptions = []\n\t\t\t} finally {\n\t\t\t\tthis.optionsLoading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-settings-field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tmin-width: 0;\n}\n\n.cn-settings-field__hint,\n.cn-settings-field__error {\n\tmargin: 0;\n\tfont-size: 13px;\n\tline-height: 1.4;\n}\n\n.cn-settings-field__image {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.cn-settings-field__image-label {\n\tfont-weight: 600;\n}\n\n.cn-settings-field__image-row {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 12px;\n}\n\n.cn-settings-field__image-tile {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 64px;\n\theight: 64px;\n\toverflow: hidden;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large);\n\tbackground: var(--color-primary-element-light);\n}\n\n.cn-settings-field__image-tile img {\n\tmax-width: 100%;\n\tmax-height: 100%;\n\tobject-fit: contain;\n}\n\n.cn-settings-field__image-initials {\n\tfont-size: 20px;\n\tfont-weight: 700;\n\tcolor: var(--color-primary-element-light-text, var(--color-primary-element));\n}\n\n.cn-settings-field__hint {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-settings-field__error {\n\tcolor: var(--color-error-text, var(--color-error));\n}\n</style>\n"],"names":["t","axios"],"mappings":"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"}
@@ -0,0 +1,191 @@
1
+ import { resolveComponent, openBlock, createElementBlock, createBlock, withCtx, createTextVNode, toDisplayString, createElementVNode, createSlots, createVNode, createCommentVNode } from 'vue';
2
+
3
+ const _hoisted_1 = ["data-testid"];
4
+ const _hoisted_2 = ["aria-labelledby"];
5
+ const _hoisted_3 = ["id"];
6
+ const _hoisted_4 = { class: "cn-settings-field__image-row" };
7
+ const _hoisted_5 = ["data-testid"];
8
+ const _hoisted_6 = ["src", "alt"];
9
+ const _hoisted_7 = {
10
+ key: 1,
11
+ class: "cn-settings-field__image-initials",
12
+ "aria-hidden": "true"
13
+ };
14
+ const _hoisted_8 = ["id", "accept", "aria-labelledby", "aria-describedby"];
15
+ const _hoisted_9 = ["id", "data-testid"];
16
+ const _hoisted_10 = ["id"];
17
+
18
+ function render(_ctx, _cache, $props, $setup, $data, $options) {
19
+ const _component_NcCheckboxRadioSwitch = resolveComponent("NcCheckboxRadioSwitch");
20
+ const _component_NcLoadingIcon = resolveComponent("NcLoadingIcon");
21
+ const _component_NcButton = resolveComponent("NcButton");
22
+ const _component_NcSelect = resolveComponent("NcSelect");
23
+ const _component_NcTextArea = resolveComponent("NcTextArea");
24
+ const _component_NcTextField = resolveComponent("NcTextField");
25
+
26
+ return (openBlock(), createElementBlock("div", {
27
+ class: "cn-settings-field",
28
+ "data-testid": `cn-settings-field-${$props.field.key}`
29
+ }, [
30
+ ($options.kind === 'switch' || $options.kind === 'boolean')
31
+ ? (openBlock(), createBlock(_component_NcCheckboxRadioSwitch, {
32
+ key: 0,
33
+ type: $options.kind === 'switch' ? 'switch' : 'checkbox',
34
+ modelValue: !!$props.modelValue,
35
+ disabled: $props.field.readOnly,
36
+ "aria-describedby": $options.describedBy,
37
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = $event => ($options.emitValue($event)))
38
+ }, {
39
+ default: withCtx(() => [
40
+ createTextVNode(toDisplayString($options.label), 1 /* TEXT */)
41
+ ]),
42
+ _: 1 /* STABLE */
43
+ }, 8 /* PROPS */, ["type", "modelValue", "disabled", "aria-describedby"]))
44
+ : ($options.kind === 'image')
45
+ ? (openBlock(), createElementBlock("div", {
46
+ key: 1,
47
+ class: "cn-settings-field__image",
48
+ role: "group",
49
+ "aria-labelledby": `${$options.inputId}-label`
50
+ }, [
51
+ createElementVNode("span", {
52
+ id: `${$options.inputId}-label`,
53
+ class: "cn-settings-field__image-label"
54
+ }, toDisplayString($options.label), 9 /* TEXT, PROPS */, _hoisted_3),
55
+ createElementVNode("div", _hoisted_4, [
56
+ createElementVNode("span", {
57
+ class: "cn-settings-field__image-tile",
58
+ "data-testid": `cn-settings-field-image-${$props.field.key}`
59
+ }, [
60
+ ($options.stringValue)
61
+ ? (openBlock(), createElementBlock("img", {
62
+ key: 0,
63
+ src: $options.stringValue,
64
+ alt: $options.t('nextcloud-vue', 'Current {name}', { name: $options.label })
65
+ }, null, 8 /* PROPS */, _hoisted_6))
66
+ : (openBlock(), createElementBlock("span", _hoisted_7, toDisplayString($props.field.initials || ''), 1 /* TEXT */))
67
+ ], 8 /* PROPS */, _hoisted_5),
68
+ createElementVNode("input", {
69
+ id: $options.inputId,
70
+ ref: "file",
71
+ class: "hidden-visually",
72
+ type: "file",
73
+ accept: $props.field.accept || 'image/*',
74
+ tabindex: "-1",
75
+ "aria-labelledby": `${$options.inputId}-label`,
76
+ "aria-describedby": $options.describedBy,
77
+ onChange: _cache[1] || (_cache[1] = $event => ($options.upload($event.target.files && $event.target.files[0])))
78
+ }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_8),
79
+ (!$props.field.readOnly && $props.field.uploadUrl)
80
+ ? (openBlock(), createBlock(_component_NcButton, {
81
+ key: 0,
82
+ disabled: $data.uploading,
83
+ "aria-describedby": $options.describedBy,
84
+ "data-testid": `cn-settings-field-upload-${$props.field.key}`,
85
+ onClick: _cache[2] || (_cache[2] = $event => (_ctx.$refs.file && _ctx.$refs.file.click()))
86
+ }, createSlots({
87
+ default: withCtx(() => [
88
+ createTextVNode(" " + toDisplayString($props.field.uploadLabel || $options.t('nextcloud-vue', 'Upload {name}', { name: $options.label })), 1 /* TEXT */)
89
+ ]),
90
+ _: 2 /* DYNAMIC */
91
+ }, [
92
+ ($data.uploading)
93
+ ? {
94
+ name: "icon",
95
+ fn: withCtx(() => [
96
+ createVNode(_component_NcLoadingIcon, { size: 20 })
97
+ ]),
98
+ key: "0"
99
+ }
100
+ : undefined
101
+ ]), 1032 /* PROPS, DYNAMIC_SLOTS */, ["disabled", "aria-describedby", "data-testid"]))
102
+ : createCommentVNode("v-if", true)
103
+ ])
104
+ ], 8 /* PROPS */, _hoisted_2))
105
+ : ($options.kind === 'select')
106
+ ? (openBlock(), createBlock(_component_NcSelect, {
107
+ key: 2,
108
+ inputId: $options.inputId,
109
+ modelValue: $options.selectedOption,
110
+ options: $options.normalizedOptions,
111
+ inputLabel: $options.label,
112
+ placeholder: $props.field.placeholder || '',
113
+ loading: $data.optionsLoading,
114
+ disabled: $props.field.readOnly,
115
+ clearable: !$props.field.required,
116
+ label: "label",
117
+ "aria-describedby": $options.describedBy,
118
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = $event => ($options.emitValue($options.optionValue($event))))
119
+ }, null, 8 /* PROPS */, ["inputId", "modelValue", "options", "inputLabel", "placeholder", "loading", "disabled", "clearable", "aria-describedby"]))
120
+ : ($options.kind === 'textarea')
121
+ ? (openBlock(), createBlock(_component_NcTextArea, {
122
+ key: 3,
123
+ id: $options.inputId,
124
+ label: $options.label,
125
+ modelValue: $options.stringValue,
126
+ rows: $props.field.rows || 4,
127
+ placeholder: $props.field.placeholder || '',
128
+ readonly: $props.field.readOnly,
129
+ error: !!$props.error,
130
+ "aria-describedby": $options.describedBy,
131
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => ($options.emitValue($event)))
132
+ }, null, 8 /* PROPS */, ["id", "label", "modelValue", "rows", "placeholder", "readonly", "error", "aria-describedby"]))
133
+ : ($options.kind === 'secret')
134
+ ? (openBlock(), createBlock(_component_NcTextField, {
135
+ key: 4,
136
+ id: $options.inputId,
137
+ label: $options.label,
138
+ type: "password",
139
+ autocomplete: "new-password",
140
+ modelValue: $options.stringValue,
141
+ placeholder: $props.field.secretSet ? $options.secretSetPlaceholder : ($props.field.placeholder || ''),
142
+ readonly: $props.field.readOnly,
143
+ error: !!$props.error,
144
+ "aria-describedby": $options.describedBy,
145
+ "onUpdate:modelValue": _cache[5] || (_cache[5] = $event => ($options.emitValue($event)))
146
+ }, null, 8 /* PROPS */, ["id", "label", "modelValue", "placeholder", "readonly", "error", "aria-describedby"]))
147
+ : ($options.kind === 'number')
148
+ ? (openBlock(), createBlock(_component_NcTextField, {
149
+ key: 5,
150
+ id: $options.inputId,
151
+ label: $options.label,
152
+ type: "number",
153
+ min: $props.field.min,
154
+ max: $props.field.max,
155
+ modelValue: $options.stringValue,
156
+ readonly: $props.field.readOnly,
157
+ error: !!$props.error,
158
+ "aria-describedby": $options.describedBy,
159
+ "onUpdate:modelValue": _cache[6] || (_cache[6] = $event => ($options.emitValue($event === '' ? null : Number($event))))
160
+ }, null, 8 /* PROPS */, ["id", "label", "min", "max", "modelValue", "readonly", "error", "aria-describedby"]))
161
+ : (openBlock(), createBlock(_component_NcTextField, {
162
+ key: 6,
163
+ id: $options.inputId,
164
+ label: $options.label,
165
+ type: $options.kind === 'password' ? 'password' : 'text',
166
+ modelValue: $options.stringValue,
167
+ placeholder: $props.field.placeholder || '',
168
+ readonly: $props.field.readOnly,
169
+ error: !!$props.error,
170
+ "aria-describedby": $options.describedBy,
171
+ "onUpdate:modelValue": _cache[7] || (_cache[7] = $event => ($options.emitValue($event)))
172
+ }, null, 8 /* PROPS */, ["id", "label", "type", "modelValue", "placeholder", "readonly", "error", "aria-describedby"])),
173
+ ($options.shownError)
174
+ ? (openBlock(), createElementBlock("p", {
175
+ key: 7,
176
+ id: `${$options.inputId}-error`,
177
+ class: "cn-settings-field__error",
178
+ "data-testid": `cn-settings-field-error-${$props.field.key}`
179
+ }, toDisplayString($options.shownError), 9 /* TEXT, PROPS */, _hoisted_9))
180
+ : ($props.hint)
181
+ ? (openBlock(), createElementBlock("p", {
182
+ key: 8,
183
+ id: `${$options.inputId}-hint`,
184
+ class: "cn-settings-field__hint"
185
+ }, toDisplayString($props.hint), 9 /* TEXT, PROPS */, _hoisted_10))
186
+ : createCommentVNode("v-if", true)
187
+ ], 8 /* PROPS */, _hoisted_1))
188
+ }
189
+
190
+ export { render };
191
+ //# sourceMappingURL=CnSettingsField.vue3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CnSettingsField.vue3.js","sources":["../../../../src/components/CnSettingsField/CnSettingsField.vue?vue&type=template&id=d2218996&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-settings-field\" :data-testid=\"`cn-settings-field-${field.key}`\">\n\t\t<NcCheckboxRadioSwitch\n\t\t\tv-if=\"kind === 'switch' || kind === 'boolean'\"\n\t\t\t:type=\"kind === 'switch' ? 'switch' : 'checkbox'\"\n\t\t\t:modelValue=\"!!modelValue\"\n\t\t\t:disabled=\"field.readOnly\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue($event)\">\n\t\t\t{{ label }}\n\t\t</NcCheckboxRadioSwitch>\n\t\t<div v-else-if=\"kind === 'image'\"\n\t\t\tclass=\"cn-settings-field__image\"\n\t\t\trole=\"group\"\n\t\t\t:aria-labelledby=\"`${inputId}-label`\">\n\t\t\t<span :id=\"`${inputId}-label`\" class=\"cn-settings-field__image-label\">{{ label }}</span>\n\t\t\t<div class=\"cn-settings-field__image-row\">\n\t\t\t\t<span class=\"cn-settings-field__image-tile\" :data-testid=\"`cn-settings-field-image-${field.key}`\">\n\t\t\t\t\t<img v-if=\"stringValue\" :src=\"stringValue\" :alt=\"t('nextcloud-vue', 'Current {name}', { name: label })\">\n\t\t\t\t\t<span v-else class=\"cn-settings-field__image-initials\" aria-hidden=\"true\">{{ field.initials || '' }}</span>\n\t\t\t\t</span>\n\t\t\t\t<input\n\t\t\t\t\t:id=\"inputId\"\n\t\t\t\t\tref=\"file\"\n\t\t\t\t\tclass=\"hidden-visually\"\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\t:accept=\"field.accept || 'image/*'\"\n\t\t\t\t\ttabindex=\"-1\"\n\t\t\t\t\t:aria-labelledby=\"`${inputId}-label`\"\n\t\t\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t\t\t@change=\"upload($event.target.files && $event.target.files[0])\">\n\t\t\t\t<NcButton\n\t\t\t\t\tv-if=\"!field.readOnly && field.uploadUrl\"\n\t\t\t\t\t:disabled=\"uploading\"\n\t\t\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t\t\t:data-testid=\"`cn-settings-field-upload-${field.key}`\"\n\t\t\t\t\t@click=\"$refs.file && $refs.file.click()\">\n\t\t\t\t\t<template v-if=\"uploading\" #icon>\n\t\t\t\t\t\t<NcLoadingIcon :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ field.uploadLabel || t('nextcloud-vue', 'Upload {name}', { name: label }) }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\t\t<NcSelect\n\t\t\tv-else-if=\"kind === 'select'\"\n\t\t\t:inputId=\"inputId\"\n\t\t\t:modelValue=\"selectedOption\"\n\t\t\t:options=\"normalizedOptions\"\n\t\t\t:inputLabel=\"label\"\n\t\t\t:placeholder=\"field.placeholder || ''\"\n\t\t\t:loading=\"optionsLoading\"\n\t\t\t:disabled=\"field.readOnly\"\n\t\t\t:clearable=\"!field.required\"\n\t\t\tlabel=\"label\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue(optionValue($event))\" />\n\t\t<NcTextArea\n\t\t\tv-else-if=\"kind === 'textarea'\"\n\t\t\t:id=\"inputId\"\n\t\t\t:label=\"label\"\n\t\t\t:modelValue=\"stringValue\"\n\t\t\t:rows=\"field.rows || 4\"\n\t\t\t:placeholder=\"field.placeholder || ''\"\n\t\t\t:readonly=\"field.readOnly\"\n\t\t\t:error=\"!!error\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue($event)\" />\n\t\t<NcTextField\n\t\t\tv-else-if=\"kind === 'secret'\"\n\t\t\t:id=\"inputId\"\n\t\t\t:label=\"label\"\n\t\t\ttype=\"password\"\n\t\t\tautocomplete=\"new-password\"\n\t\t\t:modelValue=\"stringValue\"\n\t\t\t:placeholder=\"field.secretSet ? secretSetPlaceholder : (field.placeholder || '')\"\n\t\t\t:readonly=\"field.readOnly\"\n\t\t\t:error=\"!!error\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue($event)\" />\n\t\t<NcTextField\n\t\t\tv-else-if=\"kind === 'number'\"\n\t\t\t:id=\"inputId\"\n\t\t\t:label=\"label\"\n\t\t\ttype=\"number\"\n\t\t\t:min=\"field.min\"\n\t\t\t:max=\"field.max\"\n\t\t\t:modelValue=\"stringValue\"\n\t\t\t:readonly=\"field.readOnly\"\n\t\t\t:error=\"!!error\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue($event === '' ? null : Number($event))\" />\n\t\t<NcTextField\n\t\t\tv-else\n\t\t\t:id=\"inputId\"\n\t\t\t:label=\"label\"\n\t\t\t:type=\"kind === 'password' ? 'password' : 'text'\"\n\t\t\t:modelValue=\"stringValue\"\n\t\t\t:placeholder=\"field.placeholder || ''\"\n\t\t\t:readonly=\"field.readOnly\"\n\t\t\t:error=\"!!error\"\n\t\t\t:aria-describedby=\"describedBy\"\n\t\t\t@update:modelValue=\"emitValue($event)\" />\n\t\t<p v-if=\"shownError\"\n\t\t\t:id=\"`${inputId}-error`\"\n\t\t\tclass=\"cn-settings-field__error\"\n\t\t\t:data-testid=\"`cn-settings-field-error-${field.key}`\">\n\t\t\t{{ shownError }}\n\t\t</p>\n\t\t<p v-else-if=\"hint\" :id=\"`${inputId}-hint`\" class=\"cn-settings-field__hint\">\n\t\t\t{{ hint }}\n\t\t</p>\n\t</div>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon, NcSelect, NcTextArea, NcTextField } from '@nextcloud/vue'\nimport { buildHeaders, prefixUrl } from '../../utils/headers.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { serverErrorMessage } from '../../utils/serverErrorMessage.js'\n\nlet fieldUid = 0\n\n/** Field types and the names CnSettingsPage's manifest uses for them. */\nconst KIND_ALIASES = { enum: 'select', string: 'text' }\n\n/**\n * CnSettingsField - one settings field: the control for its type with its\n * label, and under it an error or a hint. Shared by CnSettingsPage and\n * CnSettingsFieldsSection.\n *\n * Types: `text` (default), `textarea`, `number`, `switch`, `boolean` (a checkbox),\n * `select` (`enum`) with static `options` or options read from `optionsUrl`,\n * `password` (a masked input that shows its value back) and `secret`\n * (replace-only: the input stays empty, and with `secretSet` says a value is\n * stored; the host sends it only when something is typed), and `image` (a\n * preview tile, the initials without an image, and an upload button that\n * posts the file to `uploadUrl` at once and emits `uploaded`).\n *\n * ```vue\n * <CnSettingsField\n * :field=\"{ key: 'apiKey', label: 'API key', type: 'secret', secretSet: true }\"\n * v-model=\"form.apiKey\" />\n * ```\n */\nexport default {\n\tname: 'CnSettingsField',\n\n\tcomponents: { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon, NcSelect, NcTextArea, NcTextField },\n\n\tprops: {\n\t\t/**\n\t\t * The field: `{ key, label, type?, options?, optionsUrl?, optionsPath?,\n\t\t * optionLabel?, optionValue?, placeholder?, rows?, min?, max?, required?,\n\t\t * readOnly?, secretSet? }`. `label` arrives translated.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tfield: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/**\n\t\t * The value: text, a number, a boolean or a select value. Any type,\n\t\t * because a Boolean in a type list would read an empty string as true.\n\t\t */\n\t\tmodelValue: {\n\t\t\ttype: null,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** A validation message, drawn under the control and tied to it. */\n\t\terror: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** A hint under the control (not drawn while there is an error). */\n\t\thint: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['update:modelValue', 'uploaded'],\n\n\tdata() {\n\t\tfieldUid += 1\n\t\treturn {\n\t\t\tuid: fieldUid,\n\t\t\tfetchedOptions: null,\n\t\t\toptionsLoading: false,\n\t\t\tuploading: false,\n\t\t\tuploadError: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} The control kind. */\n\t\tkind() {\n\t\t\tconst type = String(this.field.type || 'text')\n\t\t\treturn KIND_ALIASES[type] || type\n\t\t},\n\n\t\t/** @return {string} The label. */\n\t\tlabel() {\n\t\t\treturn String(this.field.label || this.field.key || '')\n\t\t},\n\n\t\t/** @return {string} The control's id. */\n\t\tinputId() {\n\t\t\treturn `cn-settings-field-${this.uid}-${String(this.field.key).replace(/[^A-Za-z0-9_-]/g, '-')}`\n\t\t},\n\n\t\t/** @return {string} The message shown under the control: an upload failure, else `error`. */\n\t\tshownError() {\n\t\t\treturn this.uploadError || this.error\n\t\t},\n\n\t\t/** @return {string|null} The id of the error or hint the control is described by. */\n\t\tdescribedBy() {\n\t\t\tif (this.shownError) {\n\t\t\t\treturn `${this.inputId}-error`\n\t\t\t}\n\t\t\treturn this.hint ? `${this.inputId}-hint` : null\n\t\t},\n\n\t\t/** @return {string} The value as text for a text control. */\n\t\tstringValue() {\n\t\t\treturn this.modelValue === null || this.modelValue === undefined ? '' : String(this.modelValue)\n\t\t},\n\n\t\t/** @return {string} The placeholder of a secret that is stored. */\n\t\tsecretSetPlaceholder() {\n\t\t\treturn t('nextcloud-vue', 'Stored. Type a new value to replace it.')\n\t\t},\n\n\t\t/**\n\t\t * The select options as `{ label, value }`: the static `options` (strings,\n\t\t * numbers or objects), or those read from `optionsUrl`.\n\t\t *\n\t\t * @return {Array<{label: string, value: (string|number|boolean)}>}\n\t\t */\n\t\tnormalizedOptions() {\n\t\t\tconst raw = Array.isArray(this.field.options) ? this.field.options : (this.fetchedOptions || [])\n\t\t\treturn raw.map((option) => (option && typeof option === 'object'\n\t\t\t\t? { ...option, label: String(option.label ?? option.value ?? ''), value: option.value }\n\t\t\t\t: { label: String(option), value: option }))\n\t\t},\n\n\t\t/** @return {object|null} The option the value selects, for NcSelect. */\n\t\tselectedOption() {\n\t\t\tif (this.modelValue === null || this.modelValue === undefined || this.modelValue === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.normalizedOptions.find((option) => option.value === this.modelValue)\n\t\t\t\t|| { label: String(this.modelValue), value: this.modelValue }\n\t\t},\n\t},\n\n\twatch: {\n\t\t'field.optionsUrl': {\n\t\t\thandler() {\n\t\t\t\tthis.loadOptions()\n\t\t\t},\n\n\t\t\timmediate: true,\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Upload a chosen image to `uploadUrl` as multipart form data (the\n\t\t * file under `uploadField`, default `image`, plus `uploadParams`), then\n\t\t * take the new image url from the answer at `uploadValuePath` (or a\n\t\t * cache-busted `previewUrl`).\n\t\t *\n\t\t * @param {File|undefined} file The chosen file.\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/settings-fields-section/specs/settings-fields-section/spec.md#requirement-an-image-field-uploads-at-once\n\t\t */\n\t\tasync upload(file) {\n\t\t\tif (!file || !this.field.uploadUrl) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst form = new FormData()\n\t\t\tfor (const [name, value] of Object.entries(this.field.uploadParams || {})) {\n\t\t\t\tform.append(name, value)\n\t\t\t}\n\t\t\tform.append(this.field.uploadField || 'image', file)\n\t\t\tthis.uploading = true\n\t\t\tthis.uploadError = ''\n\t\t\ttry {\n\t\t\t\tconst response = await axios.post(prefixUrl(this.field.uploadUrl), form)\n\t\t\t\tconst fromAnswer = this.field.uploadValuePath ? readPath(response?.data, this.field.uploadValuePath) : ''\n\t\t\t\tconst next = fromAnswer || (this.field.previewUrl ? `${prefixUrl(this.field.previewUrl)}${this.field.previewUrl.includes('?') ? '&' : '?'}v=${Date.now()}` : '')\n\t\t\t\t/**\n\t\t\t\t * @event uploaded An image was uploaded. Payload: its new url.\n\t\t\t\t */\n\t\t\t\tthis.$emit('uploaded', next)\n\t\t\t} catch (error) {\n\t\t\t\tthis.uploadError = t('nextcloud-vue', 'The image could not be uploaded: {reason}', { reason: serverErrorMessage(error) })\n\t\t\t} finally {\n\t\t\t\tthis.uploading = false\n\t\t\t\tif (this.$refs.file) {\n\t\t\t\t\tthis.$refs.file.value = ''\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Report a new value.\n\t\t *\n\t\t * @param {unknown} value The value.\n\t\t * @return {void}\n\t\t */\n\t\temitValue(value) {\n\t\t\t/**\n\t\t\t * @event update:modelValue The value changed. Payload: the new value.\n\t\t\t */\n\t\t\tthis.$emit('update:modelValue', value)\n\t\t},\n\n\t\t/**\n\t\t * The storable value of what NcSelect emits.\n\t\t *\n\t\t * @param {object|string|number|null} emitted An option, or null on clear.\n\t\t * @return {string|number|boolean|null}\n\t\t */\n\t\toptionValue(emitted) {\n\t\t\tif (emitted === null || emitted === undefined) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn typeof emitted === 'object' && 'value' in emitted ? emitted.value : emitted\n\t\t},\n\n\t\t/**\n\t\t * Read a sourced select's options: a list (or the list at\n\t\t * `optionsPath`, or under `results`) mapped through `optionLabel` and\n\t\t * `optionValue` (dotted paths; default `label`/`title`/`name` and `value`/`id`).\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadOptions() {\n\t\t\tconst url = this.kind === 'select' && !Array.isArray(this.field.options) ? this.field.optionsUrl : ''\n\t\t\tif (!url) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.optionsLoading = true\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(url), { headers: buildHeaders() })\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthis.fetchedOptions = []\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst data = await response.json()\n\t\t\t\tconst list = this.field.optionsPath ? readPath(data, this.field.optionsPath) : (Array.isArray(data) ? data : data?.results)\n\t\t\t\tthis.fetchedOptions = (Array.isArray(list) ? list : []).map((item) => {\n\t\t\t\t\tif (!item || typeof item !== 'object') {\n\t\t\t\t\t\treturn { label: String(item), value: item }\n\t\t\t\t\t}\n\t\t\t\t\tconst value = this.field.optionValue ? readPath(item, this.field.optionValue) : (item.value ?? item.id)\n\t\t\t\t\tconst label = this.field.optionLabel ? readPath(item, this.field.optionLabel) : (item.label ?? item.title ?? item.name ?? value)\n\t\t\t\t\treturn { label: String(label ?? ''), value }\n\t\t\t\t})\n\t\t\t} catch {\n\t\t\t\tthis.fetchedOptions = []\n\t\t\t} finally {\n\t\t\t\tthis.optionsLoading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-settings-field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tmin-width: 0;\n}\n\n.cn-settings-field__hint,\n.cn-settings-field__error {\n\tmargin: 0;\n\tfont-size: 13px;\n\tline-height: 1.4;\n}\n\n.cn-settings-field__image {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.cn-settings-field__image-label {\n\tfont-weight: 600;\n}\n\n.cn-settings-field__image-row {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 12px;\n}\n\n.cn-settings-field__image-tile {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 64px;\n\theight: 64px;\n\toverflow: hidden;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large);\n\tbackground: var(--color-primary-element-light);\n}\n\n.cn-settings-field__image-tile img {\n\tmax-width: 100%;\n\tmax-height: 100%;\n\tobject-fit: contain;\n}\n\n.cn-settings-field__image-initials {\n\tfont-size: 20px;\n\tfont-weight: 700;\n\tcolor: var(--color-primary-element-light-text, var(--color-primary-element));\n}\n\n.cn-settings-field__hint {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-settings-field__error {\n\tcolor: var(--color-error-text, var(--color-error));\n}\n</style>\n"],"names":["_createBlock","_createElementBlock","_createElementVNode","_openBlock","_toDisplayString","_createTextVNode","_createVNode"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import script from './CnSettingsFieldsSection.vue2.js';
2
+ import { render } from './CnSettingsFieldsSection.vue3.js';
3
+
4
+ script.render = render;
5
+ script.__scopeId = "data-v-090828e4";
6
+ const __sfc_main = script;
7
+
8
+ export { __sfc_main as default };
9
+ //# sourceMappingURL=CnSettingsFieldsSection.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CnSettingsFieldsSection.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}