@conduction/nextcloud-vue 2.124.0 → 2.125.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 (66) hide show
  1. package/dist/esm/components/CnActionDialog/CnActionDialog.vue.js +1 -1
  2. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js +120 -11
  3. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js.map +1 -1
  4. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js +78 -32
  5. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js.map +1 -1
  6. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +8 -7
  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 +2 -1
  11. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js.map +1 -1
  12. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js +2 -2
  13. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js.map +1 -1
  14. package/dist/esm/components/CnDialog/CnDialog.vue2.js +5 -0
  15. package/dist/esm/components/CnDialog/CnDialog.vue2.js.map +1 -1
  16. package/dist/esm/components/CnDialog/CnDialog.vue3.js +1 -1
  17. package/dist/esm/components/CnDialog/CnDialog.vue3.js.map +1 -1
  18. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +13 -0
  19. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  20. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +2 -1
  21. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  22. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
  23. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +7 -2
  24. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  25. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  26. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  27. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +159 -10
  28. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  29. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +151 -90
  30. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  31. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js +12 -0
  32. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js.map +1 -1
  33. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js +1 -1
  34. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js.map +1 -1
  35. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js +1 -1
  36. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js +39 -68
  37. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js.map +1 -1
  38. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js +70 -116
  39. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js.map +1 -1
  40. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
  41. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +19 -3
  42. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  43. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  44. package/dist/esm/l10n/en.json.js +8 -8
  45. package/dist/esm/l10n/nl.json.js +8 -8
  46. package/dist/esm/library-style.js +1 -1
  47. package/dist/esm/nextcloud-vue.css +316 -185
  48. package/dist/nextcloud-vue.cjs.js +1149 -808
  49. package/dist/nextcloud-vue.cjs.js.map +2 -2
  50. package/dist/nextcloud-vue.css +316 -185
  51. package/l10n/en.json +8 -8
  52. package/l10n/nl.json +8 -8
  53. package/package.json +1 -1
  54. package/src/components/CnActionDialog/CnActionDialog.vue +173 -14
  55. package/src/components/CnAppRoot/CnAppRoot.vue +8 -7
  56. package/src/components/CnAssignDialog/CnAssignDialog.vue +4 -3
  57. package/src/components/CnDialog/CnDialog.vue +6 -1
  58. package/src/components/CnIndexPage/CnIndexPage.vue +14 -0
  59. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +7 -2
  60. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +237 -23
  61. package/src/components/CnSavedViewsControl/CnSavedViewsControl.vue +13 -1
  62. package/src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue +147 -145
  63. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +19 -3
  64. package/src/css/dialog.css +23 -0
  65. package/src/css/look-board-index.css +5 -1
  66. package/src/css/look-board.css +19 -0
@@ -1 +1 @@
1
- {"version":3,"file":"CnSavedViewsControl.vue2.js","sources":["../../../../src/components/CnSavedViewsControl/CnSavedViewsControl.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<!--\n\t\tThe toolbar half of saved views. Under the board look the views are\n\t\ta row of chips that apply them; everywhere a \"Save view\" button saves\n\t\tthe current filters. Listing, editing, sharing and deleting live in the\n\t\tsidebar's Filters tab (CnSavedViewsPanel).\n\t-->\n\t<div\n\t\tv-if=\"isBoardLook && chipRows.length > 0\"\n\t\tclass=\"cn-saved-views__chips\"\n\t\trole=\"group\"\n\t\t:aria-label=\"t('nextcloud-vue', 'Saved views')\"\n\t\tdata-testid=\"cn-saved-views-chips\">\n\t\t<button\n\t\t\tv-for=\"row in chipRows\"\n\t\t\t:key=\"`chip-${row.view.id || row.view.slug}`\"\n\t\t\ttype=\"button\"\n\t\t\tclass=\"cn-saved-views__chip\"\n\t\t\t:class=\"{ 'cn-saved-views__chip--selected': isSelected(row.view) }\"\n\t\t\t:aria-pressed=\"isSelected(row.view)\"\n\t\t\tdata-testid=\"cn-saved-views-chip\"\n\t\t\t:data-view-id=\"row.view.id || row.view.slug\"\n\t\t\t@click=\"onApply(row.view)\">\n\t\t\t<span class=\"cn-saved-views__chip-name\">{{ row.view.name }}</span>\n\t\t\t<span\n\t\t\t\tv-if=\"countOf(row.view) !== null\"\n\t\t\t\tclass=\"cn-saved-views__chip-count\"\n\t\t\t\tdata-testid=\"cn-saved-views-chip-count\">{{ countOf(row.view) }}</span>\n\t\t</button>\n\t</div>\n\t<!-- The wrapper carries the board look's class, so the bar's row rules\n\t and the ghost-button rules reach the button the way they did when it\n\t was an NcActions trigger. -->\n\t<div v-bind=\"$attrs\" :class=\"{ 'cn-saved-views__save': isBoardLook }\">\n\t\t<NcButton\n\t\t\t:variant=\"isBoardLook ? 'tertiary' : 'secondary'\"\n\t\t\t:aria-label=\"t('nextcloud-vue', 'Save view')\"\n\t\t\tdata-testid=\"cn-saved-views-control\"\n\t\t\t@click=\"onSaveRequest\">\n\t\t\t<template #icon>\n\t\t\t\t<ContentSaveOutline :size=\"isBoardLook ? 14 : 20\" />\n\t\t\t</template>\n\t\t\t{{ t('nextcloud-vue', 'Save view') }}\n\t\t</NcButton>\n\t</div>\n</template>\n\n<script>\nimport { NcButton } from '@nextcloud/vue'\nimport ContentSaveOutline from 'vue-material-design-icons/ContentSaveOutline.vue'\nimport { normalizeLook } from '../../composables/useLook.js'\nimport { savedViewsList } from '../../mixins/savedViewsList.js'\n\n/**\n * CnSavedViewsControl — the toolbar entry to saved views: a \"Save view\"\n * button and, under the board look, the saved views as chips that apply\n * them. Everything else (the list, edit, share, delete, add to menu) lives in\n * the index sidebar's `CnSavedViewsPanel`.\n *\n * Purely presentational: `CnIndexPage` owns fetching and every write.\n *\n * @event {object} apply — A chip was clicked; apply its view. Payload: the View API object.\n * @event {void} save-request — \"Save view\" clicked; open the save dialog.\n */\nexport default {\n\tname: 'CnSavedViewsControl',\n\n\tcomponents: { NcButton, ContentSaveOutline },\n\n\tmixins: [savedViewsList],\n\n\tinject: {\n\t\t/** The look CnAppRoot provides; `board` draws the views as chips. */\n\t\tcnLook: { default: 'nextcloud' },\n\t},\n\n\t// The chips and the button are two roots under the board look.\n\tinheritAttrs: false,\n\n\temits: ['apply', 'save-request'],\n\n\tcomputed: {\n\t\t/** @return {boolean} Whether the saved views draw as chips. */\n\t\tisBoardLook() {\n\t\t\treturn normalizeLook(this.cnLook) === 'board'\n\t\t},\n\n\t\t/** @return {Array<object>} The top level of the tree, in tree order. */\n\t\tchipRows() {\n\t\t\treturn this.rows.filter((row) => row.depth === 0)\n\t\t},\n\t},\n\n\tmethods: {\n\t\tonApply(view) {\n\t\t\t/**\n\t\t\t * @event apply A chip was clicked; apply its stored state.\n\t\t\t * @type {object}\n\t\t\t */\n\t\t\tthis.$emit('apply', view)\n\t\t},\n\n\t\tonSaveRequest() {\n\t\t\t/** @event save-request \"Save view\" clicked; open the save dialog. */\n\t\t\tthis.$emit('save-request')\n\t\t},\n\t},\n}\n</script>\n"],"names":[],"mappings":";;;;;AAyDA;;;AAGC;AACA;AACA;;AAEA;AACA;;;AAGD,aAAe;CACd,IAAI,EAAE,qBAAqB;;AAE3B,CAAA,UAAU,EAAE,EAAE,QAAQ,EAAE,oBAAoB;;CAE5C,MAAM,EAAE,CAAC,cAAc,CAAC;;AAExB,CAAA,MAAM,EAAE;;EAEP,MAAM,EAAE,EAAE,OAAO,EAAE,WAAU,EAAG;EAChC;;;AAGD,CAAA,YAAY,EAAE,KAAK;;AAEnB,CAAA,KAAK,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC;;AAEhC,CAAA,QAAQ,EAAE;;EAET,WAAW,GAAG;AACb,GAAA,OAAO,aAAa,CAAC,IAAI,CAAC,MAAM,CAAE,KAAI,OAAM;GAC5C;;;EAGD,QAAQ,GAAG;AACV,GAAA,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,UAAU,CAAC,CAAA;GAChD;EACD;;AAED,CAAA,OAAO,EAAE;EACR,OAAO,CAAC,IAAI,EAAE;AACb;;;;GAIA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,EAAA;GACxB;;AAED,EAAA,aAAa,GAAG;;GAEf,IAAI,CAAC,KAAK,CAAC,cAAc,EAAA;GACzB;EACD;AACF;;;;"}
1
+ {"version":3,"file":"CnSavedViewsControl.vue2.js","sources":["../../../../src/components/CnSavedViewsControl/CnSavedViewsControl.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<!--\n\t\tThe toolbar half of saved views. Under the board look the views are\n\t\ta row of chips that apply them; everywhere a \"Save view\" button saves\n\t\tthe current filters. Listing, editing, sharing and deleting live in the\n\t\tsidebar's Filters tab (CnSavedViewsPanel).\n\t-->\n\t<div\n\t\tv-if=\"isBoardLook && chips && chipRows.length > 0\"\n\t\tclass=\"cn-saved-views__chips\"\n\t\trole=\"group\"\n\t\t:aria-label=\"t('nextcloud-vue', 'Saved views')\"\n\t\tdata-testid=\"cn-saved-views-chips\">\n\t\t<button\n\t\t\tv-for=\"row in chipRows\"\n\t\t\t:key=\"`chip-${row.view.id || row.view.slug}`\"\n\t\t\ttype=\"button\"\n\t\t\tclass=\"cn-saved-views__chip\"\n\t\t\t:class=\"{ 'cn-saved-views__chip--selected': isSelected(row.view) }\"\n\t\t\t:aria-pressed=\"isSelected(row.view)\"\n\t\t\tdata-testid=\"cn-saved-views-chip\"\n\t\t\t:data-view-id=\"row.view.id || row.view.slug\"\n\t\t\t@click=\"onApply(row.view)\">\n\t\t\t<span class=\"cn-saved-views__chip-name\">{{ row.view.name }}</span>\n\t\t\t<span\n\t\t\t\tv-if=\"countOf(row.view) !== null\"\n\t\t\t\tclass=\"cn-saved-views__chip-count\"\n\t\t\t\tdata-testid=\"cn-saved-views-chip-count\">{{ countOf(row.view) }}</span>\n\t\t</button>\n\t</div>\n\t<!-- The wrapper carries the board look's class, so the bar's row rules\n\t and the ghost-button rules reach the button the way they did when it\n\t was an NcActions trigger. -->\n\t<div v-bind=\"$attrs\" :class=\"{ 'cn-saved-views__save': isBoardLook }\">\n\t\t<NcButton\n\t\t\t:variant=\"isBoardLook ? 'tertiary' : 'secondary'\"\n\t\t\t:aria-label=\"t('nextcloud-vue', 'Save view')\"\n\t\t\tdata-testid=\"cn-saved-views-control\"\n\t\t\t@click=\"onSaveRequest\">\n\t\t\t<template #icon>\n\t\t\t\t<ContentSaveOutline :size=\"isBoardLook ? 14 : 20\" />\n\t\t\t</template>\n\t\t\t{{ t('nextcloud-vue', 'Save view') }}\n\t\t</NcButton>\n\t</div>\n</template>\n\n<script>\nimport { NcButton } from '@nextcloud/vue'\nimport ContentSaveOutline from 'vue-material-design-icons/ContentSaveOutline.vue'\nimport { normalizeLook } from '../../composables/useLook.js'\nimport { savedViewsList } from '../../mixins/savedViewsList.js'\n\n/**\n * CnSavedViewsControl — the toolbar entry to saved views: a \"Save view\"\n * button and, under the board look, the saved views as chips that apply\n * them. Everything else (the list, edit, share, delete, add to menu) lives in\n * the index sidebar's `CnSavedViewsPanel`.\n *\n * Purely presentational: `CnIndexPage` owns fetching and every write.\n *\n * @event {object} apply — A chip was clicked; apply its view. Payload: the View API object.\n * @event {void} save-request — \"Save view\" clicked; open the save dialog.\n */\nexport default {\n\tname: 'CnSavedViewsControl',\n\n\tcomponents: { NcButton, ContentSaveOutline },\n\n\tmixins: [savedViewsList],\n\n\tinject: {\n\t\t/** The look CnAppRoot provides; `board` draws the views as chips. */\n\t\tcnLook: { default: 'nextcloud' },\n\t},\n\n\t// The chips and the button are two roots under the board look.\n\tinheritAttrs: false,\n\n\tprops: {\n\t\t/**\n\t\t * Whether the board look draws the saved views as chips. `false`\n\t\t * leaves only Save view, for a page whose views live in the side\n\t\t * panel (DqZaken).\n\t\t */\n\t\tchips: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\t},\n\n\temits: ['apply', 'save-request'],\n\n\tcomputed: {\n\t\t/** @return {boolean} Whether the saved views draw as chips. */\n\t\tisBoardLook() {\n\t\t\treturn normalizeLook(this.cnLook) === 'board'\n\t\t},\n\n\t\t/** @return {Array<object>} The top level of the tree, in tree order. */\n\t\tchipRows() {\n\t\t\treturn this.rows.filter((row) => row.depth === 0)\n\t\t},\n\t},\n\n\tmethods: {\n\t\tonApply(view) {\n\t\t\t/**\n\t\t\t * @event apply A chip was clicked; apply its stored state.\n\t\t\t * @type {object}\n\t\t\t */\n\t\t\tthis.$emit('apply', view)\n\t\t},\n\n\t\tonSaveRequest() {\n\t\t\t/** @event save-request \"Save view\" clicked; open the save dialog. */\n\t\t\tthis.$emit('save-request')\n\t\t},\n\t},\n}\n</script>\n"],"names":[],"mappings":";;;;;AAyDA;;;AAGC;AACA;AACA;;AAEA;AACA;;;AAGD,aAAe;CACd,IAAI,EAAE,qBAAqB;;AAE3B,CAAA,UAAU,EAAE,EAAE,QAAQ,EAAE,oBAAoB;;CAE5C,MAAM,EAAE,CAAC,cAAc,CAAC;;AAExB,CAAA,MAAM,EAAE;;EAEP,MAAM,EAAE,EAAE,OAAO,EAAE,WAAU,EAAG;EAChC;;;AAGD,CAAA,YAAY,EAAE,KAAK;;AAEnB,CAAA,KAAK,EAAE;AACN;;;AAGC;;AAED,EAAA,KAAK,EAAE;GACN,IAAI,EAAE,OAAO;GACb,OAAO,EAAE,IAAI;GACb;EACD;;AAED,CAAA,KAAK,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC;;AAEhC,CAAA,QAAQ,EAAE;;EAET,WAAW,GAAG;AACb,GAAA,OAAO,aAAa,CAAC,IAAI,CAAC,MAAM,CAAE,KAAI,OAAM;GAC5C;;;EAGD,QAAQ,GAAG;AACV,GAAA,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,UAAU,CAAC,CAAA;GAChD;EACD;;AAED,CAAA,OAAO,EAAE;EACR,OAAO,CAAC,IAAI,EAAE;AACb;;;;GAIA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,EAAA;GACxB;;AAED,EAAA,aAAa,GAAG;;GAEf,IAAI,CAAC,KAAK,CAAC,cAAc,EAAA;GACzB;EACD;AACF;;;;"}
@@ -14,7 +14,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
14
14
  const _component_NcButton = resolveComponent("NcButton");
15
15
 
16
16
  return (openBlock(), createElementBlock(Fragment, null, [
17
- ($options.isBoardLook && $options.chipRows.length > 0)
17
+ ($options.isBoardLook && $props.chips && $options.chipRows.length > 0)
18
18
  ? (openBlock(), createElementBlock("div", {
19
19
  key: 0,
20
20
  class: "cn-saved-views__chips",
@@ -1 +1 @@
1
- {"version":3,"file":"CnSavedViewsControl.vue3.js","sources":["../../../../src/components/CnSavedViewsControl/CnSavedViewsControl.vue?vue&type=template&id=957c35b6&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<!--\n\t\tThe toolbar half of saved views. Under the board look the views are\n\t\ta row of chips that apply them; everywhere a \"Save view\" button saves\n\t\tthe current filters. Listing, editing, sharing and deleting live in the\n\t\tsidebar's Filters tab (CnSavedViewsPanel).\n\t-->\n\t<div\n\t\tv-if=\"isBoardLook && chipRows.length > 0\"\n\t\tclass=\"cn-saved-views__chips\"\n\t\trole=\"group\"\n\t\t:aria-label=\"t('nextcloud-vue', 'Saved views')\"\n\t\tdata-testid=\"cn-saved-views-chips\">\n\t\t<button\n\t\t\tv-for=\"row in chipRows\"\n\t\t\t:key=\"`chip-${row.view.id || row.view.slug}`\"\n\t\t\ttype=\"button\"\n\t\t\tclass=\"cn-saved-views__chip\"\n\t\t\t:class=\"{ 'cn-saved-views__chip--selected': isSelected(row.view) }\"\n\t\t\t:aria-pressed=\"isSelected(row.view)\"\n\t\t\tdata-testid=\"cn-saved-views-chip\"\n\t\t\t:data-view-id=\"row.view.id || row.view.slug\"\n\t\t\t@click=\"onApply(row.view)\">\n\t\t\t<span class=\"cn-saved-views__chip-name\">{{ row.view.name }}</span>\n\t\t\t<span\n\t\t\t\tv-if=\"countOf(row.view) !== null\"\n\t\t\t\tclass=\"cn-saved-views__chip-count\"\n\t\t\t\tdata-testid=\"cn-saved-views-chip-count\">{{ countOf(row.view) }}</span>\n\t\t</button>\n\t</div>\n\t<!-- The wrapper carries the board look's class, so the bar's row rules\n\t and the ghost-button rules reach the button the way they did when it\n\t was an NcActions trigger. -->\n\t<div v-bind=\"$attrs\" :class=\"{ 'cn-saved-views__save': isBoardLook }\">\n\t\t<NcButton\n\t\t\t:variant=\"isBoardLook ? 'tertiary' : 'secondary'\"\n\t\t\t:aria-label=\"t('nextcloud-vue', 'Save view')\"\n\t\t\tdata-testid=\"cn-saved-views-control\"\n\t\t\t@click=\"onSaveRequest\">\n\t\t\t<template #icon>\n\t\t\t\t<ContentSaveOutline :size=\"isBoardLook ? 14 : 20\" />\n\t\t\t</template>\n\t\t\t{{ t('nextcloud-vue', 'Save view') }}\n\t\t</NcButton>\n\t</div>\n</template>\n\n<script>\nimport { NcButton } from '@nextcloud/vue'\nimport ContentSaveOutline from 'vue-material-design-icons/ContentSaveOutline.vue'\nimport { normalizeLook } from '../../composables/useLook.js'\nimport { savedViewsList } from '../../mixins/savedViewsList.js'\n\n/**\n * CnSavedViewsControl — the toolbar entry to saved views: a \"Save view\"\n * button and, under the board look, the saved views as chips that apply\n * them. Everything else (the list, edit, share, delete, add to menu) lives in\n * the index sidebar's `CnSavedViewsPanel`.\n *\n * Purely presentational: `CnIndexPage` owns fetching and every write.\n *\n * @event {object} apply — A chip was clicked; apply its view. Payload: the View API object.\n * @event {void} save-request — \"Save view\" clicked; open the save dialog.\n */\nexport default {\n\tname: 'CnSavedViewsControl',\n\n\tcomponents: { NcButton, ContentSaveOutline },\n\n\tmixins: [savedViewsList],\n\n\tinject: {\n\t\t/** The look CnAppRoot provides; `board` draws the views as chips. */\n\t\tcnLook: { default: 'nextcloud' },\n\t},\n\n\t// The chips and the button are two roots under the board look.\n\tinheritAttrs: false,\n\n\temits: ['apply', 'save-request'],\n\n\tcomputed: {\n\t\t/** @return {boolean} Whether the saved views draw as chips. */\n\t\tisBoardLook() {\n\t\t\treturn normalizeLook(this.cnLook) === 'board'\n\t\t},\n\n\t\t/** @return {Array<object>} The top level of the tree, in tree order. */\n\t\tchipRows() {\n\t\t\treturn this.rows.filter((row) => row.depth === 0)\n\t\t},\n\t},\n\n\tmethods: {\n\t\tonApply(view) {\n\t\t\t/**\n\t\t\t * @event apply A chip was clicked; apply its stored state.\n\t\t\t * @type {object}\n\t\t\t */\n\t\t\tthis.$emit('apply', view)\n\t\t},\n\n\t\tonSaveRequest() {\n\t\t\t/** @event save-request \"Save view\" clicked; open the save dialog. */\n\t\t\tthis.$emit('save-request')\n\t\t},\n\t},\n}\n</script>\n"],"names":["_createElementBlock","_Fragment","_renderList","_createElementVNode","_toDisplayString","_openBlock","_mergeProps","_createVNode"],"mappings":";;;;AA+BS,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,2BAA2B,GAAA;;;AAGtC,EAAA,KAAM,EAAA,4BAA4B;eACvB,EAAC,2BAA2B;;;;;;;;KAnBnC,QAAW,CAAA,WAAA,IAAI,QAAQ,CAAA,QAAA,CAAC,MAAI,GAAA,CAAA;sBADlCA,kBAsBK,CAAA,KAAA,EAAA;;AApBL,UAAA,KAAK,EAAC,uBAAA;AACL,UAAA,IAAG,EAAC,OAAO;AACX,UAAA,YAAU,EAAE,IAAC,CAAA,CAAA,CAAA,eAAA,EAAA,aAAA,CAAA;uBACH,EAAC,sBAAC;;8CAgBJ,CAAAC,QAAA,EAAA,IAAA,EAAAC,UAAA,CAdM,QAAQ,CAAA,QAAA,EAAA,CAAf,GAAG,KAAA;mDAcF,CAAA,QAAA,EAAA;cAbP,GAAG,EAAA,CAAA,KAAA,EAAU,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,IAAE,CAAA,IAAA,CAAA,CAAA;AACnC,cAAA,IAAI,EAAC,QAAQ;AACb,cAAA,KAAK,kBAAC,sBAAsB,EAAA,EAAA,gCAAA,EACF,eAAA,CAAA,GAAA,CAAA,IAAA,CAAA,EAAA,CAAA,CAAA;AACzB,cAAA,cAAY,EAAE,IAAA,CAAA,UAAU,CAAC,GAAG,CAAC,IAAI,CAAA;AAClC,cAAA,aAAI,EAAA,qBAAA;cACH,cAAY,EAAE,GAAG,CAAC,IAAI,CAAA,EAAG,IAAI,GAAG,CAAA,IAAA,CAAA,IAAA;AAChC,cAAA,OAAK,EAAE,MAAA,KAAA,QAAA,CAAA,OAAO,CAAC,GAAG,CAAC,IAAI,CAAA,CAAA;;AACvB,cAAAC,kBAAA,CAAiE,QAAjE,UAAiE,EAAAC,eAAA,CAAtB,GAAE,CAAC,IAAI,CAAC,IAAI,CAAA,EAAA,CAAA,YAAA;eAErD,IAAA,CAAA,OAAA,CAAA,GAAA,CAAA,IAAA,CAAA,KAAA,IAAA;AADH,mBAAAC,SAAA,EAAA,EAAAL,kBAAA,CAGsE,QAHtE,UAGsE,EAAAI,eAAA,CAA1B,YAAO,CAAC,GAAG,CAAC,IAAI,CAAA,CAAA,EAAA,CAAA,YAAA;;;;;;IAM5DD,0BAAAG,UAAW,KAAM,CAAA,MAAA,EAAA;AAAG,MAAA,KAAK,4BAAU,QAAA,CAAA,WAAA,EAAA;;;AAElC,QAAA,OAAO,EAAE,QAAK,CAAA,WAAA,GAAA,UAAA,GAAA,WAAA;AACd,QAAA,YAAU,EAAE,IAAC,CAAA,CAAA,CAAA,eAAA,EAAA,WAAA,CAAA;AACd,QAAA,aAAU,EAAA,wBAAA;AACT,QAAA,OAAK,EAAE,QAAY,CAAA,aAAA;;AACX,QAAA,IAAA,UACR,MAAE;UAAFC,WAAE,CAAA,6BAAA,EAAA;AAAA,YAAA,IAAA,EAAA,QAAA,CAAA,WAAA,GAAA,EAAA,GAAA,EAAA;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"CnSavedViewsControl.vue3.js","sources":["../../../../src/components/CnSavedViewsControl/CnSavedViewsControl.vue?vue&type=template&id=6cb497db&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<!--\n\t\tThe toolbar half of saved views. Under the board look the views are\n\t\ta row of chips that apply them; everywhere a \"Save view\" button saves\n\t\tthe current filters. Listing, editing, sharing and deleting live in the\n\t\tsidebar's Filters tab (CnSavedViewsPanel).\n\t-->\n\t<div\n\t\tv-if=\"isBoardLook && chips && chipRows.length > 0\"\n\t\tclass=\"cn-saved-views__chips\"\n\t\trole=\"group\"\n\t\t:aria-label=\"t('nextcloud-vue', 'Saved views')\"\n\t\tdata-testid=\"cn-saved-views-chips\">\n\t\t<button\n\t\t\tv-for=\"row in chipRows\"\n\t\t\t:key=\"`chip-${row.view.id || row.view.slug}`\"\n\t\t\ttype=\"button\"\n\t\t\tclass=\"cn-saved-views__chip\"\n\t\t\t:class=\"{ 'cn-saved-views__chip--selected': isSelected(row.view) }\"\n\t\t\t:aria-pressed=\"isSelected(row.view)\"\n\t\t\tdata-testid=\"cn-saved-views-chip\"\n\t\t\t:data-view-id=\"row.view.id || row.view.slug\"\n\t\t\t@click=\"onApply(row.view)\">\n\t\t\t<span class=\"cn-saved-views__chip-name\">{{ row.view.name }}</span>\n\t\t\t<span\n\t\t\t\tv-if=\"countOf(row.view) !== null\"\n\t\t\t\tclass=\"cn-saved-views__chip-count\"\n\t\t\t\tdata-testid=\"cn-saved-views-chip-count\">{{ countOf(row.view) }}</span>\n\t\t</button>\n\t</div>\n\t<!-- The wrapper carries the board look's class, so the bar's row rules\n\t and the ghost-button rules reach the button the way they did when it\n\t was an NcActions trigger. -->\n\t<div v-bind=\"$attrs\" :class=\"{ 'cn-saved-views__save': isBoardLook }\">\n\t\t<NcButton\n\t\t\t:variant=\"isBoardLook ? 'tertiary' : 'secondary'\"\n\t\t\t:aria-label=\"t('nextcloud-vue', 'Save view')\"\n\t\t\tdata-testid=\"cn-saved-views-control\"\n\t\t\t@click=\"onSaveRequest\">\n\t\t\t<template #icon>\n\t\t\t\t<ContentSaveOutline :size=\"isBoardLook ? 14 : 20\" />\n\t\t\t</template>\n\t\t\t{{ t('nextcloud-vue', 'Save view') }}\n\t\t</NcButton>\n\t</div>\n</template>\n\n<script>\nimport { NcButton } from '@nextcloud/vue'\nimport ContentSaveOutline from 'vue-material-design-icons/ContentSaveOutline.vue'\nimport { normalizeLook } from '../../composables/useLook.js'\nimport { savedViewsList } from '../../mixins/savedViewsList.js'\n\n/**\n * CnSavedViewsControl — the toolbar entry to saved views: a \"Save view\"\n * button and, under the board look, the saved views as chips that apply\n * them. Everything else (the list, edit, share, delete, add to menu) lives in\n * the index sidebar's `CnSavedViewsPanel`.\n *\n * Purely presentational: `CnIndexPage` owns fetching and every write.\n *\n * @event {object} apply — A chip was clicked; apply its view. Payload: the View API object.\n * @event {void} save-request — \"Save view\" clicked; open the save dialog.\n */\nexport default {\n\tname: 'CnSavedViewsControl',\n\n\tcomponents: { NcButton, ContentSaveOutline },\n\n\tmixins: [savedViewsList],\n\n\tinject: {\n\t\t/** The look CnAppRoot provides; `board` draws the views as chips. */\n\t\tcnLook: { default: 'nextcloud' },\n\t},\n\n\t// The chips and the button are two roots under the board look.\n\tinheritAttrs: false,\n\n\tprops: {\n\t\t/**\n\t\t * Whether the board look draws the saved views as chips. `false`\n\t\t * leaves only Save view, for a page whose views live in the side\n\t\t * panel (DqZaken).\n\t\t */\n\t\tchips: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\t},\n\n\temits: ['apply', 'save-request'],\n\n\tcomputed: {\n\t\t/** @return {boolean} Whether the saved views draw as chips. */\n\t\tisBoardLook() {\n\t\t\treturn normalizeLook(this.cnLook) === 'board'\n\t\t},\n\n\t\t/** @return {Array<object>} The top level of the tree, in tree order. */\n\t\tchipRows() {\n\t\t\treturn this.rows.filter((row) => row.depth === 0)\n\t\t},\n\t},\n\n\tmethods: {\n\t\tonApply(view) {\n\t\t\t/**\n\t\t\t * @event apply A chip was clicked; apply its stored state.\n\t\t\t * @type {object}\n\t\t\t */\n\t\t\tthis.$emit('apply', view)\n\t\t},\n\n\t\tonSaveRequest() {\n\t\t\t/** @event save-request \"Save view\" clicked; open the save dialog. */\n\t\t\tthis.$emit('save-request')\n\t\t},\n\t},\n}\n</script>\n"],"names":["_createElementBlock","_Fragment","_renderList","_createElementVNode","_toDisplayString","_openBlock","_mergeProps","_createVNode"],"mappings":";;;;AA+BS,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,2BAA2B,GAAA;;;AAGtC,EAAA,KAAM,EAAA,4BAA4B;eACvB,EAAC,2BAA2B;;;;;;;;AAnBnC,IAAA,CAAA,QAAA,CAAA,WAAW,IAAI,MAAA,CAAA,KAAK,IAAI,QAAA,CAAA,QAAI,CAAA,MAAA,GAAA,CAAA;sBADlCA,kBAsBK,CAAA,KAAA,EAAA;;AApBL,UAAA,KAAK,EAAC,uBAAA;AACL,UAAA,IAAG,EAAC,OAAO;AACX,UAAA,YAAU,EAAE,IAAC,CAAA,CAAA,CAAA,eAAA,EAAA,aAAA,CAAA;uBACH,EAAC,sBAAC;;8CAgBJ,CAAAC,QAAA,EAAA,IAAA,EAAAC,UAAA,CAdM,QAAQ,CAAA,QAAA,EAAA,CAAf,GAAG,KAAA;mDAcF,CAAA,QAAA,EAAA;cAbP,GAAG,EAAA,CAAA,KAAA,EAAU,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,IAAE,CAAA,IAAA,CAAA,CAAA;AACnC,cAAA,IAAI,EAAC,QAAQ;AACb,cAAA,KAAK,kBAAC,sBAAsB,EAAA,EAAA,gCAAA,EACF,eAAA,CAAA,GAAA,CAAA,IAAA,CAAA,EAAA,CAAA,CAAA;AACzB,cAAA,cAAY,EAAE,IAAA,CAAA,UAAU,CAAC,GAAG,CAAC,IAAI,CAAA;AAClC,cAAA,aAAI,EAAA,qBAAA;cACH,cAAY,EAAE,GAAG,CAAC,IAAI,CAAA,EAAG,IAAI,GAAG,CAAA,IAAA,CAAA,IAAA;AAChC,cAAA,OAAK,EAAE,MAAA,KAAA,QAAA,CAAA,OAAO,CAAC,GAAG,CAAC,IAAI,CAAA,CAAA;;AACvB,cAAAC,kBAAA,CAAiE,QAAjE,UAAiE,EAAAC,eAAA,CAAtB,GAAE,CAAC,IAAI,CAAC,IAAI,CAAA,EAAA,CAAA,YAAA;eAErD,IAAA,CAAA,OAAA,CAAA,GAAA,CAAA,IAAA,CAAA,KAAA,IAAA;AADH,mBAAAC,SAAA,EAAA,EAAAL,kBAAA,CAGsE,QAHtE,UAGsE,EAAAI,eAAA,CAA1B,YAAO,CAAC,GAAG,CAAC,IAAI,CAAA,CAAA,EAAA,CAAA,YAAA;;;;;;IAM5DD,0BAAAG,UAAW,KAAM,CAAA,MAAA,EAAA;AAAG,MAAA,KAAK,4BAAU,QAAA,CAAA,WAAA,EAAA;;;AAElC,QAAA,OAAO,EAAE,QAAK,CAAA,WAAA,GAAA,UAAA,GAAA,WAAA;AACd,QAAA,YAAU,EAAE,IAAC,CAAA,CAAA,CAAA,eAAA,EAAA,WAAA,CAAA;AACd,QAAA,aAAU,EAAA,wBAAA;AACT,QAAA,OAAK,EAAE,QAAY,CAAA,aAAA;;AACX,QAAA,IAAA,UACR,MAAE;UAAFC,WAAE,CAAA,6BAAA,EAAA;AAAA,YAAA,IAAA,EAAA,QAAA,CAAA,WAAA,GAAA,EAAA,GAAA,EAAA;;;;;;;;;;;;;;"}
@@ -2,7 +2,7 @@ import script from './CnUserSettingsDialog.vue2.js';
2
2
  import { render } from './CnUserSettingsDialog.vue3.js';
3
3
 
4
4
  script.render = render;
5
- script.__scopeId = "data-v-6d3e749e";
5
+ script.__scopeId = "data-v-7d896e3e";
6
6
  const __sfc_main = script;
7
7
 
8
8
  export { __sfc_main as default };
@@ -1,9 +1,9 @@
1
1
  import { translate } from '@nextcloud/l10n';
2
2
  import { generateUrl } from '@nextcloud/router';
3
3
  import { NcButton } from '@nextcloud/vue';
4
- import { ref, markRaw, cloneVNode } from 'vue';
4
+ import { ref } from 'vue';
5
+ import Close from 'vue-material-design-icons/Close.vue';
5
6
  import __sfc_main from '../CnDialog/CnDialog.vue.js';
6
- import __sfc_main$1 from '../CnIcon/CnIcon.vue.js';
7
7
 
8
8
  /**
9
9
  * The key NcAppSettingsSection injects to register itself with its dialog
@@ -14,37 +14,28 @@ const REGISTRATION_KEY = Symbol.for('NcAppSettingsDialog:registration');
14
14
  /** The key NcAppSettingsSection injects for the legacy design flag. */
15
15
  const LEGACY_DESIGN_KEY = Symbol.for('NcAppSettingsDialog:legacy');
16
16
 
17
- /** Renders a section's icon vnodes as they were registered. */
18
- const CnVNodes = {
19
- name: 'CnVNodes',
20
- props: { vnodes: { type: [Array, Object], default: null } },
21
- render() {
22
- // A section's icon is drawn twice (navigation and heading), so each draw gets its own copy.
23
- const list = Array.isArray(this.vnodes) ? this.vnodes : [this.vnodes];
24
- return list.map((vnode) => (vnode && typeof vnode === 'object' ? cloneVNode(vnode) : vnode))
25
- },
26
- };
27
-
28
17
  /**
29
- * CnUserSettingsDialog - the user settings dialog in the board look (board
30
- * PqPersoonlijk): eyebrow, title and subtitle, a left navigation listing the
31
- * sections with their icons, the current section (the others stay mounted
32
- * but hidden), and a footer with a note that changes save straight away and
33
- * a Close button.
18
+ * CnUserSettingsDialog - the user settings dialog in the board look, as the
19
+ * DqPersoonlijkeInstellingen board draws Nextcloud's own settings dialog:
20
+ * 900px wide, the title at the top of a tinted navigation column, every
21
+ * section stacked on a white pane that the navigation scrolls, a close icon
22
+ * in the corner, and no header or footer. Under the sections a line says
23
+ * that changes save straight away.
34
24
  *
35
25
  * The sections stay the app's: any `NcAppSettingsSection` in the default slot
36
26
  * registers itself with this dialog exactly as it does with
37
- * `NcAppSettingsDialog`, with its name, order and `#icon` slot. CnAppRoot
38
- * renders this dialog instead of `NcAppSettingsDialog` under the board look.
27
+ * `NcAppSettingsDialog`, with its name and order. CnAppRoot renders this
28
+ * dialog instead of `NcAppSettingsDialog` under the board look.
39
29
  *
40
30
  * @spec openspec/changes/user-settings-board-dialog/specs/user-settings-board-dialog/spec.md#requirement-the-user-settings-dialog-takes-the-board-look
31
+ * @spec openspec/changes/user-settings-dialog-dq-board/specs/user-settings-dialog-dq-board/spec.md#requirement-the-user-settings-dialog-follows-the-dq-board
41
32
  *
42
33
  * @event update:open Emitted with `false` when the dialog closes.
43
34
  */
44
35
  var script = {
45
36
  name: 'CnUserSettingsDialog',
46
37
 
47
- components: { CnDialog: __sfc_main, CnIcon: __sfc_main$1, CnVNodes, NcButton },
38
+ components: { Close, CnDialog: __sfc_main, NcButton },
48
39
 
49
40
  provide() {
50
41
  return {
@@ -63,9 +54,19 @@ var script = {
63
54
  open: { type: Boolean, default: false },
64
55
  /** Dialog title; also its accessible name. */
65
56
  title: { type: String, required: true },
66
- /** Context line above the title. */
57
+ /**
58
+ * Deprecated and ignored: the board draws no line above the title.
59
+ * Kept so a host that passes it stays valid.
60
+ *
61
+ * @deprecated
62
+ */
67
63
  eyebrow: { type: String, default: () => translate('nextcloud-vue', 'Your account') },
68
- /** Sentence under the title. */
64
+ /**
65
+ * Deprecated and ignored: the board draws no line under the title.
66
+ * Kept so a host that passes it stays valid.
67
+ *
68
+ * @deprecated
69
+ */
69
70
  subtitle: { type: String, default: () => translate('nextcloud-vue', 'Only for you. Colleagues keep their own settings.') },
70
71
  /** The app's name, after the footer note and as the navigation entry holding its sections. */
71
72
  appName: { type: String, default: '' },
@@ -84,8 +85,6 @@ var script = {
84
85
  return {
85
86
  sections: [],
86
87
  selected: '',
87
- /** Ids of the sections whose heading is in the page, for the heading icons. */
88
- headingTargets: [],
89
88
  picked: false,
90
89
  }
91
90
  },
@@ -108,9 +107,9 @@ var script = {
108
107
  }))
109
108
  },
110
109
 
111
- /** @return {object} The board's eyebrow: muted, in sentence case. */
112
- eyebrowStyle() {
113
- return { '--cn-dialog-eyebrow-transform': 'none', '--cn-dialog-eyebrow-color': 'var(--color-text-maxcontrast)' }
110
+ /** @return {object} The board's 900px width, over CnDialog's width roles. */
111
+ frameStyle() {
112
+ return { '--cn-dialog-width': '900px' }
114
113
  },
115
114
 
116
115
  /** @return {string} The navigation's accessible name. */
@@ -130,21 +129,6 @@ var script = {
130
129
  },
131
130
  },
132
131
 
133
- watch: {
134
- sections() {
135
- this.$nextTick(() => {
136
- this.headingTargets = typeof document === 'undefined'
137
- ? []
138
- : this.sections.filter((section) => section.icon && document.getElementById(`settings-section_${section.id}--label`)).map((section) => section.id);
139
- this.showSelected();
140
- });
141
- },
142
-
143
- selected() {
144
- this.$nextTick(() => this.showSelected());
145
- },
146
- },
147
-
148
132
  methods: {
149
133
  /**
150
134
  * Add a section to the navigation, kept in `order`; a section
@@ -153,13 +137,14 @@ var script = {
153
137
  *
154
138
  * @param {string} id The section id.
155
139
  * @param {string} name The section name.
156
- * @param {number} [order] The section's place.
157
- * @param {Array} [icon] The section's icon vnodes.
140
+ * @param {number} [order] The section's place. A section's icon, the
141
+ * fourth argument NcAppSettingsSection passes, is not drawn: the
142
+ * board lists the sections by name alone.
158
143
  */
159
- registerSection(id, name, order, icon) {
144
+ registerSection(id, name, order) {
160
145
  const rest = this.sections.filter((section) => section.id !== id);
161
146
  const place = typeof order === 'number' ? order : Math.max(0, ...rest.map((section) => section.order)) + 1;
162
- this.sections = [...rest, { id, name, order: place, icon: icon ? markRaw(icon) : null }].sort((a, b) => a.order - b.order);
147
+ this.sections = [...rest, { id, name, order: place }].sort((a, b) => a.order - b.order);
163
148
  if (!this.picked) {
164
149
  this.selected = this.sections[0].id;
165
150
  }
@@ -178,7 +163,8 @@ var script = {
178
163
  },
179
164
 
180
165
  /**
181
- * Mark a section current and scroll it into view.
166
+ * Mark a section current, scroll it to the top of the pane and focus
167
+ * its heading. Every section stays in the pane.
182
168
  *
183
169
  * @param {string} id The section id.
184
170
  */
@@ -186,33 +172,18 @@ var script = {
186
172
  this.picked = true;
187
173
  this.selected = id;
188
174
  this.$nextTick(() => {
189
- this.showSelected();
175
+ const el = typeof document !== 'undefined' ? document.getElementById(`settings-section_${id}`) : null;
176
+ if (el && typeof el.scrollIntoView === 'function') {
177
+ el.scrollIntoView({ block: 'start', behavior: 'smooth' });
178
+ }
190
179
  const heading = typeof document !== 'undefined' ? document.getElementById(`settings-section_${id}--label`) : null;
191
180
  if (heading) {
192
181
  heading.setAttribute('tabindex', '-1');
193
- heading.focus();
182
+ heading.focus({ preventScroll: true });
194
183
  }
195
184
  });
196
185
  },
197
186
 
198
- /**
199
- * Show the current section and hide the others. They stay mounted,
200
- * so what a reader typed in one survives a switch.
201
- *
202
- * @spec openspec/changes/user-settings-one-section/specs/user-settings-board-dialog/spec.md#requirement-the-board-user-settings-dialog-shows-one-section-at-a-time
203
- */
204
- showSelected() {
205
- if (typeof document === 'undefined') {
206
- return
207
- }
208
- for (const section of this.sections) {
209
- const el = document.getElementById(`settings-section_${section.id}`);
210
- if (el) {
211
- el.hidden = section.id !== this.selected;
212
- }
213
- }
214
- },
215
-
216
187
  /**
217
188
  * Follow NcDialog's own open state.
218
189
  *
@@ -1 +1 @@
1
- {"version":3,"file":"CnUserSettingsDialog.vue2.js","sources":["../../../../src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<CnDialog\n\t\tclass=\"cn-user-settings-dialog\"\n\t\t:name=\"title\"\n\t\tlook=\"board\"\n\t\twidth=\"wizard\"\n\t\t:eyebrow=\"eyebrow\"\n\t\t:subtitle=\"subtitle\"\n\t\t:open=\"open\"\n\t\t:style=\"eyebrowStyle\"\n\t\tdata-testid=\"cn-user-settings-dialog\"\n\t\t@update:open=\"onUpdateOpen\"\n\t\t@closing=\"close\">\n\t\t<div class=\"cn-user-settings-dialog__body\">\n\t\t\t<nav\n\t\t\t\tv-if=\"sections.length > 0\"\n\t\t\t\tclass=\"cn-user-settings-dialog__nav\"\n\t\t\t\t:aria-label=\"navLabel\"\n\t\t\t\tdata-testid=\"cn-user-settings-nav\">\n\t\t\t\t<!-- `nextcloudLinks`: Nextcloud's own personal settings first, as\n\t\t\t\t links, then one entry for this app holding its sections. -->\n\t\t\t\t<ul v-if=\"ncLinks.length > 0\" class=\"cn-user-settings-dialog__nc-links\" data-testid=\"cn-user-settings-nc-links\">\n\t\t\t\t\t<li v-for=\"link in ncLinks\" :key=\"link.key\">\n\t\t\t\t\t\t<a :href=\"link.href\" class=\"cn-user-settings-dialog__nav-link\">\n\t\t\t\t\t\t\t<span v-if=\"link.icon\" class=\"cn-user-settings-dialog__nav-icon\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t<CnIcon :name=\"link.icon\" :size=\"18\" />\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span>{{ link.label }}</span>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t\t<p v-if=\"ncLinks.length > 0 && appName\"\n\t\t\t\t\tclass=\"cn-user-settings-dialog__group\"\n\t\t\t\t\tdata-testid=\"cn-user-settings-app-group\">\n\t\t\t\t\t{{ appName }}\n\t\t\t\t</p>\n\t\t\t\t<ul :class=\"{ 'cn-user-settings-dialog__group-sections': ncLinks.length > 0 }\">\n\t\t\t\t\t<li v-for=\"section in sections\" :key=\"section.id\">\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t:href=\"`#settings-section_${section.id}`\"\n\t\t\t\t\t\t\tclass=\"cn-user-settings-dialog__nav-link\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-user-settings-dialog__nav-link--active': section.id === selected }\"\n\t\t\t\t\t\t\t:aria-current=\"section.id === selected ? 'true' : undefined\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-user-settings-nav-${section.id}`\"\n\t\t\t\t\t\t\t@click.prevent=\"selectSection(section.id)\">\n\t\t\t\t\t\t\t<span v-if=\"section.icon\" class=\"cn-user-settings-dialog__nav-icon\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t<CnVNodes :vnodes=\"section.icon\" />\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span>{{ section.name }}</span>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t</nav>\n\t\t\t<div class=\"cn-user-settings-dialog__sections\">\n\t\t\t\t<!-- @slot default NcAppSettingsSection children; each registers itself in the navigation. -->\n\t\t\t\t<slot />\n\t\t\t\t<!-- A section's `#icon` also stands before its heading. -->\n\t\t\t\t<template v-for=\"section in sections\" :key=\"`heading-icon-${section.id}-${section.name}`\">\n\t\t\t\t\t<Teleport v-if=\"section.icon && headingTargets.includes(section.id)\" :to=\"`#settings-section_${section.id}--label`\">\n\t\t\t\t\t\t<span class=\"cn-user-settings-dialog__heading-icon\" aria-hidden=\"true\" :data-testid=\"`cn-user-settings-heading-icon-${section.id}`\">\n\t\t\t\t\t\t\t<CnVNodes :vnodes=\"section.icon\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</Teleport>\n\t\t\t\t</template>\n\t\t\t</div>\n\t\t</div>\n\t\t<template #actions>\n\t\t\t<p class=\"cn-user-settings-dialog__note\" data-testid=\"cn-user-settings-note\">\n\t\t\t\t{{ footerNote }}\n\t\t\t</p>\n\t\t\t<NcButton variant=\"secondary\" data-testid=\"cn-user-settings-close\" @click=\"close\">\n\t\t\t\t{{ closeLabel }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</CnDialog>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcButton } from '@nextcloud/vue'\nimport { cloneVNode, markRaw, ref } from 'vue'\nimport CnDialog from '../CnDialog/CnDialog.vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\n\n/**\n * The key NcAppSettingsSection injects to register itself with its dialog\n * (`Symbol.for`, so the same symbol `@nextcloud/vue` provides).\n */\nconst REGISTRATION_KEY = Symbol.for('NcAppSettingsDialog:registration')\n\n/** The key NcAppSettingsSection injects for the legacy design flag. */\nconst LEGACY_DESIGN_KEY = Symbol.for('NcAppSettingsDialog:legacy')\n\n/** Renders a section's icon vnodes as they were registered. */\nconst CnVNodes = {\n\tname: 'CnVNodes',\n\tprops: { vnodes: { type: [Array, Object], default: null } },\n\trender() {\n\t\t// A section's icon is drawn twice (navigation and heading), so each draw gets its own copy.\n\t\tconst list = Array.isArray(this.vnodes) ? this.vnodes : [this.vnodes]\n\t\treturn list.map((vnode) => (vnode && typeof vnode === 'object' ? cloneVNode(vnode) : vnode))\n\t},\n}\n\n/**\n * CnUserSettingsDialog - the user settings dialog in the board look (board\n * PqPersoonlijk): eyebrow, title and subtitle, a left navigation listing the\n * sections with their icons, the current section (the others stay mounted\n * but hidden), and a footer with a note that changes save straight away and\n * a Close button.\n *\n * The sections stay the app's: any `NcAppSettingsSection` in the default slot\n * registers itself with this dialog exactly as it does with\n * `NcAppSettingsDialog`, with its name, order and `#icon` slot. CnAppRoot\n * renders this dialog instead of `NcAppSettingsDialog` under the board look.\n *\n * @spec openspec/changes/user-settings-board-dialog/specs/user-settings-board-dialog/spec.md#requirement-the-user-settings-dialog-takes-the-board-look\n *\n * @event update:open Emitted with `false` when the dialog closes.\n */\nexport default {\n\tname: 'CnUserSettingsDialog',\n\n\tcomponents: { CnDialog, CnIcon, CnVNodes, NcButton },\n\n\tprovide() {\n\t\treturn {\n\t\t\t[REGISTRATION_KEY]: {\n\t\t\t\tregisterSection: this.registerSection,\n\t\t\t\tunregisterSection: this.unregisterSection,\n\t\t\t},\n\n\t\t\t// NcAppSettingsSection also asks its dialog whether to use the legacy design.\n\t\t\t[LEGACY_DESIGN_KEY]: ref(false),\n\t\t}\n\t},\n\n\tprops: {\n\t\t/** Whether the dialog is open. */\n\t\topen: { type: Boolean, default: false },\n\t\t/** Dialog title; also its accessible name. */\n\t\ttitle: { type: String, required: true },\n\t\t/** Context line above the title. */\n\t\teyebrow: { type: String, default: () => t('nextcloud-vue', 'Your account') },\n\t\t/** Sentence under the title. */\n\t\tsubtitle: { type: String, default: () => t('nextcloud-vue', 'Only for you. Colleagues keep their own settings.') },\n\t\t/** The app's name, after the footer note and as the navigation entry holding its sections. */\n\t\tappName: { type: String, default: '' },\n\t\t/**\n\t\t * Nextcloud's own personal settings, listed first in the navigation as\n\t\t * links: `[{ label, section? | href?, icon? }]`. `section` is a\n\t\t * personal settings section id (`/settings/user/<section>`). With any,\n\t\t * the app's sections sit under one entry named after the app.\n\t\t */\n\t\tnextcloudLinks: { type: Array, default: () => [] },\n\t},\n\n\temits: ['update:open'],\n\n\tdata() {\n\t\treturn {\n\t\t\tsections: [],\n\t\t\tselected: '',\n\t\t\t/** Ids of the sections whose heading is in the page, for the heading icons. */\n\t\t\theadingTargets: [],\n\t\t\tpicked: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The Nextcloud links with their URL.\n\t\t *\n\t\t * @spec openspec/changes/user-settings-nav-groups/specs/user-settings-board-dialog/spec.md#requirement-the-board-user-settings-navigation-can-list-nextclouds-own-sections-first\n\t\t * @return {Array<{key: string, label: string, href: string, icon: string}>}\n\t\t */\n\t\tncLinks() {\n\t\t\treturn (Array.isArray(this.nextcloudLinks) ? this.nextcloudLinks : [])\n\t\t\t\t.filter((link) => link && typeof link === 'object' && typeof link.label === 'string' && link.label !== '' && (link.href || link.section))\n\t\t\t\t.map((link, index) => ({\n\t\t\t\t\tkey: String(link.section || link.href || index),\n\t\t\t\t\tlabel: link.label,\n\t\t\t\t\thref: link.href || generateUrl('/settings/user/{section}', { section: String(link.section) }),\n\t\t\t\t\ticon: typeof link.icon === 'string' ? link.icon : '',\n\t\t\t\t}))\n\t\t},\n\n\t\t/** @return {object} The board's eyebrow: muted, in sentence case. */\n\t\teyebrowStyle() {\n\t\t\treturn { '--cn-dialog-eyebrow-transform': 'none', '--cn-dialog-eyebrow-color': 'var(--color-text-maxcontrast)' }\n\t\t},\n\n\t\t/** @return {string} The navigation's accessible name. */\n\t\tnavLabel() {\n\t\t\treturn t('nextcloud-vue', 'Sections of the settings')\n\t\t},\n\n\t\t/** @return {string} The footer note, with the app's name when known. */\n\t\tfooterNote() {\n\t\t\tconst note = t('nextcloud-vue', 'Changes are saved straight away')\n\t\t\treturn this.appName ? `${note} · ${this.appName}` : note\n\t\t},\n\n\t\t/** @return {string} The Close button label. */\n\t\tcloseLabel() {\n\t\t\treturn t('nextcloud-vue', 'Close')\n\t\t},\n\t},\n\n\twatch: {\n\t\tsections() {\n\t\t\tthis.$nextTick(() => {\n\t\t\t\tthis.headingTargets = typeof document === 'undefined'\n\t\t\t\t\t? []\n\t\t\t\t\t: this.sections.filter((section) => section.icon && document.getElementById(`settings-section_${section.id}--label`)).map((section) => section.id)\n\t\t\t\tthis.showSelected()\n\t\t\t})\n\t\t},\n\n\t\tselected() {\n\t\t\tthis.$nextTick(() => this.showSelected())\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Add a section to the navigation, kept in `order`; a section\n\t\t * without one goes last. Until the reader picks one, the first\n\t\t * section is current.\n\t\t *\n\t\t * @param {string} id The section id.\n\t\t * @param {string} name The section name.\n\t\t * @param {number} [order] The section's place.\n\t\t * @param {Array} [icon] The section's icon vnodes.\n\t\t */\n\t\tregisterSection(id, name, order, icon) {\n\t\t\tconst rest = this.sections.filter((section) => section.id !== id)\n\t\t\tconst place = typeof order === 'number' ? order : Math.max(0, ...rest.map((section) => section.order)) + 1\n\t\t\tthis.sections = [...rest, { id, name, order: place, icon: icon ? markRaw(icon) : null }].sort((a, b) => a.order - b.order)\n\t\t\tif (!this.picked) {\n\t\t\t\tthis.selected = this.sections[0].id\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Remove a section from the navigation.\n\t\t *\n\t\t * @param {string} id The section id.\n\t\t */\n\t\tunregisterSection(id) {\n\t\t\tthis.sections = this.sections.filter((section) => section.id !== id)\n\t\t\tif (this.selected === id) {\n\t\t\t\tthis.selected = this.sections.length > 0 ? this.sections[0].id : ''\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Mark a section current and scroll it into view.\n\t\t *\n\t\t * @param {string} id The section id.\n\t\t */\n\t\tselectSection(id) {\n\t\t\tthis.picked = true\n\t\t\tthis.selected = id\n\t\t\tthis.$nextTick(() => {\n\t\t\t\tthis.showSelected()\n\t\t\t\tconst heading = typeof document !== 'undefined' ? document.getElementById(`settings-section_${id}--label`) : null\n\t\t\t\tif (heading) {\n\t\t\t\t\theading.setAttribute('tabindex', '-1')\n\t\t\t\t\theading.focus()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Show the current section and hide the others. They stay mounted,\n\t\t * so what a reader typed in one survives a switch.\n\t\t *\n\t\t * @spec openspec/changes/user-settings-one-section/specs/user-settings-board-dialog/spec.md#requirement-the-board-user-settings-dialog-shows-one-section-at-a-time\n\t\t */\n\t\tshowSelected() {\n\t\t\tif (typeof document === 'undefined') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tfor (const section of this.sections) {\n\t\t\t\tconst el = document.getElementById(`settings-section_${section.id}`)\n\t\t\t\tif (el) {\n\t\t\t\t\tel.hidden = section.id !== this.selected\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Follow NcDialog's own open state.\n\t\t *\n\t\t * @param {boolean} value Whether NcDialog is open.\n\t\t */\n\t\tonUpdateOpen(value) {\n\t\t\tif (!value) {\n\t\t\t\tthis.close()\n\t\t\t}\n\t\t},\n\n\t\t/** Close the dialog. */\n\t\tclose() {\n\t\t\t/**\n\t\t\t * @event update:open Emitted with `false` when the dialog closes (Close button, close icon, Escape).\n\t\t\t */\n\t\t\tthis.$emit('update:open', false)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-user-settings-dialog__body {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 0 24px;\n}\n\n.cn-user-settings-dialog__nav {\n\tflex: 0 0 200px;\n\twidth: 200px;\n\tpadding-top: 18px;\n}\n\n.cn-user-settings-dialog__nav ul {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n\n/* A navigation entry, not a link in running text: no underline, also not\n on hover. `!important` because a theme's `a { text-decoration }` carries\n it (thematiq), and a bare `a` with `!important` beats any class. */\n.cn-user-settings-dialog__nav-link,\n.cn-user-settings-dialog__nav-link:visited {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tmin-height: 40px;\n\tpadding: 0 12px;\n\tborder-radius: var(--border-radius-element, 8px);\n\tfont-size: 15px;\n\tcolor: var(--color-main-text);\n\ttext-decoration: none !important;\n}\n\n.cn-user-settings-dialog__nav-link:hover {\n\tbackground: var(--color-background-hover);\n\ttext-decoration: none !important;\n}\n\n.cn-user-settings-dialog__nav-link:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 2px;\n}\n\n.cn-user-settings-dialog__nav-link--active,\n.cn-user-settings-dialog__nav-link--active:hover {\n\tbackground: var(--color-primary-element-light);\n\tcolor: var(--color-primary-element-light-text);\n\tfont-weight: 600;\n}\n\n.cn-user-settings-dialog__nav-icon {\n\tdisplay: inline-flex;\n\tflex: none;\n\twidth: 18px;\n\theight: 18px;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.cn-user-settings-dialog__sections {\n\tdisplay: flex;\n\tflex: 1 1 380px;\n\tflex-direction: column;\n\tmin-width: 0;\n}\n\n.cn-user-settings-dialog__sections :deep(.app-settings-section) {\n\tmargin: 0;\n\tpadding: 18px 0;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-user-settings-dialog__sections :deep(.app-settings-section__name) {\n\tmargin: 0 0 12px;\n\tfont-size: 17px;\n\tfont-weight: 700;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n}\n\n.cn-user-settings-dialog__note {\n\tflex: 1 1 auto;\n\tmargin: 0;\n\tfont-size: 14px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-user-settings-dialog__nc-links {\n\tmargin-bottom: 2px;\n}\n\n.cn-user-settings-dialog__group {\n\tmargin: 10px 0 2px;\n\tpadding: 0 12px;\n\tfont-size: 15px;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-user-settings-dialog__group-sections {\n\tpadding-inline-start: 12px;\n}\n\n.cn-user-settings-dialog__heading-icon {\n\tdisplay: inline-flex;\n\torder: -1;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n/* One section at a time: the others are mounted but hidden. */\n.cn-user-settings-dialog__sections :deep(.app-settings-section[hidden]) {\n\tdisplay: none;\n}\n</style>\n"],"names":["CnDialog","CnIcon","t"],"mappings":"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"}
1
+ {"version":3,"file":"CnUserSettingsDialog.vue2.js","sources":["../../../../src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<CnDialog\n\t\tclass=\"cn-user-settings-dialog\"\n\t\t:name=\"title\"\n\t\tlook=\"board\"\n\t\theadless\n\t\t:open=\"open\"\n\t\t:style=\"frameStyle\"\n\t\tdata-testid=\"cn-user-settings-dialog\"\n\t\t@update:open=\"onUpdateOpen\"\n\t\t@closing=\"close\">\n\t\t<div class=\"cn-user-settings-dialog__body\">\n\t\t\t<nav\n\t\t\t\tclass=\"cn-user-settings-dialog__nav\"\n\t\t\t\t:aria-label=\"navLabel\"\n\t\t\t\tdata-testid=\"cn-user-settings-nav\">\n\t\t\t\t<h2 class=\"cn-user-settings-dialog__title\" data-testid=\"cn-user-settings-title\">\n\t\t\t\t\t{{ title }}\n\t\t\t\t</h2>\n\t\t\t\t<!-- `nextcloudLinks`: Nextcloud's own personal settings first, as\n\t\t\t\t links, then one entry for this app holding its sections. -->\n\t\t\t\t<ul v-if=\"ncLinks.length > 0\" class=\"cn-user-settings-dialog__nc-links\" data-testid=\"cn-user-settings-nc-links\">\n\t\t\t\t\t<li v-for=\"link in ncLinks\" :key=\"link.key\">\n\t\t\t\t\t\t<a :href=\"link.href\" class=\"cn-user-settings-dialog__nav-link\">\n\t\t\t\t\t\t\t<span class=\"cn-user-settings-dialog__nav-label\">{{ link.label }}</span>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t\t<p v-if=\"ncLinks.length > 0 && appName\"\n\t\t\t\t\tclass=\"cn-user-settings-dialog__group\"\n\t\t\t\t\tdata-testid=\"cn-user-settings-app-group\">\n\t\t\t\t\t{{ appName }}\n\t\t\t\t</p>\n\t\t\t\t<ul :class=\"{ 'cn-user-settings-dialog__group-sections': ncLinks.length > 0 }\">\n\t\t\t\t\t<li v-for=\"section in sections\" :key=\"section.id\">\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t:href=\"`#settings-section_${section.id}`\"\n\t\t\t\t\t\t\tclass=\"cn-user-settings-dialog__nav-link\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-user-settings-dialog__nav-link--active': section.id === selected }\"\n\t\t\t\t\t\t\t:aria-current=\"section.id === selected ? 'true' : undefined\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-user-settings-nav-${section.id}`\"\n\t\t\t\t\t\t\t@click.prevent=\"selectSection(section.id)\">\n\t\t\t\t\t\t\t<span class=\"cn-user-settings-dialog__nav-label\">{{ section.name }}</span>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t</nav>\n\t\t\t<div class=\"cn-user-settings-dialog__sections\">\n\t\t\t\t<!-- @slot default NcAppSettingsSection children; each registers itself in the navigation. -->\n\t\t\t\t<slot />\n\t\t\t\t<p class=\"cn-user-settings-dialog__note\" data-testid=\"cn-user-settings-note\">\n\t\t\t\t\t{{ footerNote }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t\t<NcButton\n\t\t\t\tclass=\"cn-user-settings-dialog__close\"\n\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t:aria-label=\"closeLabel\"\n\t\t\t\t:title=\"closeLabel\"\n\t\t\t\tdata-testid=\"cn-user-settings-close\"\n\t\t\t\t@click=\"close\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Close :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t</NcButton>\n\t\t</div>\n\t</CnDialog>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcButton } from '@nextcloud/vue'\nimport { ref } from 'vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport CnDialog from '../CnDialog/CnDialog.vue'\n\n/**\n * The key NcAppSettingsSection injects to register itself with its dialog\n * (`Symbol.for`, so the same symbol `@nextcloud/vue` provides).\n */\nconst REGISTRATION_KEY = Symbol.for('NcAppSettingsDialog:registration')\n\n/** The key NcAppSettingsSection injects for the legacy design flag. */\nconst LEGACY_DESIGN_KEY = Symbol.for('NcAppSettingsDialog:legacy')\n\n/**\n * CnUserSettingsDialog - the user settings dialog in the board look, as the\n * DqPersoonlijkeInstellingen board draws Nextcloud's own settings dialog:\n * 900px wide, the title at the top of a tinted navigation column, every\n * section stacked on a white pane that the navigation scrolls, a close icon\n * in the corner, and no header or footer. Under the sections a line says\n * that changes save straight away.\n *\n * The sections stay the app's: any `NcAppSettingsSection` in the default slot\n * registers itself with this dialog exactly as it does with\n * `NcAppSettingsDialog`, with its name and order. CnAppRoot renders this\n * dialog instead of `NcAppSettingsDialog` under the board look.\n *\n * @spec openspec/changes/user-settings-board-dialog/specs/user-settings-board-dialog/spec.md#requirement-the-user-settings-dialog-takes-the-board-look\n * @spec openspec/changes/user-settings-dialog-dq-board/specs/user-settings-dialog-dq-board/spec.md#requirement-the-user-settings-dialog-follows-the-dq-board\n *\n * @event update:open Emitted with `false` when the dialog closes.\n */\nexport default {\n\tname: 'CnUserSettingsDialog',\n\n\tcomponents: { Close, CnDialog, NcButton },\n\n\tprovide() {\n\t\treturn {\n\t\t\t[REGISTRATION_KEY]: {\n\t\t\t\tregisterSection: this.registerSection,\n\t\t\t\tunregisterSection: this.unregisterSection,\n\t\t\t},\n\n\t\t\t// NcAppSettingsSection also asks its dialog whether to use the legacy design.\n\t\t\t[LEGACY_DESIGN_KEY]: ref(false),\n\t\t}\n\t},\n\n\tprops: {\n\t\t/** Whether the dialog is open. */\n\t\topen: { type: Boolean, default: false },\n\t\t/** Dialog title; also its accessible name. */\n\t\ttitle: { type: String, required: true },\n\t\t/**\n\t\t * Deprecated and ignored: the board draws no line above the title.\n\t\t * Kept so a host that passes it stays valid.\n\t\t *\n\t\t * @deprecated\n\t\t */\n\t\teyebrow: { type: String, default: () => t('nextcloud-vue', 'Your account') },\n\t\t/**\n\t\t * Deprecated and ignored: the board draws no line under the title.\n\t\t * Kept so a host that passes it stays valid.\n\t\t *\n\t\t * @deprecated\n\t\t */\n\t\tsubtitle: { type: String, default: () => t('nextcloud-vue', 'Only for you. Colleagues keep their own settings.') },\n\t\t/** The app's name, after the footer note and as the navigation entry holding its sections. */\n\t\tappName: { type: String, default: '' },\n\t\t/**\n\t\t * Nextcloud's own personal settings, listed first in the navigation as\n\t\t * links: `[{ label, section? | href?, icon? }]`. `section` is a\n\t\t * personal settings section id (`/settings/user/<section>`). With any,\n\t\t * the app's sections sit under one entry named after the app.\n\t\t */\n\t\tnextcloudLinks: { type: Array, default: () => [] },\n\t},\n\n\temits: ['update:open'],\n\n\tdata() {\n\t\treturn {\n\t\t\tsections: [],\n\t\t\tselected: '',\n\t\t\tpicked: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The Nextcloud links with their URL.\n\t\t *\n\t\t * @spec openspec/changes/user-settings-nav-groups/specs/user-settings-board-dialog/spec.md#requirement-the-board-user-settings-navigation-can-list-nextclouds-own-sections-first\n\t\t * @return {Array<{key: string, label: string, href: string, icon: string}>}\n\t\t */\n\t\tncLinks() {\n\t\t\treturn (Array.isArray(this.nextcloudLinks) ? this.nextcloudLinks : [])\n\t\t\t\t.filter((link) => link && typeof link === 'object' && typeof link.label === 'string' && link.label !== '' && (link.href || link.section))\n\t\t\t\t.map((link, index) => ({\n\t\t\t\t\tkey: String(link.section || link.href || index),\n\t\t\t\t\tlabel: link.label,\n\t\t\t\t\thref: link.href || generateUrl('/settings/user/{section}', { section: String(link.section) }),\n\t\t\t\t\ticon: typeof link.icon === 'string' ? link.icon : '',\n\t\t\t\t}))\n\t\t},\n\n\t\t/** @return {object} The board's 900px width, over CnDialog's width roles. */\n\t\tframeStyle() {\n\t\t\treturn { '--cn-dialog-width': '900px' }\n\t\t},\n\n\t\t/** @return {string} The navigation's accessible name. */\n\t\tnavLabel() {\n\t\t\treturn t('nextcloud-vue', 'Sections of the settings')\n\t\t},\n\n\t\t/** @return {string} The footer note, with the app's name when known. */\n\t\tfooterNote() {\n\t\t\tconst note = t('nextcloud-vue', 'Changes are saved straight away')\n\t\t\treturn this.appName ? `${note} · ${this.appName}` : note\n\t\t},\n\n\t\t/** @return {string} The Close button label. */\n\t\tcloseLabel() {\n\t\t\treturn t('nextcloud-vue', 'Close')\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Add a section to the navigation, kept in `order`; a section\n\t\t * without one goes last. Until the reader picks one, the first\n\t\t * section is current.\n\t\t *\n\t\t * @param {string} id The section id.\n\t\t * @param {string} name The section name.\n\t\t * @param {number} [order] The section's place. A section's icon, the\n\t\t * fourth argument NcAppSettingsSection passes, is not drawn: the\n\t\t * board lists the sections by name alone.\n\t\t */\n\t\tregisterSection(id, name, order) {\n\t\t\tconst rest = this.sections.filter((section) => section.id !== id)\n\t\t\tconst place = typeof order === 'number' ? order : Math.max(0, ...rest.map((section) => section.order)) + 1\n\t\t\tthis.sections = [...rest, { id, name, order: place }].sort((a, b) => a.order - b.order)\n\t\t\tif (!this.picked) {\n\t\t\t\tthis.selected = this.sections[0].id\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Remove a section from the navigation.\n\t\t *\n\t\t * @param {string} id The section id.\n\t\t */\n\t\tunregisterSection(id) {\n\t\t\tthis.sections = this.sections.filter((section) => section.id !== id)\n\t\t\tif (this.selected === id) {\n\t\t\t\tthis.selected = this.sections.length > 0 ? this.sections[0].id : ''\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Mark a section current, scroll it to the top of the pane and focus\n\t\t * its heading. Every section stays in the pane.\n\t\t *\n\t\t * @param {string} id The section id.\n\t\t */\n\t\tselectSection(id) {\n\t\t\tthis.picked = true\n\t\t\tthis.selected = id\n\t\t\tthis.$nextTick(() => {\n\t\t\t\tconst el = typeof document !== 'undefined' ? document.getElementById(`settings-section_${id}`) : null\n\t\t\t\tif (el && typeof el.scrollIntoView === 'function') {\n\t\t\t\t\tel.scrollIntoView({ block: 'start', behavior: 'smooth' })\n\t\t\t\t}\n\t\t\t\tconst heading = typeof document !== 'undefined' ? document.getElementById(`settings-section_${id}--label`) : null\n\t\t\t\tif (heading) {\n\t\t\t\t\theading.setAttribute('tabindex', '-1')\n\t\t\t\t\theading.focus({ preventScroll: true })\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Follow NcDialog's own open state.\n\t\t *\n\t\t * @param {boolean} value Whether NcDialog is open.\n\t\t */\n\t\tonUpdateOpen(value) {\n\t\t\tif (!value) {\n\t\t\t\tthis.close()\n\t\t\t}\n\t\t},\n\n\t\t/** Close the dialog. */\n\t\tclose() {\n\t\t\t/**\n\t\t\t * @event update:open Emitted with `false` when the dialog closes (Close button, close icon, Escape).\n\t\t\t */\n\t\t\tthis.$emit('update:open', false)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n/* The DqPersoonlijkeInstellingen board: a tinted navigation column with the\n title on top, the sections on a white pane beside it, and the close icon\n in the corner. The dialog's frame (900px, its tint, no padding) is in\n dialog.css, on the teleported container. */\n.cn-user-settings-dialog__body {\n\tposition: relative;\n\tdisplay: flex;\n\tmin-height: 440px;\n\tmax-height: min(760px, calc(100vh - 112px));\n}\n\n.cn-user-settings-dialog__nav {\n\tdisplay: flex;\n\tflex: 0 0 200px;\n\tflex-direction: column;\n\tgap: 2px;\n\tbox-sizing: border-box;\n\twidth: 200px;\n\tpadding: 0 4px 12px;\n\toverflow-y: auto;\n}\n\n.cn-user-settings-dialog__title {\n\tmargin: 0;\n\tpadding: 14px 10px 12px;\n\tfont-size: 20px;\n\tfont-weight: 700;\n\tline-height: 1.25;\n\tcolor: var(--color-main-text);\n}\n\n.cn-user-settings-dialog__nav ul {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n\n/* A navigation entry, not a link in running text: no underline, also not\n on hover. `!important` because a theme's `a { text-decoration }` carries\n it (thematiq), and a bare `a` with `!important` beats any class. */\n.cn-user-settings-dialog__nav-link,\n.cn-user-settings-dialog__nav-link:visited {\n\tposition: relative;\n\tdisplay: flex;\n\talign-items: center;\n\tmin-height: 36px;\n\tpadding: 0 10px;\n\tborder-radius: var(--border-radius-element, 8px);\n\tfont-size: 15px;\n\tfont-weight: 500;\n\tcolor: var(--color-main-text);\n\ttext-decoration: none !important;\n}\n\n.cn-user-settings-dialog__nav-label {\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n.cn-user-settings-dialog__nav-link:hover {\n\tbackground: color-mix(in srgb, var(--color-primary-element) 8%, transparent);\n\ttext-decoration: none !important;\n}\n\n.cn-user-settings-dialog__nav-link:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 2px;\n}\n\n/* The open section: a stronger tint and a 3px bar at the left edge. */\n.cn-user-settings-dialog__nav-link--active,\n.cn-user-settings-dialog__nav-link--active:hover {\n\tbackground: color-mix(in srgb, var(--color-primary-element) 16%, var(--color-primary-element-light));\n}\n\n.cn-user-settings-dialog__nav-link--active::before {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 6px;\n\tbottom: 6px;\n\tinset-inline-start: 0;\n\twidth: 3px;\n\tborder-radius: 2px;\n\tbackground: var(--color-primary-element);\n}\n\n.cn-user-settings-dialog__group {\n\tmargin: 10px 0 2px;\n\tpadding: 0 10px;\n\tfont-size: 15px;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-user-settings-dialog__group-sections {\n\tpadding-inline-start: 10px;\n}\n\n.cn-user-settings-dialog__sections {\n\tdisplay: flex;\n\tflex: 1 1 auto;\n\tflex-direction: column;\n\tgap: 32px;\n\tbox-sizing: border-box;\n\tmin-width: 0;\n\tpadding: 20px 64px 20px 24px;\n\toverflow-y: auto;\n\tborder-inline-start: 1px solid var(--color-border);\n\tborder-radius: 8px 0 0 8px;\n\tbackground: var(--color-main-background);\n}\n\n.cn-user-settings-dialog__sections :deep(.app-settings-section) {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n}\n\n.cn-user-settings-dialog__sections :deep(.app-settings-section__name) {\n\tmargin: 0 0 6px;\n\tfont-size: 20px;\n\tfont-weight: 700;\n\tline-height: 1.3;\n}\n\n.cn-user-settings-dialog__note {\n\tmargin: 0;\n\tfont-size: 14px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-user-settings-dialog__close {\n\tposition: absolute;\n\ttop: 8px;\n\tinset-inline-end: 8px;\n}\n\n@media (max-width: 600px) {\n\t.cn-user-settings-dialog__body {\n\t\tflex-direction: column;\n\t}\n\n\t.cn-user-settings-dialog__nav {\n\t\tflex-basis: auto;\n\t\twidth: auto;\n\t\tmax-height: 40vh;\n\t}\n\n\t.cn-user-settings-dialog__sections {\n\t\tpadding: 20px 16px;\n\t\tborder-inline-start: 0;\n\t\tborder-radius: 8px 8px 0 0;\n\t}\n}\n</style>\n"],"names":["CnDialog","t"],"mappings":"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"}
@@ -1,39 +1,33 @@
1
- import { resolveComponent, openBlock, createBlock, normalizeStyle, withCtx, createElementVNode, toDisplayString, createVNode, createTextVNode, createElementBlock, Fragment, renderList, createCommentVNode, normalizeClass, withModifiers, renderSlot, Teleport } from 'vue';
1
+ import { resolveComponent, openBlock, createBlock, normalizeStyle, withCtx, createElementVNode, toDisplayString, createElementBlock, Fragment, renderList, createCommentVNode, normalizeClass, withModifiers, renderSlot, createVNode } from 'vue';
2
2
 
3
3
  const _hoisted_1 = { class: "cn-user-settings-dialog__body" };
4
4
  const _hoisted_2 = ["aria-label"];
5
5
  const _hoisted_3 = {
6
+ class: "cn-user-settings-dialog__title",
7
+ "data-testid": "cn-user-settings-title"
8
+ };
9
+ const _hoisted_4 = {
6
10
  key: 0,
7
11
  class: "cn-user-settings-dialog__nc-links",
8
12
  "data-testid": "cn-user-settings-nc-links"
9
13
  };
10
- const _hoisted_4 = ["href"];
11
- const _hoisted_5 = {
12
- key: 0,
13
- class: "cn-user-settings-dialog__nav-icon",
14
- "aria-hidden": "true"
15
- };
16
- const _hoisted_6 = {
14
+ const _hoisted_5 = ["href"];
15
+ const _hoisted_6 = { class: "cn-user-settings-dialog__nav-label" };
16
+ const _hoisted_7 = {
17
17
  key: 1,
18
18
  class: "cn-user-settings-dialog__group",
19
19
  "data-testid": "cn-user-settings-app-group"
20
20
  };
21
- const _hoisted_7 = ["href", "aria-current", "data-testid", "onClick"];
22
- const _hoisted_8 = {
23
- key: 0,
24
- class: "cn-user-settings-dialog__nav-icon",
25
- "aria-hidden": "true"
26
- };
27
- const _hoisted_9 = { class: "cn-user-settings-dialog__sections" };
28
- const _hoisted_10 = ["data-testid"];
21
+ const _hoisted_8 = ["href", "aria-current", "data-testid", "onClick"];
22
+ const _hoisted_9 = { class: "cn-user-settings-dialog__nav-label" };
23
+ const _hoisted_10 = { class: "cn-user-settings-dialog__sections" };
29
24
  const _hoisted_11 = {
30
25
  class: "cn-user-settings-dialog__note",
31
26
  "data-testid": "cn-user-settings-note"
32
27
  };
33
28
 
34
29
  function render(_ctx, _cache, $props, $setup, $data, $options) {
35
- const _component_CnIcon = resolveComponent("CnIcon");
36
- const _component_CnVNodes = resolveComponent("CnVNodes");
30
+ const _component_Close = resolveComponent("Close");
37
31
  const _component_NcButton = resolveComponent("NcButton");
38
32
  const _component_CnDialog = resolveComponent("CnDialog");
39
33
 
@@ -41,121 +35,81 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
41
35
  class: "cn-user-settings-dialog",
42
36
  name: $props.title,
43
37
  look: "board",
44
- width: "wizard",
45
- eyebrow: $props.eyebrow,
46
- subtitle: $props.subtitle,
38
+ headless: "",
47
39
  open: $props.open,
48
- style: normalizeStyle($options.eyebrowStyle),
40
+ style: normalizeStyle($options.frameStyle),
49
41
  "data-testid": "cn-user-settings-dialog",
50
42
  "onUpdate:open": $options.onUpdateOpen,
51
43
  onClosing: $options.close
52
44
  }, {
53
- actions: withCtx(() => [
54
- createElementVNode("p", _hoisted_11, toDisplayString($options.footerNote), 1 /* TEXT */),
55
- createVNode(_component_NcButton, {
56
- variant: "secondary",
57
- "data-testid": "cn-user-settings-close",
58
- onClick: $options.close
59
- }, {
60
- default: withCtx(() => [
61
- createTextVNode(toDisplayString($options.closeLabel), 1 /* TEXT */)
62
- ]),
63
- _: 1 /* STABLE */
64
- }, 8 /* PROPS */, ["onClick"])
65
- ]),
66
45
  default: withCtx(() => [
67
46
  createElementVNode("div", _hoisted_1, [
68
- ($data.sections.length > 0)
69
- ? (openBlock(), createElementBlock("nav", {
70
- key: 0,
71
- class: "cn-user-settings-dialog__nav",
72
- "aria-label": $options.navLabel,
73
- "data-testid": "cn-user-settings-nav"
74
- }, [
75
- ($options.ncLinks.length > 0)
76
- ? (openBlock(), createElementBlock("ul", _hoisted_3, [
77
- (openBlock(true), createElementBlock(Fragment, null, renderList($options.ncLinks, (link) => {
78
- return (openBlock(), createElementBlock("li", {
79
- key: link.key
80
- }, [
81
- createElementVNode("a", {
82
- href: link.href,
83
- class: "cn-user-settings-dialog__nav-link"
84
- }, [
85
- (link.icon)
86
- ? (openBlock(), createElementBlock("span", _hoisted_5, [
87
- createVNode(_component_CnIcon, {
88
- name: link.icon,
89
- size: 18
90
- }, null, 8 /* PROPS */, ["name"])
91
- ]))
92
- : createCommentVNode("v-if", true),
93
- createElementVNode("span", null, toDisplayString(link.label), 1 /* TEXT */)
94
- ], 8 /* PROPS */, _hoisted_4)
95
- ]))
96
- }), 128 /* KEYED_FRAGMENT */))
97
- ]))
98
- : createCommentVNode("v-if", true),
99
- ($options.ncLinks.length > 0 && $props.appName)
100
- ? (openBlock(), createElementBlock("p", _hoisted_6, toDisplayString($props.appName), 1 /* TEXT */))
101
- : createCommentVNode("v-if", true),
102
- createElementVNode("ul", {
103
- class: normalizeClass({ 'cn-user-settings-dialog__group-sections': $options.ncLinks.length > 0 })
104
- }, [
105
- (openBlock(true), createElementBlock(Fragment, null, renderList($data.sections, (section) => {
47
+ createElementVNode("nav", {
48
+ class: "cn-user-settings-dialog__nav",
49
+ "aria-label": $options.navLabel,
50
+ "data-testid": "cn-user-settings-nav"
51
+ }, [
52
+ createElementVNode("h2", _hoisted_3, toDisplayString($props.title), 1 /* TEXT */),
53
+ ($options.ncLinks.length > 0)
54
+ ? (openBlock(), createElementBlock("ul", _hoisted_4, [
55
+ (openBlock(true), createElementBlock(Fragment, null, renderList($options.ncLinks, (link) => {
106
56
  return (openBlock(), createElementBlock("li", {
107
- key: section.id
57
+ key: link.key
108
58
  }, [
109
59
  createElementVNode("a", {
110
- href: `#settings-section_${section.id}`,
111
- class: normalizeClass(["cn-user-settings-dialog__nav-link", { 'cn-user-settings-dialog__nav-link--active': section.id === $data.selected }]),
112
- "aria-current": section.id === $data.selected ? 'true' : undefined,
113
- "data-testid": `cn-user-settings-nav-${section.id}`,
114
- onClick: withModifiers($event => ($options.selectSection(section.id)), ["prevent"])
60
+ href: link.href,
61
+ class: "cn-user-settings-dialog__nav-link"
115
62
  }, [
116
- (section.icon)
117
- ? (openBlock(), createElementBlock("span", _hoisted_8, [
118
- createVNode(_component_CnVNodes, {
119
- vnodes: section.icon
120
- }, null, 8 /* PROPS */, ["vnodes"])
121
- ]))
122
- : createCommentVNode("v-if", true),
123
- createElementVNode("span", null, toDisplayString(section.name), 1 /* TEXT */)
124
- ], 10 /* CLASS, PROPS */, _hoisted_7)
63
+ createElementVNode("span", _hoisted_6, toDisplayString(link.label), 1 /* TEXT */)
64
+ ], 8 /* PROPS */, _hoisted_5)
125
65
  ]))
126
66
  }), 128 /* KEYED_FRAGMENT */))
127
- ], 2 /* CLASS */)
128
- ], 8 /* PROPS */, _hoisted_2))
129
- : createCommentVNode("v-if", true),
130
- createElementVNode("div", _hoisted_9, [
67
+ ]))
68
+ : createCommentVNode("v-if", true),
69
+ ($options.ncLinks.length > 0 && $props.appName)
70
+ ? (openBlock(), createElementBlock("p", _hoisted_7, toDisplayString($props.appName), 1 /* TEXT */))
71
+ : createCommentVNode("v-if", true),
72
+ createElementVNode("ul", {
73
+ class: normalizeClass({ 'cn-user-settings-dialog__group-sections': $options.ncLinks.length > 0 })
74
+ }, [
75
+ (openBlock(true), createElementBlock(Fragment, null, renderList($data.sections, (section) => {
76
+ return (openBlock(), createElementBlock("li", {
77
+ key: section.id
78
+ }, [
79
+ createElementVNode("a", {
80
+ href: `#settings-section_${section.id}`,
81
+ class: normalizeClass(["cn-user-settings-dialog__nav-link", { 'cn-user-settings-dialog__nav-link--active': section.id === $data.selected }]),
82
+ "aria-current": section.id === $data.selected ? 'true' : undefined,
83
+ "data-testid": `cn-user-settings-nav-${section.id}`,
84
+ onClick: withModifiers($event => ($options.selectSection(section.id)), ["prevent"])
85
+ }, [
86
+ createElementVNode("span", _hoisted_9, toDisplayString(section.name), 1 /* TEXT */)
87
+ ], 10 /* CLASS, PROPS */, _hoisted_8)
88
+ ]))
89
+ }), 128 /* KEYED_FRAGMENT */))
90
+ ], 2 /* CLASS */)
91
+ ], 8 /* PROPS */, _hoisted_2),
92
+ createElementVNode("div", _hoisted_10, [
131
93
  renderSlot(_ctx.$slots, "default"),
132
- (openBlock(true), createElementBlock(Fragment, null, renderList($data.sections, (section) => {
133
- return (openBlock(), createElementBlock(Fragment, {
134
- key: `heading-icon-${section.id}-${section.name}`
135
- }, [
136
- (section.icon && $data.headingTargets.includes(section.id))
137
- ? (openBlock(), createBlock(Teleport, {
138
- key: 0,
139
- to: `#settings-section_${section.id}--label`
140
- }, [
141
- createElementVNode("span", {
142
- class: "cn-user-settings-dialog__heading-icon",
143
- "aria-hidden": "true",
144
- "data-testid": `cn-user-settings-heading-icon-${section.id}`
145
- }, [
146
- createVNode(_component_CnVNodes, {
147
- vnodes: section.icon
148
- }, null, 8 /* PROPS */, ["vnodes"])
149
- ], 8 /* PROPS */, _hoisted_10)
150
- ], 8 /* PROPS */, ["to"]))
151
- : createCommentVNode("v-if", true)
152
- ], 64 /* STABLE_FRAGMENT */))
153
- }), 128 /* KEYED_FRAGMENT */))
154
- ])
94
+ createElementVNode("p", _hoisted_11, toDisplayString($options.footerNote), 1 /* TEXT */)
95
+ ]),
96
+ createVNode(_component_NcButton, {
97
+ class: "cn-user-settings-dialog__close",
98
+ variant: "tertiary",
99
+ "aria-label": $options.closeLabel,
100
+ title: $options.closeLabel,
101
+ "data-testid": "cn-user-settings-close",
102
+ onClick: $options.close
103
+ }, {
104
+ icon: withCtx(() => [
105
+ createVNode(_component_Close, { size: 20 })
106
+ ]),
107
+ _: 1 /* STABLE */
108
+ }, 8 /* PROPS */, ["aria-label", "title", "onClick"])
155
109
  ])
156
110
  ]),
157
111
  _: 3 /* FORWARDED */
158
- }, 8 /* PROPS */, ["name", "eyebrow", "subtitle", "open", "style", "onUpdate:open", "onClosing"]))
112
+ }, 8 /* PROPS */, ["name", "open", "style", "onUpdate:open", "onClosing"]))
159
113
  }
160
114
 
161
115
  export { render };