@conduction/nextcloud-vue 2.98.0 → 2.99.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 (84) 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/CnBreadcrumbs/CnBreadcrumbs.vue.js +1 -1
  6. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue2.js.map +1 -1
  7. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js +1 -1
  8. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js.map +1 -1
  9. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  10. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +2 -1
  11. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  12. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue.js +1 -1
  13. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js +26 -7
  14. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js.map +1 -1
  15. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js +78 -17
  16. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js.map +1 -1
  17. package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +9 -0
  18. package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js.map +1 -0
  19. package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js +265 -0
  20. package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -0
  21. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +191 -0
  22. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -0
  23. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue.js +9 -0
  24. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue.js.map +1 -0
  25. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue2.js +508 -0
  26. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue2.js.map +1 -0
  27. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue3.js +99 -0
  28. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue3.js.map +1 -0
  29. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue.js +1 -1
  30. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js +18 -70
  31. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js.map +1 -1
  32. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js +6 -44
  33. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js.map +1 -1
  34. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
  35. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  36. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue.js +9 -0
  37. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue.js.map +1 -0
  38. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue2.js +472 -0
  39. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue2.js.map +1 -0
  40. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue3.js +231 -0
  41. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue3.js.map +1 -0
  42. package/dist/esm/components/CnWorkingCalendarWidget/index.js +27 -0
  43. package/dist/esm/components/CnWorkingCalendarWidget/index.js.map +1 -0
  44. package/dist/esm/composables/useFlowStore.js +2 -1
  45. package/dist/esm/composables/useFlowStore.js.map +1 -1
  46. package/dist/esm/index.js +3 -0
  47. package/dist/esm/index.js.map +1 -1
  48. package/dist/esm/l10n/en.json.js +95 -1
  49. package/dist/esm/l10n/en.json.js.map +1 -1
  50. package/dist/esm/l10n/nl.json.js +109 -1
  51. package/dist/esm/l10n/nl.json.js.map +1 -1
  52. package/dist/esm/library-style.js +1 -1
  53. package/dist/esm/nextcloud-vue.css +660 -81
  54. package/dist/esm/utils/libraryWidgetKeys.js +1 -0
  55. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  56. package/dist/esm/utils/workingCalendarMonth.js +85 -0
  57. package/dist/esm/utils/workingCalendarMonth.js.map +1 -0
  58. package/dist/nextcloud-vue.cjs.js +9355 -7303
  59. package/dist/nextcloud-vue.cjs.js.map +2 -2
  60. package/dist/nextcloud-vue.css +660 -81
  61. package/l10n/en.json +95 -1
  62. package/l10n/nl.json +109 -1
  63. package/package.json +1 -1
  64. package/src/components/CnActionsMenu/CnActionsMenu.vue +14 -1
  65. package/src/components/CnBreadcrumbs/CnBreadcrumbs.vue +1 -0
  66. package/src/components/CnDetailPage/CnDetailPage.vue +1 -0
  67. package/src/components/CnOrderedListField/CnOrderedListField.vue +81 -9
  68. package/src/components/CnSettingsField/CnSettingsField.vue +449 -0
  69. package/src/components/CnSettingsField/index.js +4 -0
  70. package/src/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue +613 -0
  71. package/src/components/CnSettingsFieldsSection/index.js +4 -0
  72. package/src/components/CnSettingsPage/CnSettingsPage.vue +6 -86
  73. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
  74. package/src/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue +725 -0
  75. package/src/components/CnWorkingCalendarWidget/index.js +26 -0
  76. package/src/components/index.js +3 -0
  77. package/src/composables/useFlowStore.js +2 -1
  78. package/src/css/badge.css +32 -16
  79. package/src/css/look-board-detail.css +80 -8
  80. package/src/css/look-board-index.css +52 -8
  81. package/src/css/look-board.css +219 -1
  82. package/src/index.js +3 -0
  83. package/src/utils/libraryWidgetKeys.js +1 -0
  84. package/src/utils/workingCalendarMonth.js +82 -0
@@ -2,7 +2,7 @@ import script from './CnOrderedListField.vue2.js';
2
2
  import { render } from './CnOrderedListField.vue3.js';
3
3
 
4
4
  script.render = render;
5
- script.__scopeId = "data-v-81cf425a";
5
+ script.__scopeId = "data-v-3ab313d4";
6
6
  const __sfc_main = script;
7
7
 
8
8
  export { __sfc_main as default };
@@ -3,6 +3,7 @@ import { NcSelect } from '@nextcloud/vue';
3
3
  import ChevronDown from 'vue-material-design-icons/ChevronDown.vue';
4
4
  import ChevronUp from 'vue-material-design-icons/ChevronUp.vue';
5
5
  import Close from 'vue-material-design-icons/Close.vue';
6
+ import __sfc_main from '../CnIcon/CnIcon.vue.js';
6
7
 
7
8
  let orderedListUid = 0;
8
9
 
@@ -32,7 +33,7 @@ let orderedListUid = 0;
32
33
  var script = {
33
34
  name: 'CnOrderedListField',
34
35
 
35
- components: { ChevronDown, ChevronUp, Close, NcSelect },
36
+ components: { ChevronDown, ChevronUp, Close, CnIcon: __sfc_main, NcSelect },
36
37
 
37
38
  props: {
38
39
  /** The values in their order. */
@@ -42,8 +43,11 @@ var script = {
42
43
  },
43
44
 
44
45
  /**
45
- * The choices, `{ value, label }` (a plain string is its own label).
46
- * A value in `modelValue` without a choice shows the value itself.
46
+ * The choices, `{ value, label, description?, icon? }` (a plain string
47
+ * is its own label). `description` is a muted second line ("19 open
48
+ * cases"), in the row and in the picker; `icon` an MDI name drawn in a
49
+ * small tile before the label. A value in `modelValue` without a
50
+ * choice shows the value itself.
47
51
  */
48
52
  options: {
49
53
  type: Array,
@@ -108,17 +112,22 @@ var script = {
108
112
  choices() {
109
113
  return (Array.isArray(this.options) ? this.options : [])
110
114
  .map((option) => (option && typeof option === 'object'
111
- ? { value: String(option.value ?? option.id ?? ''), label: String(option.label ?? option.title ?? option.value ?? '') }
112
- : { value: String(option), label: String(option) }))
115
+ ? {
116
+ value: String(option.value ?? option.id ?? ''),
117
+ label: String(option.label ?? option.title ?? option.value ?? ''),
118
+ description: typeof option.description === 'string' ? option.description : '',
119
+ icon: typeof option.icon === 'string' ? option.icon : '',
120
+ }
121
+ : { value: String(option), label: String(option), description: '', icon: '' }))
113
122
  .filter((option) => option.value !== '')
114
123
  },
115
124
 
116
- /** @return {Array<{value: string, label: string}>} The rows, in order. */
125
+ /** @return {Array<{value: string, label: string, description: string, icon: string}>} The rows, in order. */
117
126
  rows() {
118
127
  return (Array.isArray(this.modelValue) ? this.modelValue : []).map((value) => {
119
128
  const key = String(value);
120
129
  const choice = this.choices.find((option) => option.value === key);
121
- return { value: key, label: choice ? choice.label : key }
130
+ return choice || { value: key, label: key, description: '', icon: '' }
122
131
  })
123
132
  },
124
133
 
@@ -137,6 +146,16 @@ var script = {
137
146
  methods: {
138
147
  t: translate,
139
148
 
149
+ /**
150
+ * The id of a row's description, which its buttons name as their description.
151
+ *
152
+ * @param {{value: string}} row The row.
153
+ * @return {string}
154
+ */
155
+ descriptionId(row) {
156
+ return `${this.labelId}-desc-${String(row.value).replace(/[^\w-]/g, '-')}`
157
+ },
158
+
140
159
  /**
141
160
  * Emit the new order.
142
161
  *
@@ -1 +1 @@
1
- {"version":3,"file":"CnOrderedListField.vue2.js","sources":["../../../../src/components/CnOrderedListField/CnOrderedListField.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-ordered-list-field\" data-testid=\"cn-ordered-list-field\">\n\t\t<p v-if=\"label\" :id=\"labelId\" class=\"cn-ordered-list-field__label\">\n\t\t\t{{ label }}\n\t\t</p>\n\t\t<ol\n\t\t\tv-if=\"rows.length > 0\"\n\t\t\tclass=\"cn-ordered-list-field__rows\"\n\t\t\t:aria-labelledby=\"label ? labelId : null\"\n\t\t\t:aria-label=\"label ? null : listLabel\">\n\t\t\t<li\n\t\t\t\tv-for=\"(row, index) in rows\"\n\t\t\t\t:key=\"row.value\"\n\t\t\t\tclass=\"cn-ordered-list-field__row\"\n\t\t\t\t:data-testid=\"`cn-ordered-list-row-${row.value}`\">\n\t\t\t\t<span class=\"cn-ordered-list-field__position\" aria-hidden=\"true\">{{ index + 1 }}</span>\n\t\t\t\t<span class=\"cn-ordered-list-field__text\">{{ row.label }}</span>\n\t\t\t\t<span class=\"cn-ordered-list-field__actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled || index === 0\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {item} up', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-up-${row.value}`\"\n\t\t\t\t\t\t@click=\"move(index, index - 1)\">\n\t\t\t\t\t\t<ChevronUp :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled || index === rows.length - 1\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {item} down', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-down-${row.value}`\"\n\t\t\t\t\t\t@click=\"move(index, index + 1)\">\n\t\t\t\t\t\t<ChevronDown :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Remove {item}', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-remove-${row.value}`\"\n\t\t\t\t\t\t@click=\"remove(index)\">\n\t\t\t\t\t\t<Close :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t</span>\n\t\t\t</li>\n\t\t</ol>\n\t\t<p v-else class=\"cn-ordered-list-field__empty\" data-testid=\"cn-ordered-list-empty\">\n\t\t\t{{ emptyText || t('nextcloud-vue', 'Nothing added yet.') }}\n\t\t</p>\n\t\t<div v-if=\"!disabled\" class=\"cn-ordered-list-field__add\">\n\t\t\t<NcSelect\n\t\t\t\t:modelValue=\"null\"\n\t\t\t\t:options=\"available\"\n\t\t\t\tlabel=\"label\"\n\t\t\t\t:inputLabel=\"addLabel || t('nextcloud-vue', 'Add')\"\n\t\t\t\t:placeholder=\"addPlaceholder\"\n\t\t\t\t:loading=\"loading\"\n\t\t\t\t:clearable=\"false\"\n\t\t\t\t:filterable=\"!searchable\"\n\t\t\t\tdata-testid=\"cn-ordered-list-add\"\n\t\t\t\t@search=\"onSearch\"\n\t\t\t\t@update:modelValue=\"add\" />\n\t\t</div>\n\t\t<p class=\"hidden-visually\" aria-live=\"polite\" data-testid=\"cn-ordered-list-live\">\n\t\t\t{{ announcement }}\n\t\t</p>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcSelect } from '@nextcloud/vue'\nimport ChevronDown from 'vue-material-design-icons/ChevronDown.vue'\nimport ChevronUp from 'vue-material-design-icons/ChevronUp.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\n\nlet orderedListUid = 0\n\n/**\n * CnOrderedListField - an ordered list a user keeps for themselves: rows in\n * their order with a move up, a move down and a remove button each, and a\n * search-as-you-type picker under it that adds a row (board\n * DqPersoonlijkeInstellingen, \"Zaaktypen in mijn menu\").\n *\n * The app supplies the choices (`options`) and keeps the value: every change\n * emits `update:modelValue` with the new list of values. With `searchable`\n * the picker emits `search` as the user types, so the app can fetch matching\n * choices itself; otherwise it filters `options`. Every move is announced in a\n * polite live region, so reordering works with the keyboard and a screen\n * reader, not by dragging.\n *\n * ```vue\n * <CnOrderedListField\n * v-model=\"menuCaseTypes\"\n * label=\"Case types in my menu\"\n * add-label=\"Add case type\"\n * :options=\"caseTypes\" />\n * ```\n *\n * @spec openspec/changes/ordered-list-field/specs/ordered-list-field/spec.md#requirement-a-user-keeps-an-ordered-list-with-the-keyboard\n */\nexport default {\n\tname: 'CnOrderedListField',\n\n\tcomponents: { ChevronDown, ChevronUp, Close, NcSelect },\n\n\tprops: {\n\t\t/** The values in their order. */\n\t\tmodelValue: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * The choices, `{ value, label }` (a plain string is its own label).\n\t\t * A value in `modelValue` without a choice shows the value itself.\n\t\t */\n\t\toptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** The list's label, also its accessible name. */\n\t\tlabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** The picker's label. */\n\t\taddLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Placeholder in the picker. */\n\t\taddPlaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Shown when the list is empty. */\n\t\temptyText: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Whether the app searches (`search` event) instead of the picker filtering `options`. */\n\t\tsearchable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether the app is fetching choices. */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** A read-only list: no buttons and no picker. */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\n\temits: ['update:modelValue', 'search'],\n\n\tdata() {\n\t\torderedListUid += 1\n\t\treturn {\n\t\t\tlabelId: `cn-ordered-list-label-${orderedListUid}`,\n\t\t\tannouncement: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {Array<{value: string, label: string}>} The choices in one shape. */\n\t\tchoices() {\n\t\t\treturn (Array.isArray(this.options) ? this.options : [])\n\t\t\t\t.map((option) => (option && typeof option === 'object'\n\t\t\t\t\t? { value: String(option.value ?? option.id ?? ''), label: String(option.label ?? option.title ?? option.value ?? '') }\n\t\t\t\t\t: { value: String(option), label: String(option) }))\n\t\t\t\t.filter((option) => option.value !== '')\n\t\t},\n\n\t\t/** @return {Array<{value: string, label: string}>} The rows, in order. */\n\t\trows() {\n\t\t\treturn (Array.isArray(this.modelValue) ? this.modelValue : []).map((value) => {\n\t\t\t\tconst key = String(value)\n\t\t\t\tconst choice = this.choices.find((option) => option.value === key)\n\t\t\t\treturn { value: key, label: choice ? choice.label : key }\n\t\t\t})\n\t\t},\n\n\t\t/** @return {Array<{value: string, label: string}>} The choices not in the list yet. */\n\t\tavailable() {\n\t\t\tconst taken = new Set(this.rows.map((row) => row.value))\n\t\t\treturn this.choices.filter((option) => !taken.has(option.value))\n\t\t},\n\n\t\t/** @return {string} The list's accessible name without a label. */\n\t\tlistLabel() {\n\t\t\treturn t('nextcloud-vue', 'Ordered list')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Emit the new order.\n\t\t *\n\t\t * @param {Array<string>} values The values.\n\t\t */\n\t\temitValue(values) {\n\t\t\t/**\n\t\t\t * @event update:modelValue The list changed. Payload: the values in their order.\n\t\t\t */\n\t\t\tthis.$emit('update:modelValue', values)\n\t\t},\n\n\t\t/**\n\t\t * Move a row to another place and keep focus on the pressed button\n\t\t * where it still makes sense.\n\t\t *\n\t\t * @param {number} from Its index.\n\t\t * @param {number} to The index it moves to.\n\t\t */\n\t\tmove(from, to) {\n\t\t\tif (to < 0 || to >= this.rows.length) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst values = this.rows.map((row) => row.value)\n\t\t\tconst [value] = values.splice(from, 1)\n\t\t\tvalues.splice(to, 0, value)\n\t\t\tconst row = this.rows[from]\n\t\t\tthis.emitValue(values)\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} moved to position {position} of {total}', { item: row.label, position: to + 1, total: values.length })\n\t\t\tthis.$nextTick(() => {\n\t\t\t\tconst direction = to < from ? 'up' : 'down'\n\t\t\t\tconst atEdge = (direction === 'up' && to === 0) || (direction === 'down' && to === values.length - 1)\n\t\t\t\tconst target = this.$el.querySelector(`[data-testid=\"cn-ordered-list-${atEdge ? (direction === 'up' ? 'down' : 'up') : direction}-${row.value}\"]`)\n\t\t\t\tif (target && !target.disabled) {\n\t\t\t\t\ttarget.focus()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Remove a row.\n\t\t *\n\t\t * @param {number} index Its index.\n\t\t */\n\t\tremove(index) {\n\t\t\tconst row = this.rows[index]\n\t\t\tthis.emitValue(this.rows.filter((_, i) => i !== index).map((r) => r.value))\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} removed', { item: row.label })\n\t\t},\n\n\t\t/**\n\t\t * Add the picked choice at the end.\n\t\t *\n\t\t * @param {{value: string, label: string}|null} option The choice.\n\t\t */\n\t\tadd(option) {\n\t\t\tif (!option) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.emitValue([...this.rows.map((row) => row.value), option.value])\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} added', { item: option.label })\n\t\t},\n\n\t\t/**\n\t\t * Pass the typed text on when the app searches.\n\t\t *\n\t\t * @param {string} query The text.\n\t\t */\n\t\tonSearch(query) {\n\t\t\tif (this.searchable) {\n\t\t\t\t/**\n\t\t\t\t * @event search The user typed in the picker (with `searchable`). Payload: the text.\n\t\t\t\t */\n\t\t\t\tthis.$emit('search', query)\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-ordered-list-field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n}\n\n.cn-ordered-list-field__label {\n\tmargin: 0;\n\tfont-weight: 600;\n}\n\n.cn-ordered-list-field__rows {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-element, 8px);\n\tlist-style: none;\n}\n\n.cn-ordered-list-field__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tmin-height: 44px;\n\tpadding: 2px 6px 2px 12px;\n}\n\n.cn-ordered-list-field__row + .cn-ordered-list-field__row {\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-ordered-list-field__position {\n\tflex: none;\n\tmin-width: 18px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n\tfont-variant-numeric: tabular-nums;\n}\n\n.cn-ordered-list-field__text {\n\tflex: 1 1 auto;\n\tmin-width: 0;\n\toverflow-wrap: anywhere;\n}\n\n.cn-ordered-list-field__actions {\n\tdisplay: flex;\n\tflex: none;\n\tgap: 2px;\n}\n\n.cn-ordered-list-field__button {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 40px;\n\tmin-width: 40px;\n\theight: 40px;\n\tmin-height: 40px;\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tborder-radius: var(--border-radius-element, 8px);\n\tbackground: transparent;\n\tcolor: var(--color-main-text);\n\tcursor: pointer;\n}\n\n.cn-ordered-list-field__button:hover:not(:disabled) {\n\tbackground: var(--color-background-hover);\n}\n\n.cn-ordered-list-field__button:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 1px;\n}\n\n.cn-ordered-list-field__button:disabled {\n\topacity: 0.4;\n\tcursor: default;\n}\n\n.cn-ordered-list-field__empty {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["t"],"mappings":"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"}
1
+ {"version":3,"file":"CnOrderedListField.vue2.js","sources":["../../../../src/components/CnOrderedListField/CnOrderedListField.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-ordered-list-field\" data-testid=\"cn-ordered-list-field\">\n\t\t<p v-if=\"label\" :id=\"labelId\" class=\"cn-ordered-list-field__label\">\n\t\t\t{{ label }}\n\t\t</p>\n\t\t<ol\n\t\t\tv-if=\"rows.length > 0\"\n\t\t\tclass=\"cn-ordered-list-field__rows\"\n\t\t\t:aria-labelledby=\"label ? labelId : null\"\n\t\t\t:aria-label=\"label ? null : listLabel\">\n\t\t\t<li\n\t\t\t\tv-for=\"(row, index) in rows\"\n\t\t\t\t:key=\"row.value\"\n\t\t\t\tclass=\"cn-ordered-list-field__row\"\n\t\t\t\t:data-testid=\"`cn-ordered-list-row-${row.value}`\">\n\t\t\t\t<span class=\"cn-ordered-list-field__position\" aria-hidden=\"true\">{{ index + 1 }}</span>\n\t\t\t\t<span v-if=\"row.icon\" class=\"cn-ordered-list-field__tile\" aria-hidden=\"true\">\n\t\t\t\t\t<CnIcon :name=\"row.icon\" :size=\"18\" />\n\t\t\t\t</span>\n\t\t\t\t<span class=\"cn-ordered-list-field__text\">\n\t\t\t\t\t<span class=\"cn-ordered-list-field__name\">{{ row.label }}</span>\n\t\t\t\t\t<span v-if=\"row.description\"\n\t\t\t\t\t\t:id=\"descriptionId(row)\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__description\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-description-${row.value}`\">{{ row.description }}</span>\n\t\t\t\t</span>\n\t\t\t\t<span class=\"cn-ordered-list-field__actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled || index === 0\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {item} up', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-up-${row.value}`\"\n\t\t\t\t\t\t:aria-describedby=\"row.description ? descriptionId(row) : null\"\n\t\t\t\t\t\t@click=\"move(index, index - 1)\">\n\t\t\t\t\t\t<ChevronUp :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled || index === rows.length - 1\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {item} down', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-down-${row.value}`\"\n\t\t\t\t\t\t:aria-describedby=\"row.description ? descriptionId(row) : null\"\n\t\t\t\t\t\t@click=\"move(index, index + 1)\">\n\t\t\t\t\t\t<ChevronDown :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Remove {item}', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-remove-${row.value}`\"\n\t\t\t\t\t\t:aria-describedby=\"row.description ? descriptionId(row) : null\"\n\t\t\t\t\t\t@click=\"remove(index)\">\n\t\t\t\t\t\t<Close :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t</span>\n\t\t\t</li>\n\t\t</ol>\n\t\t<p v-else class=\"cn-ordered-list-field__empty\" data-testid=\"cn-ordered-list-empty\">\n\t\t\t{{ emptyText || t('nextcloud-vue', 'Nothing added yet.') }}\n\t\t</p>\n\t\t<div v-if=\"!disabled\" class=\"cn-ordered-list-field__add\">\n\t\t\t<NcSelect\n\t\t\t\t:modelValue=\"null\"\n\t\t\t\t:options=\"available\"\n\t\t\t\tlabel=\"label\"\n\t\t\t\t:inputLabel=\"addLabel || t('nextcloud-vue', 'Add')\"\n\t\t\t\t:placeholder=\"addPlaceholder\"\n\t\t\t\t:loading=\"loading\"\n\t\t\t\t:clearable=\"false\"\n\t\t\t\t:filterable=\"!searchable\"\n\t\t\t\tdata-testid=\"cn-ordered-list-add\"\n\t\t\t\t@search=\"onSearch\"\n\t\t\t\t@update:modelValue=\"add\">\n\t\t\t\t<template #option=\"option\">\n\t\t\t\t\t<span class=\"cn-ordered-list-field__option\">\n\t\t\t\t\t\t<span v-if=\"option.icon\" class=\"cn-ordered-list-field__tile\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t<CnIcon :name=\"option.icon\" :size=\"18\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span class=\"cn-ordered-list-field__text\">\n\t\t\t\t\t\t\t<span class=\"cn-ordered-list-field__name\">{{ option.label }}</span>\n\t\t\t\t\t\t\t<span v-if=\"option.description\" class=\"cn-ordered-list-field__description\">{{ option.description }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t</NcSelect>\n\t\t</div>\n\t\t<p class=\"hidden-visually\" aria-live=\"polite\" data-testid=\"cn-ordered-list-live\">\n\t\t\t{{ announcement }}\n\t\t</p>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcSelect } from '@nextcloud/vue'\nimport ChevronDown from 'vue-material-design-icons/ChevronDown.vue'\nimport ChevronUp from 'vue-material-design-icons/ChevronUp.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\n\nlet orderedListUid = 0\n\n/**\n * CnOrderedListField - an ordered list a user keeps for themselves: rows in\n * their order with a move up, a move down and a remove button each, and a\n * search-as-you-type picker under it that adds a row (board\n * DqPersoonlijkeInstellingen, \"Zaaktypen in mijn menu\").\n *\n * The app supplies the choices (`options`) and keeps the value: every change\n * emits `update:modelValue` with the new list of values. With `searchable`\n * the picker emits `search` as the user types, so the app can fetch matching\n * choices itself; otherwise it filters `options`. Every move is announced in a\n * polite live region, so reordering works with the keyboard and a screen\n * reader, not by dragging.\n *\n * ```vue\n * <CnOrderedListField\n * v-model=\"menuCaseTypes\"\n * label=\"Case types in my menu\"\n * add-label=\"Add case type\"\n * :options=\"caseTypes\" />\n * ```\n *\n * @spec openspec/changes/ordered-list-field/specs/ordered-list-field/spec.md#requirement-a-user-keeps-an-ordered-list-with-the-keyboard\n */\nexport default {\n\tname: 'CnOrderedListField',\n\n\tcomponents: { ChevronDown, ChevronUp, Close, CnIcon, NcSelect },\n\n\tprops: {\n\t\t/** The values in their order. */\n\t\tmodelValue: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * The choices, `{ value, label, description?, icon? }` (a plain string\n\t\t * is its own label). `description` is a muted second line (\"19 open\n\t\t * cases\"), in the row and in the picker; `icon` an MDI name drawn in a\n\t\t * small tile before the label. A value in `modelValue` without a\n\t\t * choice shows the value itself.\n\t\t */\n\t\toptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** The list's label, also its accessible name. */\n\t\tlabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** The picker's label. */\n\t\taddLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Placeholder in the picker. */\n\t\taddPlaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Shown when the list is empty. */\n\t\temptyText: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Whether the app searches (`search` event) instead of the picker filtering `options`. */\n\t\tsearchable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether the app is fetching choices. */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** A read-only list: no buttons and no picker. */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\n\temits: ['update:modelValue', 'search'],\n\n\tdata() {\n\t\torderedListUid += 1\n\t\treturn {\n\t\t\tlabelId: `cn-ordered-list-label-${orderedListUid}`,\n\t\t\tannouncement: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {Array<{value: string, label: string}>} The choices in one shape. */\n\t\tchoices() {\n\t\t\treturn (Array.isArray(this.options) ? this.options : [])\n\t\t\t\t.map((option) => (option && typeof option === 'object'\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tvalue: String(option.value ?? option.id ?? ''),\n\t\t\t\t\t\t\tlabel: String(option.label ?? option.title ?? option.value ?? ''),\n\t\t\t\t\t\t\tdescription: typeof option.description === 'string' ? option.description : '',\n\t\t\t\t\t\t\ticon: typeof option.icon === 'string' ? option.icon : '',\n\t\t\t\t\t\t}\n\t\t\t\t\t: { value: String(option), label: String(option), description: '', icon: '' }))\n\t\t\t\t.filter((option) => option.value !== '')\n\t\t},\n\n\t\t/** @return {Array<{value: string, label: string, description: string, icon: string}>} The rows, in order. */\n\t\trows() {\n\t\t\treturn (Array.isArray(this.modelValue) ? this.modelValue : []).map((value) => {\n\t\t\t\tconst key = String(value)\n\t\t\t\tconst choice = this.choices.find((option) => option.value === key)\n\t\t\t\treturn choice || { value: key, label: key, description: '', icon: '' }\n\t\t\t})\n\t\t},\n\n\t\t/** @return {Array<{value: string, label: string}>} The choices not in the list yet. */\n\t\tavailable() {\n\t\t\tconst taken = new Set(this.rows.map((row) => row.value))\n\t\t\treturn this.choices.filter((option) => !taken.has(option.value))\n\t\t},\n\n\t\t/** @return {string} The list's accessible name without a label. */\n\t\tlistLabel() {\n\t\t\treturn t('nextcloud-vue', 'Ordered list')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * The id of a row's description, which its buttons name as their description.\n\t\t *\n\t\t * @param {{value: string}} row The row.\n\t\t * @return {string}\n\t\t */\n\t\tdescriptionId(row) {\n\t\t\treturn `${this.labelId}-desc-${String(row.value).replace(/[^\\w-]/g, '-')}`\n\t\t},\n\n\t\t/**\n\t\t * Emit the new order.\n\t\t *\n\t\t * @param {Array<string>} values The values.\n\t\t */\n\t\temitValue(values) {\n\t\t\t/**\n\t\t\t * @event update:modelValue The list changed. Payload: the values in their order.\n\t\t\t */\n\t\t\tthis.$emit('update:modelValue', values)\n\t\t},\n\n\t\t/**\n\t\t * Move a row to another place and keep focus on the pressed button\n\t\t * where it still makes sense.\n\t\t *\n\t\t * @param {number} from Its index.\n\t\t * @param {number} to The index it moves to.\n\t\t */\n\t\tmove(from, to) {\n\t\t\tif (to < 0 || to >= this.rows.length) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst values = this.rows.map((row) => row.value)\n\t\t\tconst [value] = values.splice(from, 1)\n\t\t\tvalues.splice(to, 0, value)\n\t\t\tconst row = this.rows[from]\n\t\t\tthis.emitValue(values)\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} moved to position {position} of {total}', { item: row.label, position: to + 1, total: values.length })\n\t\t\tthis.$nextTick(() => {\n\t\t\t\tconst direction = to < from ? 'up' : 'down'\n\t\t\t\tconst atEdge = (direction === 'up' && to === 0) || (direction === 'down' && to === values.length - 1)\n\t\t\t\tconst target = this.$el.querySelector(`[data-testid=\"cn-ordered-list-${atEdge ? (direction === 'up' ? 'down' : 'up') : direction}-${row.value}\"]`)\n\t\t\t\tif (target && !target.disabled) {\n\t\t\t\t\ttarget.focus()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Remove a row.\n\t\t *\n\t\t * @param {number} index Its index.\n\t\t */\n\t\tremove(index) {\n\t\t\tconst row = this.rows[index]\n\t\t\tthis.emitValue(this.rows.filter((_, i) => i !== index).map((r) => r.value))\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} removed', { item: row.label })\n\t\t},\n\n\t\t/**\n\t\t * Add the picked choice at the end.\n\t\t *\n\t\t * @param {{value: string, label: string}|null} option The choice.\n\t\t */\n\t\tadd(option) {\n\t\t\tif (!option) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.emitValue([...this.rows.map((row) => row.value), option.value])\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} added', { item: option.label })\n\t\t},\n\n\t\t/**\n\t\t * Pass the typed text on when the app searches.\n\t\t *\n\t\t * @param {string} query The text.\n\t\t */\n\t\tonSearch(query) {\n\t\t\tif (this.searchable) {\n\t\t\t\t/**\n\t\t\t\t * @event search The user typed in the picker (with `searchable`). Payload: the text.\n\t\t\t\t */\n\t\t\t\tthis.$emit('search', query)\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-ordered-list-field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n}\n\n.cn-ordered-list-field__label {\n\tmargin: 0;\n\tfont-weight: 600;\n}\n\n.cn-ordered-list-field__rows {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-element, 8px);\n\tlist-style: none;\n}\n\n.cn-ordered-list-field__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tmin-height: 44px;\n\tpadding: 2px 6px 2px 12px;\n}\n\n.cn-ordered-list-field__row + .cn-ordered-list-field__row {\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-ordered-list-field__position {\n\tflex: none;\n\tmin-width: 18px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n\tfont-variant-numeric: tabular-nums;\n}\n\n.cn-ordered-list-field__text {\n\tflex: 1 1 auto;\n\tmin-width: 0;\n\toverflow-wrap: anywhere;\n}\n\n.cn-ordered-list-field__actions {\n\tdisplay: flex;\n\tflex: none;\n\tgap: 2px;\n}\n\n.cn-ordered-list-field__button {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 40px;\n\tmin-width: 40px;\n\theight: 40px;\n\tmin-height: 40px;\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tborder-radius: var(--border-radius-element, 8px);\n\tbackground: transparent;\n\tcolor: var(--color-main-text);\n\tcursor: pointer;\n}\n\n.cn-ordered-list-field__button:hover:not(:disabled) {\n\tbackground: var(--color-background-hover);\n}\n\n.cn-ordered-list-field__button:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 1px;\n}\n\n.cn-ordered-list-field__button:disabled {\n\topacity: 0.4;\n\tcursor: default;\n}\n\n.cn-ordered-list-field__empty {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-ordered-list-field__tile {\n\tdisplay: inline-flex;\n\tflex: none;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 32px;\n\theight: 32px;\n\tborder-radius: var(--border-radius-element, 8px);\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-main-text);\n}\n\n.cn-ordered-list-field__name {\n\tdisplay: block;\n}\n\n.cn-ordered-list-field__description {\n\tdisplay: block;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-ordered-list-field__option {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tmin-width: 0;\n}\n</style>\n"],"names":["CnIcon","t"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { resolveComponent, openBlock, createElementBlock, toDisplayString, createCommentVNode, Fragment, renderList, createElementVNode, createVNode } from 'vue';
1
+ import { resolveComponent, openBlock, createElementBlock, toDisplayString, createCommentVNode, Fragment, renderList, createElementVNode, createVNode, withCtx } from 'vue';
2
2
 
3
3
  const _hoisted_1 = {
4
4
  class: "cn-ordered-list-field",
@@ -11,27 +11,47 @@ const _hoisted_5 = {
11
11
  class: "cn-ordered-list-field__position",
12
12
  "aria-hidden": "true"
13
13
  };
14
- const _hoisted_6 = { class: "cn-ordered-list-field__text" };
15
- const _hoisted_7 = { class: "cn-ordered-list-field__actions" };
16
- const _hoisted_8 = ["disabled", "aria-label", "data-testid", "onClick"];
17
- const _hoisted_9 = ["disabled", "aria-label", "data-testid", "onClick"];
18
- const _hoisted_10 = ["disabled", "aria-label", "data-testid", "onClick"];
19
- const _hoisted_11 = {
14
+ const _hoisted_6 = {
15
+ key: 0,
16
+ class: "cn-ordered-list-field__tile",
17
+ "aria-hidden": "true"
18
+ };
19
+ const _hoisted_7 = { class: "cn-ordered-list-field__text" };
20
+ const _hoisted_8 = { class: "cn-ordered-list-field__name" };
21
+ const _hoisted_9 = ["id", "data-testid"];
22
+ const _hoisted_10 = { class: "cn-ordered-list-field__actions" };
23
+ const _hoisted_11 = ["disabled", "aria-label", "data-testid", "aria-describedby", "onClick"];
24
+ const _hoisted_12 = ["disabled", "aria-label", "data-testid", "aria-describedby", "onClick"];
25
+ const _hoisted_13 = ["disabled", "aria-label", "data-testid", "aria-describedby", "onClick"];
26
+ const _hoisted_14 = {
20
27
  key: 2,
21
28
  class: "cn-ordered-list-field__empty",
22
29
  "data-testid": "cn-ordered-list-empty"
23
30
  };
24
- const _hoisted_12 = {
31
+ const _hoisted_15 = {
25
32
  key: 3,
26
33
  class: "cn-ordered-list-field__add"
27
34
  };
28
- const _hoisted_13 = {
35
+ const _hoisted_16 = { class: "cn-ordered-list-field__option" };
36
+ const _hoisted_17 = {
37
+ key: 0,
38
+ class: "cn-ordered-list-field__tile",
39
+ "aria-hidden": "true"
40
+ };
41
+ const _hoisted_18 = { class: "cn-ordered-list-field__text" };
42
+ const _hoisted_19 = { class: "cn-ordered-list-field__name" };
43
+ const _hoisted_20 = {
44
+ key: 0,
45
+ class: "cn-ordered-list-field__description"
46
+ };
47
+ const _hoisted_21 = {
29
48
  class: "hidden-visually",
30
49
  "aria-live": "polite",
31
50
  "data-testid": "cn-ordered-list-live"
32
51
  };
33
52
 
34
53
  function render(_ctx, _cache, $props, $setup, $data, $options) {
54
+ const _component_CnIcon = resolveComponent("CnIcon");
35
55
  const _component_ChevronUp = resolveComponent("ChevronUp");
36
56
  const _component_ChevronDown = resolveComponent("ChevronDown");
37
57
  const _component_Close = resolveComponent("Close");
@@ -59,45 +79,66 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
59
79
  "data-testid": `cn-ordered-list-row-${row.value}`
60
80
  }, [
61
81
  createElementVNode("span", _hoisted_5, toDisplayString(index + 1), 1 /* TEXT */),
62
- createElementVNode("span", _hoisted_6, toDisplayString(row.label), 1 /* TEXT */),
82
+ (row.icon)
83
+ ? (openBlock(), createElementBlock("span", _hoisted_6, [
84
+ createVNode(_component_CnIcon, {
85
+ name: row.icon,
86
+ size: 18
87
+ }, null, 8 /* PROPS */, ["name"])
88
+ ]))
89
+ : createCommentVNode("v-if", true),
63
90
  createElementVNode("span", _hoisted_7, [
91
+ createElementVNode("span", _hoisted_8, toDisplayString(row.label), 1 /* TEXT */),
92
+ (row.description)
93
+ ? (openBlock(), createElementBlock("span", {
94
+ key: 0,
95
+ id: $options.descriptionId(row),
96
+ class: "cn-ordered-list-field__description",
97
+ "data-testid": `cn-ordered-list-description-${row.value}`
98
+ }, toDisplayString(row.description), 9 /* TEXT, PROPS */, _hoisted_9))
99
+ : createCommentVNode("v-if", true)
100
+ ]),
101
+ createElementVNode("span", _hoisted_10, [
64
102
  createElementVNode("button", {
65
103
  type: "button",
66
104
  class: "cn-ordered-list-field__button",
67
105
  disabled: $props.disabled || index === 0,
68
106
  "aria-label": $options.t('nextcloud-vue', 'Move {item} up', { item: row.label }),
69
107
  "data-testid": `cn-ordered-list-up-${row.value}`,
108
+ "aria-describedby": row.description ? $options.descriptionId(row) : null,
70
109
  onClick: $event => ($options.move(index, index - 1))
71
110
  }, [
72
111
  createVNode(_component_ChevronUp, { size: 20 })
73
- ], 8 /* PROPS */, _hoisted_8),
112
+ ], 8 /* PROPS */, _hoisted_11),
74
113
  createElementVNode("button", {
75
114
  type: "button",
76
115
  class: "cn-ordered-list-field__button",
77
116
  disabled: $props.disabled || index === $options.rows.length - 1,
78
117
  "aria-label": $options.t('nextcloud-vue', 'Move {item} down', { item: row.label }),
79
118
  "data-testid": `cn-ordered-list-down-${row.value}`,
119
+ "aria-describedby": row.description ? $options.descriptionId(row) : null,
80
120
  onClick: $event => ($options.move(index, index + 1))
81
121
  }, [
82
122
  createVNode(_component_ChevronDown, { size: 20 })
83
- ], 8 /* PROPS */, _hoisted_9),
123
+ ], 8 /* PROPS */, _hoisted_12),
84
124
  createElementVNode("button", {
85
125
  type: "button",
86
126
  class: "cn-ordered-list-field__button",
87
127
  disabled: $props.disabled,
88
128
  "aria-label": $options.t('nextcloud-vue', 'Remove {item}', { item: row.label }),
89
129
  "data-testid": `cn-ordered-list-remove-${row.value}`,
130
+ "aria-describedby": row.description ? $options.descriptionId(row) : null,
90
131
  onClick: $event => ($options.remove(index))
91
132
  }, [
92
133
  createVNode(_component_Close, { size: 20 })
93
- ], 8 /* PROPS */, _hoisted_10)
134
+ ], 8 /* PROPS */, _hoisted_13)
94
135
  ])
95
136
  ], 8 /* PROPS */, _hoisted_4))
96
137
  }), 128 /* KEYED_FRAGMENT */))
97
138
  ], 8 /* PROPS */, _hoisted_3))
98
- : (openBlock(), createElementBlock("p", _hoisted_11, toDisplayString($props.emptyText || $options.t('nextcloud-vue', 'Nothing added yet.')), 1 /* TEXT */)),
139
+ : (openBlock(), createElementBlock("p", _hoisted_14, toDisplayString($props.emptyText || $options.t('nextcloud-vue', 'Nothing added yet.')), 1 /* TEXT */)),
99
140
  (!$props.disabled)
100
- ? (openBlock(), createElementBlock("div", _hoisted_12, [
141
+ ? (openBlock(), createElementBlock("div", _hoisted_15, [
101
142
  createVNode(_component_NcSelect, {
102
143
  modelValue: null,
103
144
  options: $options.available,
@@ -110,10 +151,30 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
110
151
  "data-testid": "cn-ordered-list-add",
111
152
  onSearch: $options.onSearch,
112
153
  "onUpdate:modelValue": $options.add
113
- }, null, 8 /* PROPS */, ["options", "inputLabel", "placeholder", "loading", "filterable", "onSearch", "onUpdate:modelValue"])
154
+ }, {
155
+ option: withCtx((option) => [
156
+ createElementVNode("span", _hoisted_16, [
157
+ (option.icon)
158
+ ? (openBlock(), createElementBlock("span", _hoisted_17, [
159
+ createVNode(_component_CnIcon, {
160
+ name: option.icon,
161
+ size: 18
162
+ }, null, 8 /* PROPS */, ["name"])
163
+ ]))
164
+ : createCommentVNode("v-if", true),
165
+ createElementVNode("span", _hoisted_18, [
166
+ createElementVNode("span", _hoisted_19, toDisplayString(option.label), 1 /* TEXT */),
167
+ (option.description)
168
+ ? (openBlock(), createElementBlock("span", _hoisted_20, toDisplayString(option.description), 1 /* TEXT */))
169
+ : createCommentVNode("v-if", true)
170
+ ])
171
+ ])
172
+ ]),
173
+ _: 1 /* STABLE */
174
+ }, 8 /* PROPS */, ["options", "inputLabel", "placeholder", "loading", "filterable", "onSearch", "onUpdate:modelValue"])
114
175
  ]))
115
176
  : createCommentVNode("v-if", true),
116
- createElementVNode("p", _hoisted_13, toDisplayString($data.announcement), 1 /* TEXT */)
177
+ createElementVNode("p", _hoisted_21, toDisplayString($data.announcement), 1 /* TEXT */)
117
178
  ]))
118
179
  }
119
180
 
@@ -1 +1 @@
1
- {"version":3,"file":"CnOrderedListField.vue3.js","sources":["../../../../src/components/CnOrderedListField/CnOrderedListField.vue?vue&type=template&id=81cf425a&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-ordered-list-field\" data-testid=\"cn-ordered-list-field\">\n\t\t<p v-if=\"label\" :id=\"labelId\" class=\"cn-ordered-list-field__label\">\n\t\t\t{{ label }}\n\t\t</p>\n\t\t<ol\n\t\t\tv-if=\"rows.length > 0\"\n\t\t\tclass=\"cn-ordered-list-field__rows\"\n\t\t\t:aria-labelledby=\"label ? labelId : null\"\n\t\t\t:aria-label=\"label ? null : listLabel\">\n\t\t\t<li\n\t\t\t\tv-for=\"(row, index) in rows\"\n\t\t\t\t:key=\"row.value\"\n\t\t\t\tclass=\"cn-ordered-list-field__row\"\n\t\t\t\t:data-testid=\"`cn-ordered-list-row-${row.value}`\">\n\t\t\t\t<span class=\"cn-ordered-list-field__position\" aria-hidden=\"true\">{{ index + 1 }}</span>\n\t\t\t\t<span class=\"cn-ordered-list-field__text\">{{ row.label }}</span>\n\t\t\t\t<span class=\"cn-ordered-list-field__actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled || index === 0\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {item} up', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-up-${row.value}`\"\n\t\t\t\t\t\t@click=\"move(index, index - 1)\">\n\t\t\t\t\t\t<ChevronUp :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled || index === rows.length - 1\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {item} down', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-down-${row.value}`\"\n\t\t\t\t\t\t@click=\"move(index, index + 1)\">\n\t\t\t\t\t\t<ChevronDown :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Remove {item}', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-remove-${row.value}`\"\n\t\t\t\t\t\t@click=\"remove(index)\">\n\t\t\t\t\t\t<Close :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t</span>\n\t\t\t</li>\n\t\t</ol>\n\t\t<p v-else class=\"cn-ordered-list-field__empty\" data-testid=\"cn-ordered-list-empty\">\n\t\t\t{{ emptyText || t('nextcloud-vue', 'Nothing added yet.') }}\n\t\t</p>\n\t\t<div v-if=\"!disabled\" class=\"cn-ordered-list-field__add\">\n\t\t\t<NcSelect\n\t\t\t\t:modelValue=\"null\"\n\t\t\t\t:options=\"available\"\n\t\t\t\tlabel=\"label\"\n\t\t\t\t:inputLabel=\"addLabel || t('nextcloud-vue', 'Add')\"\n\t\t\t\t:placeholder=\"addPlaceholder\"\n\t\t\t\t:loading=\"loading\"\n\t\t\t\t:clearable=\"false\"\n\t\t\t\t:filterable=\"!searchable\"\n\t\t\t\tdata-testid=\"cn-ordered-list-add\"\n\t\t\t\t@search=\"onSearch\"\n\t\t\t\t@update:modelValue=\"add\" />\n\t\t</div>\n\t\t<p class=\"hidden-visually\" aria-live=\"polite\" data-testid=\"cn-ordered-list-live\">\n\t\t\t{{ announcement }}\n\t\t</p>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcSelect } from '@nextcloud/vue'\nimport ChevronDown from 'vue-material-design-icons/ChevronDown.vue'\nimport ChevronUp from 'vue-material-design-icons/ChevronUp.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\n\nlet orderedListUid = 0\n\n/**\n * CnOrderedListField - an ordered list a user keeps for themselves: rows in\n * their order with a move up, a move down and a remove button each, and a\n * search-as-you-type picker under it that adds a row (board\n * DqPersoonlijkeInstellingen, \"Zaaktypen in mijn menu\").\n *\n * The app supplies the choices (`options`) and keeps the value: every change\n * emits `update:modelValue` with the new list of values. With `searchable`\n * the picker emits `search` as the user types, so the app can fetch matching\n * choices itself; otherwise it filters `options`. Every move is announced in a\n * polite live region, so reordering works with the keyboard and a screen\n * reader, not by dragging.\n *\n * ```vue\n * <CnOrderedListField\n * v-model=\"menuCaseTypes\"\n * label=\"Case types in my menu\"\n * add-label=\"Add case type\"\n * :options=\"caseTypes\" />\n * ```\n *\n * @spec openspec/changes/ordered-list-field/specs/ordered-list-field/spec.md#requirement-a-user-keeps-an-ordered-list-with-the-keyboard\n */\nexport default {\n\tname: 'CnOrderedListField',\n\n\tcomponents: { ChevronDown, ChevronUp, Close, NcSelect },\n\n\tprops: {\n\t\t/** The values in their order. */\n\t\tmodelValue: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * The choices, `{ value, label }` (a plain string is its own label).\n\t\t * A value in `modelValue` without a choice shows the value itself.\n\t\t */\n\t\toptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** The list's label, also its accessible name. */\n\t\tlabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** The picker's label. */\n\t\taddLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Placeholder in the picker. */\n\t\taddPlaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Shown when the list is empty. */\n\t\temptyText: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Whether the app searches (`search` event) instead of the picker filtering `options`. */\n\t\tsearchable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether the app is fetching choices. */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** A read-only list: no buttons and no picker. */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\n\temits: ['update:modelValue', 'search'],\n\n\tdata() {\n\t\torderedListUid += 1\n\t\treturn {\n\t\t\tlabelId: `cn-ordered-list-label-${orderedListUid}`,\n\t\t\tannouncement: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {Array<{value: string, label: string}>} The choices in one shape. */\n\t\tchoices() {\n\t\t\treturn (Array.isArray(this.options) ? this.options : [])\n\t\t\t\t.map((option) => (option && typeof option === 'object'\n\t\t\t\t\t? { value: String(option.value ?? option.id ?? ''), label: String(option.label ?? option.title ?? option.value ?? '') }\n\t\t\t\t\t: { value: String(option), label: String(option) }))\n\t\t\t\t.filter((option) => option.value !== '')\n\t\t},\n\n\t\t/** @return {Array<{value: string, label: string}>} The rows, in order. */\n\t\trows() {\n\t\t\treturn (Array.isArray(this.modelValue) ? this.modelValue : []).map((value) => {\n\t\t\t\tconst key = String(value)\n\t\t\t\tconst choice = this.choices.find((option) => option.value === key)\n\t\t\t\treturn { value: key, label: choice ? choice.label : key }\n\t\t\t})\n\t\t},\n\n\t\t/** @return {Array<{value: string, label: string}>} The choices not in the list yet. */\n\t\tavailable() {\n\t\t\tconst taken = new Set(this.rows.map((row) => row.value))\n\t\t\treturn this.choices.filter((option) => !taken.has(option.value))\n\t\t},\n\n\t\t/** @return {string} The list's accessible name without a label. */\n\t\tlistLabel() {\n\t\t\treturn t('nextcloud-vue', 'Ordered list')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Emit the new order.\n\t\t *\n\t\t * @param {Array<string>} values The values.\n\t\t */\n\t\temitValue(values) {\n\t\t\t/**\n\t\t\t * @event update:modelValue The list changed. Payload: the values in their order.\n\t\t\t */\n\t\t\tthis.$emit('update:modelValue', values)\n\t\t},\n\n\t\t/**\n\t\t * Move a row to another place and keep focus on the pressed button\n\t\t * where it still makes sense.\n\t\t *\n\t\t * @param {number} from Its index.\n\t\t * @param {number} to The index it moves to.\n\t\t */\n\t\tmove(from, to) {\n\t\t\tif (to < 0 || to >= this.rows.length) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst values = this.rows.map((row) => row.value)\n\t\t\tconst [value] = values.splice(from, 1)\n\t\t\tvalues.splice(to, 0, value)\n\t\t\tconst row = this.rows[from]\n\t\t\tthis.emitValue(values)\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} moved to position {position} of {total}', { item: row.label, position: to + 1, total: values.length })\n\t\t\tthis.$nextTick(() => {\n\t\t\t\tconst direction = to < from ? 'up' : 'down'\n\t\t\t\tconst atEdge = (direction === 'up' && to === 0) || (direction === 'down' && to === values.length - 1)\n\t\t\t\tconst target = this.$el.querySelector(`[data-testid=\"cn-ordered-list-${atEdge ? (direction === 'up' ? 'down' : 'up') : direction}-${row.value}\"]`)\n\t\t\t\tif (target && !target.disabled) {\n\t\t\t\t\ttarget.focus()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Remove a row.\n\t\t *\n\t\t * @param {number} index Its index.\n\t\t */\n\t\tremove(index) {\n\t\t\tconst row = this.rows[index]\n\t\t\tthis.emitValue(this.rows.filter((_, i) => i !== index).map((r) => r.value))\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} removed', { item: row.label })\n\t\t},\n\n\t\t/**\n\t\t * Add the picked choice at the end.\n\t\t *\n\t\t * @param {{value: string, label: string}|null} option The choice.\n\t\t */\n\t\tadd(option) {\n\t\t\tif (!option) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.emitValue([...this.rows.map((row) => row.value), option.value])\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} added', { item: option.label })\n\t\t},\n\n\t\t/**\n\t\t * Pass the typed text on when the app searches.\n\t\t *\n\t\t * @param {string} query The text.\n\t\t */\n\t\tonSearch(query) {\n\t\t\tif (this.searchable) {\n\t\t\t\t/**\n\t\t\t\t * @event search The user typed in the picker (with `searchable`). Payload: the text.\n\t\t\t\t */\n\t\t\t\tthis.$emit('search', query)\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-ordered-list-field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n}\n\n.cn-ordered-list-field__label {\n\tmargin: 0;\n\tfont-weight: 600;\n}\n\n.cn-ordered-list-field__rows {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-element, 8px);\n\tlist-style: none;\n}\n\n.cn-ordered-list-field__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tmin-height: 44px;\n\tpadding: 2px 6px 2px 12px;\n}\n\n.cn-ordered-list-field__row + .cn-ordered-list-field__row {\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-ordered-list-field__position {\n\tflex: none;\n\tmin-width: 18px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n\tfont-variant-numeric: tabular-nums;\n}\n\n.cn-ordered-list-field__text {\n\tflex: 1 1 auto;\n\tmin-width: 0;\n\toverflow-wrap: anywhere;\n}\n\n.cn-ordered-list-field__actions {\n\tdisplay: flex;\n\tflex: none;\n\tgap: 2px;\n}\n\n.cn-ordered-list-field__button {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 40px;\n\tmin-width: 40px;\n\theight: 40px;\n\tmin-height: 40px;\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tborder-radius: var(--border-radius-element, 8px);\n\tbackground: transparent;\n\tcolor: var(--color-main-text);\n\tcursor: pointer;\n}\n\n.cn-ordered-list-field__button:hover:not(:disabled) {\n\tbackground: var(--color-background-hover);\n}\n\n.cn-ordered-list-field__button:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 1px;\n}\n\n.cn-ordered-list-field__button:disabled {\n\topacity: 0.4;\n\tcursor: default;\n}\n\n.cn-ordered-list-field__empty {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_Fragment","_renderList","_createElementVNode","_toDisplayString","_createVNode"],"mappings":";;;AAWM,EAAA,KAAK,EAAC,uBAAY;AAAA,EAAA,aAAA,EAAA,uBAAA;;;;;;AAcd,EAAA,KAAK,EAAC,iCAA0B;AAAA,EAAA,aAAA,EAAA,MAAA;;AAChC,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,6BAAwB,GAAA;AAC9B,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,gCAAgC,GAAA;;;;;;AA+BpC,EAAA,KAAK,EAAC,8BAAG;AAAA,EAAA,aAAA,EAAA,uBAAA;;;;AAGG,EAAA,KAAK,EAAC,4BAAwB;;;;;;;;;;;;;;AAlDnD,EAAA,QAAAA,SAAA,EAAA,EAAAC,kBAAA,QAAA;KACQ,MAAK,CAAA,KAAA;sBAAbA,kBAEG,CAAA,GAAA,EAAA;;AAFa,UAAA,EAAE,EAAE,KAAO,CAAA,OAAA;AAAE,UAAA,KAAK,EAAA,8BAAA;2BAC/B,MAAK,CAAA,KAAA,CAAA,EAAA,CAAA,oBAAA,UAAA,CAAA;;AAGF,IAAA,CAAA,QAAA,CAAA,IAAI,CAAC,MAAM,GAAA,CAAA;sBADjBA,kBA0CI,CAAA,IAAA,EAAA;;AAxCH,UAAA,KAAI,EAAC,6BAAU;UACf,iBAAe,EAAE,MAAK,CAAA,KAAA,GAAG,KAAO,CAAA,OAAA,GAAA,IAAA;UAChC,YAAU,EAAE,MAAK,CAAA,KAAA,GAAA,IAAA,GAAU,QAAS,CAAA,SAAA;;AACpC,WAAAD,SAAA,CAAA,IAAA,CAAA,EAAAC,kBAAA,CAoCIC,QAnCmB,EAAA,IAAA,EAAAC,UAAA,CAAA,QAAA,CAAA,IAAI,EAAnB,CAAA,GAAG,EAAE,KAAK,KAAA;iCADlBF,kBAoCI,CAAA,IAAA,EAAA;cAlCH,GAAG,EAAE,GAAG,CAAC,KAAK;AACd,cAAA,KAAI,EAAC,4BAAC;2BACK,EAAA,CAAA,oBAAA,EAAE,GAAA,CAAA,KAAA,CAAA,CAAA;;cACZG,kBAAoC,CAAA,MAAA,EAApC,UAAoC,EAAAC,eAAA,CAAA,KAAA,GAAA,CAAA,CAAA,EAAA,CAAA,YAAA;AACpC,cAAAD,kBAAA,CAAkC,MAAlC,EAAA,UAAkC,EAAAC,eAAA,CAAA,GAAA,CAAA,KAAA,CAAA,EAAA,CAAA,YAAA;AAClC,cAAAD,kBAAA,CA4BD,QA5BC,UA4BD,EAAA;kCAnBS,CAAA,QAAA,EAAA;AAPR,kBAAA,IAAI,EAAC,QAAQ;AACb,kBAAA,KAAK,EAAC,+BAAiB;kBACtB,QAAM,EAAA,MAAA,CAAA,QAAA,IAAA,KAAA,KAAA,CAAA;AACN,kBAAA,YAAI,EAAA,QAAA,CAAA,CAAA,CAAA,eAAA,EAAA,gBAAA,EAAA,EAAA,IAAA,EAAA,GAAA,CAAA,KAAA,EAAA,CAAA;kBACJ,aAAW,EAAA,CAAA,mBAAA,EAAA,GAAA,CAAA,KAAA,CAAA,CAAA;AACX,kBAAA,OAAK,EAAE,MAAA,KAAA,QAAA,CAAA,IAAI,CAAC,KAAK,EAAE,KAAK,GAAA,CAAA,CAAA,CAAA;;kBACzBE,WAAwB,CAAA,oBAAA,EAAA,EAAZ,IAAI,EAAE,EAAE,EAAA,CAAA;;kCAUZ,CAAA,QAAA,EAAA;AAPR,kBAAA,IAAI,EAAC,QAAQ;AACb,kBAAA,KAAK,EAAC,+BAAmB;AACxB,kBAAA,QAAM,EAAA,MAAA,CAAA,QAAA,IAAA,KAAA,KAAA,QAAA,CAAA,IAAA,CAAA,MAAA,GAAA,CAAA;AACN,kBAAA,YAAI,EAAA,QAAA,CAAA,CAAA,CAAA,eAAA,EAAA,kBAAA,EAAA,EAAA,IAAA,EAAA,GAAA,CAAA,KAAA,EAAA,CAAA;kBACJ,aAAW,EAAA,CAAA,qBAAA,EAAA,GAAA,CAAA,KAAA,CAAA,CAAA;AACX,kBAAA,OAAK,EAAE,MAAA,KAAA,QAAA,CAAA,IAAI,CAAC,KAAK,EAAE,KAAK,GAAA,CAAA,CAAA,CAAA;;kBACzBA,WAAmB,CAAA,sBAAA,EAAA,EAAL,IAAI,EAAC,EAAA,EAAA,CAAA;;kCAUX,CAAA,QAAA,EAAA;AAPR,kBAAA,IAAI,EAAC,QAAQ;AACb,kBAAA,KAAK,iCAAc;AAClB,kBAAA,QAAM,EAAA,MAAA,CAAA,QAAA;AACN,kBAAA,YAAG,EAAA,QAAA,CAAA,CAAA,CAAA,eAAA,EAAA,eAAA,EAAA,EAAA,IAAA,EAAA,GAAA,CAAA,KAAA,EAAA,CAAA;kBACH,aAAA,EAAA,CAAA,uBAAA,EAAA,GAAA,CAAA,KAAA,CAAA,CAAA;kBACD,OAAA,EAAA,MAAA,KAAA,QAAA,CAAA,MAAA,CAAA,KAAA,CAAA,CAAA;;kBACAA,WAAoB,CAAA,gBAAA,EAAA,EAAZ,IAAI,EAAE,EAAE,EAAA,CAAA;;;;;;AAKlB,SAAAN,SAAA,EAAA,EAAAC,kBAAA,CAEE,GAFF,EAAA,WAEE,EADAI,eAAA,CAAA,MAAA,CAAA,SAAS,IAAI,QAAC,CAAA,CAAA,CAAA,eAAA,EAAA,oBAAA,CAAA,CAAA,EAAA,CAAA,YAAA,CAAA;MAEN,MAAQ,CAAA,QAAA;;qBAYhB,CAAA,mBAAA,EAAA;AAVD,YAAA,UAAU,EAAE,IAAI;AAChB,YAAA,OAAO,EAAE,QAAO,CAAA,SAAA;AACjB,YAAA,KAAK,EAAC,OAAO;YACZ,UAAU,EAAE,MAAQ,CAAA,QAAA,IAAI,QAAC,CAAA,CAAA,CAAA,eAAA,EAAA,KAAA,CAAA;AACzB,YAAA,WAAW,EAAE,MAAG,CAAA,cAAA;AAChB,YAAA,OAAO,EAAE,MAAO,CAAA,OAAA;AAChB,YAAA,SAAE,EAAA,KAAA;AACF,YAAA,UAAU,GAAG,MAAS,CAAA,UAAA;AACvB,YAAA,aAAW,EAAC,qBAAI;AACf,YAAA,QAAA,EAAA,QAAA,CAAA,QAAA;AACA,YAAA,qBAAC,EAAA,QAAA,CAAA,GAAA;;;;;;;;;;"}
1
+ {"version":3,"file":"CnOrderedListField.vue3.js","sources":["../../../../src/components/CnOrderedListField/CnOrderedListField.vue?vue&type=template&id=3ab313d4&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-ordered-list-field\" data-testid=\"cn-ordered-list-field\">\n\t\t<p v-if=\"label\" :id=\"labelId\" class=\"cn-ordered-list-field__label\">\n\t\t\t{{ label }}\n\t\t</p>\n\t\t<ol\n\t\t\tv-if=\"rows.length > 0\"\n\t\t\tclass=\"cn-ordered-list-field__rows\"\n\t\t\t:aria-labelledby=\"label ? labelId : null\"\n\t\t\t:aria-label=\"label ? null : listLabel\">\n\t\t\t<li\n\t\t\t\tv-for=\"(row, index) in rows\"\n\t\t\t\t:key=\"row.value\"\n\t\t\t\tclass=\"cn-ordered-list-field__row\"\n\t\t\t\t:data-testid=\"`cn-ordered-list-row-${row.value}`\">\n\t\t\t\t<span class=\"cn-ordered-list-field__position\" aria-hidden=\"true\">{{ index + 1 }}</span>\n\t\t\t\t<span v-if=\"row.icon\" class=\"cn-ordered-list-field__tile\" aria-hidden=\"true\">\n\t\t\t\t\t<CnIcon :name=\"row.icon\" :size=\"18\" />\n\t\t\t\t</span>\n\t\t\t\t<span class=\"cn-ordered-list-field__text\">\n\t\t\t\t\t<span class=\"cn-ordered-list-field__name\">{{ row.label }}</span>\n\t\t\t\t\t<span v-if=\"row.description\"\n\t\t\t\t\t\t:id=\"descriptionId(row)\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__description\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-description-${row.value}`\">{{ row.description }}</span>\n\t\t\t\t</span>\n\t\t\t\t<span class=\"cn-ordered-list-field__actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled || index === 0\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {item} up', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-up-${row.value}`\"\n\t\t\t\t\t\t:aria-describedby=\"row.description ? descriptionId(row) : null\"\n\t\t\t\t\t\t@click=\"move(index, index - 1)\">\n\t\t\t\t\t\t<ChevronUp :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled || index === rows.length - 1\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Move {item} down', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-down-${row.value}`\"\n\t\t\t\t\t\t:aria-describedby=\"row.description ? descriptionId(row) : null\"\n\t\t\t\t\t\t@click=\"move(index, index + 1)\">\n\t\t\t\t\t\t<ChevronDown :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclass=\"cn-ordered-list-field__button\"\n\t\t\t\t\t\t:disabled=\"disabled\"\n\t\t\t\t\t\t:aria-label=\"t('nextcloud-vue', 'Remove {item}', { item: row.label })\"\n\t\t\t\t\t\t:data-testid=\"`cn-ordered-list-remove-${row.value}`\"\n\t\t\t\t\t\t:aria-describedby=\"row.description ? descriptionId(row) : null\"\n\t\t\t\t\t\t@click=\"remove(index)\">\n\t\t\t\t\t\t<Close :size=\"20\" />\n\t\t\t\t\t</button>\n\t\t\t\t</span>\n\t\t\t</li>\n\t\t</ol>\n\t\t<p v-else class=\"cn-ordered-list-field__empty\" data-testid=\"cn-ordered-list-empty\">\n\t\t\t{{ emptyText || t('nextcloud-vue', 'Nothing added yet.') }}\n\t\t</p>\n\t\t<div v-if=\"!disabled\" class=\"cn-ordered-list-field__add\">\n\t\t\t<NcSelect\n\t\t\t\t:modelValue=\"null\"\n\t\t\t\t:options=\"available\"\n\t\t\t\tlabel=\"label\"\n\t\t\t\t:inputLabel=\"addLabel || t('nextcloud-vue', 'Add')\"\n\t\t\t\t:placeholder=\"addPlaceholder\"\n\t\t\t\t:loading=\"loading\"\n\t\t\t\t:clearable=\"false\"\n\t\t\t\t:filterable=\"!searchable\"\n\t\t\t\tdata-testid=\"cn-ordered-list-add\"\n\t\t\t\t@search=\"onSearch\"\n\t\t\t\t@update:modelValue=\"add\">\n\t\t\t\t<template #option=\"option\">\n\t\t\t\t\t<span class=\"cn-ordered-list-field__option\">\n\t\t\t\t\t\t<span v-if=\"option.icon\" class=\"cn-ordered-list-field__tile\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t<CnIcon :name=\"option.icon\" :size=\"18\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span class=\"cn-ordered-list-field__text\">\n\t\t\t\t\t\t\t<span class=\"cn-ordered-list-field__name\">{{ option.label }}</span>\n\t\t\t\t\t\t\t<span v-if=\"option.description\" class=\"cn-ordered-list-field__description\">{{ option.description }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t</NcSelect>\n\t\t</div>\n\t\t<p class=\"hidden-visually\" aria-live=\"polite\" data-testid=\"cn-ordered-list-live\">\n\t\t\t{{ announcement }}\n\t\t</p>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcSelect } from '@nextcloud/vue'\nimport ChevronDown from 'vue-material-design-icons/ChevronDown.vue'\nimport ChevronUp from 'vue-material-design-icons/ChevronUp.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\n\nlet orderedListUid = 0\n\n/**\n * CnOrderedListField - an ordered list a user keeps for themselves: rows in\n * their order with a move up, a move down and a remove button each, and a\n * search-as-you-type picker under it that adds a row (board\n * DqPersoonlijkeInstellingen, \"Zaaktypen in mijn menu\").\n *\n * The app supplies the choices (`options`) and keeps the value: every change\n * emits `update:modelValue` with the new list of values. With `searchable`\n * the picker emits `search` as the user types, so the app can fetch matching\n * choices itself; otherwise it filters `options`. Every move is announced in a\n * polite live region, so reordering works with the keyboard and a screen\n * reader, not by dragging.\n *\n * ```vue\n * <CnOrderedListField\n * v-model=\"menuCaseTypes\"\n * label=\"Case types in my menu\"\n * add-label=\"Add case type\"\n * :options=\"caseTypes\" />\n * ```\n *\n * @spec openspec/changes/ordered-list-field/specs/ordered-list-field/spec.md#requirement-a-user-keeps-an-ordered-list-with-the-keyboard\n */\nexport default {\n\tname: 'CnOrderedListField',\n\n\tcomponents: { ChevronDown, ChevronUp, Close, CnIcon, NcSelect },\n\n\tprops: {\n\t\t/** The values in their order. */\n\t\tmodelValue: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * The choices, `{ value, label, description?, icon? }` (a plain string\n\t\t * is its own label). `description` is a muted second line (\"19 open\n\t\t * cases\"), in the row and in the picker; `icon` an MDI name drawn in a\n\t\t * small tile before the label. A value in `modelValue` without a\n\t\t * choice shows the value itself.\n\t\t */\n\t\toptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** The list's label, also its accessible name. */\n\t\tlabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** The picker's label. */\n\t\taddLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Placeholder in the picker. */\n\t\taddPlaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Shown when the list is empty. */\n\t\temptyText: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Whether the app searches (`search` event) instead of the picker filtering `options`. */\n\t\tsearchable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether the app is fetching choices. */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** A read-only list: no buttons and no picker. */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\n\temits: ['update:modelValue', 'search'],\n\n\tdata() {\n\t\torderedListUid += 1\n\t\treturn {\n\t\t\tlabelId: `cn-ordered-list-label-${orderedListUid}`,\n\t\t\tannouncement: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {Array<{value: string, label: string}>} The choices in one shape. */\n\t\tchoices() {\n\t\t\treturn (Array.isArray(this.options) ? this.options : [])\n\t\t\t\t.map((option) => (option && typeof option === 'object'\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tvalue: String(option.value ?? option.id ?? ''),\n\t\t\t\t\t\t\tlabel: String(option.label ?? option.title ?? option.value ?? ''),\n\t\t\t\t\t\t\tdescription: typeof option.description === 'string' ? option.description : '',\n\t\t\t\t\t\t\ticon: typeof option.icon === 'string' ? option.icon : '',\n\t\t\t\t\t\t}\n\t\t\t\t\t: { value: String(option), label: String(option), description: '', icon: '' }))\n\t\t\t\t.filter((option) => option.value !== '')\n\t\t},\n\n\t\t/** @return {Array<{value: string, label: string, description: string, icon: string}>} The rows, in order. */\n\t\trows() {\n\t\t\treturn (Array.isArray(this.modelValue) ? this.modelValue : []).map((value) => {\n\t\t\t\tconst key = String(value)\n\t\t\t\tconst choice = this.choices.find((option) => option.value === key)\n\t\t\t\treturn choice || { value: key, label: key, description: '', icon: '' }\n\t\t\t})\n\t\t},\n\n\t\t/** @return {Array<{value: string, label: string}>} The choices not in the list yet. */\n\t\tavailable() {\n\t\t\tconst taken = new Set(this.rows.map((row) => row.value))\n\t\t\treturn this.choices.filter((option) => !taken.has(option.value))\n\t\t},\n\n\t\t/** @return {string} The list's accessible name without a label. */\n\t\tlistLabel() {\n\t\t\treturn t('nextcloud-vue', 'Ordered list')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * The id of a row's description, which its buttons name as their description.\n\t\t *\n\t\t * @param {{value: string}} row The row.\n\t\t * @return {string}\n\t\t */\n\t\tdescriptionId(row) {\n\t\t\treturn `${this.labelId}-desc-${String(row.value).replace(/[^\\w-]/g, '-')}`\n\t\t},\n\n\t\t/**\n\t\t * Emit the new order.\n\t\t *\n\t\t * @param {Array<string>} values The values.\n\t\t */\n\t\temitValue(values) {\n\t\t\t/**\n\t\t\t * @event update:modelValue The list changed. Payload: the values in their order.\n\t\t\t */\n\t\t\tthis.$emit('update:modelValue', values)\n\t\t},\n\n\t\t/**\n\t\t * Move a row to another place and keep focus on the pressed button\n\t\t * where it still makes sense.\n\t\t *\n\t\t * @param {number} from Its index.\n\t\t * @param {number} to The index it moves to.\n\t\t */\n\t\tmove(from, to) {\n\t\t\tif (to < 0 || to >= this.rows.length) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst values = this.rows.map((row) => row.value)\n\t\t\tconst [value] = values.splice(from, 1)\n\t\t\tvalues.splice(to, 0, value)\n\t\t\tconst row = this.rows[from]\n\t\t\tthis.emitValue(values)\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} moved to position {position} of {total}', { item: row.label, position: to + 1, total: values.length })\n\t\t\tthis.$nextTick(() => {\n\t\t\t\tconst direction = to < from ? 'up' : 'down'\n\t\t\t\tconst atEdge = (direction === 'up' && to === 0) || (direction === 'down' && to === values.length - 1)\n\t\t\t\tconst target = this.$el.querySelector(`[data-testid=\"cn-ordered-list-${atEdge ? (direction === 'up' ? 'down' : 'up') : direction}-${row.value}\"]`)\n\t\t\t\tif (target && !target.disabled) {\n\t\t\t\t\ttarget.focus()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Remove a row.\n\t\t *\n\t\t * @param {number} index Its index.\n\t\t */\n\t\tremove(index) {\n\t\t\tconst row = this.rows[index]\n\t\t\tthis.emitValue(this.rows.filter((_, i) => i !== index).map((r) => r.value))\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} removed', { item: row.label })\n\t\t},\n\n\t\t/**\n\t\t * Add the picked choice at the end.\n\t\t *\n\t\t * @param {{value: string, label: string}|null} option The choice.\n\t\t */\n\t\tadd(option) {\n\t\t\tif (!option) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.emitValue([...this.rows.map((row) => row.value), option.value])\n\t\t\tthis.announcement = t('nextcloud-vue', '{item} added', { item: option.label })\n\t\t},\n\n\t\t/**\n\t\t * Pass the typed text on when the app searches.\n\t\t *\n\t\t * @param {string} query The text.\n\t\t */\n\t\tonSearch(query) {\n\t\t\tif (this.searchable) {\n\t\t\t\t/**\n\t\t\t\t * @event search The user typed in the picker (with `searchable`). Payload: the text.\n\t\t\t\t */\n\t\t\t\tthis.$emit('search', query)\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-ordered-list-field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n}\n\n.cn-ordered-list-field__label {\n\tmargin: 0;\n\tfont-weight: 600;\n}\n\n.cn-ordered-list-field__rows {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-element, 8px);\n\tlist-style: none;\n}\n\n.cn-ordered-list-field__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tmin-height: 44px;\n\tpadding: 2px 6px 2px 12px;\n}\n\n.cn-ordered-list-field__row + .cn-ordered-list-field__row {\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-ordered-list-field__position {\n\tflex: none;\n\tmin-width: 18px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n\tfont-variant-numeric: tabular-nums;\n}\n\n.cn-ordered-list-field__text {\n\tflex: 1 1 auto;\n\tmin-width: 0;\n\toverflow-wrap: anywhere;\n}\n\n.cn-ordered-list-field__actions {\n\tdisplay: flex;\n\tflex: none;\n\tgap: 2px;\n}\n\n.cn-ordered-list-field__button {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 40px;\n\tmin-width: 40px;\n\theight: 40px;\n\tmin-height: 40px;\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tborder-radius: var(--border-radius-element, 8px);\n\tbackground: transparent;\n\tcolor: var(--color-main-text);\n\tcursor: pointer;\n}\n\n.cn-ordered-list-field__button:hover:not(:disabled) {\n\tbackground: var(--color-background-hover);\n}\n\n.cn-ordered-list-field__button:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 1px;\n}\n\n.cn-ordered-list-field__button:disabled {\n\topacity: 0.4;\n\tcursor: default;\n}\n\n.cn-ordered-list-field__empty {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-ordered-list-field__tile {\n\tdisplay: inline-flex;\n\tflex: none;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 32px;\n\theight: 32px;\n\tborder-radius: var(--border-radius-element, 8px);\n\tbackground: var(--color-background-dark);\n\tcolor: var(--color-main-text);\n}\n\n.cn-ordered-list-field__name {\n\tdisplay: block;\n}\n\n.cn-ordered-list-field__description {\n\tdisplay: block;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-ordered-list-field__option {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tmin-width: 0;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_Fragment","_renderList","_toDisplayString","_createElementVNode","_createVNode","_withCtx"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import script from './CnSettingsField.vue2.js';
2
+ import { render } from './CnSettingsField.vue3.js';
3
+
4
+ script.render = render;
5
+ script.__scopeId = "data-v-d2218996";
6
+ const __sfc_main = script;
7
+
8
+ export { __sfc_main as default };
9
+ //# sourceMappingURL=CnSettingsField.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CnSettingsField.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}