@conduction/nextcloud-vue 2.110.0 → 2.112.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 (142) hide show
  1. package/dist/esm/components/CnActionDialog/CnActionDialog.vue.js +1 -1
  2. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js +3 -2
  3. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js.map +1 -1
  4. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js +4 -2
  5. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js.map +1 -1
  6. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +2 -1
  7. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  8. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  9. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue.js +1 -1
  10. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js +3 -2
  11. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js.map +1 -1
  12. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js +2 -1
  13. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js.map +1 -1
  14. package/dist/esm/components/CnBoardView/CnBoardView.vue.js +1 -1
  15. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +54 -5
  16. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
  17. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +16 -2
  18. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
  19. package/dist/esm/components/CnCardGrid/CnCardGrid.vue.js +1 -1
  20. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +10 -0
  21. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
  22. package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js +2 -1
  23. package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
  24. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
  25. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +22 -2
  26. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  27. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +17 -3
  28. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  29. package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
  30. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
  31. package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
  32. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +52 -8
  33. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  34. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +98 -63
  35. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  36. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  37. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +48 -11
  38. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  39. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +160 -97
  40. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  41. package/dist/esm/components/CnFormDialog/CnFormDialog.vue.js +1 -1
  42. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  43. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +2 -2
  44. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  45. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +203 -14
  46. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  47. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +19 -4
  48. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  49. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
  50. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js +1 -1
  51. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
  52. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue.js +1 -1
  53. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue2.js +21 -1
  54. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue2.js.map +1 -1
  55. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue3.js.map +1 -1
  56. package/dist/esm/components/CnObjectCard/CnObjectCard.vue.js +1 -1
  57. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +36 -2
  58. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
  59. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +44 -5
  60. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
  61. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue.js +1 -0
  62. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue.js.map +1 -1
  63. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue2.js +22 -2
  64. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue2.js.map +1 -1
  65. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue3.js +36 -16
  66. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue3.js.map +1 -1
  67. package/dist/esm/components/CnSearchSelect/CnSearchSelect.vue.js +1 -1
  68. package/dist/esm/components/CnSearchSelect/CnSearchSelect.vue2.js.map +1 -1
  69. package/dist/esm/components/CnSearchSelect/CnSearchSelect.vue3.js.map +1 -1
  70. package/dist/esm/composables/useRefLabels.js +26 -6
  71. package/dist/esm/composables/useRefLabels.js.map +1 -1
  72. package/dist/esm/integrations/registry.js +4 -0
  73. package/dist/esm/integrations/registry.js.map +1 -1
  74. package/dist/esm/l10n/en.json.js +3 -1
  75. package/dist/esm/l10n/en.json.js.map +1 -1
  76. package/dist/esm/l10n/nl.json.js +3 -1
  77. package/dist/esm/l10n/nl.json.js.map +1 -1
  78. package/dist/esm/library-style.js +1 -1
  79. package/dist/esm/nextcloud-vue.css +630 -303
  80. package/dist/esm/store/plugins/liveUpdates.js +3 -1
  81. package/dist/esm/store/plugins/liveUpdates.js.map +1 -1
  82. package/dist/esm/store/plugins/logs.js +2 -1
  83. package/dist/esm/store/plugins/logs.js.map +1 -1
  84. package/dist/esm/utils/detailActionModel.js +28 -1
  85. package/dist/esm/utils/detailActionModel.js.map +1 -1
  86. package/dist/esm/utils/fillTemplate.js +13 -5
  87. package/dist/esm/utils/fillTemplate.js.map +1 -1
  88. package/dist/esm/utils/headerFieldChips.js +21 -2
  89. package/dist/esm/utils/headerFieldChips.js.map +1 -1
  90. package/dist/esm/utils/mapList.js +26 -11
  91. package/dist/esm/utils/mapList.js.map +1 -1
  92. package/dist/esm/utils/savedViewHelpers.js +40 -3
  93. package/dist/esm/utils/savedViewHelpers.js.map +1 -1
  94. package/dist/esm/utils/savedViewMenu.js +12 -5
  95. package/dist/esm/utils/savedViewMenu.js.map +1 -1
  96. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  97. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  98. package/dist/nextcloud-vue.cjs.js +2760 -1995
  99. package/dist/nextcloud-vue.cjs.js.map +2 -2
  100. package/dist/nextcloud-vue.css +630 -303
  101. package/l10n/en.json +3 -1
  102. package/l10n/nl.json +3 -1
  103. package/package.json +1 -1
  104. package/src/components/CnActionDialog/CnActionDialog.vue +32 -9
  105. package/src/components/CnAppRoot/CnAppRoot.vue +2 -1
  106. package/src/components/CnAssignDialog/CnAssignDialog.vue +4 -2
  107. package/src/components/CnBoardView/CnBoardView.vue +58 -5
  108. package/src/components/CnCardGrid/CnCardGrid.md +1 -0
  109. package/src/components/CnCardGrid/CnCardGrid.vue +11 -0
  110. package/src/components/CnCellRenderer/CnCellRenderer.vue +27 -3
  111. package/src/components/CnChartWidget/CnChartWidget.vue +6 -0
  112. package/src/components/CnDetailPage/CnDetailPage.vue +77 -20
  113. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +100 -5
  114. package/src/components/CnFormDialog/CnFormDialog.vue +1 -1
  115. package/src/components/CnIndexPage/CnIndexPage.md +1 -1
  116. package/src/components/CnIndexPage/CnIndexPage.vue +211 -16
  117. package/src/components/CnIndexSidebar/CnIndexSidebar.md +1 -1
  118. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +2 -2
  119. package/src/components/CnNcDashboardList/CnNcDashboardList.vue +21 -1
  120. package/src/components/CnObjectCard/CnObjectCard.md +1 -0
  121. package/src/components/CnObjectCard/CnObjectCard.vue +51 -5
  122. package/src/components/CnPartyPicker/CnPartyPicker.vue +62 -16
  123. package/src/components/CnSearchSelect/CnSearchSelect.vue +8 -0
  124. package/src/composables/useRefLabels.js +25 -5
  125. package/src/css/board.css +5 -2
  126. package/src/css/dialog.css +53 -3
  127. package/src/css/index-page.css +26 -1
  128. package/src/css/look-board-detail.css +55 -22
  129. package/src/css/look-board-index.css +82 -12
  130. package/src/css/look-board-reports.css +1 -1
  131. package/src/css/look-board.css +84 -11
  132. package/src/integrations/registry.js +4 -0
  133. package/src/schemas/app-manifest-v2.schema.json +11 -5
  134. package/src/store/plugins/liveUpdates.js +3 -1
  135. package/src/store/plugins/logs.js +2 -1
  136. package/src/utils/detailActionModel.js +27 -0
  137. package/src/utils/fillTemplate.js +13 -5
  138. package/src/utils/headerFieldChips.js +21 -2
  139. package/src/utils/mapList.js +26 -11
  140. package/src/utils/savedViewHelpers.js +39 -2
  141. package/src/utils/savedViewMenu.js +12 -5
  142. package/src/utils/validateManifestV2.compiled.js +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"CnSearchSelect.vue2.js","sources":["../../../../src/components/CnSearchSelect/CnSearchSelect.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-search-select\" :class=\"{ 'cn-search-select--label-outside': labelOutside }\" data-testid=\"cn-search-select\">\n\t\t<NcSelect\n\t\t\t:inputId=\"inputId\"\n\t\t\t:inputLabel=\"inputLabel\"\n\t\t\t:labelOutside=\"labelOutside\"\n\t\t\t:modelValue=\"selectedOption\"\n\t\t\t:options=\"options\"\n\t\t\t:loading=\"loading\"\n\t\t\t:clearable=\"clearable\"\n\t\t\t:disabled=\"disabled\"\n\t\t\t:placeholder=\"resolvedPlaceholder\"\n\t\t\t:filterable=\"filterable\"\n\t\t\tlabel=\"label\"\n\t\t\t@search=\"onSearch\"\n\t\t\t@update:modelValue=\"onInput\">\n\t\t\t<template #option=\"option\">\n\t\t\t\t<span class=\"cn-search-select__row\" data-testid=\"cn-search-select-row\">\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"option.avatar || option.icon\"\n\t\t\t\t\t\tclass=\"cn-search-select__lead\"\n\t\t\t\t\t\t:class=\"{ 'cn-search-select__lead--avatar': option.avatar && !option.icon }\"\n\t\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t\t<CnIcon v-if=\"option.icon\" :name=\"option.icon\" :size=\"18\" />\n\t\t\t\t\t\t<template v-else>{{ initialsOf(option) }}</template>\n\t\t\t\t\t</span>\n\t\t\t\t\t<span class=\"cn-search-select__text\">\n\t\t\t\t\t\t<span class=\"cn-search-select__name\">{{ option.label }}</span>\n\t\t\t\t\t\t<span v-if=\"option.secondary\" class=\"cn-search-select__secondary\">{{ option.secondary }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t\t<Check\n\t\t\t\t\t\tv-if=\"isSelected(option)\"\n\t\t\t\t\t\tclass=\"cn-search-select__check\"\n\t\t\t\t\t\t:size=\"18\"\n\t\t\t\t\t\tdata-testid=\"cn-search-select-check\" />\n\t\t\t\t</span>\n\t\t\t</template>\n\t\t</NcSelect>\n\t\t<Magnify class=\"cn-search-select__magnifier\" :size=\"18\" aria-hidden=\"true\" />\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcSelect } from '@nextcloud/vue'\nimport Check from 'vue-material-design-icons/Check.vue'\nimport Magnify from 'vue-material-design-icons/Magnify.vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport { initialsOf } from '../../utils/initials.js'\n\n/**\n * CnSearchSelect — a single picker drawn as a search field: a magnifier\n * instead of the chevron, and results as rows with an icon or initials, a\n * name, a secondary line and a check on the chosen one (boards DqOverdragen\n * \"Nieuw team\", DqNieuweZaak \"Aanvrager\").\n *\n * Each option is `{ id, label, secondary?, icon?, avatar? }`: `icon` names a\n * CnIcon, `avatar: true` draws the label's initials in a circle. The value is\n * the option's `id` (or `value`); `update:modelValue` emits that id, or null\n * when cleared. Searching is the host's: listen to `search` and pass new\n * `options`, with `filterable: false` when the host already filtered them.\n *\n * ```vue\n * <CnSearchSelect\n * v-model=\"team\"\n * inputLabel=\"Nieuw team\"\n * :options=\"[{ id: 'legal', label: 'Juridische zaken', secondary: '6 leden · bezwaar, beroep en Woo-advies', avatar: true }]\" />\n * ```\n */\nexport default {\n\tname: 'CnSearchSelect',\n\n\tcomponents: { Check, CnIcon, Magnify, NcSelect },\n\n\tprops: {\n\t\t/** The chosen option's id, or the option itself. */\n\t\tmodelValue: {\n\t\t\ttype: [String, Number, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The options: `{ id, label, secondary?, icon?, avatar? }`.\n\t\t *\n\t\t * @type {Array<{id: (string|number), label: string, secondary?: string, icon?: string, avatar?: boolean}>}\n\t\t */\n\t\toptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** The field's label. */\n\t\tinputLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Draw the label above the field instead of inside it. */\n\t\tlabelOutside: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** The input's id. */\n\t\tinputId: {\n\t\t\ttype: String,\n\t\t\tdefault: undefined,\n\t\t},\n\n\t\t/** Placeholder text; defaults to \"Search…\". */\n\t\tplaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Show the loading spinner. */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Offer a clear button. */\n\t\tclearable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Disable the field. */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Filter the options on the typed text; false when the host searches. */\n\t\tfilterable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\t},\n\n\temits: ['update:modelValue', 'search'],\n\n\tcomputed: {\n\t\t/**\n\t\t * The option matching `modelValue`, or a bare one carrying it.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tselectedOption() {\n\t\t\tconst value = this.modelValue\n\t\t\tif (value === null || value === undefined || value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (typeof value === 'object') {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn this.options.find((o) => this.idOf(o) === String(value)) || { id: value, label: String(value) }\n\t\t},\n\n\t\t/** @return {string} The placeholder. */\n\t\tresolvedPlaceholder() {\n\t\t\treturn this.placeholder || t('nextcloud-vue', 'Search…')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tinitialsOf(option) {\n\t\t\treturn initialsOf(option.label || '')\n\t\t},\n\n\t\t/**\n\t\t * @param {object} option An option.\n\t\t * @return {string} Its id as a string, '' without one.\n\t\t */\n\t\tidOf(option) {\n\t\t\tconst id = option && (option.id ?? option.value)\n\t\t\treturn id === null || id === undefined ? '' : String(id)\n\t\t},\n\n\t\t/**\n\t\t * @param {object} option An option.\n\t\t * @return {boolean} Whether it is the chosen one.\n\t\t */\n\t\tisSelected(option) {\n\t\t\treturn this.selectedOption !== null && this.idOf(option) !== '' && this.idOf(option) === this.idOf(this.selectedOption)\n\t\t},\n\n\t\t/**\n\t\t * @param {object|null} option The picked option.\n\t\t */\n\t\tonInput(option) {\n\t\t\tconst id = option ? (option.id ?? option.value ?? null) : null\n\t\t\t/** @event update:modelValue The picked option's id, or null when cleared. */\n\t\t\tthis.$emit('update:modelValue', id)\n\t\t},\n\n\t\t/**\n\t\t * @param {string} query The typed text.\n\t\t */\n\t\tonSearch(query) {\n\t\t\t/** @event search The typed text, for a host that searches itself. */\n\t\t\tthis.$emit('search', query)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-search-select {\n\tposition: relative;\n}\n\n/* The magnifier sits where the chevron was: in the field, at its end. */\n.cn-search-select__magnifier {\n\tposition: absolute;\n\tinset-inline-end: 12px;\n\tbottom: 0;\n\theight: var(--default-clickable-area, 34px);\n\tdisplay: flex;\n\talign-items: center;\n\tcolor: var(--color-text-maxcontrast);\n\tpointer-events: none;\n}\n\n.cn-search-select :deep(.vs__open-indicator),\n.cn-search-select :deep(.vs__open-indicator-button) {\n\tdisplay: none;\n}\n\n.cn-search-select :deep(.vs__actions) {\n\tpadding-inline-end: 36px;\n}\n\n.cn-search-select__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\twidth: 100%;\n\tmin-width: 0;\n\tpadding: 4px 0;\n}\n\n.cn-search-select__lead {\n\tflex: 0 0 32px;\n\twidth: 32px;\n\theight: 32px;\n\tborder-radius: 50%;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tbackground: var(--color-primary-element-light);\n\tcolor: var(--color-primary-element-light-text);\n\tfont-size: 13px;\n\tfont-weight: 600;\n}\n\n.cn-search-select__text {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1 1 auto;\n\tmin-width: 0;\n}\n\n.cn-search-select__name {\n\tfont-weight: 600;\n\toverflow-wrap: anywhere;\n}\n\n.cn-search-select__secondary {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow-wrap: anywhere;\n}\n\n.cn-search-select__check {\n\tflex: 0 0 auto;\n\tcolor: var(--color-primary-element);\n}\n</style>\n"],"names":["CnIcon","t"],"mappings":"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"}
1
+ {"version":3,"file":"CnSearchSelect.vue2.js","sources":["../../../../src/components/CnSearchSelect/CnSearchSelect.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-search-select\" :class=\"{ 'cn-search-select--label-outside': labelOutside }\" data-testid=\"cn-search-select\">\n\t\t<NcSelect\n\t\t\t:inputId=\"inputId\"\n\t\t\t:inputLabel=\"inputLabel\"\n\t\t\t:labelOutside=\"labelOutside\"\n\t\t\t:modelValue=\"selectedOption\"\n\t\t\t:options=\"options\"\n\t\t\t:loading=\"loading\"\n\t\t\t:clearable=\"clearable\"\n\t\t\t:disabled=\"disabled\"\n\t\t\t:placeholder=\"resolvedPlaceholder\"\n\t\t\t:filterable=\"filterable\"\n\t\t\tlabel=\"label\"\n\t\t\t@search=\"onSearch\"\n\t\t\t@update:modelValue=\"onInput\">\n\t\t\t<template #option=\"option\">\n\t\t\t\t<span class=\"cn-search-select__row\" data-testid=\"cn-search-select-row\">\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"option.avatar || option.icon\"\n\t\t\t\t\t\tclass=\"cn-search-select__lead\"\n\t\t\t\t\t\t:class=\"{ 'cn-search-select__lead--avatar': option.avatar && !option.icon }\"\n\t\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t\t<CnIcon v-if=\"option.icon\" :name=\"option.icon\" :size=\"18\" />\n\t\t\t\t\t\t<template v-else>{{ initialsOf(option) }}</template>\n\t\t\t\t\t</span>\n\t\t\t\t\t<span class=\"cn-search-select__text\">\n\t\t\t\t\t\t<span class=\"cn-search-select__name\">{{ option.label }}</span>\n\t\t\t\t\t\t<span v-if=\"option.secondary\" class=\"cn-search-select__secondary\">{{ option.secondary }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t\t<Check\n\t\t\t\t\t\tv-if=\"isSelected(option)\"\n\t\t\t\t\t\tclass=\"cn-search-select__check\"\n\t\t\t\t\t\t:size=\"18\"\n\t\t\t\t\t\tdata-testid=\"cn-search-select-check\" />\n\t\t\t\t</span>\n\t\t\t</template>\n\t\t</NcSelect>\n\t\t<Magnify class=\"cn-search-select__magnifier\" :size=\"18\" aria-hidden=\"true\" />\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcSelect } from '@nextcloud/vue'\nimport Check from 'vue-material-design-icons/Check.vue'\nimport Magnify from 'vue-material-design-icons/Magnify.vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport { initialsOf } from '../../utils/initials.js'\n\n/**\n * CnSearchSelect — a single picker drawn as a search field: a magnifier\n * instead of the chevron, and results as rows with an icon or initials, a\n * name, a secondary line and a check on the chosen one (boards DqOverdragen\n * \"Nieuw team\", DqNieuweZaak \"Aanvrager\").\n *\n * Each option is `{ id, label, secondary?, icon?, avatar? }`: `icon` names a\n * CnIcon, `avatar: true` draws the label's initials in a circle. The value is\n * the option's `id` (or `value`); `update:modelValue` emits that id, or null\n * when cleared. Searching is the host's: listen to `search` and pass new\n * `options`, with `filterable: false` when the host already filtered them.\n *\n * ```vue\n * <CnSearchSelect\n * v-model=\"team\"\n * inputLabel=\"Nieuw team\"\n * :options=\"[{ id: 'legal', label: 'Juridische zaken', secondary: '6 leden · bezwaar, beroep en Woo-advies', avatar: true }]\" />\n * ```\n */\nexport default {\n\tname: 'CnSearchSelect',\n\n\tcomponents: { Check, CnIcon, Magnify, NcSelect },\n\n\tprops: {\n\t\t/** The chosen option's id, or the option itself. */\n\t\tmodelValue: {\n\t\t\ttype: [String, Number, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The options: `{ id, label, secondary?, icon?, avatar? }`.\n\t\t *\n\t\t * @type {Array<{id: (string|number), label: string, secondary?: string, icon?: string, avatar?: boolean}>}\n\t\t */\n\t\toptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** The field's label. */\n\t\tinputLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Draw the label above the field instead of inside it. */\n\t\tlabelOutside: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** The input's id. */\n\t\tinputId: {\n\t\t\ttype: String,\n\t\t\tdefault: undefined,\n\t\t},\n\n\t\t/** Placeholder text; defaults to \"Search…\". */\n\t\tplaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Show the loading spinner. */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Offer a clear button. */\n\t\tclearable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Disable the field. */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Filter the options on the typed text; false when the host searches. */\n\t\tfilterable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\t},\n\n\temits: ['update:modelValue', 'search'],\n\n\tcomputed: {\n\t\t/**\n\t\t * The option matching `modelValue`, or a bare one carrying it.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tselectedOption() {\n\t\t\tconst value = this.modelValue\n\t\t\tif (value === null || value === undefined || value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (typeof value === 'object') {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn this.options.find((o) => this.idOf(o) === String(value)) || { id: value, label: String(value) }\n\t\t},\n\n\t\t/** @return {string} The placeholder. */\n\t\tresolvedPlaceholder() {\n\t\t\treturn this.placeholder || t('nextcloud-vue', 'Search…')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tinitialsOf(option) {\n\t\t\treturn initialsOf(option.label || '')\n\t\t},\n\n\t\t/**\n\t\t * @param {object} option An option.\n\t\t * @return {string} Its id as a string, '' without one.\n\t\t */\n\t\tidOf(option) {\n\t\t\tconst id = option && (option.id ?? option.value)\n\t\t\treturn id === null || id === undefined ? '' : String(id)\n\t\t},\n\n\t\t/**\n\t\t * @param {object} option An option.\n\t\t * @return {boolean} Whether it is the chosen one.\n\t\t */\n\t\tisSelected(option) {\n\t\t\treturn this.selectedOption !== null && this.idOf(option) !== '' && this.idOf(option) === this.idOf(this.selectedOption)\n\t\t},\n\n\t\t/**\n\t\t * @param {object|null} option The picked option.\n\t\t */\n\t\tonInput(option) {\n\t\t\tconst id = option ? (option.id ?? option.value ?? null) : null\n\t\t\t/** @event update:modelValue The picked option's id, or null when cleared. */\n\t\t\tthis.$emit('update:modelValue', id)\n\t\t},\n\n\t\t/**\n\t\t * @param {string} query The typed text.\n\t\t */\n\t\tonSearch(query) {\n\t\t\t/** @event search The typed text, for a host that searches itself. */\n\t\t\tthis.$emit('search', query)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-search-select {\n\tposition: relative;\n}\n\n/* The field takes the row: NcSelect is an inline block of at least 260px,\n which left the magnifier, placed at the row's end, outside the field\n (DqOverdragen \"Nieuw team\"). */\n.cn-search-select :deep(.v-select) {\n\twidth: 100%;\n}\n\n/* The magnifier sits where the chevron was: in the field, at its end. */\n.cn-search-select__magnifier {\n\tposition: absolute;\n\tinset-inline-end: 12px;\n\tbottom: 0;\n\theight: var(--default-clickable-area, 34px);\n\tdisplay: flex;\n\talign-items: center;\n\tz-index: 1;\n\tcolor: var(--color-text-maxcontrast);\n\tpointer-events: none;\n}\n\n.cn-search-select :deep(.vs__open-indicator),\n.cn-search-select :deep(.vs__open-indicator-button) {\n\tdisplay: none;\n}\n\n.cn-search-select :deep(.vs__actions) {\n\tpadding-inline-end: 36px;\n}\n\n.cn-search-select__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\twidth: 100%;\n\tmin-width: 0;\n\tpadding: 4px 0;\n}\n\n.cn-search-select__lead {\n\tflex: 0 0 32px;\n\twidth: 32px;\n\theight: 32px;\n\tborder-radius: 50%;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tbackground: var(--color-primary-element-light);\n\tcolor: var(--color-primary-element-light-text);\n\tfont-size: 13px;\n\tfont-weight: 600;\n}\n\n.cn-search-select__text {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1 1 auto;\n\tmin-width: 0;\n}\n\n.cn-search-select__name {\n\tfont-weight: 600;\n\toverflow-wrap: anywhere;\n}\n\n.cn-search-select__secondary {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow-wrap: anywhere;\n}\n\n.cn-search-select__check {\n\tflex: 0 0 auto;\n\tcolor: var(--color-primary-element);\n}\n</style>\n"],"names":["CnIcon","t"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CnSearchSelect.vue3.js","sources":["../../../../src/components/CnSearchSelect/CnSearchSelect.vue?vue&type=template&id=6cd354af&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-search-select\" :class=\"{ 'cn-search-select--label-outside': labelOutside }\" data-testid=\"cn-search-select\">\n\t\t<NcSelect\n\t\t\t:inputId=\"inputId\"\n\t\t\t:inputLabel=\"inputLabel\"\n\t\t\t:labelOutside=\"labelOutside\"\n\t\t\t:modelValue=\"selectedOption\"\n\t\t\t:options=\"options\"\n\t\t\t:loading=\"loading\"\n\t\t\t:clearable=\"clearable\"\n\t\t\t:disabled=\"disabled\"\n\t\t\t:placeholder=\"resolvedPlaceholder\"\n\t\t\t:filterable=\"filterable\"\n\t\t\tlabel=\"label\"\n\t\t\t@search=\"onSearch\"\n\t\t\t@update:modelValue=\"onInput\">\n\t\t\t<template #option=\"option\">\n\t\t\t\t<span class=\"cn-search-select__row\" data-testid=\"cn-search-select-row\">\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"option.avatar || option.icon\"\n\t\t\t\t\t\tclass=\"cn-search-select__lead\"\n\t\t\t\t\t\t:class=\"{ 'cn-search-select__lead--avatar': option.avatar && !option.icon }\"\n\t\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t\t<CnIcon v-if=\"option.icon\" :name=\"option.icon\" :size=\"18\" />\n\t\t\t\t\t\t<template v-else>{{ initialsOf(option) }}</template>\n\t\t\t\t\t</span>\n\t\t\t\t\t<span class=\"cn-search-select__text\">\n\t\t\t\t\t\t<span class=\"cn-search-select__name\">{{ option.label }}</span>\n\t\t\t\t\t\t<span v-if=\"option.secondary\" class=\"cn-search-select__secondary\">{{ option.secondary }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t\t<Check\n\t\t\t\t\t\tv-if=\"isSelected(option)\"\n\t\t\t\t\t\tclass=\"cn-search-select__check\"\n\t\t\t\t\t\t:size=\"18\"\n\t\t\t\t\t\tdata-testid=\"cn-search-select-check\" />\n\t\t\t\t</span>\n\t\t\t</template>\n\t\t</NcSelect>\n\t\t<Magnify class=\"cn-search-select__magnifier\" :size=\"18\" aria-hidden=\"true\" />\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcSelect } from '@nextcloud/vue'\nimport Check from 'vue-material-design-icons/Check.vue'\nimport Magnify from 'vue-material-design-icons/Magnify.vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport { initialsOf } from '../../utils/initials.js'\n\n/**\n * CnSearchSelect — a single picker drawn as a search field: a magnifier\n * instead of the chevron, and results as rows with an icon or initials, a\n * name, a secondary line and a check on the chosen one (boards DqOverdragen\n * \"Nieuw team\", DqNieuweZaak \"Aanvrager\").\n *\n * Each option is `{ id, label, secondary?, icon?, avatar? }`: `icon` names a\n * CnIcon, `avatar: true` draws the label's initials in a circle. The value is\n * the option's `id` (or `value`); `update:modelValue` emits that id, or null\n * when cleared. Searching is the host's: listen to `search` and pass new\n * `options`, with `filterable: false` when the host already filtered them.\n *\n * ```vue\n * <CnSearchSelect\n * v-model=\"team\"\n * inputLabel=\"Nieuw team\"\n * :options=\"[{ id: 'legal', label: 'Juridische zaken', secondary: '6 leden · bezwaar, beroep en Woo-advies', avatar: true }]\" />\n * ```\n */\nexport default {\n\tname: 'CnSearchSelect',\n\n\tcomponents: { Check, CnIcon, Magnify, NcSelect },\n\n\tprops: {\n\t\t/** The chosen option's id, or the option itself. */\n\t\tmodelValue: {\n\t\t\ttype: [String, Number, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The options: `{ id, label, secondary?, icon?, avatar? }`.\n\t\t *\n\t\t * @type {Array<{id: (string|number), label: string, secondary?: string, icon?: string, avatar?: boolean}>}\n\t\t */\n\t\toptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** The field's label. */\n\t\tinputLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Draw the label above the field instead of inside it. */\n\t\tlabelOutside: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** The input's id. */\n\t\tinputId: {\n\t\t\ttype: String,\n\t\t\tdefault: undefined,\n\t\t},\n\n\t\t/** Placeholder text; defaults to \"Search…\". */\n\t\tplaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Show the loading spinner. */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Offer a clear button. */\n\t\tclearable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Disable the field. */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Filter the options on the typed text; false when the host searches. */\n\t\tfilterable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\t},\n\n\temits: ['update:modelValue', 'search'],\n\n\tcomputed: {\n\t\t/**\n\t\t * The option matching `modelValue`, or a bare one carrying it.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tselectedOption() {\n\t\t\tconst value = this.modelValue\n\t\t\tif (value === null || value === undefined || value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (typeof value === 'object') {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn this.options.find((o) => this.idOf(o) === String(value)) || { id: value, label: String(value) }\n\t\t},\n\n\t\t/** @return {string} The placeholder. */\n\t\tresolvedPlaceholder() {\n\t\t\treturn this.placeholder || t('nextcloud-vue', 'Search…')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tinitialsOf(option) {\n\t\t\treturn initialsOf(option.label || '')\n\t\t},\n\n\t\t/**\n\t\t * @param {object} option An option.\n\t\t * @return {string} Its id as a string, '' without one.\n\t\t */\n\t\tidOf(option) {\n\t\t\tconst id = option && (option.id ?? option.value)\n\t\t\treturn id === null || id === undefined ? '' : String(id)\n\t\t},\n\n\t\t/**\n\t\t * @param {object} option An option.\n\t\t * @return {boolean} Whether it is the chosen one.\n\t\t */\n\t\tisSelected(option) {\n\t\t\treturn this.selectedOption !== null && this.idOf(option) !== '' && this.idOf(option) === this.idOf(this.selectedOption)\n\t\t},\n\n\t\t/**\n\t\t * @param {object|null} option The picked option.\n\t\t */\n\t\tonInput(option) {\n\t\t\tconst id = option ? (option.id ?? option.value ?? null) : null\n\t\t\t/** @event update:modelValue The picked option's id, or null when cleared. */\n\t\t\tthis.$emit('update:modelValue', id)\n\t\t},\n\n\t\t/**\n\t\t * @param {string} query The typed text.\n\t\t */\n\t\tonSearch(query) {\n\t\t\t/** @event search The typed text, for a host that searches itself. */\n\t\t\tthis.$emit('search', query)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-search-select {\n\tposition: relative;\n}\n\n/* The magnifier sits where the chevron was: in the field, at its end. */\n.cn-search-select__magnifier {\n\tposition: absolute;\n\tinset-inline-end: 12px;\n\tbottom: 0;\n\theight: var(--default-clickable-area, 34px);\n\tdisplay: flex;\n\talign-items: center;\n\tcolor: var(--color-text-maxcontrast);\n\tpointer-events: none;\n}\n\n.cn-search-select :deep(.vs__open-indicator),\n.cn-search-select :deep(.vs__open-indicator-button) {\n\tdisplay: none;\n}\n\n.cn-search-select :deep(.vs__actions) {\n\tpadding-inline-end: 36px;\n}\n\n.cn-search-select__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\twidth: 100%;\n\tmin-width: 0;\n\tpadding: 4px 0;\n}\n\n.cn-search-select__lead {\n\tflex: 0 0 32px;\n\twidth: 32px;\n\theight: 32px;\n\tborder-radius: 50%;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tbackground: var(--color-primary-element-light);\n\tcolor: var(--color-primary-element-light-text);\n\tfont-size: 13px;\n\tfont-weight: 600;\n}\n\n.cn-search-select__text {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1 1 auto;\n\tmin-width: 0;\n}\n\n.cn-search-select__name {\n\tfont-weight: 600;\n\toverflow-wrap: anywhere;\n}\n\n.cn-search-select__secondary {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow-wrap: anywhere;\n}\n\n.cn-search-select__check {\n\tflex: 0 0 auto;\n\tcolor: var(--color-primary-element);\n}\n</style>\n"],"names":["_normalizeClass","_withCtx","_createElementVNode","_createElementBlock","_createBlock","_Fragment","_createTextVNode","_toDisplayString","_openBlock"],"mappings":";;;AAyBU,EAAA,KAAM,EAAA,uBAAuB;AAAC,EAAA,aAAW,EAAC,sBAAsB;;AAShE,MAAA,UAAA,GAAA,EAAA,KAAA,EAAA,wBAAA,GAAA;AACE,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,wBAAY,GAAA;;;AACM,EAAA,KAAA,EAAA,6BAAA;;;;;;;;;;IA3B9B,KAAK,EAAAA,cAAA,CAAA,CAAC,kBAAkB,EAAA,EAAA,iCAAA,EAAA,MAAA,CAAA,YAAA,EAAA,CAAA,CAAA;AAAA,IAAA,aAAA,EAAA,kBAAA;;;AAE1B,MAAA,OAAO,EAAE,MAAO,CAAA,OAAA;AAChB,MAAA,UAAU,EAAE,MAAI,CAAA,UAAA;AAChB,MAAA,YAAY,EAAE,MAAM,CAAA,YAAA;AACpB,MAAA,UAAU,EAAE,QAAM,CAAA,cAAA;AAClB,MAAA,OAAO,EAAE,MAAO,CAAA,OAAA;AAChB,MAAA,OAAO,EAAE,MAAO,CAAA,OAAA;AAChB,MAAA,SAAS,EAAE,MAAA,CAAA,SAAA;AACX,MAAA,QAAQ,EAAE,MAAM,CAAA,QAAA;AAChB,MAAA,WAAW,EAAE,QAAc,CAAA,mBAAA;AAC3B,MAAA,UAAU,EAAE,MAAU,CAAA,UAAA;AACtB,MAAA,KAAI,EAAA,OAAQ;cACP,EAAA,QAAA,CAAA,QAAA;AACH,MAAA,qBAAe,EAAE,QAAO,CAAA,OAAA;;MAChB,MAAM,EAAAC,OAAA,CACd,CAkBA,MAnBsB,KAAA;AACtB,QAAAC,kBAAA,CAkBA,QAlBA,UAkBA,EAAA;AAhBM,UAAA,CAAA,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI;4BADlCC,kBAOK,CAAA,MAAA,EAAA;;gBALL,KAAK,EAAAH,cAAA,CAAA,CAAC,wBAAwB,EACzB,EAAA,gCAAA,EAAA,MAAA,CAAA,MAAA,IAAA,CAAA,MAAA,CAAA,IAAA,EAAA,CAAA,CAAA;AACL,gBAAA,aAAW,EAAC,MAAM;;AACJ,gBAAA,CAAA,MAAM,CAAC,IAAI;kCAAzBI,WAA4D,CAAA,iBAAA,EAAA;;sBAAhC,IAAI,EAAE,MAAM,CAAC,IAAI;AAAG,sBAAA,IAAK,EAAC,EAAE;;kCACxDD,kBAAoD,CAAAE,QAAA,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA;AAAhC,sBAAAC,eAAA,CAAAC,eAAA,CAAA,QAAA,CAAA,UAAU,CAAC,MAAM,CAAA,CAAA,EAAA,CAAA,YAAA;;;;AAEtC,UAAAL,kBAAA,CAGO,QAHP,UAGO,EAAA;AAFN,YAAAA,kBAAA,CAAwB,MAAxB,EAAA,UAAwB,EAAAK,eAAA,CAAA,MAAA,CAAA,KAAA,CAAA,EAAA,CAAA,YAAA;AACZ,YAAA,CAAA,MAAM,CAAC,SAAS;AAA5B,iBAAAC,SAAA,EAAA,EAAAL,kBAAA,CAA8B,MAA9B,EAAA,UAA8B,EAAAI,eAAA,CAAA,MAAA,CAAA,SAAA,CAAA,EAAA,CAAA,YAAA;;;AAG1B,UAAA,CAAA,QAAA,CAAA,UAAA,CAAA,MAAA,CAAA;4BADJH,WAIuC,CAAA,gBAAA,EAAA;;AAFvC,gBAAA,KAAK,EAAC,yBAAC;AACN,gBAAA,IAAI,EAAC,EAAA;AACN,gBAAA,aAAW,EAAC,wBAAwB;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"CnSearchSelect.vue3.js","sources":["../../../../src/components/CnSearchSelect/CnSearchSelect.vue?vue&type=template&id=aaa45660&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-search-select\" :class=\"{ 'cn-search-select--label-outside': labelOutside }\" data-testid=\"cn-search-select\">\n\t\t<NcSelect\n\t\t\t:inputId=\"inputId\"\n\t\t\t:inputLabel=\"inputLabel\"\n\t\t\t:labelOutside=\"labelOutside\"\n\t\t\t:modelValue=\"selectedOption\"\n\t\t\t:options=\"options\"\n\t\t\t:loading=\"loading\"\n\t\t\t:clearable=\"clearable\"\n\t\t\t:disabled=\"disabled\"\n\t\t\t:placeholder=\"resolvedPlaceholder\"\n\t\t\t:filterable=\"filterable\"\n\t\t\tlabel=\"label\"\n\t\t\t@search=\"onSearch\"\n\t\t\t@update:modelValue=\"onInput\">\n\t\t\t<template #option=\"option\">\n\t\t\t\t<span class=\"cn-search-select__row\" data-testid=\"cn-search-select-row\">\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"option.avatar || option.icon\"\n\t\t\t\t\t\tclass=\"cn-search-select__lead\"\n\t\t\t\t\t\t:class=\"{ 'cn-search-select__lead--avatar': option.avatar && !option.icon }\"\n\t\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t\t<CnIcon v-if=\"option.icon\" :name=\"option.icon\" :size=\"18\" />\n\t\t\t\t\t\t<template v-else>{{ initialsOf(option) }}</template>\n\t\t\t\t\t</span>\n\t\t\t\t\t<span class=\"cn-search-select__text\">\n\t\t\t\t\t\t<span class=\"cn-search-select__name\">{{ option.label }}</span>\n\t\t\t\t\t\t<span v-if=\"option.secondary\" class=\"cn-search-select__secondary\">{{ option.secondary }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t\t<Check\n\t\t\t\t\t\tv-if=\"isSelected(option)\"\n\t\t\t\t\t\tclass=\"cn-search-select__check\"\n\t\t\t\t\t\t:size=\"18\"\n\t\t\t\t\t\tdata-testid=\"cn-search-select-check\" />\n\t\t\t\t</span>\n\t\t\t</template>\n\t\t</NcSelect>\n\t\t<Magnify class=\"cn-search-select__magnifier\" :size=\"18\" aria-hidden=\"true\" />\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcSelect } from '@nextcloud/vue'\nimport Check from 'vue-material-design-icons/Check.vue'\nimport Magnify from 'vue-material-design-icons/Magnify.vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport { initialsOf } from '../../utils/initials.js'\n\n/**\n * CnSearchSelect — a single picker drawn as a search field: a magnifier\n * instead of the chevron, and results as rows with an icon or initials, a\n * name, a secondary line and a check on the chosen one (boards DqOverdragen\n * \"Nieuw team\", DqNieuweZaak \"Aanvrager\").\n *\n * Each option is `{ id, label, secondary?, icon?, avatar? }`: `icon` names a\n * CnIcon, `avatar: true` draws the label's initials in a circle. The value is\n * the option's `id` (or `value`); `update:modelValue` emits that id, or null\n * when cleared. Searching is the host's: listen to `search` and pass new\n * `options`, with `filterable: false` when the host already filtered them.\n *\n * ```vue\n * <CnSearchSelect\n * v-model=\"team\"\n * inputLabel=\"Nieuw team\"\n * :options=\"[{ id: 'legal', label: 'Juridische zaken', secondary: '6 leden · bezwaar, beroep en Woo-advies', avatar: true }]\" />\n * ```\n */\nexport default {\n\tname: 'CnSearchSelect',\n\n\tcomponents: { Check, CnIcon, Magnify, NcSelect },\n\n\tprops: {\n\t\t/** The chosen option's id, or the option itself. */\n\t\tmodelValue: {\n\t\t\ttype: [String, Number, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The options: `{ id, label, secondary?, icon?, avatar? }`.\n\t\t *\n\t\t * @type {Array<{id: (string|number), label: string, secondary?: string, icon?: string, avatar?: boolean}>}\n\t\t */\n\t\toptions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** The field's label. */\n\t\tinputLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Draw the label above the field instead of inside it. */\n\t\tlabelOutside: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** The input's id. */\n\t\tinputId: {\n\t\t\ttype: String,\n\t\t\tdefault: undefined,\n\t\t},\n\n\t\t/** Placeholder text; defaults to \"Search…\". */\n\t\tplaceholder: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Show the loading spinner. */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Offer a clear button. */\n\t\tclearable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Disable the field. */\n\t\tdisabled: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Filter the options on the typed text; false when the host searches. */\n\t\tfilterable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\t},\n\n\temits: ['update:modelValue', 'search'],\n\n\tcomputed: {\n\t\t/**\n\t\t * The option matching `modelValue`, or a bare one carrying it.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tselectedOption() {\n\t\t\tconst value = this.modelValue\n\t\t\tif (value === null || value === undefined || value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (typeof value === 'object') {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn this.options.find((o) => this.idOf(o) === String(value)) || { id: value, label: String(value) }\n\t\t},\n\n\t\t/** @return {string} The placeholder. */\n\t\tresolvedPlaceholder() {\n\t\t\treturn this.placeholder || t('nextcloud-vue', 'Search…')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tinitialsOf(option) {\n\t\t\treturn initialsOf(option.label || '')\n\t\t},\n\n\t\t/**\n\t\t * @param {object} option An option.\n\t\t * @return {string} Its id as a string, '' without one.\n\t\t */\n\t\tidOf(option) {\n\t\t\tconst id = option && (option.id ?? option.value)\n\t\t\treturn id === null || id === undefined ? '' : String(id)\n\t\t},\n\n\t\t/**\n\t\t * @param {object} option An option.\n\t\t * @return {boolean} Whether it is the chosen one.\n\t\t */\n\t\tisSelected(option) {\n\t\t\treturn this.selectedOption !== null && this.idOf(option) !== '' && this.idOf(option) === this.idOf(this.selectedOption)\n\t\t},\n\n\t\t/**\n\t\t * @param {object|null} option The picked option.\n\t\t */\n\t\tonInput(option) {\n\t\t\tconst id = option ? (option.id ?? option.value ?? null) : null\n\t\t\t/** @event update:modelValue The picked option's id, or null when cleared. */\n\t\t\tthis.$emit('update:modelValue', id)\n\t\t},\n\n\t\t/**\n\t\t * @param {string} query The typed text.\n\t\t */\n\t\tonSearch(query) {\n\t\t\t/** @event search The typed text, for a host that searches itself. */\n\t\t\tthis.$emit('search', query)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-search-select {\n\tposition: relative;\n}\n\n/* The field takes the row: NcSelect is an inline block of at least 260px,\n which left the magnifier, placed at the row's end, outside the field\n (DqOverdragen \"Nieuw team\"). */\n.cn-search-select :deep(.v-select) {\n\twidth: 100%;\n}\n\n/* The magnifier sits where the chevron was: in the field, at its end. */\n.cn-search-select__magnifier {\n\tposition: absolute;\n\tinset-inline-end: 12px;\n\tbottom: 0;\n\theight: var(--default-clickable-area, 34px);\n\tdisplay: flex;\n\talign-items: center;\n\tz-index: 1;\n\tcolor: var(--color-text-maxcontrast);\n\tpointer-events: none;\n}\n\n.cn-search-select :deep(.vs__open-indicator),\n.cn-search-select :deep(.vs__open-indicator-button) {\n\tdisplay: none;\n}\n\n.cn-search-select :deep(.vs__actions) {\n\tpadding-inline-end: 36px;\n}\n\n.cn-search-select__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\twidth: 100%;\n\tmin-width: 0;\n\tpadding: 4px 0;\n}\n\n.cn-search-select__lead {\n\tflex: 0 0 32px;\n\twidth: 32px;\n\theight: 32px;\n\tborder-radius: 50%;\n\tdisplay: inline-flex;\n\talign-items: center;\n\tjustify-content: center;\n\tbackground: var(--color-primary-element-light);\n\tcolor: var(--color-primary-element-light-text);\n\tfont-size: 13px;\n\tfont-weight: 600;\n}\n\n.cn-search-select__text {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1 1 auto;\n\tmin-width: 0;\n}\n\n.cn-search-select__name {\n\tfont-weight: 600;\n\toverflow-wrap: anywhere;\n}\n\n.cn-search-select__secondary {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow-wrap: anywhere;\n}\n\n.cn-search-select__check {\n\tflex: 0 0 auto;\n\tcolor: var(--color-primary-element);\n}\n</style>\n"],"names":["_normalizeClass","_withCtx","_createElementVNode","_createElementBlock","_createBlock","_Fragment","_createTextVNode","_toDisplayString","_openBlock"],"mappings":";;;AAyBU,EAAA,KAAM,EAAA,uBAAuB;AAAC,EAAA,aAAW,EAAC,sBAAsB;;AAShE,MAAA,UAAA,GAAA,EAAA,KAAA,EAAA,wBAAA,GAAA;AACE,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,wBAAY,GAAA;;;AACM,EAAA,KAAA,EAAA,6BAAA;;;;;;;;;;IA3B9B,KAAK,EAAAA,cAAA,CAAA,CAAC,kBAAkB,EAAA,EAAA,iCAAA,EAAA,MAAA,CAAA,YAAA,EAAA,CAAA,CAAA;AAAA,IAAA,aAAA,EAAA,kBAAA;;;AAE1B,MAAA,OAAO,EAAE,MAAO,CAAA,OAAA;AAChB,MAAA,UAAU,EAAE,MAAI,CAAA,UAAA;AAChB,MAAA,YAAY,EAAE,MAAM,CAAA,YAAA;AACpB,MAAA,UAAU,EAAE,QAAM,CAAA,cAAA;AAClB,MAAA,OAAO,EAAE,MAAO,CAAA,OAAA;AAChB,MAAA,OAAO,EAAE,MAAO,CAAA,OAAA;AAChB,MAAA,SAAS,EAAE,MAAA,CAAA,SAAA;AACX,MAAA,QAAQ,EAAE,MAAM,CAAA,QAAA;AAChB,MAAA,WAAW,EAAE,QAAc,CAAA,mBAAA;AAC3B,MAAA,UAAU,EAAE,MAAU,CAAA,UAAA;AACtB,MAAA,KAAI,EAAA,OAAQ;cACP,EAAA,QAAA,CAAA,QAAA;AACH,MAAA,qBAAe,EAAE,QAAO,CAAA,OAAA;;MAChB,MAAM,EAAAC,OAAA,CACd,CAkBA,MAnBsB,KAAA;AACtB,QAAAC,kBAAA,CAkBA,QAlBA,UAkBA,EAAA;AAhBM,UAAA,CAAA,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI;4BADlCC,kBAOK,CAAA,MAAA,EAAA;;gBALL,KAAK,EAAAH,cAAA,CAAA,CAAC,wBAAwB,EACzB,EAAA,gCAAA,EAAA,MAAA,CAAA,MAAA,IAAA,CAAA,MAAA,CAAA,IAAA,EAAA,CAAA,CAAA;AACL,gBAAA,aAAW,EAAC,MAAM;;AACJ,gBAAA,CAAA,MAAM,CAAC,IAAI;kCAAzBI,WAA4D,CAAA,iBAAA,EAAA;;sBAAhC,IAAI,EAAE,MAAM,CAAC,IAAI;AAAG,sBAAA,IAAK,EAAC,EAAE;;kCACxDD,kBAAoD,CAAAE,QAAA,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA;AAAhC,sBAAAC,eAAA,CAAAC,eAAA,CAAA,QAAA,CAAA,UAAU,CAAC,MAAM,CAAA,CAAA,EAAA,CAAA,YAAA;;;;AAEtC,UAAAL,kBAAA,CAGO,QAHP,UAGO,EAAA;AAFN,YAAAA,kBAAA,CAAwB,MAAxB,EAAA,UAAwB,EAAAK,eAAA,CAAA,MAAA,CAAA,KAAA,CAAA,EAAA,CAAA,YAAA;AACZ,YAAA,CAAA,MAAM,CAAC,SAAS;AAA5B,iBAAAC,SAAA,EAAA,EAAAL,kBAAA,CAA8B,MAA9B,EAAA,UAA8B,EAAAI,eAAA,CAAA,MAAA,CAAA,SAAA,CAAA,EAAA,CAAA,YAAA;;;AAG1B,UAAA,CAAA,QAAA,CAAA,UAAA,CAAA,MAAA,CAAA;4BADJH,WAIuC,CAAA,gBAAA,EAAA;;AAFvC,gBAAA,KAAK,EAAC,yBAAC;AACN,gBAAA,IAAI,EAAC,EAAA;AACN,gBAAA,aAAW,EAAC,wBAAwB;;;;;;;;;;;;;;;;;"}
@@ -66,6 +66,22 @@ function pickRefLabel(obj, labelField) {
66
66
  return null
67
67
  }
68
68
 
69
+ /**
70
+ * Read one field off a referenced object, with no fallback: a colour or an
71
+ * icon name must not fall back to the title.
72
+ *
73
+ * @param {object|null} obj The referenced object.
74
+ * @param {string} field The (possibly nested) property.
75
+ * @return {string|null} The value as text, or null when it is empty.
76
+ */
77
+ function pickRefField(obj, field) {
78
+ if (!obj || typeof obj !== 'object' || !field) {
79
+ return null
80
+ }
81
+ const text = asText(readPath(obj, field));
82
+ return text !== '' ? text : null
83
+ }
84
+
69
85
  /**
70
86
  * Create a resolver bound to an object store. Labels are cached per register,
71
87
  * schema and label field for the lifetime of the resolver.
@@ -92,9 +108,13 @@ function createRefLabelResolver(getStore) {
92
108
  * @param {string} schema Schema slug of the referenced objects.
93
109
  * @param {string[]} ids Ids to resolve (duplicates are dropped).
94
110
  * @param {string} labelField Property holding the label (dotted paths allowed).
111
+ * @param {{strict?: boolean}} [options] `strict`: read exactly that field, with no
112
+ * fallback to the title or name (a colour or an icon name).
95
113
  * @return {Promise<Object<string, string|null>>} Label by id.
96
114
  */
97
- async resolve(register, schema, ids, labelField) {
115
+ async resolve(register, schema, ids, labelField, options = {}) {
116
+ const strict = options.strict === true;
117
+ const pick = strict ? pickRefField : pickRefLabel;
98
118
  const distinct = [...new Set((ids || []).filter((id) => id !== null && id !== undefined && id !== '').map(String))];
99
119
  const out = {};
100
120
  if (distinct.length === 0) {
@@ -116,14 +136,14 @@ function createRefLabelResolver(getStore) {
116
136
  });
117
137
  return out
118
138
  }
119
- const hit = bucket(`${type}::${labelField || ''}`);
139
+ const hit = bucket(`${type}::${labelField || ''}::${strict ? 'field' : 'label'}`);
120
140
  const missing = [];
121
141
  for (const id of distinct) {
122
142
  const stored = store.objects && store.objects[type] && store.objects[type][id];
123
143
  if (hit.has(id)) {
124
144
  continue
125
145
  }
126
- const label = stored ? pickRefLabel(stored, labelField) : null;
146
+ const label = stored ? pick(stored, labelField) : null;
127
147
  if (label !== null) {
128
148
  hit.set(id, label);
129
149
  } else {
@@ -137,7 +157,7 @@ function createRefLabelResolver(getStore) {
137
157
  rows = await store.fetchCollectionForOptions(type, {
138
158
  _ids: missing.join(','),
139
159
  _limit: missing.length,
140
- _fields: [...new Set([top, 'title', 'name'])].join(','),
160
+ _fields: (strict ? [top] : [...new Set([top, 'title', 'name'])]).join(','),
141
161
  });
142
162
  } catch {
143
163
  rows = [];
@@ -149,7 +169,7 @@ function createRefLabelResolver(getStore) {
149
169
  byId.set(String(id), row);
150
170
  }
151
171
  });
152
- missing.forEach((id) => hit.set(id, pickRefLabel(byId.get(id), labelField)));
172
+ missing.forEach((id) => hit.set(id, pick(byId.get(id), labelField)));
153
173
  }
154
174
  distinct.forEach((id) => {
155
175
  out[id] = hit.has(id) ? hit.get(id) : null;
@@ -193,5 +213,5 @@ function useRefLabels() {
193
213
  })
194
214
  }
195
215
 
196
- export { createRefLabelResolver, pickRefLabel, useRefLabels };
216
+ export { createRefLabelResolver, pickRefField, pickRefLabel, useRefLabels };
197
217
  //# sourceMappingURL=useRefLabels.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useRefLabels.js","sources":["../../../src/composables/useRefLabels.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * useRefLabels — resolve the ids of a reference column to a label field of\n * the referenced objects, one batched request per schema.\n *\n * @spec openspec/changes/index-ref-column-labels/tasks.md#task-1\n */\nimport { useObjectStore } from '../store/useObjectStore.js'\nimport { resolveObjectOpType } from '../utils/actionsDispatcher.js'\n\n/**\n * Read a dotted path (`person.displayName`) from an object.\n *\n * @param {object} obj The object.\n * @param {string} path Dotted path.\n * @return {*} The value, or undefined.\n */\nfunction readPath(obj, path) {\n\treturn String(path).split('.').reduce((cur, k) => (cur !== null && cur !== undefined && typeof cur === 'object' ? cur[k] : undefined), obj)\n}\n\n/**\n * Turn a field value into display text. A per-language map collapses to its first value.\n *\n * @param {*} raw The field value.\n * @return {string} Text, or '' when unusable.\n */\nfunction asText(raw) {\n\tif (typeof raw === 'string') {\n\t\treturn raw.trim()\n\t}\n\tif (typeof raw === 'number') {\n\t\treturn String(raw)\n\t}\n\tif (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n\t\tconst first = Object.values(raw).find((v) => typeof v === 'string' && v.trim() !== '')\n\t\treturn first ? first.trim() : ''\n\t}\n\treturn ''\n}\n\n/**\n * Pick the label off a referenced object: `labelField` first, then `title`,\n * `name` and `@self.name`.\n *\n * @param {object|null} obj The referenced object.\n * @param {string} labelField Preferred (possibly nested) property.\n * @return {string|null} The label, or null when none is usable.\n */\nexport function pickRefLabel(obj, labelField) {\n\tif (!obj || typeof obj !== 'object') {\n\t\treturn null\n\t}\n\tfor (const path of [labelField, 'title', 'name', '@self.name']) {\n\t\tif (!path) {\n\t\t\tcontinue\n\t\t}\n\t\tconst text = asText(path.includes('.') ? readPath(obj, path) : obj[path])\n\t\tif (text !== '') {\n\t\t\treturn text\n\t\t}\n\t}\n\treturn null\n}\n\n/**\n * Create a resolver bound to an object store. Labels are cached per register,\n * schema and label field for the lifetime of the resolver.\n *\n * @param {Function} getStore Returns the object store, or null when none is available.\n * @return {{resolve: Function, invalidate: Function}}\n */\nexport function createRefLabelResolver(getStore) {\n\tconst cache = new Map()\n\n\tconst bucket = (key) => {\n\t\tif (!cache.has(key)) {\n\t\t\tcache.set(key, new Map())\n\t\t}\n\t\treturn cache.get(key)\n\t}\n\n\treturn {\n\t\t/**\n\t\t * Resolve ids to labels. One request per call for the ids not yet cached.\n\t\t * An id that cannot be resolved maps to null; this never throws.\n\t\t *\n\t\t * @param {string} register Register slug of the referenced schema.\n\t\t * @param {string} schema Schema slug of the referenced objects.\n\t\t * @param {string[]} ids Ids to resolve (duplicates are dropped).\n\t\t * @param {string} labelField Property holding the label (dotted paths allowed).\n\t\t * @return {Promise<Object<string, string|null>>} Label by id.\n\t\t */\n\t\tasync resolve(register, schema, ids, labelField) {\n\t\t\tconst distinct = [...new Set((ids || []).filter((id) => id !== null && id !== undefined && id !== '').map(String))]\n\t\t\tconst out = {}\n\t\t\tif (distinct.length === 0) {\n\t\t\t\treturn out\n\t\t\t}\n\t\t\tconst store = typeof getStore === 'function' ? getStore() : null\n\t\t\tif (!store || !register || !schema) {\n\t\t\t\tdistinct.forEach((id) => {\n\t\t\t\t\tout[id] = null\n\t\t\t\t})\n\t\t\t\treturn out\n\t\t\t}\n\t\t\tlet type\n\t\t\ttry {\n\t\t\t\ttype = resolveObjectOpType(store, { register, schema }, { exactSchema: true })\n\t\t\t} catch {\n\t\t\t\tdistinct.forEach((id) => {\n\t\t\t\t\tout[id] = null\n\t\t\t\t})\n\t\t\t\treturn out\n\t\t\t}\n\t\t\tconst hit = bucket(`${type}::${labelField || ''}`)\n\t\t\tconst missing = []\n\t\t\tfor (const id of distinct) {\n\t\t\t\tconst stored = store.objects && store.objects[type] && store.objects[type][id]\n\t\t\t\tif (hit.has(id)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst label = stored ? pickRefLabel(stored, labelField) : null\n\t\t\t\tif (label !== null) {\n\t\t\t\t\thit.set(id, label)\n\t\t\t\t} else {\n\t\t\t\t\tmissing.push(id)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (missing.length > 0) {\n\t\t\t\tlet rows\n\t\t\t\ttry {\n\t\t\t\t\tconst top = labelField ? String(labelField).split('.')[0] : 'name'\n\t\t\t\t\trows = await store.fetchCollectionForOptions(type, {\n\t\t\t\t\t\t_ids: missing.join(','),\n\t\t\t\t\t\t_limit: missing.length,\n\t\t\t\t\t\t_fields: [...new Set([top, 'title', 'name'])].join(','),\n\t\t\t\t\t})\n\t\t\t\t} catch {\n\t\t\t\t\trows = []\n\t\t\t\t}\n\t\t\t\tconst byId = new Map()\n\t\t\t\t;(Array.isArray(rows) ? rows : []).forEach((row) => {\n\t\t\t\t\tconst id = row && (row.id ?? row.uuid ?? (row['@self'] && row['@self'].id))\n\t\t\t\t\tif (id !== undefined && id !== null) {\n\t\t\t\t\t\tbyId.set(String(id), row)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\tmissing.forEach((id) => hit.set(id, pickRefLabel(byId.get(id), labelField)))\n\t\t\t}\n\t\t\tdistinct.forEach((id) => {\n\t\t\t\tout[id] = hit.has(id) ? hit.get(id) : null\n\t\t\t})\n\t\t\treturn out\n\t\t},\n\n\t\t/**\n\t\t * Forget cached labels, all of them or those of one register and schema.\n\t\t * Call after a write to a referenced object.\n\t\t *\n\t\t * @param {string} [register] Register slug.\n\t\t * @param {string} [schema] Schema slug.\n\t\t */\n\t\tinvalidate(register, schema) {\n\t\t\tif (!register) {\n\t\t\t\tcache.clear()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfor (const key of [...cache.keys()]) {\n\t\t\t\tif (key.includes(register) && (!schema || key.includes(schema))) {\n\t\t\t\t\tcache.delete(key)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t}\n}\n\n/**\n * Composable form of the resolver, bound to the shared object store.\n *\n * @return {{resolve: Function, invalidate: Function}} The resolver.\n */\nexport function useRefLabels() {\n\treturn createRefLabelResolver(() => {\n\t\ttry {\n\t\t\treturn useObjectStore()\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t})\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useRefLabels.js","sources":["../../../src/composables/useRefLabels.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * useRefLabels — resolve the ids of a reference column to a label field of\n * the referenced objects, one batched request per schema.\n *\n * @spec openspec/changes/index-ref-column-labels/tasks.md#task-1\n */\nimport { useObjectStore } from '../store/useObjectStore.js'\nimport { resolveObjectOpType } from '../utils/actionsDispatcher.js'\n\n/**\n * Read a dotted path (`person.displayName`) from an object.\n *\n * @param {object} obj The object.\n * @param {string} path Dotted path.\n * @return {*} The value, or undefined.\n */\nfunction readPath(obj, path) {\n\treturn String(path).split('.').reduce((cur, k) => (cur !== null && cur !== undefined && typeof cur === 'object' ? cur[k] : undefined), obj)\n}\n\n/**\n * Turn a field value into display text. A per-language map collapses to its first value.\n *\n * @param {*} raw The field value.\n * @return {string} Text, or '' when unusable.\n */\nfunction asText(raw) {\n\tif (typeof raw === 'string') {\n\t\treturn raw.trim()\n\t}\n\tif (typeof raw === 'number') {\n\t\treturn String(raw)\n\t}\n\tif (raw && typeof raw === 'object' && !Array.isArray(raw)) {\n\t\tconst first = Object.values(raw).find((v) => typeof v === 'string' && v.trim() !== '')\n\t\treturn first ? first.trim() : ''\n\t}\n\treturn ''\n}\n\n/**\n * Pick the label off a referenced object: `labelField` first, then `title`,\n * `name` and `@self.name`.\n *\n * @param {object|null} obj The referenced object.\n * @param {string} labelField Preferred (possibly nested) property.\n * @return {string|null} The label, or null when none is usable.\n */\nexport function pickRefLabel(obj, labelField) {\n\tif (!obj || typeof obj !== 'object') {\n\t\treturn null\n\t}\n\tfor (const path of [labelField, 'title', 'name', '@self.name']) {\n\t\tif (!path) {\n\t\t\tcontinue\n\t\t}\n\t\tconst text = asText(path.includes('.') ? readPath(obj, path) : obj[path])\n\t\tif (text !== '') {\n\t\t\treturn text\n\t\t}\n\t}\n\treturn null\n}\n\n/**\n * Read one field off a referenced object, with no fallback: a colour or an\n * icon name must not fall back to the title.\n *\n * @param {object|null} obj The referenced object.\n * @param {string} field The (possibly nested) property.\n * @return {string|null} The value as text, or null when it is empty.\n */\nexport function pickRefField(obj, field) {\n\tif (!obj || typeof obj !== 'object' || !field) {\n\t\treturn null\n\t}\n\tconst text = asText(readPath(obj, field))\n\treturn text !== '' ? text : null\n}\n\n/**\n * Create a resolver bound to an object store. Labels are cached per register,\n * schema and label field for the lifetime of the resolver.\n *\n * @param {Function} getStore Returns the object store, or null when none is available.\n * @return {{resolve: Function, invalidate: Function}}\n */\nexport function createRefLabelResolver(getStore) {\n\tconst cache = new Map()\n\n\tconst bucket = (key) => {\n\t\tif (!cache.has(key)) {\n\t\t\tcache.set(key, new Map())\n\t\t}\n\t\treturn cache.get(key)\n\t}\n\n\treturn {\n\t\t/**\n\t\t * Resolve ids to labels. One request per call for the ids not yet cached.\n\t\t * An id that cannot be resolved maps to null; this never throws.\n\t\t *\n\t\t * @param {string} register Register slug of the referenced schema.\n\t\t * @param {string} schema Schema slug of the referenced objects.\n\t\t * @param {string[]} ids Ids to resolve (duplicates are dropped).\n\t\t * @param {string} labelField Property holding the label (dotted paths allowed).\n\t\t * @param {{strict?: boolean}} [options] `strict`: read exactly that field, with no\n\t\t * fallback to the title or name (a colour or an icon name).\n\t\t * @return {Promise<Object<string, string|null>>} Label by id.\n\t\t */\n\t\tasync resolve(register, schema, ids, labelField, options = {}) {\n\t\t\tconst strict = options.strict === true\n\t\t\tconst pick = strict ? pickRefField : pickRefLabel\n\t\t\tconst distinct = [...new Set((ids || []).filter((id) => id !== null && id !== undefined && id !== '').map(String))]\n\t\t\tconst out = {}\n\t\t\tif (distinct.length === 0) {\n\t\t\t\treturn out\n\t\t\t}\n\t\t\tconst store = typeof getStore === 'function' ? getStore() : null\n\t\t\tif (!store || !register || !schema) {\n\t\t\t\tdistinct.forEach((id) => {\n\t\t\t\t\tout[id] = null\n\t\t\t\t})\n\t\t\t\treturn out\n\t\t\t}\n\t\t\tlet type\n\t\t\ttry {\n\t\t\t\ttype = resolveObjectOpType(store, { register, schema }, { exactSchema: true })\n\t\t\t} catch {\n\t\t\t\tdistinct.forEach((id) => {\n\t\t\t\t\tout[id] = null\n\t\t\t\t})\n\t\t\t\treturn out\n\t\t\t}\n\t\t\tconst hit = bucket(`${type}::${labelField || ''}::${strict ? 'field' : 'label'}`)\n\t\t\tconst missing = []\n\t\t\tfor (const id of distinct) {\n\t\t\t\tconst stored = store.objects && store.objects[type] && store.objects[type][id]\n\t\t\t\tif (hit.has(id)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst label = stored ? pick(stored, labelField) : null\n\t\t\t\tif (label !== null) {\n\t\t\t\t\thit.set(id, label)\n\t\t\t\t} else {\n\t\t\t\t\tmissing.push(id)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (missing.length > 0) {\n\t\t\t\tlet rows\n\t\t\t\ttry {\n\t\t\t\t\tconst top = labelField ? String(labelField).split('.')[0] : 'name'\n\t\t\t\t\trows = await store.fetchCollectionForOptions(type, {\n\t\t\t\t\t\t_ids: missing.join(','),\n\t\t\t\t\t\t_limit: missing.length,\n\t\t\t\t\t\t_fields: (strict ? [top] : [...new Set([top, 'title', 'name'])]).join(','),\n\t\t\t\t\t})\n\t\t\t\t} catch {\n\t\t\t\t\trows = []\n\t\t\t\t}\n\t\t\t\tconst byId = new Map()\n\t\t\t\t;(Array.isArray(rows) ? rows : []).forEach((row) => {\n\t\t\t\t\tconst id = row && (row.id ?? row.uuid ?? (row['@self'] && row['@self'].id))\n\t\t\t\t\tif (id !== undefined && id !== null) {\n\t\t\t\t\t\tbyId.set(String(id), row)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\tmissing.forEach((id) => hit.set(id, pick(byId.get(id), labelField)))\n\t\t\t}\n\t\t\tdistinct.forEach((id) => {\n\t\t\t\tout[id] = hit.has(id) ? hit.get(id) : null\n\t\t\t})\n\t\t\treturn out\n\t\t},\n\n\t\t/**\n\t\t * Forget cached labels, all of them or those of one register and schema.\n\t\t * Call after a write to a referenced object.\n\t\t *\n\t\t * @param {string} [register] Register slug.\n\t\t * @param {string} [schema] Schema slug.\n\t\t */\n\t\tinvalidate(register, schema) {\n\t\t\tif (!register) {\n\t\t\t\tcache.clear()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfor (const key of [...cache.keys()]) {\n\t\t\t\tif (key.includes(register) && (!schema || key.includes(schema))) {\n\t\t\t\t\tcache.delete(key)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t}\n}\n\n/**\n * Composable form of the resolver, bound to the shared object store.\n *\n * @return {{resolve: Function, invalidate: Function}} The resolver.\n */\nexport function useRefLabels() {\n\treturn createRefLabelResolver(() => {\n\t\ttry {\n\t\t\treturn useObjectStore()\n\t\t} catch {\n\t\t\treturn null\n\t\t}\n\t})\n}\n"],"names":[],"mappings":"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"}
@@ -89,6 +89,7 @@ function createIntegrationRegistry() {
89
89
  * @param {?object} [entry.offlineConfig] Opaque per-integration config bag forwarded verbatim to the integration's components (e.g. the field-inspection leaf's offline schema/filter config). A consuming app overrides it by pre-registering the same id.
90
90
  * @param {'component'|'mount'} [entry.renderMode] Render strategy (openregister#2127 / ADR-066). `'component'` (default) interprets the SFC `tab`/`widget` under the host's own Vue runtime. `'mount'` hands the leaf a bare host-owned DOM element via `mount`/`unmount`, so a leaf built against a different Vue major than the host renders its own framework instance inside that element.
91
91
  * @param {(el: Element, props: object) => void} [entry.mount] Mount hand-off. Required together with `unmount` when `renderMode` is `'mount'`; the host calls it against a bare element with the same context an SFC widget/tab receives (`{ register, schema, objectId, surface, integrationContext, … }`). May also be supplied alongside an SFC pair as a same-major fast path.
92
+ * @param {'card'} [entry.chrome] `'card'` when a mount-mode leaf draws no card of its own: a detail page then hosts it in the library card and hands it `onHeader(header)` to report its count, actions and empty state.
92
93
  * @param {(el: Element) => void} [entry.unmount] Teardown hand-off, called by the host before it removes the element and on surface hide / bound-object change. Travels as a pair with `mount`.
93
94
  *
94
95
  * @return {?object} Normalised entry, or null on collision / malformed mount pair in prod.
@@ -209,6 +210,9 @@ function createIntegrationRegistry() {
209
210
  // registration, with the tabbed panel silently keeping the sidebar
210
211
  // component.
211
212
  bareWidget: entry.bareWidget === true,
213
+ // `card`: a mount-mode leaf that draws no card of its own, so a
214
+ // detail page hosts it in the library card (CnDetailWidgetHost).
215
+ chrome: entry.chrome === 'card' ? 'card' : null,
212
216
  // Marker set by `registerBuiltinIntegrations` /
213
217
  // `registerLeafIntegrations` so `useIntegrationRegistry` can
214
218
  // distinguish lib-owned registrations (whose components must
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sources":["../../../src/integrations/registry.js"],"sourcesContent":["/**\n * Pluggable integration registry — JS surface.\n *\n * Provides the runtime that consuming apps use to register integration\n * tabs and widgets. The registry is reactive: subscribers via\n * `onChange()` are notified whenever a provider is registered or\n * unregistered, so list views (CnObjectSidebar, CnDashboardPage,\n * CnDetailPage) update without manual refresh.\n *\n * Per design.md (AD-13 collision policy, AD-19 surface fallback):\n * - tab + widget are REQUIRED at registration; missing throws\n * - duplicate id throws in dev, warns + keeps first in prod\n * - widgetCompact / widgetExpanded / widgetEntity are optional\n * - surfaces without a dedicated widget fall back to `widget`\n *\n * The OpenRegister app's main bundle attaches a singleton to\n * `window.OCA.OpenRegister.integrations`. Consuming apps load after\n * and call `register(...)`; if they load before, the shim queues\n * calls and replays them when the real registry initialises.\n *\n * @module integrations/registry\n */\n\n/*\n * `process.env.NODE_ENV` is not a runtime global in the browser: every\n * consuming app's bundler substitutes it at build time (webpack's\n * DefinePlugin, rollup's replace). Declared here so the reference is\n * described rather than assumed.\n */\n/* global process */\n\nconst DEV = process.env.NODE_ENV !== 'production'\n\nconst VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity']\n\n/**\n * Create a fresh integration registry instance.\n *\n * Most callers want the default singleton exported as `integrations` —\n * use this factory only when you need an isolated registry (e.g. in\n * unit tests) so registrations don't leak across cases.\n *\n * @return {object} Registry API.\n */\nexport function createIntegrationRegistry() {\n\tconst providers = new Map()\n\tconst listeners = new Set()\n\n\tfunction notify() {\n\t\tconst snapshot = list()\n\t\tfor (const fn of listeners) {\n\t\t\ttry {\n\t\t\t\tfn(snapshot)\n\t\t\t} catch (e) {\n\t\t\t\t// One bad subscriber shouldn't take down the rest of\n\t\t\t\t// the chain. Surface in dev so it gets noticed.\n\t\t\t\tif (DEV) {\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.error('[integrations] onChange subscriber threw', e)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Register an integration. Returns the registered descriptor on\n\t * success; returns `null` (and warns) on collision in production.\n\t *\n\t * @param {object} entry Integration descriptor — see design.md.\n\t * @param {string} entry.id Stable provider id (matches PHP-side).\n\t * @param {string} entry.label Human-readable label (already translated).\n\t * @param {string} [entry.icon] MDI icon name.\n\t * @param {string} [entry.requiredApp] Required Nextcloud app id.\n\t * @param {number} [entry.order] Numeric ordering hint (default 100).\n\t * @param {?string} [entry.group] Named group (core/comms/docs/workflow/external).\n\t * @param {?string} [entry.requiresPermission] Permission string.\n\t * @param {?string} [entry.referenceType] Marker for schema property targeting.\n\t * @param {object} [entry.tab] Vue component for the sidebar tab — REQUIRED in `component` mode; optional (same-major fast path) in `mount` mode.\n\t * @param {object} [entry.widget] Vue component for dashboard/detail surfaces — REQUIRED in `component` mode; optional (same-major fast path) in `mount` mode.\n\t * @param {object} [entry.widgetCompact] Override for `user-dashboard` surface.\n\t * @param {object} [entry.widgetExpanded] Override for `detail-page` surface.\n\t * @param {object} [entry.widgetEntity] Override for `single-entity` surface.\n\t * @param {object} [entry.defaultSize] Default grid dimensions `{w, h}`.\n\t * @param {string[]} [entry.surfaces] Explicit surface allowlist; when omitted the integration is eligible for every surface (CnIntegrationWidget contract).\n\t * @param {?boolean} [entry.available] Backing-app availability hint (true/false); null when unknown — the widget then resolves availability from the OCS capability / isAppInstalled fallback.\n\t * @param {?string} [entry.accentColor] Per-app brand accent hex (e.g. Deck's `#0082c9`) used by CnIntegrationWidget for the tab/header tint. Per-app waves fill these in.\n\t * @param {?string} [entry.appName] Human-readable backing-app name for empty-state copy (\"{App} not available\"); defaults to `label` when omitted.\n\t * @param {?string} [entry.docsUrl] Setup-docs URL for the empty state; defaults to `https://openregister.conduction.nl/docs/Integrations/{id}/`.\n\t * @param {?object} [entry.offlineConfig] Opaque per-integration config bag forwarded verbatim to the integration's components (e.g. the field-inspection leaf's offline schema/filter config). A consuming app overrides it by pre-registering the same id.\n\t * @param {'component'|'mount'} [entry.renderMode] Render strategy (openregister#2127 / ADR-066). `'component'` (default) interprets the SFC `tab`/`widget` under the host's own Vue runtime. `'mount'` hands the leaf a bare host-owned DOM element via `mount`/`unmount`, so a leaf built against a different Vue major than the host renders its own framework instance inside that element.\n\t * @param {(el: Element, props: object) => void} [entry.mount] Mount hand-off. Required together with `unmount` when `renderMode` is `'mount'`; the host calls it against a bare element with the same context an SFC widget/tab receives (`{ register, schema, objectId, surface, integrationContext, … }`). May also be supplied alongside an SFC pair as a same-major fast path.\n\t * @param {(el: Element) => void} [entry.unmount] Teardown hand-off, called by the host before it removes the element and on surface hide / bound-object change. Travels as a pair with `mount`.\n\t *\n\t * @return {?object} Normalised entry, or null on collision / malformed mount pair in prod.\n\t */\n\tfunction register(entry) {\n\t\tif (entry === null || typeof entry !== 'object') {\n\t\t\tthrow new TypeError('[integrations] register() requires an object descriptor')\n\t\t}\n\t\tif (typeof entry.id !== 'string' || entry.id === '') {\n\t\t\tthrow new TypeError('[integrations] register() requires a non-empty string `id`')\n\t\t}\n\t\tif (typeof entry.label !== 'string' || entry.label === '') {\n\t\t\tthrow new TypeError(`[integrations] integration \"${entry.id}\" requires a non-empty string \\`label\\``)\n\t\t}\n\t\t// renderMode gates which render pair is required (openregister#2127,\n\t\t// ADR-066). `component` (default) keeps the SFC contract — tab +\n\t\t// widget interpreted under the host's Vue. `mount` swaps in a\n\t\t// mount/unmount DOM hand-off so a cross-Vue-major leaf renders its\n\t\t// own framework instance; tab/widget become an optional same-major\n\t\t// fast path.\n\t\tconst renderMode = (entry.renderMode === undefined || entry.renderMode === null)\n\t\t\t? 'component'\n\t\t\t: entry.renderMode\n\t\tif (renderMode !== 'component' && renderMode !== 'mount') {\n\t\t\tthrow new TypeError(`[integrations] integration \"${entry.id}\" has invalid \\`renderMode\\` \"${entry.renderMode}\" — expected 'component' or 'mount'`)\n\t\t}\n\n\t\tconst hasMount = typeof entry.mount === 'function'\n\t\tconst hasUnmount = typeof entry.unmount === 'function'\n\n\t\t// The mount pair travels together — supplying one half without the\n\t\t// other is invalid in either render mode. Mirror the AD-13 duplicate\n\t\t// policy: throw in dev, warn-and-drop in prod.\n\t\tif (hasMount !== hasUnmount) {\n\t\t\tconst message = `[integrations] integration \"${entry.id}\" supplies only one of \\`mount\\`/\\`unmount\\` — the mount pair must travel together`\n\t\t\tif (DEV) {\n\t\t\t\tthrow new Error(message)\n\t\t\t}\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(message)\n\t\t\treturn null\n\t\t}\n\n\t\tif (renderMode === 'mount') {\n\t\t\t// mount mode: the mount pair is the render artefact; tab/widget\n\t\t\t// are optional. A missing pair is a malformed descriptor.\n\t\t\tif (hasMount === false) {\n\t\t\t\tconst message = `[integrations] integration \"${entry.id}\" declares renderMode 'mount' but is missing the \\`mount\\`/\\`unmount\\` pair`\n\t\t\t\tif (DEV) {\n\t\t\t\t\tthrow new Error(message)\n\t\t\t\t}\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(message)\n\t\t\t\treturn null\n\t\t\t}\n\t\t} else {\n\t\t\t// component mode: the SFC pair is required, exactly as before.\n\t\t\tif (entry.tab === undefined || entry.tab === null) {\n\t\t\t\tthrow new TypeError(`[integrations] integration \"${entry.id}\" is missing required \\`tab\\` component`)\n\t\t\t}\n\t\t\tif (entry.widget === undefined || entry.widget === null) {\n\t\t\t\tthrow new TypeError(`[integrations] integration \"${entry.id}\" is missing required \\`widget\\` component`)\n\t\t\t}\n\t\t}\n\n\t\tif (providers.has(entry.id)) {\n\t\t\tconst message = `[integrations] duplicate registration for \"${entry.id}\" — first call wins`\n\t\t\tif (DEV) {\n\t\t\t\tthrow new Error(message)\n\t\t\t}\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(message)\n\t\t\treturn null\n\t\t}\n\n\t\tconst normalised = {\n\t\t\tid: entry.id,\n\t\t\tlabel: entry.label,\n\t\t\ticon: entry.icon || null,\n\t\t\trequiredApp: entry.requiredApp || null,\n\t\t\torder: typeof entry.order === 'number' ? entry.order : 100,\n\t\t\tgroup: entry.group || null,\n\t\t\trequiresPermission: entry.requiresPermission || null,\n\t\t\treferenceType: entry.referenceType || null,\n\t\t\t// Render strategy + the mount hand-off pair (openregister#2127).\n\t\t\t// `tab`/`widget` are null when a mount-mode leaf omits the SFC\n\t\t\t// fast path; `mount`/`unmount` are null for component-mode leaves.\n\t\t\trenderMode,\n\t\t\tmount: hasMount ? entry.mount : null,\n\t\t\tunmount: hasUnmount ? entry.unmount : null,\n\t\t\ttab: entry.tab || null,\n\t\t\twidget: entry.widget || null,\n\t\t\twidgetCompact: entry.widgetCompact || null,\n\t\t\twidgetExpanded: entry.widgetExpanded || null,\n\t\t\twidgetEntity: entry.widgetEntity || null,\n\t\t\tdefaultSize: entry.defaultSize || null,\n\t\t\t// CnIntegrationWidget contract fields (Phase: integration-widget-framework).\n\t\t\t// `surfaces` stays undefined-as-null so consumers can treat\n\t\t\t// \"no allowlist\" as \"eligible everywhere\".\n\t\t\tsurfaces: Array.isArray(entry.surfaces) ? entry.surfaces.slice() : null,\n\t\t\tavailable: typeof entry.available === 'boolean' ? entry.available : null,\n\t\t\taccentColor: typeof entry.accentColor === 'string' && entry.accentColor !== '' ? entry.accentColor : null,\n\t\t\tappName: typeof entry.appName === 'string' && entry.appName !== '' ? entry.appName : entry.label,\n\t\t\tdocsUrl: typeof entry.docsUrl === 'string' && entry.docsUrl !== ''\n\t\t\t\t? entry.docsUrl\n\t\t\t\t: `https://openregister.conduction.nl/docs/Integrations/${entry.id}/`,\n\t\t\t// Opaque per-integration config bag. The registry does not interpret\n\t\t\t// it — it is forwarded verbatim so an integration's components can\n\t\t\t// read their own settings (e.g. the field-inspection leaf's offline\n\t\t\t// schema/filter config) and a consuming app can override it by\n\t\t\t// pre-registering the same id with its own `offlineConfig`.\n\t\t\tofflineConfig: (entry.offlineConfig && typeof entry.offlineConfig === 'object') ? entry.offlineConfig : null,\n\t\t\t// Whether this provider's WIDGET is already bare, so a tab panel\n\t\t\t// gets it instead of the sidebar `tab`. This normaliser copies a\n\t\t\t// fixed key list and drops everything else, so a descriptor key\n\t\t\t// that is not named here never reaches a consumer: the flag was set\n\t\t\t// on the notes descriptor, survived the build, and vanished at\n\t\t\t// registration, with the tabbed panel silently keeping the sidebar\n\t\t\t// component.\n\t\t\tbareWidget: entry.bareWidget === true,\n\t\t\t// Marker set by `registerBuiltinIntegrations` /\n\t\t\t// `registerLeafIntegrations` so `useIntegrationRegistry` can\n\t\t\t// distinguish lib-owned registrations (whose components must\n\t\t\t// resolve locally per render-bundle to avoid the ADR-019\n\t\t\t// cross-Vue trap, openregister#1958) from consumer-custom\n\t\t\t// registrations (whose components live in the consumer's own\n\t\t\t// bundle and must NOT be swapped).\n\t\t\t__libOwned: entry.__libOwned === true,\n\t\t}\n\t\tproviders.set(entry.id, normalised)\n\t\tnotify()\n\t\treturn normalised\n\t}\n\n\t/**\n\t * Remove a previously registered integration.\n\t *\n\t * @param {string} id Integration id.\n\t *\n\t * @return {boolean} True if removed.\n\t */\n\tfunction unregister(id) {\n\t\tconst removed = providers.delete(id)\n\t\tif (removed) {\n\t\t\tnotify()\n\t\t}\n\t\treturn removed\n\t}\n\n\t/**\n\t * Snapshot of all currently registered integrations, sorted by\n\t * `order` ascending then `id` ascending for stable rendering.\n\t *\n\t * @return {object[]} Array of normalised entries.\n\t */\n\tfunction list() {\n\t\treturn Array.from(providers.values()).sort((a, b) => {\n\t\t\tif (a.order !== b.order) {\n\t\t\t\treturn a.order - b.order\n\t\t\t}\n\t\t\treturn a.id.localeCompare(b.id)\n\t\t})\n\t}\n\n\t/**\n\t * Get a single integration by id.\n\t *\n\t * @param {string} id Integration id.\n\t *\n\t * @return {?object} The entry, or null if not registered.\n\t */\n\tfunction get(id) {\n\t\treturn providers.get(id) || null\n\t}\n\n\t/**\n\t * Check whether an id is currently registered.\n\t *\n\t * @param {string} id Integration id.\n\t *\n\t * @return {boolean} True if registered.\n\t */\n\tfunction has(id) {\n\t\treturn providers.has(id)\n\t}\n\n\t/**\n\t * Resolve the widget component for a specific surface, applying\n\t * the AD-19 fallback rule: surface-specific override wins, else\n\t * the main `widget`.\n\t *\n\t * @param {string} id Integration id.\n\t * @param {string} surface Surface name (see VALID_SURFACES).\n\t *\n\t * @return {?object} The Vue component, or null when unknown id.\n\t */\n\tfunction resolveWidget(id, surface) {\n\t\tconst entry = providers.get(id)\n\t\tif (entry === undefined) {\n\t\t\treturn null\n\t\t}\n\t\tif (DEV && !VALID_SURFACES.includes(surface)) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[integrations] unknown surface \"${surface}\" — falling back to default widget`)\n\t\t}\n\t\tif (surface === 'user-dashboard' && entry.widgetCompact !== null) {\n\t\t\treturn entry.widgetCompact\n\t\t}\n\t\tif (surface === 'detail-page' && entry.widgetExpanded !== null) {\n\t\t\treturn entry.widgetExpanded\n\t\t}\n\t\tif (surface === 'single-entity' && entry.widgetEntity !== null) {\n\t\t\treturn entry.widgetEntity\n\t\t}\n\t\treturn entry.widget\n\t}\n\n\t/**\n\t * Subscribe to registry changes. Subscriber receives the current\n\t * snapshot on each register/unregister.\n\t *\n\t * @param {(snapshot: object[]) => void} fn Listener callback.\n\t *\n\t * @return {() => boolean} Unsubscribe function.\n\t */\n\tfunction onChange(fn) {\n\t\tif (typeof fn !== 'function') {\n\t\t\tthrow new TypeError('[integrations] onChange() requires a function')\n\t\t}\n\t\tlisteners.add(fn)\n\t\treturn () => listeners.delete(fn)\n\t}\n\n\t/**\n\t * Test seam: clear all providers and listeners. Not exported on\n\t * the public window shim.\n\t *\n\t * @return {void}\n\t */\n\tfunction __resetForTests() {\n\t\tproviders.clear()\n\t\tlisteners.clear()\n\t}\n\n\treturn {\n\t\tregister,\n\t\tunregister,\n\t\tlist,\n\t\tget,\n\t\thas,\n\t\tresolveWidget,\n\t\tonChange,\n\t\t__resetForTests,\n\t}\n}\n\n/**\n * Default singleton — call sites that don't need test isolation\n * should import this directly.\n */\nexport const integrations = createIntegrationRegistry()\n\n/**\n * Install the singleton onto `window.OCA.OpenRegister.integrations`\n * and drain any calls that were queued by a stub before this\n * module loaded.\n *\n * Consuming apps that load before OpenRegister's main bundle install\n * a stub like:\n *\n * window.OCA = window.OCA || {}\n * window.OCA.OpenRegister = window.OCA.OpenRegister || {}\n * window.OCA.OpenRegister.integrations = window.OCA.OpenRegister.integrations || {\n * _queue: [],\n * register(entry) { this._queue.push(entry) },\n * }\n *\n * When the real registry installs, queued entries are replayed in\n * insertion order. This makes bootstrap order forgiving.\n *\n * @param {object} [globalRef] Global to attach to (defaults to `window`; pass an override for tests).\n *\n * @return {object} The installed registry.\n */\nexport function installIntegrationRegistry(globalRef) {\n\tconst target = globalRef || (typeof window !== 'undefined' ? window : null)\n\tif (target === null) {\n\t\treturn integrations\n\t}\n\ttarget.OCA = target.OCA || {}\n\ttarget.OCA.OpenRegister = target.OCA.OpenRegister || {}\n\n\tconst prior = target.OCA.OpenRegister.integrations\n\n\t// Converge, don't clobber. If another bundle already installed a REAL\n\t// registry (has register(), no _queue), every later caller CONVERGES\n\t// on that same object — otherwise each app's bundle would install its\n\t// own per-bundle singleton and a consuming app's useIntegrationRegistry\n\t// would read an empty registry while a leaf registered into a\n\t// different one. First bundle to install wins; all others share it.\n\tif (prior !== undefined\n\t\t&& prior !== integrations\n\t\t&& typeof prior.register === 'function'\n\t\t&& prior._queue === undefined) {\n\t\treturn prior\n\t}\n\n\ttarget.OCA.OpenRegister.integrations = integrations\n\n\tif (prior !== undefined && Array.isArray(prior._queue) === true) {\n\t\tfor (const queued of prior._queue) {\n\t\t\ttry {\n\t\t\t\tintegrations.register(queued)\n\t\t\t} catch (e) {\n\t\t\t\tif (DEV) {\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.error('[integrations] failed to replay queued registration', queued, e)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn integrations\n}\n\n/**\n * Read the shared registry IF one is already installed on the global —\n * WITHOUT installing or mutating anything.\n *\n * Used by `useIntegrationRegistry` so a consuming app reads the same\n * registry OpenRegister's global bootstrap populated, instead of its own\n * per-bundle module singleton. Returns null when no real registry is\n * installed yet (a bare stub queue does NOT count) so callers fall back\n * to the module singleton — keeping unit tests that never install a\n * global on the module-singleton path.\n *\n * @param {object} [globalRef] Global to read. Defaults to `window`.\n * @return {object|null} The installed shared registry, or null.\n */\nexport function sharedRegistryIfInstalled(globalRef) {\n\tconst target = globalRef || (typeof window !== 'undefined' ? window : null)\n\tif (target === null) {\n\t\treturn null\n\t}\n\tconst g = target.OCA && target.OCA.OpenRegister && target.OCA.OpenRegister.integrations\n\tif (g && typeof g.register === 'function' && g._queue === undefined) {\n\t\treturn g\n\t}\n\treturn null\n}\n\n/**\n * Resolve the canonical shared registry, INSTALLING the module singleton\n * onto the global when none exists yet (and draining any stub queue).\n *\n * This is the entry point OpenRegister's global bootstrap uses so that\n * `registerBuiltinIntegrations` / `registerLeafIntegrations` /\n * `registerIntegrationIcons` all populate the one shared registry every\n * consuming app reads via `useIntegrationRegistry`. Idempotent.\n *\n * @param {object} [globalRef] Global to resolve against. Defaults to `window`.\n * @return {object} The shared registry (always a real registry instance).\n */\nexport function getSharedRegistry(globalRef) {\n\tconst existing = sharedRegistryIfInstalled(globalRef)\n\tif (existing !== null) {\n\t\treturn existing\n\t}\n\treturn installIntegrationRegistry(globalRef)\n}\n\n/**\n * Load-order-safe registration entry point for a LEAF app's bespoke\n * integration component (Path 2).\n *\n * This is the symmetric counterpart to `installIntegrationRegistry`,\n * which OpenRegister calls to install its singleton. A leaf app must\n * NOT call `installIntegrationRegistry` — that replaces the global with\n * OR's singleton and would clobber it. Instead the leaf ships a small\n * bundle, loaded globally on every Nextcloud page via the app's own\n * `\\OCP\\Util::addInitScript()`, that calls `registerIntegration()`.\n *\n * Behaviour by load order:\n * - OR already installed its singleton → register the descriptor live;\n * it appears in `integrations.list()` immediately.\n * - OR not loaded yet (this leaf, or another leaf, ran first) →\n * install/extend a `{ _queue, register }` stub on\n * `window.OCA.OpenRegister.integrations` and push the descriptor. OR\n * replays the queue when it later calls `installIntegrationRegistry`.\n *\n * Validation, collision policy (AD-13), required `tab`/`widget`, and\n * `referenceType` defaulting are unchanged — they apply identically\n * whether the call lands live or via replay, because both paths funnel\n * through the same `register()`.\n *\n * @param {object} descriptor The integration descriptor (same shape as\n * `integrations.register()` — id, label, icon, tab, widget, etc.).\n * @param {object} [globalRef] Global object to attach to. Defaults to\n * `window`. Injectable for tests / SSR.\n * @return {void}\n */\nexport function registerIntegration(descriptor, globalRef) {\n\tconst target = globalRef || (typeof window !== 'undefined' ? window : null)\n\tif (target === null) {\n\t\t// No global (SSR / non-browser) — register on the module singleton\n\t\t// directly so unit tests and isomorphic callers still work.\n\t\tintegrations.register(descriptor)\n\t\treturn\n\t}\n\n\ttarget.OCA = target.OCA || {}\n\ttarget.OCA.OpenRegister = target.OCA.OpenRegister || {}\n\tconst current = target.OCA.OpenRegister.integrations\n\n\t// OR's real singleton is installed when the global exposes `register`\n\t// and carries NO `_queue` (only the stub has a `_queue`).\n\tif (current === integrations || (current && typeof current.register === 'function' && current._queue === undefined)) {\n\t\tcurrent.register(descriptor)\n\t\treturn\n\t}\n\n\t// Not installed yet — ensure a queue stub exists, then enqueue.\n\tif (current === undefined || current === null) {\n\t\ttarget.OCA.OpenRegister.integrations = {\n\t\t\t_queue: [],\n\t\t\tregister(entry) {\n\t\t\t\tthis._queue.push(entry)\n\t\t\t},\n\t\t}\n\t}\n\ttarget.OCA.OpenRegister.integrations.register(descriptor)\n}\n\nexport { VALID_SURFACES }\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sources":["../../../src/integrations/registry.js"],"sourcesContent":["/**\n * Pluggable integration registry — JS surface.\n *\n * Provides the runtime that consuming apps use to register integration\n * tabs and widgets. The registry is reactive: subscribers via\n * `onChange()` are notified whenever a provider is registered or\n * unregistered, so list views (CnObjectSidebar, CnDashboardPage,\n * CnDetailPage) update without manual refresh.\n *\n * Per design.md (AD-13 collision policy, AD-19 surface fallback):\n * - tab + widget are REQUIRED at registration; missing throws\n * - duplicate id throws in dev, warns + keeps first in prod\n * - widgetCompact / widgetExpanded / widgetEntity are optional\n * - surfaces without a dedicated widget fall back to `widget`\n *\n * The OpenRegister app's main bundle attaches a singleton to\n * `window.OCA.OpenRegister.integrations`. Consuming apps load after\n * and call `register(...)`; if they load before, the shim queues\n * calls and replays them when the real registry initialises.\n *\n * @module integrations/registry\n */\n\n/*\n * `process.env.NODE_ENV` is not a runtime global in the browser: every\n * consuming app's bundler substitutes it at build time (webpack's\n * DefinePlugin, rollup's replace). Declared here so the reference is\n * described rather than assumed.\n */\n/* global process */\n\nconst DEV = process.env.NODE_ENV !== 'production'\n\nconst VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity']\n\n/**\n * Create a fresh integration registry instance.\n *\n * Most callers want the default singleton exported as `integrations` —\n * use this factory only when you need an isolated registry (e.g. in\n * unit tests) so registrations don't leak across cases.\n *\n * @return {object} Registry API.\n */\nexport function createIntegrationRegistry() {\n\tconst providers = new Map()\n\tconst listeners = new Set()\n\n\tfunction notify() {\n\t\tconst snapshot = list()\n\t\tfor (const fn of listeners) {\n\t\t\ttry {\n\t\t\t\tfn(snapshot)\n\t\t\t} catch (e) {\n\t\t\t\t// One bad subscriber shouldn't take down the rest of\n\t\t\t\t// the chain. Surface in dev so it gets noticed.\n\t\t\t\tif (DEV) {\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.error('[integrations] onChange subscriber threw', e)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Register an integration. Returns the registered descriptor on\n\t * success; returns `null` (and warns) on collision in production.\n\t *\n\t * @param {object} entry Integration descriptor — see design.md.\n\t * @param {string} entry.id Stable provider id (matches PHP-side).\n\t * @param {string} entry.label Human-readable label (already translated).\n\t * @param {string} [entry.icon] MDI icon name.\n\t * @param {string} [entry.requiredApp] Required Nextcloud app id.\n\t * @param {number} [entry.order] Numeric ordering hint (default 100).\n\t * @param {?string} [entry.group] Named group (core/comms/docs/workflow/external).\n\t * @param {?string} [entry.requiresPermission] Permission string.\n\t * @param {?string} [entry.referenceType] Marker for schema property targeting.\n\t * @param {object} [entry.tab] Vue component for the sidebar tab — REQUIRED in `component` mode; optional (same-major fast path) in `mount` mode.\n\t * @param {object} [entry.widget] Vue component for dashboard/detail surfaces — REQUIRED in `component` mode; optional (same-major fast path) in `mount` mode.\n\t * @param {object} [entry.widgetCompact] Override for `user-dashboard` surface.\n\t * @param {object} [entry.widgetExpanded] Override for `detail-page` surface.\n\t * @param {object} [entry.widgetEntity] Override for `single-entity` surface.\n\t * @param {object} [entry.defaultSize] Default grid dimensions `{w, h}`.\n\t * @param {string[]} [entry.surfaces] Explicit surface allowlist; when omitted the integration is eligible for every surface (CnIntegrationWidget contract).\n\t * @param {?boolean} [entry.available] Backing-app availability hint (true/false); null when unknown — the widget then resolves availability from the OCS capability / isAppInstalled fallback.\n\t * @param {?string} [entry.accentColor] Per-app brand accent hex (e.g. Deck's `#0082c9`) used by CnIntegrationWidget for the tab/header tint. Per-app waves fill these in.\n\t * @param {?string} [entry.appName] Human-readable backing-app name for empty-state copy (\"{App} not available\"); defaults to `label` when omitted.\n\t * @param {?string} [entry.docsUrl] Setup-docs URL for the empty state; defaults to `https://openregister.conduction.nl/docs/Integrations/{id}/`.\n\t * @param {?object} [entry.offlineConfig] Opaque per-integration config bag forwarded verbatim to the integration's components (e.g. the field-inspection leaf's offline schema/filter config). A consuming app overrides it by pre-registering the same id.\n\t * @param {'component'|'mount'} [entry.renderMode] Render strategy (openregister#2127 / ADR-066). `'component'` (default) interprets the SFC `tab`/`widget` under the host's own Vue runtime. `'mount'` hands the leaf a bare host-owned DOM element via `mount`/`unmount`, so a leaf built against a different Vue major than the host renders its own framework instance inside that element.\n\t * @param {(el: Element, props: object) => void} [entry.mount] Mount hand-off. Required together with `unmount` when `renderMode` is `'mount'`; the host calls it against a bare element with the same context an SFC widget/tab receives (`{ register, schema, objectId, surface, integrationContext, … }`). May also be supplied alongside an SFC pair as a same-major fast path.\n\t * @param {'card'} [entry.chrome] `'card'` when a mount-mode leaf draws no card of its own: a detail page then hosts it in the library card and hands it `onHeader(header)` to report its count, actions and empty state.\n\t * @param {(el: Element) => void} [entry.unmount] Teardown hand-off, called by the host before it removes the element and on surface hide / bound-object change. Travels as a pair with `mount`.\n\t *\n\t * @return {?object} Normalised entry, or null on collision / malformed mount pair in prod.\n\t */\n\tfunction register(entry) {\n\t\tif (entry === null || typeof entry !== 'object') {\n\t\t\tthrow new TypeError('[integrations] register() requires an object descriptor')\n\t\t}\n\t\tif (typeof entry.id !== 'string' || entry.id === '') {\n\t\t\tthrow new TypeError('[integrations] register() requires a non-empty string `id`')\n\t\t}\n\t\tif (typeof entry.label !== 'string' || entry.label === '') {\n\t\t\tthrow new TypeError(`[integrations] integration \"${entry.id}\" requires a non-empty string \\`label\\``)\n\t\t}\n\t\t// renderMode gates which render pair is required (openregister#2127,\n\t\t// ADR-066). `component` (default) keeps the SFC contract — tab +\n\t\t// widget interpreted under the host's Vue. `mount` swaps in a\n\t\t// mount/unmount DOM hand-off so a cross-Vue-major leaf renders its\n\t\t// own framework instance; tab/widget become an optional same-major\n\t\t// fast path.\n\t\tconst renderMode = (entry.renderMode === undefined || entry.renderMode === null)\n\t\t\t? 'component'\n\t\t\t: entry.renderMode\n\t\tif (renderMode !== 'component' && renderMode !== 'mount') {\n\t\t\tthrow new TypeError(`[integrations] integration \"${entry.id}\" has invalid \\`renderMode\\` \"${entry.renderMode}\" — expected 'component' or 'mount'`)\n\t\t}\n\n\t\tconst hasMount = typeof entry.mount === 'function'\n\t\tconst hasUnmount = typeof entry.unmount === 'function'\n\n\t\t// The mount pair travels together — supplying one half without the\n\t\t// other is invalid in either render mode. Mirror the AD-13 duplicate\n\t\t// policy: throw in dev, warn-and-drop in prod.\n\t\tif (hasMount !== hasUnmount) {\n\t\t\tconst message = `[integrations] integration \"${entry.id}\" supplies only one of \\`mount\\`/\\`unmount\\` — the mount pair must travel together`\n\t\t\tif (DEV) {\n\t\t\t\tthrow new Error(message)\n\t\t\t}\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(message)\n\t\t\treturn null\n\t\t}\n\n\t\tif (renderMode === 'mount') {\n\t\t\t// mount mode: the mount pair is the render artefact; tab/widget\n\t\t\t// are optional. A missing pair is a malformed descriptor.\n\t\t\tif (hasMount === false) {\n\t\t\t\tconst message = `[integrations] integration \"${entry.id}\" declares renderMode 'mount' but is missing the \\`mount\\`/\\`unmount\\` pair`\n\t\t\t\tif (DEV) {\n\t\t\t\t\tthrow new Error(message)\n\t\t\t\t}\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(message)\n\t\t\t\treturn null\n\t\t\t}\n\t\t} else {\n\t\t\t// component mode: the SFC pair is required, exactly as before.\n\t\t\tif (entry.tab === undefined || entry.tab === null) {\n\t\t\t\tthrow new TypeError(`[integrations] integration \"${entry.id}\" is missing required \\`tab\\` component`)\n\t\t\t}\n\t\t\tif (entry.widget === undefined || entry.widget === null) {\n\t\t\t\tthrow new TypeError(`[integrations] integration \"${entry.id}\" is missing required \\`widget\\` component`)\n\t\t\t}\n\t\t}\n\n\t\tif (providers.has(entry.id)) {\n\t\t\tconst message = `[integrations] duplicate registration for \"${entry.id}\" — first call wins`\n\t\t\tif (DEV) {\n\t\t\t\tthrow new Error(message)\n\t\t\t}\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(message)\n\t\t\treturn null\n\t\t}\n\n\t\tconst normalised = {\n\t\t\tid: entry.id,\n\t\t\tlabel: entry.label,\n\t\t\ticon: entry.icon || null,\n\t\t\trequiredApp: entry.requiredApp || null,\n\t\t\torder: typeof entry.order === 'number' ? entry.order : 100,\n\t\t\tgroup: entry.group || null,\n\t\t\trequiresPermission: entry.requiresPermission || null,\n\t\t\treferenceType: entry.referenceType || null,\n\t\t\t// Render strategy + the mount hand-off pair (openregister#2127).\n\t\t\t// `tab`/`widget` are null when a mount-mode leaf omits the SFC\n\t\t\t// fast path; `mount`/`unmount` are null for component-mode leaves.\n\t\t\trenderMode,\n\t\t\tmount: hasMount ? entry.mount : null,\n\t\t\tunmount: hasUnmount ? entry.unmount : null,\n\t\t\ttab: entry.tab || null,\n\t\t\twidget: entry.widget || null,\n\t\t\twidgetCompact: entry.widgetCompact || null,\n\t\t\twidgetExpanded: entry.widgetExpanded || null,\n\t\t\twidgetEntity: entry.widgetEntity || null,\n\t\t\tdefaultSize: entry.defaultSize || null,\n\t\t\t// CnIntegrationWidget contract fields (Phase: integration-widget-framework).\n\t\t\t// `surfaces` stays undefined-as-null so consumers can treat\n\t\t\t// \"no allowlist\" as \"eligible everywhere\".\n\t\t\tsurfaces: Array.isArray(entry.surfaces) ? entry.surfaces.slice() : null,\n\t\t\tavailable: typeof entry.available === 'boolean' ? entry.available : null,\n\t\t\taccentColor: typeof entry.accentColor === 'string' && entry.accentColor !== '' ? entry.accentColor : null,\n\t\t\tappName: typeof entry.appName === 'string' && entry.appName !== '' ? entry.appName : entry.label,\n\t\t\tdocsUrl: typeof entry.docsUrl === 'string' && entry.docsUrl !== ''\n\t\t\t\t? entry.docsUrl\n\t\t\t\t: `https://openregister.conduction.nl/docs/Integrations/${entry.id}/`,\n\t\t\t// Opaque per-integration config bag. The registry does not interpret\n\t\t\t// it — it is forwarded verbatim so an integration's components can\n\t\t\t// read their own settings (e.g. the field-inspection leaf's offline\n\t\t\t// schema/filter config) and a consuming app can override it by\n\t\t\t// pre-registering the same id with its own `offlineConfig`.\n\t\t\tofflineConfig: (entry.offlineConfig && typeof entry.offlineConfig === 'object') ? entry.offlineConfig : null,\n\t\t\t// Whether this provider's WIDGET is already bare, so a tab panel\n\t\t\t// gets it instead of the sidebar `tab`. This normaliser copies a\n\t\t\t// fixed key list and drops everything else, so a descriptor key\n\t\t\t// that is not named here never reaches a consumer: the flag was set\n\t\t\t// on the notes descriptor, survived the build, and vanished at\n\t\t\t// registration, with the tabbed panel silently keeping the sidebar\n\t\t\t// component.\n\t\t\tbareWidget: entry.bareWidget === true,\n\t\t\t// `card`: a mount-mode leaf that draws no card of its own, so a\n\t\t\t// detail page hosts it in the library card (CnDetailWidgetHost).\n\t\t\tchrome: entry.chrome === 'card' ? 'card' : null,\n\t\t\t// Marker set by `registerBuiltinIntegrations` /\n\t\t\t// `registerLeafIntegrations` so `useIntegrationRegistry` can\n\t\t\t// distinguish lib-owned registrations (whose components must\n\t\t\t// resolve locally per render-bundle to avoid the ADR-019\n\t\t\t// cross-Vue trap, openregister#1958) from consumer-custom\n\t\t\t// registrations (whose components live in the consumer's own\n\t\t\t// bundle and must NOT be swapped).\n\t\t\t__libOwned: entry.__libOwned === true,\n\t\t}\n\t\tproviders.set(entry.id, normalised)\n\t\tnotify()\n\t\treturn normalised\n\t}\n\n\t/**\n\t * Remove a previously registered integration.\n\t *\n\t * @param {string} id Integration id.\n\t *\n\t * @return {boolean} True if removed.\n\t */\n\tfunction unregister(id) {\n\t\tconst removed = providers.delete(id)\n\t\tif (removed) {\n\t\t\tnotify()\n\t\t}\n\t\treturn removed\n\t}\n\n\t/**\n\t * Snapshot of all currently registered integrations, sorted by\n\t * `order` ascending then `id` ascending for stable rendering.\n\t *\n\t * @return {object[]} Array of normalised entries.\n\t */\n\tfunction list() {\n\t\treturn Array.from(providers.values()).sort((a, b) => {\n\t\t\tif (a.order !== b.order) {\n\t\t\t\treturn a.order - b.order\n\t\t\t}\n\t\t\treturn a.id.localeCompare(b.id)\n\t\t})\n\t}\n\n\t/**\n\t * Get a single integration by id.\n\t *\n\t * @param {string} id Integration id.\n\t *\n\t * @return {?object} The entry, or null if not registered.\n\t */\n\tfunction get(id) {\n\t\treturn providers.get(id) || null\n\t}\n\n\t/**\n\t * Check whether an id is currently registered.\n\t *\n\t * @param {string} id Integration id.\n\t *\n\t * @return {boolean} True if registered.\n\t */\n\tfunction has(id) {\n\t\treturn providers.has(id)\n\t}\n\n\t/**\n\t * Resolve the widget component for a specific surface, applying\n\t * the AD-19 fallback rule: surface-specific override wins, else\n\t * the main `widget`.\n\t *\n\t * @param {string} id Integration id.\n\t * @param {string} surface Surface name (see VALID_SURFACES).\n\t *\n\t * @return {?object} The Vue component, or null when unknown id.\n\t */\n\tfunction resolveWidget(id, surface) {\n\t\tconst entry = providers.get(id)\n\t\tif (entry === undefined) {\n\t\t\treturn null\n\t\t}\n\t\tif (DEV && !VALID_SURFACES.includes(surface)) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[integrations] unknown surface \"${surface}\" — falling back to default widget`)\n\t\t}\n\t\tif (surface === 'user-dashboard' && entry.widgetCompact !== null) {\n\t\t\treturn entry.widgetCompact\n\t\t}\n\t\tif (surface === 'detail-page' && entry.widgetExpanded !== null) {\n\t\t\treturn entry.widgetExpanded\n\t\t}\n\t\tif (surface === 'single-entity' && entry.widgetEntity !== null) {\n\t\t\treturn entry.widgetEntity\n\t\t}\n\t\treturn entry.widget\n\t}\n\n\t/**\n\t * Subscribe to registry changes. Subscriber receives the current\n\t * snapshot on each register/unregister.\n\t *\n\t * @param {(snapshot: object[]) => void} fn Listener callback.\n\t *\n\t * @return {() => boolean} Unsubscribe function.\n\t */\n\tfunction onChange(fn) {\n\t\tif (typeof fn !== 'function') {\n\t\t\tthrow new TypeError('[integrations] onChange() requires a function')\n\t\t}\n\t\tlisteners.add(fn)\n\t\treturn () => listeners.delete(fn)\n\t}\n\n\t/**\n\t * Test seam: clear all providers and listeners. Not exported on\n\t * the public window shim.\n\t *\n\t * @return {void}\n\t */\n\tfunction __resetForTests() {\n\t\tproviders.clear()\n\t\tlisteners.clear()\n\t}\n\n\treturn {\n\t\tregister,\n\t\tunregister,\n\t\tlist,\n\t\tget,\n\t\thas,\n\t\tresolveWidget,\n\t\tonChange,\n\t\t__resetForTests,\n\t}\n}\n\n/**\n * Default singleton — call sites that don't need test isolation\n * should import this directly.\n */\nexport const integrations = createIntegrationRegistry()\n\n/**\n * Install the singleton onto `window.OCA.OpenRegister.integrations`\n * and drain any calls that were queued by a stub before this\n * module loaded.\n *\n * Consuming apps that load before OpenRegister's main bundle install\n * a stub like:\n *\n * window.OCA = window.OCA || {}\n * window.OCA.OpenRegister = window.OCA.OpenRegister || {}\n * window.OCA.OpenRegister.integrations = window.OCA.OpenRegister.integrations || {\n * _queue: [],\n * register(entry) { this._queue.push(entry) },\n * }\n *\n * When the real registry installs, queued entries are replayed in\n * insertion order. This makes bootstrap order forgiving.\n *\n * @param {object} [globalRef] Global to attach to (defaults to `window`; pass an override for tests).\n *\n * @return {object} The installed registry.\n */\nexport function installIntegrationRegistry(globalRef) {\n\tconst target = globalRef || (typeof window !== 'undefined' ? window : null)\n\tif (target === null) {\n\t\treturn integrations\n\t}\n\ttarget.OCA = target.OCA || {}\n\ttarget.OCA.OpenRegister = target.OCA.OpenRegister || {}\n\n\tconst prior = target.OCA.OpenRegister.integrations\n\n\t// Converge, don't clobber. If another bundle already installed a REAL\n\t// registry (has register(), no _queue), every later caller CONVERGES\n\t// on that same object — otherwise each app's bundle would install its\n\t// own per-bundle singleton and a consuming app's useIntegrationRegistry\n\t// would read an empty registry while a leaf registered into a\n\t// different one. First bundle to install wins; all others share it.\n\tif (prior !== undefined\n\t\t&& prior !== integrations\n\t\t&& typeof prior.register === 'function'\n\t\t&& prior._queue === undefined) {\n\t\treturn prior\n\t}\n\n\ttarget.OCA.OpenRegister.integrations = integrations\n\n\tif (prior !== undefined && Array.isArray(prior._queue) === true) {\n\t\tfor (const queued of prior._queue) {\n\t\t\ttry {\n\t\t\t\tintegrations.register(queued)\n\t\t\t} catch (e) {\n\t\t\t\tif (DEV) {\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.error('[integrations] failed to replay queued registration', queued, e)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn integrations\n}\n\n/**\n * Read the shared registry IF one is already installed on the global —\n * WITHOUT installing or mutating anything.\n *\n * Used by `useIntegrationRegistry` so a consuming app reads the same\n * registry OpenRegister's global bootstrap populated, instead of its own\n * per-bundle module singleton. Returns null when no real registry is\n * installed yet (a bare stub queue does NOT count) so callers fall back\n * to the module singleton — keeping unit tests that never install a\n * global on the module-singleton path.\n *\n * @param {object} [globalRef] Global to read. Defaults to `window`.\n * @return {object|null} The installed shared registry, or null.\n */\nexport function sharedRegistryIfInstalled(globalRef) {\n\tconst target = globalRef || (typeof window !== 'undefined' ? window : null)\n\tif (target === null) {\n\t\treturn null\n\t}\n\tconst g = target.OCA && target.OCA.OpenRegister && target.OCA.OpenRegister.integrations\n\tif (g && typeof g.register === 'function' && g._queue === undefined) {\n\t\treturn g\n\t}\n\treturn null\n}\n\n/**\n * Resolve the canonical shared registry, INSTALLING the module singleton\n * onto the global when none exists yet (and draining any stub queue).\n *\n * This is the entry point OpenRegister's global bootstrap uses so that\n * `registerBuiltinIntegrations` / `registerLeafIntegrations` /\n * `registerIntegrationIcons` all populate the one shared registry every\n * consuming app reads via `useIntegrationRegistry`. Idempotent.\n *\n * @param {object} [globalRef] Global to resolve against. Defaults to `window`.\n * @return {object} The shared registry (always a real registry instance).\n */\nexport function getSharedRegistry(globalRef) {\n\tconst existing = sharedRegistryIfInstalled(globalRef)\n\tif (existing !== null) {\n\t\treturn existing\n\t}\n\treturn installIntegrationRegistry(globalRef)\n}\n\n/**\n * Load-order-safe registration entry point for a LEAF app's bespoke\n * integration component (Path 2).\n *\n * This is the symmetric counterpart to `installIntegrationRegistry`,\n * which OpenRegister calls to install its singleton. A leaf app must\n * NOT call `installIntegrationRegistry` — that replaces the global with\n * OR's singleton and would clobber it. Instead the leaf ships a small\n * bundle, loaded globally on every Nextcloud page via the app's own\n * `\\OCP\\Util::addInitScript()`, that calls `registerIntegration()`.\n *\n * Behaviour by load order:\n * - OR already installed its singleton → register the descriptor live;\n * it appears in `integrations.list()` immediately.\n * - OR not loaded yet (this leaf, or another leaf, ran first) →\n * install/extend a `{ _queue, register }` stub on\n * `window.OCA.OpenRegister.integrations` and push the descriptor. OR\n * replays the queue when it later calls `installIntegrationRegistry`.\n *\n * Validation, collision policy (AD-13), required `tab`/`widget`, and\n * `referenceType` defaulting are unchanged — they apply identically\n * whether the call lands live or via replay, because both paths funnel\n * through the same `register()`.\n *\n * @param {object} descriptor The integration descriptor (same shape as\n * `integrations.register()` — id, label, icon, tab, widget, etc.).\n * @param {object} [globalRef] Global object to attach to. Defaults to\n * `window`. Injectable for tests / SSR.\n * @return {void}\n */\nexport function registerIntegration(descriptor, globalRef) {\n\tconst target = globalRef || (typeof window !== 'undefined' ? window : null)\n\tif (target === null) {\n\t\t// No global (SSR / non-browser) — register on the module singleton\n\t\t// directly so unit tests and isomorphic callers still work.\n\t\tintegrations.register(descriptor)\n\t\treturn\n\t}\n\n\ttarget.OCA = target.OCA || {}\n\ttarget.OCA.OpenRegister = target.OCA.OpenRegister || {}\n\tconst current = target.OCA.OpenRegister.integrations\n\n\t// OR's real singleton is installed when the global exposes `register`\n\t// and carries NO `_queue` (only the stub has a `_queue`).\n\tif (current === integrations || (current && typeof current.register === 'function' && current._queue === undefined)) {\n\t\tcurrent.register(descriptor)\n\t\treturn\n\t}\n\n\t// Not installed yet — ensure a queue stub exists, then enqueue.\n\tif (current === undefined || current === null) {\n\t\ttarget.OCA.OpenRegister.integrations = {\n\t\t\t_queue: [],\n\t\t\tregister(entry) {\n\t\t\t\tthis._queue.push(entry)\n\t\t\t},\n\t\t}\n\t}\n\ttarget.OCA.OpenRegister.integrations.register(descriptor)\n}\n\nexport { VALID_SURFACES }\n"],"names":[],"mappings":"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"}
@@ -1911,7 +1911,9 @@ var translations = {
1911
1911
  "New team": "New team",
1912
1912
  "Why it is moving": "Why it is moving",
1913
1913
  "Use \"{name}\"": "Use \"{name}\"",
1914
- "It was not handed over.": "It was not handed over."
1914
+ "It was not handed over.": "It was not handed over.",
1915
+ "This search could not be read.": "This search could not be read.",
1916
+ "{source} could not be searched, so this list may be incomplete.": "{source} could not be searched, so this list may be incomplete."
1915
1917
  };
1916
1918
  var plurals = {
1917
1919
  "{count} member": [
@@ -1 +1 @@
1
- {"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -2123,7 +2123,9 @@ var translations = {
2123
2123
  "New team": "Nieuw team",
2124
2124
  "Why it is moving": "Waarom het overgaat",
2125
2125
  "Use \"{name}\"": "\"{name}\" gebruiken",
2126
- "It was not handed over.": "Het is niet overgedragen."
2126
+ "It was not handed over.": "Het is niet overgedragen.",
2127
+ "This search could not be read.": "Deze zoekopdracht kon niet worden gelezen.",
2128
+ "{source} could not be searched, so this list may be incomplete.": "{source} kon niet worden doorzocht, dus deze lijst is mogelijk niet compleet."
2127
2129
  };
2128
2130
  var plurals = {
2129
2131
  "{count} member": [
@@ -1 +1 @@
1
- {"version":3,"file":"nl.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"nl.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}