@conduction/nextcloud-vue 2.136.0 → 2.137.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.
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +9 -0
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +4 -3
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +4 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +61 -28
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +20 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +33 -25
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +13 -0
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +2 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +36 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +4 -4
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +11 -0
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js +10 -2
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue.js +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js.map +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js +1 -0
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js.map +1 -1
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue.js +1 -1
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnSavedViewMenuSettings/CnSavedViewMenuSettings.vue.js +1 -1
- package/dist/esm/components/CnSavedViewMenuSettings/CnSavedViewMenuSettings.vue2.js +14 -4
- package/dist/esm/components/CnSavedViewMenuSettings/CnSavedViewMenuSettings.vue2.js.map +1 -1
- package/dist/esm/components/CnSavedViewMenuSettings/CnSavedViewMenuSettings.vue3.js.map +1 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue.js +1 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue2.js +10 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue2.js.map +1 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue3.js +29 -13
- package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue3.js.map +1 -1
- package/dist/esm/components/CnTimelineWidget/dashboardRegistration.js +3 -1
- package/dist/esm/components/CnTimelineWidget/dashboardRegistration.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +258 -160
- package/dist/esm/utils/contentHeaderLink.js +7 -1
- package/dist/esm/utils/contentHeaderLink.js.map +1 -1
- package/dist/esm/utils/savedViewMenu.js +4 -1
- package/dist/esm/utils/savedViewMenu.js.map +1 -1
- package/dist/esm/utils/savedViewSummary.js +11 -4
- package/dist/esm/utils/savedViewSummary.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +422 -225
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +258 -160
- package/package.json +1 -1
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +13 -1
- package/src/components/CnAppNav/CnAppNav.vue +28 -3
- package/src/components/CnDataTable/CnDataTable.vue +25 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +14 -1
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +1 -0
- package/src/components/CnIndexPage/CnIndexPage.vue +40 -5
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.md +1 -0
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +21 -0
- package/src/components/CnRegisterMapping/CnRegisterMapping.vue +7 -0
- package/src/components/CnRetentionWidget/CnRetentionWidget.vue +13 -0
- package/src/components/CnSavedViewMenuSettings/CnSavedViewMenuSettings.vue +14 -4
- package/src/components/CnTimelineWidget/CnTimelineManage.vue +23 -0
- package/src/components/CnTimelineWidget/dashboardRegistration.js +3 -1
- package/src/css/look-board-detail.css +10 -0
- package/src/css/look-board-index.css +50 -0
- package/src/css/look-board.css +5 -1
- package/src/css/table.css +5 -0
- package/src/schemas/app-manifest-v2.schema.json +4 -2
- package/src/utils/contentHeaderLink.js +7 -1
- package/src/utils/savedViewMenu.js +4 -1
- package/src/utils/savedViewSummary.js +11 -4
- package/src/utils/validateManifestV2.compiled.js +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnAppNav.vue2.js","sources":["../../../../src/components/CnAppNav/CnAppNav.vue"],"sourcesContent":["<!--\n CnAppNav — manifest-driven app navigation.\n\n Renders the manifest's `menu[]` array as a Nextcloud app navigation\n (NcAppNavigation + NcAppNavigationItem). One level of nested\n `children[]` is supported. Items are sorted by `order` at BOTH levels —\n top-level entries and a group's children — and items without an order\n render last. Items with a `permission` are filtered against\n the `permissions` prop — when the prop is omitted, all items render.\n\n An optional primary action renders above the main list as an\n NcAppNavigationNew button (e.g. a \"new\" button or an active-context\n switcher). Hosts supply it via the `#primary-action` slot (full\n control over dynamic content + click handling); a static\n `nav.primaryAction` ({ label, icon?, route?, href? }) manifest field\n is the declarative fallback. The slot wins when both are present;\n nothing renders when neither is.\n\n Items split into three RENDERED groups by `section`, plus one section\n this component deliberately renders nowhere:\n - `section: \"main\"` (default) — top of the navigation, scrollable.\n - `section: \"footer\"` — rendered in NcAppNavigation's `#footer` slot,\n OUTSIDE the scrollable list and directly above the settings foldout,\n so they stay visible regardless of how long the main menu is. (The\n earlier `pinned`-prop approach kept them inside the scroll container:\n `margin-top: auto` only bottom-pins while the list does not overflow,\n so apps with long menus showed them mid-scroll.) For always-visible,\n non-settings links: Documentation, Features & Roadmap, About.\n - `section: \"settings\"` — rendered INSIDE an NcAppNavigationSettings\n foldout (the NC-native gear-icon button that slides a panel open).\n A \"Personal settings\" entry is auto-prepended at the top of the\n foldout (opens the host app's NcAppSettingsDialog via\n cnOpenUserSettings); opt out with `nav.includePersonalSettings:\n false`. Right below it, an \"Admin settings\" entry is auto-prepended\n for INSTANCE ADMINS only — gated on the `isAdmin` prop (computed by\n CnAppRoot from `getCurrentUser()?.isAdmin`). It is a LINK to\n `/settings/admin/<appId>` that opens in a NEW TAB and carries an\n open-in-new marker (the destination is outside the app — the marker\n says so up front, the new tab keeps the app open), not a modal: per\n ADR-079 app-level\n configuration lives in Nextcloud's own settings framework, which\n authorizes it server-side. `isAdmin` gates VISIBILITY only and is\n never an authorization decision; it is also NOT interchangeable with\n `isOwner`, which means \"owns this app\" rather than \"administers this\n instance\" and keeps its own separate uses. The\n foldout mounts whenever there are settings items OR personal\n settings is enabled — so every app shows a Settings gear with at\n least Personal settings. It is only fully suppressed when there are\n no settings items AND `nav.includePersonalSettings: false`.\n - `section: \"integrations\"` — rendered by this component NOWHERE. Per\n ADR-110 these are the links that LEAVE this app for another one, and\n they belong in the Integrations section at the bottom of the per-user\n settings modal, which CnAppRoot owns. A link to another app cannot be\n the active route and carries no counter, so putting it in the nav\n makes another app's capability read as this app's feature. The one\n deep link that stays in the navigation is the auto-prepended Admin\n settings above — apps never declare that one themselves.\n\n Manifest and translate are injected from CnAppRoot by default but can\n also be passed as props for standalone use without CnAppRoot. Props\n win over inject when both are present.\n\n Items can opt out of routing in favour of a built-in action by\n setting `action` on the manifest entry. Supported keywords:\n `\"user-settings\"` invokes the `cnOpenUserSettings` provide-injected\n by CnAppRoot, which opens the host app's NcAppSettingsDialog modal;\n `\"admin-settings\"` opens `/settings/admin/<appId>` in a new tab (ADR-079);\n `\"replay-walkthrough\"` invokes `cnReplayWalkthrough` (optionally\n with the item's `tourId`) to re-run the product walkthrough from\n the first step (ADR-043). Both `route` and `href` are ignored when\n `action` is set. The injects default to a no-op so CnAppNav stays\n usable standalone (without a CnAppRoot ancestor).\n\n See REQ-JMR-004 of the json-manifest-renderer specification.\n-->\n<template>\n\t<NcAppNavigation :aria-label=\"ariaLabel\" data-testid=\"cn-nav\">\n\t\t<template v-if=\"$slots.search || $slots.brand || navBrand\" #search>\n\t\t\t<!--\n\t\t\t\t@slot brand\n\t\t\t\t@description Replace the brand block at the very top of the\n\t\t\t\tnavigation. Default content: the logo, name and caption from\n\t\t\t\tthe `brand` prop or the manifest's `nav.brand`. Renders\n\t\t\t\tnothing when neither is set.\n\t\t\t\t@binding {object|null} brand The resolved brand (`{ logo, name, caption, alt }`), or null.\n\t\t\t-->\n\t\t\t<slot name=\"brand\" :brand=\"resolvedBrand\">\n\t\t\t\t<div\n\t\t\t\t\tv-if=\"navBrand\"\n\t\t\t\t\tclass=\"cn-app-nav__brand\"\n\t\t\t\t\tdata-testid=\"cn-nav-brand\">\n\t\t\t\t\t<!-- Decorative beside a name: the name already says whose\n\t\t\t\t\t app this is, and an alt text would say it twice. A logo\n\t\t\t\t\t on its own carries the name as its alt text. -->\n\t\t\t\t\t<!-- An emblem (`nav.brand.emblem`) stands in for the logo:\n\t\t\t\t\t the municipality's mark beside the app name, distinct\n\t\t\t\t\t from the wordmark in the top bar. `true` draws the\n\t\t\t\t\t theme's emblem from --nldesign-emblem-url. -->\n\t\t\t\t\t<img\n\t\t\t\t\t\tv-if=\"typeof resolvedBrand.emblem === 'string' && resolvedBrand.emblem !== ''\"\n\t\t\t\t\t\tclass=\"cn-app-nav__brand-emblem\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-brand-emblem\"\n\t\t\t\t\t\t:src=\"resolvedBrand.emblem\"\n\t\t\t\t\t\t:alt=\"resolvedBrand.name ? '' : resolvedBrand.alt\">\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-else-if=\"resolvedBrand.emblem === true\"\n\t\t\t\t\t\tclass=\"cn-app-nav__brand-emblem cn-app-nav__brand-emblem--theme\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-brand-emblem\"\n\t\t\t\t\t\taria-hidden=\"true\" />\n\t\t\t\t\t<img\n\t\t\t\t\t\tv-else-if=\"resolvedBrand.logo\"\n\t\t\t\t\t\tclass=\"cn-app-nav__brand-logo\"\n\t\t\t\t\t\t:src=\"resolvedBrand.logo\"\n\t\t\t\t\t\t:alt=\"resolvedBrand.name ? '' : resolvedBrand.alt\">\n\t\t\t\t\t<span v-if=\"resolvedBrand.name || resolvedBrand.caption\" class=\"cn-app-nav__brand-text\">\n\t\t\t\t\t\t<strong v-if=\"resolvedBrand.name\" class=\"cn-app-nav__brand-name\">{{ resolvedBrand.name }}</strong>\n\t\t\t\t\t\t<span v-if=\"resolvedBrand.caption\" class=\"cn-app-nav__brand-caption\">{{ resolvedBrand.caption }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</slot>\n\t\t\t<!--\n\t\t\t\t@slot search\n\t\t\t\t@description Forwarded into NcAppNavigation's #search slot.\n\t\t\t\tHosts mount NcAppNavigationSearch here. When unset, no search\n\t\t\t\tinput renders inside the navigation.\n\t\t\t-->\n\t\t\t<slot name=\"search\" />\n\t\t</template>\n\t\t<!-- @slot primary-action Optional primary action rendered above the\n\t\t main list as NcAppNavigation's top region (e.g. an app's \"new\"\n\t\t button or an active-context switcher). When provided, it takes\n\t\t precedence over the manifest-declared primaryAction (page-scoped\n\t\t OR nav root). Omitted entirely when neither the slot nor any\n\t\t resolvable primaryAction is present. -->\n\t\t<slot name=\"primary-action\">\n\t\t\t<!-- A primary action that carries an `action` runs a page action\n\t\t\t (open-form opens the create dialog, navigate pushes a route)\n\t\t\t through CnActionButtons, so \"New case\" can live in the\n\t\t\t navigation without a create page. Drawn as one solid,\n\t\t\t full-width primary button. -->\n\t\t\t<div\n\t\t\t\tv-if=\"activePrimaryAction && primaryDispatchEntry\"\n\t\t\t\tclass=\"app-navigation-new cn-app-nav__primary-action cn-app-nav__primary-action--solid\"\n\t\t\t\tdata-testid=\"cn-nav-primary-action\">\n\t\t\t\t<CnActionButtons\n\t\t\t\t\t:actions=\"[primaryDispatchEntry]\"\n\t\t\t\t\tdata-testid=\"cn-nav-primary-action-dispatch\"\n\t\t\t\t\t@created=\"onPrimaryActionCreated\" />\n\t\t\t</div>\n\t\t\t<!-- A primary action with an href or route is a real link.\n\t\t\t NcAppNavigationNew cannot render one, so this mirrors its\n\t\t\t wrapper and button. `solid: true` takes this same solid,\n\t\t\t full-width button for an action with neither. -->\n\t\t\t<div\n\t\t\t\tv-else-if=\"activePrimaryAction && (primaryActionLink || activePrimaryAction.solid === true)\"\n\t\t\t\tclass=\"app-navigation-new cn-app-nav__primary-action\"\n\t\t\t\t:class=\"{ 'cn-app-nav__primary-action--solid': activePrimaryAction.solid === true }\"\n\t\t\t\tdata-testid=\"cn-nav-primary-action\">\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\twide\n\t\t\t\t\tv-bind=\"primaryActionLink || {}\"\n\t\t\t\t\t@click=\"onPrimaryActionClick\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<component :is=\"primaryActionIconComponent\" :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ resolveLabel(activePrimaryAction) }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t\t<NcAppNavigationNew\n\t\t\t\tv-else-if=\"activePrimaryAction\"\n\t\t\t\t:text=\"resolveLabel(activePrimaryAction)\"\n\t\t\t\tdata-testid=\"cn-nav-primary-action\"\n\t\t\t\t@click=\"onPrimaryActionClick\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<component :is=\"primaryActionIconComponent\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t</NcAppNavigationNew>\n\t\t</slot>\n\t\t<template #list>\n\t\t\t<template v-for=\"item in mainItems\">\n\t\t\t\t<NcAppNavigationCaption\n\t\t\t\t\tv-if=\"isCaption(item)\"\n\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\t:name=\"resolveLabel(item)\"\n\t\t\t\t\t:data-testid=\"`cn-nav-caption-${item.id}`\">\n\t\t\t\t\t<template v-if=\"item.href\" #actions>\n\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\t:href=\"item.href\"\n\t\t\t\t\t\t\t:aria-label=\"captionEditLabel(item)\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-nav-caption-edit-${item.id}`\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Pencil :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ captionEditLabel(item) }}\n\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t</template>\n\t\t\t\t</NcAppNavigationCaption>\n\t\t\t\t<!-- `type: \"hint\"`: a muted line, no link, as the empty \"My\n\t\t\t\t filters\" group says how to add a filter. -->\n\t\t\t\t<li\n\t\t\t\t\tv-else-if=\"item.type === 'hint'\"\n\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\tclass=\"cn-app-nav__hint\"\n\t\t\t\t\t:data-testid=\"`cn-nav-hint-${item.id}`\">\n\t\t\t\t\t{{ resolveLabel(item) }}\n\t\t\t\t</li>\n\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\tv-else\n\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\t:name=\"resolveLabel(item)\"\n\t\t\t\t\t:title=\"itemTooltip(item)\"\n\t\t\t\t\t:to=\"linkTo(item)\"\n\t\t\t\t\t:href=\"linkHref(item)\"\n\t\t\t\t\t:icon=\"cssIconClass(item)\"\n\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t:pinned=\"Boolean(item.pinned)\"\n\t\t\t\t\t:allowCollapse=\"visibleChildren(item).length > 0\"\n\t\t\t\t\t:open=\"isItemOpen(item)\"\n\t\t\t\t\t:data-testid=\"`cn-nav-entry-${item.id}`\"\n\t\t\t\t\t:data-cn-route=\"item.route\"\n\t\t\t\t\t@update:open=\"setItemOpen(item, $event)\"\n\t\t\t\t\t@click=\"onItemClick(item, $event)\">\n\t\t\t\t\t<template v-if=\"mdiIconComponent(item) || isRichIcon(item) || isRegistryIcon(item) || isUnresolvedIcon(item)\" #icon>\n\t\t\t\t\t\t<component :is=\"mdiIconComponent(item)\" v-if=\"mdiIconComponent(item)\" :size=\"20\" />\n\t\t\t\t\t\t<HelpCircleOutline v-else-if=\"isUnresolvedIcon(item)\" :size=\"20\" />\n\t\t\t\t\t\t<CnMenuItemIcon v-else :icon=\"item.icon\" :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t<template v-if=\"resolveCount(item)\" #counter>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tv-if=\"isBoard\"\n\t\t\t\t\t\t\tclass=\"cn-app-nav__count\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-app-nav__count--attention': isAttention(item) }\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-nav-count-${item.id}`\">\n\t\t\t\t\t\t\t{{ resolveCount(item) }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcCounterBubble\n\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t:count=\"resolveCount(item)\"\n\t\t\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t\t\t:type=\"isAttention(item) ? 'highlighted' : undefined\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t<template v-if=\"hasItemActionsSlot(item)\" #actions>\n\t\t\t\t\t\t<!--\n\t\t\t\t\t\t\t@slot `item-${item.id}-actions`\n\t\t\t\t\t\t\t@description Per-item scoped slot whose content lands inside\n\t\t\t\t\t\t\tthe NcAppNavigationItem's #actions slot for the menu entry\n\t\t\t\t\t\t\twith that id. Use it for inline NcActions menus (e.g. an\n\t\t\t\t\t\t\titem-level \"Pin\" button). Scope receives the menu item.\n\t\t\t\t\t\t\t@binding {object} item The menu item descriptor.\n\t\t\t\t\t\t-->\n\t\t\t\t\t\t<slot :name=\"`item-${item.id}-actions`\" :item=\"item\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\tv-for=\"child in visibleChildren(item)\"\n\t\t\t\t\t\t:key=\"child.id\"\n\t\t\t\t\t\t:name=\"resolveLabel(child)\"\n\t\t\t\t\t\t:to=\"linkTo(child)\"\n\t\t\t\t\t\t:href=\"linkHref(child)\"\n\t\t\t\t\t\t:icon=\"cssIconClass(child)\"\n\t\t\t\t\t\t:active=\"isActive(child)\"\n\t\t\t\t\t\t:pinned=\"Boolean(child.pinned)\"\n\t\t\t\t\t\t:data-testid=\"`cn-nav-entry-${child.id}`\"\n\t\t\t\t\t\t:data-cn-route=\"child.route\"\n\t\t\t\t\t\t@click=\"onItemClick(child, $event)\">\n\t\t\t\t\t\t<template v-if=\"mdiIconComponent(child) || isRichIcon(child) || isRegistryIcon(child) || isUnresolvedIcon(child)\" #icon>\n\t\t\t\t\t\t\t<component :is=\"mdiIconComponent(child)\" v-if=\"mdiIconComponent(child)\" :size=\"20\" />\n\t\t\t\t\t\t\t<HelpCircleOutline v-else-if=\"isUnresolvedIcon(child)\" :size=\"20\" />\n\t\t\t\t\t\t\t<CnMenuItemIcon v-else :icon=\"child.icon\" :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t<template v-if=\"resolveCount(child)\" #counter>\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tv-if=\"isBoard\"\n\t\t\t\t\t\t\t\tclass=\"cn-app-nav__count\"\n\t\t\t\t\t\t\t\t:class=\"{ 'cn-app-nav__count--attention': isAttention(child) }\"\n\t\t\t\t\t\t\t\t:data-testid=\"`cn-nav-count-${child.id}`\">\n\t\t\t\t\t\t\t\t{{ resolveCount(child) }}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<NcCounterBubble\n\t\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t\t:count=\"resolveCount(child)\"\n\t\t\t\t\t\t\t\t:active=\"isActive(child)\"\n\t\t\t\t\t\t\t\t:type=\"isAttention(child) ? 'highlighted' : undefined\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t</NcAppNavigationItem>\n\t\t\t</template>\n\t\t</template>\n\t\t<template v-if=\"footerItems.length > 0 || showSettingsFoldout || resolvedCard || showsHelp\" #footer>\n\t\t\t<!--\n\t\t\t\t@slot card\n\t\t\t\t@description Replace the card above the footer entries\n\t\t\t\t(`nav.card`). Default content: a title, a line of text and one\n\t\t\t\tlink. Renders nothing when neither the slot nor `nav.card` is set.\n\t\t\t\t@binding {object|null} card The resolved card, or null.\n\t\t\t-->\n\t\t\t<slot name=\"card\" :card=\"resolvedCard\">\n\t\t\t\t<div\n\t\t\t\t\tv-if=\"resolvedCard\"\n\t\t\t\t\tclass=\"cn-app-nav__card\"\n\t\t\t\t\tdata-testid=\"cn-nav-card\">\n\t\t\t\t\t<strong class=\"cn-app-nav__card-title\">{{ resolvedCard.title }}</strong>\n\t\t\t\t\t<span v-if=\"resolvedCard.text\" class=\"cn-app-nav__card-text\">{{ resolvedCard.text }}</span>\n\t\t\t\t\t<component\n\t\t\t\t\t\t:is=\"resolvedCard.linkTag\"\n\t\t\t\t\t\tv-if=\"resolvedCard.linkTag\"\n\t\t\t\t\t\tclass=\"cn-app-nav__card-link\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-card-link\"\n\t\t\t\t\t\tv-bind=\"resolvedCard.linkAttrs\"\n\t\t\t\t\t\t@click=\"onCardLinkClick\">\n\t\t\t\t\t\t{{ resolvedCard.linkLabel }}\n\t\t\t\t\t</component>\n\t\t\t\t</div>\n\t\t\t</slot>\n\t\t\t<!-- Footer-section entries (Documentation, Features & Roadmap,\n\t\t\t About) live in NcAppNavigation's #footer slot — OUTSIDE the\n\t\t\t scrollable list — so they stay visible above the settings\n\t\t\t foldout no matter how long the main menu is. The pinned-prop\n\t\t\t approach only bottom-pinned while the list did not overflow.\n\n\t\t\t NcAppNavigationList, not a bare <ul>: its padding, gap and\n\t\t\t hover highlight are scoped to itself, so they survive being\n\t\t\t slotted. The main list's inset comes from NcAppNavigation's\n\t\t\t scope, which slot content does not carry. -->\n\t\t\t<NcAppNavigationList\n\t\t\t\tv-if=\"footerItems.length > 0 || showsHelp\"\n\t\t\t\tclass=\"cn-app-nav__footer-list\"\n\t\t\t\t:class=\"{ 'cn-app-nav__footer-list--after-settings': settingsFirst }\">\n\t\t\t\t<!-- The help entry (`nav.help`): a link to the app's own help\n\t\t\t\t with a help icon, above the footer entries (or after them,\n\t\t\t\t when a declared `nav.footer` names it last). -->\n\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\tv-if=\"showsHelp && !helpAfterItems\"\n\t\t\t\t\t:name=\"resolvedHelp.label\"\n\t\t\t\t\t:to=\"resolvedHelp.to\"\n\t\t\t\t\t:href=\"resolvedHelp.href\"\n\t\t\t\t\t:target=\"resolvedHelp.href ? '_blank' : undefined\"\n\t\t\t\t\tdata-testid=\"cn-nav-help\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<HelpCircleOutline :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\tv-for=\"item in footerItems\"\n\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\t:name=\"resolveLabel(item)\"\n\t\t\t\t\t:to=\"linkTo(item)\"\n\t\t\t\t\t:href=\"linkHref(item)\"\n\t\t\t\t\t:icon=\"cssIconClass(item)\"\n\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t:data-testid=\"`cn-nav-entry-${item.id}`\"\n\t\t\t\t\t:data-cn-route=\"item.route\"\n\t\t\t\t\t@click=\"onItemClick(item, $event)\">\n\t\t\t\t\t<template v-if=\"mdiIconComponent(item) || isRichIcon(item) || isRegistryIcon(item) || isUnresolvedIcon(item)\" #icon>\n\t\t\t\t\t\t<component :is=\"mdiIconComponent(item)\" v-if=\"mdiIconComponent(item)\" :size=\"20\" />\n\t\t\t\t\t\t<HelpCircleOutline v-else-if=\"isUnresolvedIcon(item)\" :size=\"20\" />\n\t\t\t\t\t\t<CnMenuItemIcon v-else :icon=\"item.icon\" :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t<template v-if=\"resolveCount(item)\" #counter>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tv-if=\"isBoard\"\n\t\t\t\t\t\t\tclass=\"cn-app-nav__count\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-app-nav__count--attention': isAttention(item) }\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-nav-count-${item.id}`\">\n\t\t\t\t\t\t\t{{ resolveCount(item) }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcCounterBubble\n\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t:count=\"resolveCount(item)\"\n\t\t\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t\t\t:type=\"isAttention(item) ? 'highlighted' : undefined\" />\n\t\t\t\t\t</template>\n\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\tv-if=\"showsHelp && helpAfterItems\"\n\t\t\t\t\t:name=\"resolvedHelp.label\"\n\t\t\t\t\t:to=\"resolvedHelp.to\"\n\t\t\t\t\t:href=\"resolvedHelp.href\"\n\t\t\t\t\t:target=\"resolvedHelp.href ? '_blank' : undefined\"\n\t\t\t\t\tdata-testid=\"cn-nav-help\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<HelpCircleOutline :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t</NcAppNavigationItem>\n\t\t\t</NcAppNavigationList>\n\t\t\t<!-- Settings foldout (section: \"settings\" items). NC-native\n\t\t\t gear-icon button that slides open a panel; the first entry\n\t\t\t is an auto-prepended \"Personal settings\" that opens the\n\t\t\t host app's NcAppSettingsDialog via cnOpenUserSettings. -->\n\t\t\t<NcAppNavigationSettings\n\t\t\t\tv-if=\"showSettingsFoldout\"\n\t\t\t\t:name=\"settingsFoldoutLabel\"\n\t\t\t\t:class=\"{ 'cn-app-nav__settings--first': settingsFirst }\"\n\t\t\t\tdata-testid=\"cn-nav-settings\">\n\t\t\t\t<ul class=\"cn-app-nav__settings-list\">\n\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\tv-if=\"includePersonalSettings\"\n\t\t\t\t\t\t:name=\"personalSettingsLabel\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-personal-settings\"\n\t\t\t\t\t\t@click=\"onPersonalSettingsClick\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<Cog :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\tv-if=\"roadmapEntry\"\n\t\t\t\t\t\t:name=\"roadmapEntry.label\"\n\t\t\t\t\t\t:to=\"roadmapEntry.to\"\n\t\t\t\t\t\t:href=\"roadmapEntry.href\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-roadmap\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<MapMarkerPath :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\tv-if=\"documentationEntry\"\n\t\t\t\t\t\t:name=\"documentationEntry.label\"\n\t\t\t\t\t\t:href=\"documentationEntry.href\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-documentation\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<BookOpenVariant :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t\t<!-- The target is Nextcloud's OWN settings area, not an\n\t\t\t\t\t in-app route: a new tab keeps the app open, and the\n\t\t\t\t\t trailing open-in-new marker tells the user they are\n\t\t\t\t\t leaving the app before they click. The new tab comes\n\t\t\t\t\t from the href being ABSOLUTE (see adminSettingsHref) —\n\t\t\t\t\t NcAppNavigationItem ignores a `target` attr and only\n\t\t\t\t\t sets target=\"_blank\" for scheme-prefixed hrefs. -->\n\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\tv-if=\"showAdminSettingsLink\"\n\t\t\t\t\t\t:name=\"adminSettingsLabel\"\n\t\t\t\t\t\t:href=\"adminSettingsHref\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-admin-settings\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<ShieldAccountOutline :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t<template #counter>\n\t\t\t\t\t\t\t<OpenInNew :size=\"16\" :title=\"opensInNewTabHint\" data-testid=\"cn-nav-admin-settings-external\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t\t<template v-for=\"item in settingsItems\">\n\t\t\t\t\t\t<NcAppNavigationCaption\n\t\t\t\t\t\t\tv-if=\"isCaption(item)\"\n\t\t\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\t\t\t:name=\"resolveLabel(item)\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-nav-caption-${item.id}`\">\n\t\t\t\t\t\t\t<template v-if=\"item.href\" #actions>\n\t\t\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\t\t\t:href=\"item.href\"\n\t\t\t\t\t\t\t\t\t:aria-label=\"captionEditLabel(item)\"\n\t\t\t\t\t\t\t\t\t:data-testid=\"`cn-nav-caption-edit-${item.id}`\">\n\t\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t\t<Pencil :size=\"20\" />\n\t\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t\t{{ captionEditLabel(item) }}\n\t\t\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcAppNavigationCaption>\n\t\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\t\t\t:name=\"resolveLabel(item)\"\n\t\t\t\t\t\t\t:to=\"linkTo(item)\"\n\t\t\t\t\t\t\t:href=\"linkHref(item)\"\n\t\t\t\t\t\t\t:icon=\"cssIconClass(item)\"\n\t\t\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t\t\t:data-cn-route=\"item.route\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-nav-entry-${item.id}`\"\n\t\t\t\t\t\t\t@click=\"onItemClick(item, $event)\">\n\t\t\t\t\t\t\t<template v-if=\"mdiIconComponent(item) || isRichIcon(item) || isRegistryIcon(item) || isUnresolvedIcon(item)\" #icon>\n\t\t\t\t\t\t\t\t<component :is=\"mdiIconComponent(item)\" v-if=\"mdiIconComponent(item)\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<HelpCircleOutline v-else-if=\"isUnresolvedIcon(item)\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<CnMenuItemIcon v-else :icon=\"item.icon\" :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t<template v-if=\"resolveCount(item)\" #counter>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tv-if=\"isBoard\"\n\t\t\t\t\t\t\t\t\tclass=\"cn-app-nav__count\"\n\t\t\t\t\t\t\t\t\t:class=\"{ 'cn-app-nav__count--attention': isAttention(item) }\"\n\t\t\t\t\t\t\t\t\t:data-testid=\"`cn-nav-count-${item.id}`\">\n\t\t\t\t\t\t\t\t\t{{ resolveCount(item) }}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<NcCounterBubble\n\t\t\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t\t\t:count=\"resolveCount(item)\"\n\t\t\t\t\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t\t\t\t\t:type=\"isAttention(item) ? 'highlighted' : undefined\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t\t</template>\n\t\t\t\t</ul>\n\t\t\t</NcAppNavigationSettings>\n\t\t</template>\n\t</NcAppNavigation>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcActionLink, NcAppNavigation, NcAppNavigationCaption, NcAppNavigationItem, NcAppNavigationList, NcAppNavigationNew, NcAppNavigationSettings, NcButton, NcCounterBubble } from '@nextcloud/vue'\nimport { toRaw } from 'vue'\nimport BookOpenVariant from 'vue-material-design-icons/BookOpenVariant.vue'\nimport Cog from 'vue-material-design-icons/Cog.vue'\n// ADR-077 rule 4: visible fallback for an unresolvable icon name.\nimport HelpCircleOutline from 'vue-material-design-icons/HelpCircleOutline.vue'\nimport MapMarkerPath from 'vue-material-design-icons/MapMarkerPath.vue'\nimport OpenInNew from 'vue-material-design-icons/OpenInNew.vue'\nimport Pencil from 'vue-material-design-icons/Pencil.vue'\nimport Plus from 'vue-material-design-icons/Plus.vue'\nimport ShieldAccountOutline from 'vue-material-design-icons/ShieldAccountOutline.vue'\nimport { ICON_MAP } from '../CnIcon/CnIcon.vue'\nimport CnMenuItemIcon from '../CnMenuWidget/CnMenuItemIcon.vue'\nimport { useLook } from '../../composables/useLook.js'\nimport { isAppInstalled } from '../../utils/appInstalled.js'\nimport { isSvgPath } from '../../utils/iconUtils.js'\nimport { resolveBrand } from '../../utils/resolveBrand.js'\nimport { passesContextPredicates } from '../../utils/visibleIfContext.js'\nimport { CnActionButtons } from '../CnActionButtons/index.js'\n// The legacy `icon-*` → MDI bridge lives beside CnIcon now, so the menu EDITOR\n// resolves a seeded `icon-comment` the same way this nav does. It used to be a\n// map local to this file, which is why the nav drew a proper glyph and the\n// editor drew a help-circle \"?\" for the very same manifest value.\nimport { bridgedMdiForCssIcon } from '../CnIcon/cssIconBridge.js'\nimport { getSemanticIconComponent } from '../CnIcon/semanticIcons.js'\nimport { hasRegistryIcon, isCustomIconUrl } from '../CnWidgetGrid/widgetIcons.js'\n\n/**\n * Order two menu entries by their manifest `order`.\n *\n * Entries carrying an `order` come first, ascending; entries without one render\n * last and keep their relative order. Used at BOTH nav levels so a group's\n * children obey the same rule as the top-level list.\n *\n * @param {object} a First entry.\n * @param {object} b Second entry.\n * @return {number} Comparator result.\n */\nfunction byManifestOrder(a, b) {\n\tconst aHas = typeof a.order === 'number'\n\tconst bHas = typeof b.order === 'number'\n\tif (aHas && !bHas) {\n\t\treturn -1\n\t}\n\tif (!aHas && bHas) {\n\t\treturn 1\n\t}\n\tif (!aHas && !bHas) {\n\t\treturn 0\n\t}\n\treturn a.order - b.order\n}\n\n/** A `:name` page-path segment: name, optional `(regexp)`, optional modifier. */\nconst PARAM_SEGMENT = /^:(\\w+)(\\([^)]*\\))?([?*+])?$/\n\n/**\n * Whether a `PARAM_SEGMENT` match may be left out (`?` or `*`).\n *\n * @param {Array<string>} param The match.\n * @return {boolean} True for an optional segment.\n */\nfunction isOptionalParam(param) {\n\treturn param[3] === '?' || param[3] === '*'\n}\n\n/**\n * Whether a route param value fills its segment.\n *\n * @param {unknown} value The value.\n * @return {boolean} False for undefined, null and the empty string.\n */\nfunction isFilled(value) {\n\treturn value !== undefined && value !== null && value !== ''\n}\n\n/**\n * Decode one percent-encoded path segment, or keep it as is when it is not\n * valid percent-encoding.\n *\n * @param {string} segment The segment.\n * @return {string} The decoded segment.\n */\nfunction decodeSegment(segment) {\n\ttry {\n\t\treturn decodeURIComponent(segment)\n\t} catch {\n\t\treturn segment\n\t}\n}\n\nexport default {\n\tname: 'CnAppNav',\n\n\tcomponents: {\n\t\tNcActionLink,\n\t\tPencil,\n\t\tNcAppNavigation,\n\t\tNcAppNavigationCaption,\n\t\tNcAppNavigationItem,\n\t\tNcAppNavigationList,\n\t\tNcAppNavigationNew,\n\t\tNcAppNavigationSettings,\n\t\tNcButton,\n\t\tNcCounterBubble,\n\t\tCnActionButtons,\n\t\tCnMenuItemIcon,\n\t\tCog,\n\t\tHelpCircleOutline,\n\t\tShieldAccountOutline,\n\t\tMapMarkerPath,\n\t\tBookOpenVariant,\n\t\tOpenInNew,\n\t},\n\n\tinject: {\n\t\tcnManifest: { default: null },\n\t\t/**\n\t\t * Provided by CnAppRoot as true while the board look draws the brand\n\t\t * block in Nextcloud's header (screens-brand-block-top-bar): the\n\t\t * navigation then skips its own.\n\t\t */\n\t\tcnBrandInHeader: { default: false },\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/**\n\t\t * Provided by CnAppRoot — opens the host app's\n\t\t * NcAppSettingsDialog. Defaults to a no-op so CnAppNav is\n\t\t * still usable when mounted outside a CnAppRoot ancestor;\n\t\t * the click silently does nothing in that case rather than\n\t\t * throwing.\n\t\t */\n\t\tcnOpenUserSettings: { default: () => () => {} },\n\t\t/**\n\t\t * Provided by CnAppRoot — the consuming app's slug, used to build\n\t\t * the \"Admin settings\" link target `/settings/admin/<appId>`.\n\t\t * Overridden by the explicit `appId` prop when both are present.\n\t\t * Null outside a CnAppRoot ancestor, in which case the link is\n\t\t * suppressed (ADR-079 §2).\n\t\t */\n\t\tcnAppId: { default: null },\n\t\t/**\n\t\t * Provided by CnAppRoot — restarts the product walkthrough (ADR-043)\n\t\t * from the first step. Bound to menu entries declaring\n\t\t * `action: \"replay-walkthrough\"` (optionally with a `tourId`).\n\t\t * Defaults to a no-op so CnAppNav stays usable standalone.\n\t\t */\n\t\tcnReplayWalkthrough: { default: () => () => {} },\n\t\t/**\n\t\t * Provided by CnAppRoot — reactive `{ [register]: { [schema]: number } }`\n\t\t * map populated from `useObjectStore().totals` for every\n\t\t * `count: \"auto\"` menu entry whose resolved page is `type: \"index\"`\n\t\t * with `register + schema` in its config. Defaults to an empty\n\t\t * object so `resolveCount` returns `null` (no badge) when CnAppNav\n\t\t * is mounted outside a CnAppRoot ancestor.\n\t\t *\n\t\t * @type {{ [register: string]: { [schema: string]: number } }}\n\t\t */\n\t\tcnMenuCounts: { default: () => ({}) },\n\t\t/**\n\t\t * Provided by CnAppRoot — reactive `{ [menuItemId]: number }` totals\n\t\t * for every menu entry whose `count` is an object\n\t\t * (`{ register, schema, filter? }`): the total of that filtered\n\t\t * list, fetched under the entry's own key so an index page's\n\t\t * whole-schema total is left alone. Empty outside a CnAppRoot.\n\t\t *\n\t\t * @type {{ [itemId: string]: number }}\n\t\t */\n\t\tcnMenuItemCounts: { default: () => ({}) },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The look the navigation is drawn in: `board` or `nextcloud`. Empty\n\t\t * follows the `cnLook` that CnAppRoot provides. Under `board` the\n\t\t * navigation takes the anatomy of the screens (264px, 42px entries,\n\t\t * attention counts, Help before Advanced).\n\t\t *\n\t\t * @spec openspec/changes/screens-chrome-parity/specs/layout-components/spec.md#requirement-the-navigation-takes-the-board-anatomy\n\t\t */\n\t\tlook: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Manifest object. Falls back to injected `cnManifest`. Provide\n\t\t * explicitly when mounting CnAppNav outside of CnAppRoot.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tmanifest: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Translate function. Falls back to injected `cnTranslate`,\n\t\t * which itself defaults to an identity function.\n\t\t *\n\t\t * @type {((key: string) => string)|null}\n\t\t */\n\t\ttranslate: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * List of permission strings the current user holds. Items\n\t\t * declaring a `permission` only render when their permission\n\t\t * appears in this list. When the prop is omitted (or empty),\n\t\t * all items are visible regardless of their permission field.\n\t\t *\n\t\t * @type {Array<string>}\n\t\t */\n\t\tpermissions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * Whether the current user is an OWNER of this app\n\t\t * (admin-settings-owner-gating capability). Computed by CnAppRoot\n\t\t * from `currentUserGroups` ∩ `permissions.owners` and/or a manifest\n\t\t * `runtime.user` owner signal — deliberately NOT `OC.isUserAdmin()`.\n\t\t * Read by nothing in this component: the auto-included \"Admin\n\t\t * settings\" entry is gated on `isAdmin` alone (see the file header\n\t\t * and `showAdminSettingsLink`). The prop stays because CnAppRoot\n\t\t * binds it as published API and owner-gating is its own question,\n\t\t * not the instance-admin one.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tisOwner: { // eslint-disable-line vue/no-unused-properties -- published prop bound by CnAppRoot; owner-gating is decided upstream, not here\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Whether the current user administers this Nextcloud instance.\n\t\t * Computed by CnAppRoot from `getCurrentUser()?.isAdmin`\n\t\t * (`@nextcloud/auth`) — NOT the legacy `OC.isUserAdmin()` global,\n\t\t * and NOT interchangeable with `isOwner`, which is about owning a\n\t\t * given app rather than administering the instance (ADR-079 §3).\n\t\t *\n\t\t * Gates VISIBILITY of the \"Admin settings\" link only. It is not an\n\t\t * authorization decision and MUST NOT be used as one: the boundary\n\t\t * is Nextcloud's settings framework, which refuses\n\t\t * `/settings/admin/<app>` server-side for non-admins. Defaults to\n\t\t * `false` so CnAppNav mounted standalone never shows the link.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tisAdmin: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * App id used to build the \"Admin settings\" link target\n\t\t * (`/settings/admin/<appId>`). Falls back to the injected\n\t\t * `cnAppId` provided by CnAppRoot. With neither available the\n\t\t * link is suppressed rather than pointing at a broken URL.\n\t\t *\n\t\t * @type {string|null}\n\t\t */\n\t\tappId: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Accessible name for the navigation landmark, forwarded to\n\t\t * `NcAppNavigation`'s `aria-label`.\n\t\t *\n\t\t * `@nextcloud/vue` 9 requires `ariaLabel` or `ariaLabelledby` and warns\n\t\t * when neither is set: a `<nav>` with no accessible name is announced as\n\t\t * an unlabelled landmark, so a screen-reader user tabbing the landmark\n\t\t * list cannot tell it from any other nav on the page (WCAG 2.4.6 /\n\t\t * 1.3.1). The default covers every consumer without a code change; pass\n\t\t * your own when an app shows more than one navigation, since the point\n\t\t * of the name is to tell them apart.\n\t\t *\n\t\t * @type {string}\n\t\t */\n\t\tariaLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Main navigation'),\n\t\t},\n\n\t\t/**\n\t\t * The brand block at the top of the navigation:\n\t\t * `{ logo?, name?, caption?, alt? }`. `logo` is an image URL, `name`\n\t\t * the app or organisation name, `caption` a line under it. Falls back\n\t\t * to the manifest's `nav.brand`. `null` (the default) with no manifest\n\t\t * brand renders nothing.\n\t\t *\n\t\t * @type {{logo?: string, name?: string, caption?: string, alt?: string}|null}\n\t\t */\n\t\tbrand: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: ['primary-action', 'primary-action-click', 'primary-action-created', 'card-action'],\n\n\tsetup(props) {\n\t\tconst { isBoard } = useLook(props)\n\t\treturn { isBoard }\n\t},\n\n\t/**\n\t * The navigation's own state: which groups are open, and which entry\n\t * of a route the reader last used.\n\t *\n\t * @return {object} The state.\n\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t */\n\tdata() {\n\t\treturn {\n\t\t\t/**\n\t\t\t * Per-item expand/collapse state for menu groups, keyed by\n\t\t\t * item id. Seeded lazily from the manifest's `item.open` by\n\t\t\t * `isItemOpen`; written by the collapse chevron (via\n\t\t\t * `@update:open`), by title clicks on route-less group items\n\t\t\t * (which TOGGLE open/closed), and by title clicks on a group\n\t\t\t * that ALSO carries a route or href (which force it OPEN,\n\t\t\t * alongside the navigation — see `onItemClick`).\n\t\t\t */\n\t\t\topenState: {},\n\n\t\t\t/**\n\t\t\t * Per route name, the key of the entry that was last active on\n\t\t\t * that route in this session. Read by `subRouteParent` to keep\n\t\t\t * \"the list I came from\" marked on a page below it. In memory\n\t\t\t * only: a reload starts empty and falls back to menu order.\n\t\t\t *\n\t\t\t * @type {Record<string, string>}\n\t\t\t */\n\t\t\tlastActiveEntryByRoute: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\teffectiveManifest() {\n\t\t\treturn this.manifest ?? this.cnManifest\n\t\t},\n\n\t\teffectiveTranslate() {\n\t\t\treturn this.translate ?? this.cnTranslate\n\t\t},\n\n\t\t/**\n\t\t * The brand the navigation draws itself: the resolved brand, or null\n\t\t * while the app's top bar draws it.\n\t\t *\n\t\t * @spec openspec/changes/screens-brand-block-top-bar/specs/layout-components/spec.md#requirement-the-navigation-does-not-draw-a-brand-block-the-bar-already-draws\n\t\t * @return {object|null}\n\t\t */\n\t\tnavBrand() {\n\t\t\treturn this.cnBrandInHeader ? null : this.resolvedBrand\n\t\t},\n\n\t\t/**\n\t\t * The brand to draw: the `brand` prop, else the manifest's\n\t\t * `nav.brand`. Name and caption go through the translate function,\n\t\t * like every other manifest label. Null when there is nothing to\n\t\t * show, which is what keeps the block out of a navigation that\n\t\t * declares no brand.\n\t\t *\n\t\t * @return {{logo: string, name: string, caption: string, alt: string}|null} The brand, or null.\n\t\t * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-navigation-brand\n\t\t */\n\t\tresolvedBrand() {\n\t\t\treturn resolveBrand(this.brand ?? this.effectiveManifest?.nav?.brand, (value) => this.effectiveTranslate(value))\n\t\t},\n\n\t\t/**\n\t\t * The card above the footer entries (`nav.card`): `{ title, text?,\n\t\t * link?: { label, route?, params?, href?, action? } }`. Title, text\n\t\t * and link label go through the translate function. The link is a\n\t\t * router link for a `route` (with a router), an anchor for an\n\t\t * `href`, and a button emitting `card-action` with the `action` id\n\t\t * otherwise. Null without a title.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-the-navigation-carries-a-card-and-a-help-entry\n\t\t * @return {object|null}\n\t\t */\n\t\tresolvedCard() {\n\t\t\tconst declared = this.effectiveManifest?.nav?.card\n\t\t\tif (!declared || typeof declared !== 'object' || typeof declared.title !== 'string' || declared.title === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst text = (value) => (typeof value === 'string' && value !== '' ? this.effectiveTranslate(value) : '')\n\t\t\tconst card = { title: text(declared.title), text: text(declared.text), linkTag: '', linkAttrs: {}, linkLabel: '', action: '' }\n\t\t\tconst link = declared.link\n\t\t\tif (link && typeof link === 'object' && typeof link.label === 'string' && link.label !== '') {\n\t\t\t\tcard.linkLabel = text(link.label)\n\t\t\t\tif (link.route && this.$router) {\n\t\t\t\t\tcard.linkTag = 'router-link'\n\t\t\t\t\tcard.linkAttrs = { to: { name: link.route, ...(link.params && typeof link.params === 'object' ? { params: link.params } : {}) } }\n\t\t\t\t} else if (typeof link.href === 'string' && link.href !== '') {\n\t\t\t\t\tcard.linkTag = 'a'\n\t\t\t\t\tcard.linkAttrs = { href: link.href }\n\t\t\t\t} else if (typeof link.action === 'string' && link.action !== '') {\n\t\t\t\t\tcard.linkTag = 'button'\n\t\t\t\t\tcard.linkAttrs = { type: 'button' }\n\t\t\t\t\tcard.action = link.action\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn card\n\t\t},\n\n\t\t/**\n\t\t * The help entry (`nav.help`): `{ label, route?, href? }` rendered as\n\t\t * a footer entry with a help icon. Null without a label or a target.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-the-navigation-carries-a-card-and-a-help-entry\n\t\t * @return {{label: string, to?: object, href?: string}|null}\n\t\t */\n\t\tresolvedHelp() {\n\t\t\tconst declared = this.effectiveManifest?.nav?.help\n\t\t\tif (!declared || typeof declared !== 'object' || typeof declared.label !== 'string' || declared.label === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (declared.route && this.$router) {\n\t\t\t\treturn { label: this.effectiveTranslate(declared.label), to: { name: declared.route }, href: undefined }\n\t\t\t}\n\t\t\tif (typeof declared.href === 'string' && declared.href !== '') {\n\t\t\t\treturn { label: this.effectiveTranslate(declared.label), to: undefined, href: declared.href }\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Manifest-declared root-level primary action (`nav.primaryAction`)\n\t\t * — retained for backwards compatibility with code that reads this\n\t\t * computed. New code SHOULD read `activePrimaryAction` instead,\n\t\t * which also handles the page-scoped override.\n\t\t *\n\t\t * @return {object|null} `{ label, icon?, route?, href?, id?, payload? }` or null.\n\t\t */\n\t\tprimaryAction() {\n\t\t\treturn this.effectiveManifest?.nav?.primaryAction ?? null\n\t\t},\n\n\t\t/**\n\t\t * Resolved primary action for the current route. Resolution order:\n\t\t * 1. The current route's matching `pages[].primaryAction`\n\t\t * 2. `manifest.nav.primaryAction` as app-wide default\n\t\t * 3. `null` — no primary-action button renders\n\t\t *\n\t\t * Page-scoped declarations always win over the nav-root default. An\n\t\t * action declaring `permission` or `visibleIf` is gated like a menu\n\t\t * entry.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-navigation-primary-action-runs-a-page-action\n\t\t * @return {object|null}\n\t\t */\n\t\tactivePrimaryAction() {\n\t\t\tconst pages = this.effectiveManifest?.pages ?? []\n\t\t\tconst routeName = this.$route?.name\n\t\t\t// The same `permission` / `visibleIf` gate a menu entry has: an\n\t\t\t// action the reader may not take, or that a condition hides, is\n\t\t\t// not drawn. A gated-out page action falls back to the nav one.\n\t\t\tconst gated = (action) => (action && this.passesPermission(action) && this.passesVisibleIf(action) ? action : null)\n\t\t\tif (routeName) {\n\t\t\t\tconst page = pages.find((p) => p.id === routeName)\n\t\t\t\tif (page && page.primaryAction) {\n\t\t\t\t\tconst pageAction = gated(page.primaryAction)\n\t\t\t\t\tif (pageAction) {\n\t\t\t\t\t\treturn pageAction\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn gated(this.effectiveManifest?.nav?.primaryAction ?? null)\n\t\t},\n\n\t\t/**\n\t\t * MDI icon component for the resolved primary action. Honors the\n\t\t * action's `icon` field when set; falls back to the canonical\n\t\t * `Plus` icon to match NC's NcAppNavigationNew default styling.\n\t\t *\n\t\t * @return {import('vue').Component}\n\t\t */\n\t\tprimaryActionIconComponent() {\n\t\t\treturn this.mdiIconComponent(this.activePrimaryAction) ?? Plus\n\t\t},\n\n\t\t/**\n\t\t * The CnActionButtons entry for a primary action that carries an\n\t\t * `action` (`$defs/action`: open-form, navigate, api-call, ...):\n\t\t * the action with the primary action's `id`, `label` and `icon`\n\t\t * folded in and `variant: \"primary\"`. Null for a plain primary\n\t\t * action, which keeps its link or button.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-navigation-primary-action-runs-a-page-action\n\t\t * @return {object|null}\n\t\t */\n\t\tprimaryDispatchEntry() {\n\t\t\tconst action = this.activePrimaryAction\n\t\t\tconst inner = action && action.action\n\t\t\tif (!inner || typeof inner !== 'object' || typeof inner.type !== 'string') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ticon: action.icon || 'Plus',\n\t\t\t\t...inner,\n\t\t\t\tid: inner.id || action.id || 'primary-action',\n\t\t\t\tlabel: action.label,\n\t\t\t\tvariant: 'primary',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Link props for the primary action's button: an `href` opens in a\n\t\t * new tab, a `route` is a router link. Null when the action is\n\t\t * neither (or there is no router), so it stays a plain button.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tprimaryActionLink() {\n\t\t\tconst action = this.activePrimaryAction\n\t\t\tif (!action) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (action.href) {\n\t\t\t\treturn { href: action.href, target: '_blank' }\n\t\t\t}\n\t\t\tif (action.route && this.$router) {\n\t\t\t\treturn { to: { name: action.route } }\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * All visible items (filtered by permission and visibleIf conditions,\n\t\t * sorted by order). Retained for backwards-compat with the previous\n\t\t * public API and tests that read this computed; new code should use\n\t\t * `mainItems` / `settingsItems` instead.\n\t\t */\n\t\tvisibleItems() {\n\t\t\treturn (this.effectiveManifest?.menu ?? [])\n\t\t\t\t.filter((item) => this.passesPermission(item) && this.passesVisibleIf(item))\n\t\t\t\t.slice()\n\t\t\t\t.sort(byManifestOrder)\n\t\t},\n\n\t\t/**\n\t\t * Items that render in the top list (default placement).\n\t\t *\n\t\t * Note the `=== 'main'` rather than a negated list: an entry whose\n\t\t * section this component does not render must fall through to\n\t\t * NOTHING, not to the main list. `section: \"integrations\"` is\n\t\t * exactly that case — those entries render in CnAppRoot's\n\t\t * per-user settings modal, not in the navigation (ADR-110) — and a\n\t\t * `!== 'footer' && !== 'settings'` test would have quietly put\n\t\t * every one of them back in the nav this contract removes them\n\t\t * from.\n\t\t */\n\t\tmainItems() {\n\t\t\treturn this.visibleItems.filter((item) => (item.section ?? 'main') === 'main')\n\t\t},\n\n\t\t/**\n\t\t * Items pinned to the bottom of the navigation (section:\n\t\t * \"footer\") — rendered as flat NcAppNavigationItems above the\n\t\t * settings foldout. For always-visible, non-settings entries:\n\t\t * Documentation, Features & Roadmap, About.\n\t\t */\n\t\tfooterItems() {\n\t\t\tconst footer = this.visibleItems.filter((item) => item.section === 'footer')\n\t\t\tconst declared = this.declaredFooter\n\t\t\tif (declared === null) {\n\t\t\t\treturn footer\n\t\t\t}\n\t\t\t// A declared footer (`nav.footer`) keeps only the entries it names,\n\t\t\t// in the order it names them.\n\t\t\treturn declared\n\t\t\t\t.map((id) => footer.find((item) => item.id === id))\n\t\t\t\t.filter(Boolean)\n\t\t},\n\n\t\t/**\n\t\t * The footer the manifest declares (`nav.footer`): an ordered list of\n\t\t * menu entry ids plus the reserved ids `help` (the `nav.help` entry)\n\t\t * and `settings` (the settings foldout). Null when the manifest\n\t\t * declares none, which keeps today's footer: the help entry, then\n\t\t * every `section: \"footer\"` entry, then the foldout.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {Array<string>|null}\n\t\t */\n\t\tdeclaredFooter() {\n\t\t\tconst declared = this.effectiveManifest?.nav?.footer\n\t\t\tif (!Array.isArray(declared)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn declared.filter((id) => typeof id === 'string' && id !== '')\n\t\t},\n\n\t\t/**\n\t\t * Footer-section entries a declared footer leaves out. They move into\n\t\t * the settings foldout rather than disappearing, so a page such as\n\t\t * Store or Reports stays reachable. Empty without `nav.footer`.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {Array<object>}\n\t\t */\n\t\tundeclaredFooterItems() {\n\t\t\tconst declared = this.declaredFooter\n\t\t\tif (declared === null) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn this.visibleItems.filter((item) => item.section === 'footer' && !declared.includes(item.id))\n\t\t},\n\n\t\t/**\n\t\t * Whether the help entry renders: whenever it resolves, unless a\n\t\t * declared footer leaves `help` out.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {boolean}\n\t\t */\n\t\tshowsHelp() {\n\t\t\tif (!this.resolvedHelp) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn this.declaredFooter === null || this.declaredFooter.includes('help')\n\t\t},\n\n\t\t/**\n\t\t * Whether the help entry goes AFTER the footer entries. Only a declared\n\t\t * footer that names an entry before `help` puts it there; by default\n\t\t * it leads the list.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {boolean}\n\t\t */\n\t\thelpAfterItems() {\n\t\t\tconst declared = this.declaredFooter\n\t\t\tif (declared === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst help = declared.indexOf('help')\n\t\t\treturn this.footerItems.some((item) => declared.indexOf(item.id) < help)\n\t\t},\n\n\t\t/**\n\t\t * Whether the settings foldout goes ABOVE the footer list: only when a\n\t\t * declared footer names `settings` before every other entry\n\t\t * (`[\"settings\", \"help\"]`, the board's \"Instellingen\" then \"Hulp en\n\t\t * uitleg\"). Done with CSS `order` on the two siblings, so the markup\n\t\t * of both stays as it is.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {boolean}\n\t\t */\n\t\tsettingsFirst() {\n\t\t\t// Under the board look Help always comes first and Advanced last,\n\t\t\t// whatever order the manifest declares.\n\t\t\tif (this.isBoard) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst declared = this.declaredFooter\n\t\t\treturn declared !== null && declared.indexOf('settings') === 0\n\t\t},\n\n\t\t/**\n\t\t * Items that render INSIDE the NcAppNavigationSettings foldout\n\t\t * (section: \"settings\"). The foldout is the NC-native gear-icon\n\t\t * button that slides a panel open; these entries are app-level\n\t\t * configuration pages (Forms, Pipelines, Automations, …). A declared\n\t\t * footer (`nav.footer`) adds the footer entries it leaves out.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {Array<object>}\n\t\t */\n\t\tsettingsItems() {\n\t\t\treturn [\n\t\t\t\t...this.visibleItems.filter((item) => item.section === 'settings'),\n\t\t\t\t...this.undeclaredFooterItems,\n\t\t\t]\n\t\t},\n\n\t\t/**\n\t\t * Whether the settings foldout mounts. Mounts when there is at\n\t\t * least one `section: \"settings\"` item OR personal settings is\n\t\t * enabled — so every app shows a Settings gear with at least the\n\t\t * auto-prepended \"Personal settings\" entry. Only fully suppressed\n\t\t * when there are no settings items AND `nav.includePersonalSettings`\n\t\t * is explicitly `false`.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tshowSettingsFoldout() {\n\t\t\treturn this.settingsItems.length > 0 || this.includePersonalSettings\n\t\t\t\t|| this.roadmapEntry !== null || this.documentationEntry !== null\n\t\t},\n\n\t\t/**\n\t\t * Whether to auto-prepend the \"Personal settings\" entry at the top\n\t\t * of the foldout. On by default; opt out with\n\t\t * `manifest.nav.includePersonalSettings: false` (e.g. when the app\n\t\t * has no per-user NcAppSettingsDialog wired through\n\t\t * cnOpenUserSettings).\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tincludePersonalSettings() {\n\t\t\treturn this.effectiveManifest?.nav?.includePersonalSettings !== false\n\t\t},\n\n\t\t/**\n\t\t * Label for the foldout's gear button. Manifest override:\n\t\t * `nav.settingsLabel`; defaults to \"Advanced\".\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tsettingsFoldoutLabel() {\n\t\t\tconst custom = this.effectiveManifest?.nav?.settingsLabel\n\t\t\tif (typeof custom === 'string' && custom.length > 0) {\n\t\t\t\treturn this.effectiveTranslate(custom)\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'Advanced')\n\t\t},\n\n\t\t/**\n\t\t * Label for the auto-prepended Personal-settings entry.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tpersonalSettingsLabel() {\n\t\t\treturn t('nextcloud-vue', 'Personal settings')\n\t\t},\n\n\t\t/**\n\t\t * Optional \"Features & roadmap\" foldout entry. Enabled via\n\t\t * `nav.includeRoadmap`; `nav.roadmapUrl` is treated as an external link\n\t\t * when it looks like a URL, otherwise as an in-app router target.\n\t\t *\n\t\t * @return {{label: string, to: (string|null), href: (string|null)}|null}\n\t\t */\n\t\troadmapEntry() {\n\t\t\tconst nav = this.effectiveManifest?.nav\n\t\t\tif (!nav || nav.includeRoadmap !== true) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst label = (typeof nav.roadmapLabel === 'string' && nav.roadmapLabel)\n\t\t\t\t? this.effectiveTranslate(nav.roadmapLabel)\n\t\t\t\t: t('nextcloud-vue', 'Features & roadmap')\n\t\t\tconst target = typeof nav.roadmapUrl === 'string' ? nav.roadmapUrl.trim() : ''\n\t\t\tconst external = /^(https?:)?\\/\\//.test(target)\n\t\t\treturn { label, to: (target && !external) ? target : null, href: external ? target : null }\n\t\t},\n\n\t\t/**\n\t\t * Optional \"Documentation\" foldout entry. Enabled via\n\t\t * `nav.includeDocumentation`; always an external link (`nav.documentationUrl`).\n\t\t *\n\t\t * @return {{label: string, href: string}|null}\n\t\t */\n\t\tdocumentationEntry() {\n\t\t\tconst nav = this.effectiveManifest?.nav\n\t\t\tif (!nav || nav.includeDocumentation !== true) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst target = typeof nav.documentationUrl === 'string' ? nav.documentationUrl.trim() : ''\n\t\t\tif (!target) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst label = (typeof nav.documentationLabel === 'string' && nav.documentationLabel)\n\t\t\t\t? this.effectiveTranslate(nav.documentationLabel)\n\t\t\t\t: t('nextcloud-vue', 'Documentation')\n\t\t\treturn { label, href: target }\n\t\t},\n\n\t\t/**\n\t\t * Label for the auto-prepended Admin-settings entry.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tadminSettingsLabel() {\n\t\t\treturn t('nextcloud-vue', 'Admin settings')\n\t\t},\n\n\t\t/**\n\t\t * Accessible name (and hover tooltip) of the open-in-new marker on\n\t\t * the Admin-settings entry — the visual cue that the link leaves\n\t\t * the app for Nextcloud's own settings area.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\topensInNewTabHint() {\n\t\t\treturn t('nextcloud-vue', 'Opens in a new tab')\n\t\t},\n\n\t\t/**\n\t\t * Resolved app id for the Admin-settings link — the explicit\n\t\t * `appId` prop, else the `cnAppId` provided by CnAppRoot.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\teffectiveAppId() {\n\t\t\tconst id = this.appId || this.cnAppId\n\t\t\treturn (typeof id === 'string' && id.trim()) ? id.trim() : ''\n\t\t},\n\n\t\t/**\n\t\t * Target of the Admin-settings entry: the app's section in\n\t\t * Nextcloud's own admin settings (ADR-079 §1). This is a LINK, not\n\t\t * a modal — the app never re-implements the settings surface, and\n\t\t * the destination is authorized server-side by the settings\n\t\t * framework.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tadminSettingsHref() {\n\t\t\tif (!this.effectiveAppId) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\t// ABSOLUTE (same-origin) on purpose: NcAppNavigationItem renders\n\t\t\t// target=\"_blank\" only for hrefs its isExternal() deems external\n\t\t\t// (scheme-prefixed) and ignores a passed `target` — a relative\n\t\t\t// path therefore always opens in the SAME tab. The absolute form\n\t\t\t// gets the new tab while keeping native anchor semantics\n\t\t\t// (middle-click, copy link).\n\t\t\tconst path = generateUrl('/settings/admin/{appId}', { appId: this.effectiveAppId })\n\t\t\tconst origin = (typeof window !== 'undefined' && window.location && window.location.origin) || ''\n\t\t\treturn origin + path\n\t\t},\n\n\t\t/**\n\t\t * Whether to show the Admin-settings link: the user administers the\n\t\t * instance AND we can build a target. Visibility only — see the\n\t\t * `isAdmin` prop docs; the access check lives in Nextcloud.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tshowAdminSettingsLink() {\n\t\t\treturn this.isAdmin === true && this.adminSettingsHref !== ''\n\t\t},\n\n\t\t/**\n\t\t * Route name of the menu item that best matches the current route.\n\t\t * A direct match (current route name IS a menu target) wins;\n\t\t * otherwise the current path is matched against each item's page\n\t\t * path and the LONGEST prefix wins, so detail / nested routes (e.g.\n\t\t * `/expenses/:id`) light up — and auto-expand — their index entry\n\t\t * even though the detail route name is not in the menu. Longest\n\t\t * prefix disambiguates nested namespaces (e.g. `/pos` vs\n\t\t * `/pos/refunds`). An entry with `params` matches by its page path\n\t\t * with those params filled in (see `pageMatchDepth`). Returns null\n\t\t * when nothing matches.\n\t\t *\n\t\t * @return {string|null}\n\t\t */\n\t\tactiveRouteName() {\n\t\t\tconst routeName = this.$route?.name\n\t\t\tconst path = this.$route?.path\n\t\t\tconst flat = []\n\t\t\tfor (const item of this.visibleItems) {\n\t\t\t\tflat.push(item)\n\t\t\t\tfor (const child of this.visibleChildren(item)) {\n\t\t\t\t\tflat.push(child)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (routeName && flat.some((it) => it.route === routeName)) {\n\t\t\t\treturn routeName\n\t\t\t}\n\t\t\tif (!path) {\n\t\t\t\treturn routeName ?? null\n\t\t\t}\n\t\t\tlet best = null\n\t\t\tlet bestDepth = 0\n\t\t\tfor (const it of flat) {\n\t\t\t\tif (!it.route) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst depth = this.pageMatchDepth(it, path)\n\t\t\t\tif (depth > bestDepth) {\n\t\t\t\t\tbest = it.route\n\t\t\t\t\tbestDepth = depth\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn best ?? routeName ?? null\n\t\t},\n\n\t\t/**\n\t\t * Every visible entry and child, flat, in menu order.\n\t\t *\n\t\t * @return {Array<object>} The entries.\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tflatEntries() {\n\t\t\tconst flat = []\n\t\t\tfor (const item of this.visibleItems) {\n\t\t\t\tflat.push(item, ...this.visibleChildren(item))\n\t\t\t}\n\t\t\treturn flat\n\t\t},\n\n\t\t/**\n\t\t * The entry the query rule marks while the reader is on a menu\n\t\t * route itself (not on a page below it). Watched, so the nav can\n\t\t * remember which entry of a route the reader last used.\n\t\t *\n\t\t * @return {object|null} The entry, or null on a page below a route.\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tentryActiveOnOwnRoute() {\n\t\t\tconst routeName = this.$route?.name\n\t\t\tif (!routeName || routeName !== this.activeRouteName) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.flatEntries.find((entry) => this.isActiveByRule(entry)) ?? null\n\t\t},\n\n\t\t/**\n\t\t * The one entry to mark on a page BELOW a menu route when the query\n\t\t * rule marks none.\n\t\t *\n\t\t * On a detail page (`/cases/123`) the active route is found by path\n\t\t * prefix, and the address carries the detail page's query, not the\n\t\t * list's. When every entry on that list has a `query` (\"My work\",\n\t\t * \"Queue\"), none of them matched and the menu showed no place at\n\t\t * all. Marking all of them is the defect the query rule ended, so\n\t\t * this picks exactly one: the entry the reader last had active on\n\t\t * that route, else the first in menu order.\n\t\t *\n\t\t * Null whenever the existing rule already marks an entry, so a list\n\t\t * with an entry without a `query` behaves as it did. An entry with\n\t\t * `params` is a candidate only when the current path sits below its\n\t\t * own filled-in page path, so another param value is never marked.\n\t\t *\n\t\t * @return {object|null} The entry to mark, or null.\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tsubRouteParent() {\n\t\t\tconst active = this.activeRouteName\n\t\t\tif (!active || this.$route?.name === active) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst path = this.$route?.path\n\t\t\tconst entries = this.flatEntries.filter((entry) => !entry.href && entry.route === active\n\t\t\t\t&& (!this.hasParams(entry) || this.pageMatchDepth(entry, path) > 0))\n\t\t\tif (entries.length === 0 || entries.some((entry) => this.isActiveByRule(entry))) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst remembered = this.lastActiveEntryByRoute[active]\n\t\t\treturn entries.find((entry) => this.entryKey(entry) === remembered) ?? entries[0]\n\t\t},\n\t},\n\n\twatch: {\n\t\tactiveRouteName: {\n\t\t\timmediate: true,\n\t\t\thandler(_current, previous) {\n\t\t\t\tthis.pinGroupsEntered(previous)\n\t\t\t},\n\t\t},\n\n\t\t// The manifest can arrive after the route did.\n\t\tvisibleItems() {\n\t\t\tthis.pinGroupsEntered(this.activeRouteName)\n\t\t},\n\n\t\tentryActiveOnOwnRoute: {\n\t\t\timmediate: true,\n\t\t\t/**\n\t\t\t * Remember which entry of a route the reader used, for\n\t\t\t * `subRouteParent`.\n\t\t\t *\n\t\t\t * @param {object|null} entry The entry active on its own route.\n\t\t\t * @return {void}\n\t\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t\t */\n\t\t\thandler(entry) {\n\t\t\t\tif (entry && entry.route) {\n\t\t\t\t\tthis.lastActiveEntryByRoute[entry.route] = this.entryKey(entry)\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tcreated() {\n\t\t// Non-reactive one-shot latch for warnAutoCountMisconfigured(). It has\n\t\t// to be seeded here rather than lazily on first use: `resolveCount()`\n\t\t// runs DURING RENDER, and Vue 3's instance proxy emits\n\t\t// \"Property \"_autoCountWarned\" was accessed during render but is not\n\t\t// defined on instance\" for the first read of an unset instance field\n\t\t// (Vue 2 read it back as plain `undefined`, silently). It deliberately\n\t\t// stays out of `data()`: a reactive Set mutated inside render would\n\t\t// re-trigger the render effect.\n\t\tthis._autoCountWarned = new Set()\n\t\t// Same latch, for warnUnfilledRouteParam() (`itemTo()` runs during render).\n\t\tthis._unfilledParamWarned = new Set()\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Whether an entry's count asks for attention (`counterVariant:\n\t\t * \"attention\"`): the red pill under the board look, the counter\n\t\t * bubble's highlighted state without it.\n\t\t *\n\t\t * @spec openspec/changes/screens-chrome-parity/specs/layout-components/spec.md#requirement-a-navigation-count-can-ask-for-attention\n\t\t * @param {object} item Menu entry descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\tisAttention(item) {\n\t\t\treturn item?.counterVariant === 'attention'\n\t\t},\n\n\t\t/**\n\t\t * Resolve a menu item's `icon` string to an MDI Vue component. MDI names\n\t\t * resolve via the per-app `registerIcons()` registry; legacy Nextcloud\n\t\t * `icon-*` class names resolve via the shared `cssIconBridge` so they\n\t\t * render monochrome (fill:currentColor) like every other glyph.\n\t\t * Returns `null` (→ the `:icon=\"cssIconClass(item)\"` CSS-class fallback)\n\t\t * for unbridged `icon-*` names and unknown MDI names.\n\t\t *\n\t\t * @param {{ icon?: string }} item Menu item descriptor.\n\t\t * @return {import('vue').Component|null}\n\t\t */\n\t\t/**\n\t\t * The tooltip of a menu entry: its `description` (a saved view's, say),\n\t\t * else null, which leaves NcAppNavigationItem's own (the name).\n\t\t *\n\t\t * @param {{ description?: string }} item Menu item descriptor.\n\t\t * @return {string|null}\n\t\t * @spec openspec/changes/saved-view-icon-description-count/specs/saved-view-icon-description-count/spec.md#requirement-a-saved-view-has-an-icon-and-a-description\n\t\t */\n\t\titemTooltip(item) {\n\t\t\treturn typeof item?.description === 'string' && item.description !== '' ? item.description : null\n\t\t},\n\n\t\tmdiIconComponent(item) {\n\t\t\tconst icon = item?.icon\n\t\t\tif (typeof icon !== 'string' || icon.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (icon.startsWith('icon-')) {\n\t\t\t\treturn bridgedMdiForCssIcon(icon) || null\n\t\t\t}\n\t\t\t// ADR-077: the app's own registerIcons() entries win (so an app can\n\t\t\t// override), then the shared semantic vocabulary — which resolves\n\t\t\t// WITHOUT the app having registered anything. Before the vocabulary\n\t\t\t// existed, a name the app forgot to register resolved to null here\n\t\t\t// and the entry rendered with no icon at all.\n\t\t\treturn ICON_MAP[icon] || getSemanticIconComponent(icon) || null\n\t\t},\n\n\t\t/**\n\t\t * Whether the item declares an icon that NOTHING can resolve — not the\n\t\t * app registry, not the semantic vocabulary, not the widget registry, and\n\t\t * not a URL / SVG path.\n\t\t *\n\t\t * ADR-077 rule 4: such an icon MUST degrade to a visible fallback glyph.\n\t\t * Historically it rendered as empty space, which is indistinguishable\n\t\t * from a deliberate no-icon design choice — 29 of hrmq's 72 nav entries\n\t\t * were silently blank this way. A visible \"?\" is discoverable; blank is\n\t\t * not.\n\t\t *\n\t\t * `icon-*` values are excluded: those have their own CSS-class fallback\n\t\t * path via the `cssIconClass` method.\n\t\t *\n\t\t * @param {{ icon?: string }} item Menu item descriptor.\n\t\t * @return {boolean} true when the declared icon resolves to nothing.\n\t\t */\n\t\tisUnresolvedIcon(item) {\n\t\t\tconst icon = item?.icon\n\t\t\tif (typeof icon !== 'string' || icon.length === 0) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif (icon.startsWith('icon-')) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !this.mdiIconComponent(item)\n\t\t\t\t&& !this.isRichIcon(item)\n\t\t\t\t&& !this.isRegistryIcon(item)\n\t\t},\n\n\t\t/**\n\t\t * Whether the item's icon is a raw SVG path or an image URL (incl. the\n\t\t * `data:` URIs the bundled NL-government sets emit) — neither of which is a\n\t\t * component, so `ICON_MAP` can't resolve it and the `#icon` slot must\n\t\t * render it through CnMenuItemIcon instead.\n\t\t *\n\t\t * Without this, an icon picked from CnIconBrowser's Gemeente / Den Haag /\n\t\t * RVO tabs would simply not appear in the navigation.\n\t\t *\n\t\t * @param {{ icon?: string }} item Menu item descriptor.\n\t\t * @return {boolean} true for path/URL icons.\n\t\t */\n\t\tisRichIcon(item) {\n\t\t\tconst icon = item?.icon\n\t\t\tif (typeof icon !== 'string' || icon.length === 0 || icon.startsWith('icon-')) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn isCustomIconUrl(icon) || isSvgPath(icon)\n\t\t},\n\n\t\t/**\n\t\t * Whether the item's icon is a plain MDI *name* that the shared widget-icon\n\t\t * registry can render (e.g. \"Heart\", \"Home\" — what CnIconBrowser emits from\n\t\t * its component-name sources).\n\t\t *\n\t\t * `ICON_MAP` only holds what the consuming app passed to `registerIcons()`,\n\t\t * and an app rendering USER-AUTHORED manifests cannot pre-register whatever\n\t\t * icon a user might pick — Buildiq registers none at all. So a picked name\n\t\t * failed `mdiIconComponent` (not registered) AND `isRichIcon` (not a URL or\n\t\t * SVG path), the `#icon` slot was skipped entirely, and the menu item rendered\n\t\t * with NO icon — even though CnMenuItemIcon → CnWidgetIcon could resolve it.\n\t\t *\n\t\t * Gate on the registry actually HAVING the name: `getIconComponent` answers\n\t\t * the default icon for anything unknown, so gating on it would render a wrong\n\t\t * (but plausible) icon for a typo instead of none.\n\t\t *\n\t\t * @param {{ icon?: string }} item Menu item descriptor.\n\t\t * @return {boolean} true when the widget-icon registry can render this name.\n\t\t */\n\t\tisRegistryIcon(item) {\n\t\t\treturn hasRegistryIcon(item?.icon)\n\t\t},\n\n\t\t/**\n\t\t * Pass-through for the `:icon` prop on NcAppNavigationItem when\n\t\t * the manifest declares a Nextcloud CSS-class icon (`icon-*`).\n\t\t * Returns an empty string when the icon is an MDI name OR a bridged\n\t\t * `icon-*` (rendered via the `#icon` slot instead), so NcAppNavigationItem\n\t\t * doesn't also paint a CSS-class background-image.\n\t\t *\n\t\t * @param {{ icon?: string }} item Menu item descriptor.\n\t\t * @return {string}\n\t\t */\n\t\tcssIconClass(item) {\n\t\t\tconst icon = item?.icon\n\t\t\tif (typeof icon !== 'string' || icon.length === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (!icon.startsWith('icon-')) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn bridgedMdiForCssIcon(icon) ? '' : icon\n\t\t},\n\n\t\tpassesPermission(item) {\n\t\t\tif (!item.permission) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tif (!this.permissions || this.permissions.length === 0) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn this.permissions.includes(item.permission)\n\t\t},\n\n\t\t/**\n\t\t * Evaluate a menu item's `visibleIf` condition block.\n\t\t *\n\t\t * Returns `true` (visible) when:\n\t\t * - No `visibleIf` is declared (backwards-compatible default).\n\t\t * - `visibleIf.appInstalled` is set AND the named app is\n\t\t * installed / enabled (checked via `OC.appswebroots` then the\n\t\t * capabilities fallback, cached per page load by `isAppInstalled`).\n\t\t * - Context-path predicates (any key that is a dot-separated path\n\t\t * into `manifest.runtime`) all pass against the current runtime\n\t\t * data. Predicates are evaluated by `passesContextPredicates`.\n\t\t * Example: `{ \"user.primaryRole\": { \"in\": [\"hr\", \"compliance\"] } }`\n\t\t * hides the entry unless `manifest.runtime.user.primaryRole` is\n\t\t * `\"hr\"` or `\"compliance\"`. When the runtime block is absent the\n\t\t * entry is hidden (fail-safe: never show role-gated items to\n\t\t * unidentified users).\n\t\t *\n\t\t * All conditions are combined with implicit AND — every condition\n\t\t * must pass for the item to render. Returns `false` when any fails.\n\t\t *\n\t\t * @param {object} item Menu item (or child) to evaluate.\n\t\t * @return {boolean} Whether the item should render.\n\t\t */\n\t\tpassesVisibleIf(item) {\n\t\t\tconst condition = item.visibleIf\n\t\t\tif (!condition || typeof condition !== 'object') {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Specialised condition: appInstalled.\n\t\t\tif (condition.appInstalled) {\n\t\t\t\tif (!isAppInstalled(condition.appInstalled)) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Context-path predicates: any non-reserved key is a dot-path\n\t\t\t// into manifest.runtime evaluated by passesContextPredicates.\n\t\t\tconst runtime = this.effectiveManifest?.runtime ?? null\n\t\t\tif (!passesContextPredicates(condition, runtime)) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t},\n\n\t\t/**\n\t\t * A group's visible children, in `order`.\n\t\t *\n\t\t * The SORT is the fix for a silent no-op: this used to filter only, so\n\t\t * `order` on a child was accepted, documented and ignored. It bites\n\t\t * hardest on relocated leaves, because `applyMenuRelocations()` walks\n\t\t * the menu backwards and appends each move, which lands a group's\n\t\t * children in REVERSE manifest order — an order nobody wrote down and\n\t\t * no app can influence except by reordering `manifest.json` itself.\n\t\t * Pipelinq's Customer Support group read \"Projecten, My Work, Queue,\n\t\t * Tasks, All tickets\" against declared orders of 55, 20, 10, 60, 50.\n\t\t *\n\t\t * Same comparator as the top level, so one rule governs both: items\n\t\t * without an `order` render last, in their existing relative order\n\t\t * (Array.prototype.sort is stable).\n\t\t *\n\t\t * @param {object} item The group whose children to render.\n\t\t * @return {Array<object>} Visible children, ordered.\n\t\t */\n\t\tvisibleChildren(item) {\n\t\t\tif (!Array.isArray(item.children)) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn item.children\n\t\t\t\t.filter((c) => this.passesPermission(c) && this.passesVisibleIf(c))\n\t\t\t\t.sort(byManifestOrder)\n\t\t},\n\n\t\t/**\n\t\t * The label an entry shows: run through the translate function, or\n\t\t * as written when the entry sets `translateLabel: false` (a\n\t\t * user-authored title that may equal a translation key). Every\n\t\t * place the nav shows an entry's label reads it from here.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {string} The label to render as text.\n\t\t */\n\t\tresolveLabel(item) {\n\t\t\tif (item.translateLabel === false) {\n\t\t\t\treturn item.label\n\t\t\t}\n\t\t\treturn this.effectiveTranslate(item.label)\n\t\t},\n\n\t\t/**\n\t\t * Whether a menu entry is the page the reader is on.\n\t\t *\n\t\t * Two entries may share a route and differ only in `query` (\"My\n\t\t * work\" and \"Queue\" on one list). The route name alone lit both. An\n\t\t * entry with a `query` is active only when the address carries that\n\t\t * query; an entry without one steps back when a sibling's query\n\t\t * matches, so exactly one of them is marked. `params` work the\n\t\t * same way against the route's params, so of several entries on a\n\t\t * `/items/:slug` route only the one whose `slug` is in the address\n\t\t * is marked.\n\t\t *\n\t\t * On a page below a list where that rule marks nothing, the one\n\t\t * entry `subRouteParent` picks is active instead.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {boolean} True when the entry is the current page.\n\t\t * @spec openspec/changes/link-cards-page/specs/link-cards-page/spec.md#requirement-menu-entries-that-differ-in-query\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tisActive(item) {\n\t\t\tif (this.isActiveByRule(item)) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tconst parent = this.subRouteParent\n\t\t\treturn parent !== null && toRaw(parent) === toRaw(item)\n\t\t},\n\n\t\t/**\n\t\t * The route, query and params rule on its own, without the fallback\n\t\t * for a page below a list. `subRouteParent` asks this to see whether\n\t\t * the rule already marks an entry.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {boolean} True when the rule marks the entry.\n\t\t * @spec openspec/changes/link-cards-page/specs/link-cards-page/spec.md#requirement-menu-entries-that-differ-in-query\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tisActiveByRule(item) {\n\t\t\tif (item.href || !item.route) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif (item.route !== this.activeRouteName) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif (this.isNarrowed(item)) {\n\t\t\t\treturn this.narrowingMatches(item)\n\t\t\t}\n\t\t\treturn !this.flatEntries.some((entry) => entry !== item\n\t\t\t\t&& entry.route === item.route\n\t\t\t\t&& this.isNarrowed(entry)\n\t\t\t\t&& this.narrowingMatches(entry))\n\t\t},\n\n\t\t/**\n\t\t * Whether an entry narrows its route with a `query` or `params`.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {boolean} True when the entry declares either.\n\t\t */\n\t\tisNarrowed(item) {\n\t\t\treturn Boolean(item.query && typeof item.query === 'object') || this.hasParams(item)\n\t\t},\n\n\t\t/**\n\t\t * Whether the address carries every `query` key and every `params`\n\t\t * key the entry declares.\n\t\t *\n\t\t * @param {object} item Menu entry that narrows its route.\n\t\t * @return {boolean} True when everything it declares matches.\n\t\t */\n\t\tnarrowingMatches(item) {\n\t\t\tconst queryOk = !(item.query && typeof item.query === 'object') || this.queryMatches(item)\n\t\t\tconst paramsOk = !this.hasParams(item) || this.paramsMatch(item)\n\t\t\treturn queryOk && paramsOk\n\t\t},\n\n\t\t/**\n\t\t * Whether an entry declares a non-empty `params` object.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {boolean} True when it has route params.\n\t\t */\n\t\thasParams(item) {\n\t\t\treturn Boolean(item?.params) && typeof item.params === 'object' && Object.keys(item.params).length > 0\n\t\t},\n\n\t\t/**\n\t\t * Whether the route's params carry every key of an entry's\n\t\t * `params`. Values are compared as strings.\n\t\t *\n\t\t * @param {object} item Menu entry with `params`.\n\t\t * @return {boolean} True when every declared key matches.\n\t\t */\n\t\tparamsMatch(item) {\n\t\t\tconst current = this.$route?.params ?? {}\n\t\t\treturn Object.keys(item.params).every((key) => String(current[key] ?? '') === String(item.params[key]))\n\t\t},\n\n\t\t/**\n\t\t * The segments of an entry's page path with its `params` filled in,\n\t\t * as plain values. A missing optional `:name?` segment is dropped;\n\t\t * null when a required one has no param, or without a page.\n\t\t *\n\t\t * @param {object} item Menu entry with `params`.\n\t\t * @return {Array<string>|null} The segments, or null.\n\t\t */\n\t\tfilledPageSegments(item) {\n\t\t\tconst pagePath = this.pageForItem(item)?.route\n\t\t\tif (!pagePath) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst segments = []\n\t\t\tfor (const part of pagePath.split('/').filter(Boolean)) {\n\t\t\t\tconst param = PARAM_SEGMENT.exec(part)\n\t\t\t\tif (!param) {\n\t\t\t\t\tsegments.push(part)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst value = item.params?.[param[1]]\n\t\t\t\tif (isFilled(value)) {\n\t\t\t\t\tsegments.push(String(value))\n\t\t\t\t} else if (!isOptionalParam(param)) {\n\t\t\t\t\treturn null\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn segments\n\t\t},\n\n\t\t/**\n\t\t * The required route param the router cannot fill when it resolves\n\t\t * an entry's link on its manifest page. vue-router fills a named\n\t\t * link's required params from the current route, then overlays every\n\t\t * key the entry declares, empty or null included. So a declared key\n\t\t * decides on its own value, and only an undeclared one falls back\n\t\t * to the current route. Null without a known page, or when every\n\t\t * required segment is filled. Reads `$route`, so it follows\n\t\t * navigation.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {string|null} The param name, or null.\n\t\t */\n\t\tunfilledRouteParam(item) {\n\t\t\tconst pagePath = this.pageForItem(item)?.route\n\t\t\tif (!pagePath) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst declared = item.params && typeof item.params === 'object' ? item.params : {}\n\t\t\tconst current = this.$route?.params ?? {}\n\t\t\tfor (const part of pagePath.split('/')) {\n\t\t\t\tconst param = PARAM_SEGMENT.exec(part)\n\t\t\t\tif (!param || isOptionalParam(param)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst value = param[1] in declared ? declared[param[1]] : current[param[1]]\n\t\t\t\tif (!isFilled(value)) {\n\t\t\t\t\treturn param[1]\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * How deep a path sits on an entry's page path: the page path's\n\t\t * segment count when the path is that page or below it, else 0.\n\t\t * A `/` page path, or one with an unfilled `:name`, never matches.\n\t\t *\n\t\t * Without `params` the page path is compared as written. With\n\t\t * `params`, segments are compared decoded, because the router\n\t\t * percent-encodes param values in the path and the entry holds them\n\t\t * plain.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @param {string|undefined} path The path to test.\n\t\t * @return {number} The depth of the match, or 0.\n\t\t */\n\t\tpageMatchDepth(item, path) {\n\t\t\tif (!path) {\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\tif (!this.hasParams(item)) {\n\t\t\t\tconst pagePath = this.pageForItem(item)?.route\n\t\t\t\tif (!pagePath || pagePath === '/' || pagePath.includes(':')) {\n\t\t\t\t\treturn 0\n\t\t\t\t}\n\t\t\t\tconst below = path === pagePath || path.startsWith(pagePath + '/')\n\t\t\t\treturn below ? pagePath.split('/').filter(Boolean).length : 0\n\t\t\t}\n\t\t\tconst segments = this.filledPageSegments(item)\n\t\t\tif (!segments || segments.length === 0) {\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\tconst current = path.split('/').filter(Boolean).map(decodeSegment)\n\t\t\treturn segments.every((segment, index) => current[index] === segment) ? segments.length : 0\n\t\t},\n\n\t\t/**\n\t\t * What an entry is remembered by: its `id`, else its label.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {string} The key.\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tentryKey(item) {\n\t\t\treturn String(item.id ?? item.label ?? '')\n\t\t},\n\n\t\t/**\n\t\t * Whether the address carries every key of an entry's `query`.\n\t\t * Values are compared as strings, since an address has no numbers.\n\t\t *\n\t\t * @param {object} item Menu entry with a `query`.\n\t\t * @return {boolean} True when every declared key matches.\n\t\t * @spec openspec/changes/link-cards-page/specs/link-cards-page/spec.md#requirement-menu-entries-that-differ-in-query\n\t\t */\n\t\tqueryMatches(item) {\n\t\t\tconst current = this.$route?.query ?? {}\n\t\t\tconst keys = Object.keys(item.query)\n\t\t\treturn keys.length > 0 && keys.every((key) => String(current[key] ?? '') === String(item.query[key]))\n\t\t},\n\n\t\t/**\n\t\t * Whether a menu entry renders as a `NcAppNavigationCaption`\n\t\t * (`type: \"caption\"`) rather than a clickable\n\t\t * `NcAppNavigationItem`. Caption entries ignore `route`, `action`,\n\t\t * `icon`, `count`, `children`, and `pinned`. A caption's `href` is\n\t\t * drawn as a pencil link beside the heading: the place where what\n\t\t * stands under it is changed (a user's own choice of entries, say).\n\t\t *\n\t\t * @param {{ type?: string }} item Menu entry descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\tisCaption(item) {\n\t\t\treturn item?.type === 'caption'\n\t\t},\n\n\t\t/**\n\t\t * The accessible name of a caption's pencil link.\n\t\t *\n\t\t * @param {object} item The caption entry.\n\t\t * @return {string} \"Change {caption}\", translated.\n\t\t */\n\t\tcaptionEditLabel(item) {\n\t\t\treturn t('nextcloud-vue', 'Change {name}', { name: this.resolveLabel(item) })\n\t\t},\n\n\t\t/**\n\t\t * Whether the host has registered a scoped slot named\n\t\t * `item-${id}-actions` for this menu item. Used to gate template\n\t\t * rendering of the per-item `#actions` slot pass-through so items\n\t\t * without a matching slot don't render an empty `<template #actions>`.\n\t\t *\n\t\t * @param {{ id: string }} item Menu entry descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\thasItemActionsSlot(item) {\n\t\t\tif (!item?.id) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst name = `item-${item.id}-actions`\n\t\t\treturn Boolean((this.$slots && this.$slots[name])\n\t\t\t\t|| (this.$slots && this.$slots[name]))\n\t\t},\n\n\t\t/**\n\t\t * Resolve the count value to render in this entry's\n\t\t * `NcCounterBubble` (in the `#counter` slot of\n\t\t * `NcAppNavigationItem`).\n\t\t *\n\t\t * - Literal positive integer in `item.count` → return as-is.\n\t\t * - `item.count` is an object (`{ register, schema, filter? }`) →\n\t\t * `cnMenuItemCounts[item.id] ?? null`, the filtered total CnAppRoot\n\t\t * fetched for this entry.\n\t\t * - `item.count === \"auto\"` → look up the entry's resolved page;\n\t\t * when that page is `type: \"index\"` with a `register`/`schema`\n\t\t * in its `config`, return\n\t\t * `cnMenuCounts[register][schema] ?? null`.\n\t\t *\n\t\t * Returns `null` (no badge) when:\n\t\t * - `item.count` is unset or falsy\n\t\t * - The literal value is `0`\n\t\t * - `count === \"auto\"` but no matching index page resolves\n\t\t * (also emits a one-shot `console.warn`)\n\t\t * - The store has no entry for the resolved `(register, schema)`\n\t\t *\n\t\t * @param {object} item Menu entry descriptor.\n\t\t * @return {number|null} Count to render, or null for no badge.\n\t\t */\n\t\tresolveCount(item) {\n\t\t\tconst raw = item?.count\n\t\t\tif (raw === undefined || raw === null) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (typeof raw === 'number') {\n\t\t\t\treturn raw > 0 ? raw : null\n\t\t\t}\n\t\t\tif (raw && typeof raw === 'object') {\n\t\t\t\t// A filtered count: CnAppRoot fetched it per entry id.\n\t\t\t\tconst value = this.cnMenuItemCounts?.[item.id]\n\t\t\t\treturn (typeof value === 'number' && value > 0) ? value : null\n\t\t\t}\n\t\t\tif (raw !== 'auto') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst page = this.pageForItem(item)\n\t\t\tconst register = page?.config?.register\n\t\t\tconst schema = page?.config?.schema\n\t\t\tif (page?.type !== 'index' || !register || !schema) {\n\t\t\t\tthis.warnAutoCountMisconfigured(item)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst value = this.cnMenuCounts?.[register]?.[schema]\n\t\t\tif (typeof value !== 'number' || value <= 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn value\n\t\t},\n\n\t\t/**\n\t\t * One-shot `console.warn` per menu-item id for misconfigured\n\t\t * `count: \"auto\"` entries (no resolvable index page). Keeps the\n\t\t * console quiet on re-renders.\n\t\t *\n\t\t * @param {{ id: string }} item Menu entry descriptor.\n\t\t * @return {void}\n\t\t * @private\n\t\t */\n\t\twarnAutoCountMisconfigured(item) {\n\t\t\tif (this._autoCountWarned.has(item.id)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis._autoCountWarned.add(item.id)\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[CnAppNav] Menu entry \"${item.id}\" declares count: \"auto\" but has no resolvable index-type page with register + schema config — no badge will render.`)\n\t\t},\n\n\t\t/**\n\t\t * One-shot `console.warn` per menu entry whose link cannot fill a\n\t\t * required route param. Keyed by `id`, else route and label, so\n\t\t * entries without an id each get their own warning.\n\t\t *\n\t\t * @param {{ id?: string, route: string, label?: string }} item Menu entry descriptor.\n\t\t * @param {string} param The unfilled param name.\n\t\t * @return {void}\n\t\t * @private\n\t\t */\n\t\twarnUnfilledRouteParam(item, param) {\n\t\t\tconst key = item.id ?? `${item.route}|${item.label ?? ''}`\n\t\t\tif (this._unfilledParamWarned.has(key)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis._unfilledParamWarned.add(key)\n\t\t\tconst name = item.id ?? item.label ?? item.route\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[CnAppNav] Menu entry \"${name}\" cannot fill the required route param \"${param}\" of page \"${item.route}\" from its params or the current route — the entry renders without a link.`)\n\t\t},\n\n\t\t/**\n\t\t * Look up an item's resolved page (`pages[]` entry whose `id`\n\t\t * matches the menu item's `route`) — used to decide whether the\n\t\t * NcAppNavigationItem should match its router-link `exact`.\n\t\t *\n\t\t * @param {object} item Menu item to resolve.\n\t\t * @return {object|null} Matching page entry, or null when the item\n\t\t * has no `route` or no page matches.\n\t\t */\n\t\tpageForItem(item) {\n\t\t\tif (!item.route) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst pages = this.effectiveManifest?.pages ?? []\n\t\t\treturn pages.find((p) => p.id === item.route) ?? null\n\t\t},\n\n\t\t/**\n\t\t * Build the `:to` value for an `NcAppNavigationItem`. Action\n\t\t * items (`action: \"user-settings\"`) and `href` items return\n\t\t * `null` so the entry is NOT a vue-router link: action items\n\t\t * fall through to the click handler, `href` items render a real\n\t\t * anchor via `itemHref`. Route items return a named route that\n\t\t * carries the item's `params` and `query` when it declares them.\n\t\t *\n\t\t * An item whose manifest page has a required segment that neither\n\t\t * its `params` nor the current route fill also returns null, with a\n\t\t * one-time warning: the router throws resolving such a link, which\n\t\t * would take the whole navigation down rather than that one entry.\n\t\t *\n\t\t * @param {object} item Menu item being rendered.\n\t\t * @return {object|null} A `{ name, params?, query? }` route object,\n\t\t * or null for action / href / route-less / unfillable items.\n\t\t */\n\t\titemTo(item) {\n\t\t\tif (item.action) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (item.href) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (!item.route) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst unfilled = this.unfilledRouteParam(item)\n\t\t\tif (unfilled) {\n\t\t\t\tthis.warnUnfilledRouteParam(item, unfilled)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst to = { name: item.route }\n\t\t\t// Params fill a parameterised route (one entry per catalog →\n\t\t\t// /catalogs/:slug); query deep-links to a pre-filtered index page\n\t\t\t// (one entry per case type → Cases?caseType=…).\n\t\t\tif (this.hasParams(item)) {\n\t\t\t\tto.params = item.params\n\t\t\t}\n\t\t\tif (item.query) {\n\t\t\t\tto.query = item.query\n\t\t\t}\n\t\t\treturn to\n\t\t},\n\n\t\t/**\n\t\t * Whether another visible entry links to the same route, so the two\n\t\t * differ only in `query` or `params` (\"All cases\" and \"Woo requests\"\n\t\t * on one list).\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {boolean} True when the route is shared.\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active\n\t\t */\n\t\tsharesRoute(item) {\n\t\t\tif (!item || item.href || item.action || !item.route) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn this.flatEntries.some((entry) => entry !== item && !entry.href && !entry.action && entry.route === item.route)\n\t\t},\n\n\t\t/**\n\t\t * The app's router, or null when the nav is mounted without one. Read\n\t\t * from the app's global properties: `this.$router` warns during render\n\t\t * on an instance that has none.\n\t\t *\n\t\t * @return {object|null} The router.\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active\n\t\t */\n\t\tappRouter() {\n\t\t\treturn this.$?.appContext?.config?.globalProperties?.$router ?? null\n\t\t},\n\n\t\t/**\n\t\t * The `:to` an entry renders with. An entry that shares its route\n\t\t * renders as a plain link instead (see `linkHref`): NcAppNavigationItem\n\t\t * marks a router link active whenever vue-router calls it active, and\n\t\t * vue-router ignores the query, so \"Woo requests\" lit up beside \"All\n\t\t * cases\" on the unfiltered list. As a plain link only `isActive`\n\t\t * decides, which marks the entry that matches best.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {object|null} The router target, or null.\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active\n\t\t */\n\t\tlinkTo(item) {\n\t\t\tif (this.appRouter() && this.sharesRoute(item)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.itemTo(item)\n\t\t},\n\n\t\t/**\n\t\t * The `:href` an entry renders with: `itemHref`, or for an entry that\n\t\t * shares its route the address vue-router resolves its target to (a\n\t\t * click on it is still routed in the app, see `onItemClick`).\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {string|null} The address, or null.\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active\n\t\t */\n\t\tlinkHref(item) {\n\t\t\tconst own = this.itemHref(item)\n\t\t\tconst router = this.appRouter()\n\t\t\tif (own || !router || !this.sharesRoute(item)) {\n\t\t\t\treturn own\n\t\t\t}\n\t\t\tconst to = this.itemTo(item)\n\t\t\treturn to ? router.resolve(to).href : null\n\t\t},\n\n\t\t/**\n\t\t * Build the `:href` value for an `NcAppNavigationItem`. Returns\n\t\t * the item's `href` so the entry renders as a real anchor whose\n\t\t * destination is visible on hover and which gets the native link\n\t\t * cursor. `NcAppNavigationItem` adds `target=\"_blank\"` itself for\n\t\t * external (`scheme://`) URLs, so those open in a new tab while\n\t\t * internal app paths (e.g. `/index.php/apps/foo/`) navigate in the\n\t\t * same tab — no `window.open` interception. The `admin-settings`\n\t\t * action links to `adminSettingsHref` (absolute, so it opens in a\n\t\t * new tab); other action items carry no href. Returns `null` for\n\t\t * non-href items so the entry stays a router-link / button.\n\t\t *\n\t\t * @param {object} item Menu item being rendered.\n\t\t * @return {string|null} The destination URL, or null.\n\t\t */\n\t\titemHref(item) {\n\t\t\tif (item.action === 'admin-settings') {\n\t\t\t\treturn this.adminSettingsHref || null\n\t\t\t}\n\t\t\tif (item.action) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn item.href || null\n\t\t},\n\n\t\t/**\n\t\t * Whether a menu group renders expanded. Local `openState` (set\n\t\t * by the chevron, a title click, or `pinGroupsEntered`) wins;\n\t\t * otherwise the group auto-expands when it contains the active\n\t\t * route — so deep-linking to a child page reveals which group it\n\t\t * lives in — and finally falls back to the manifest's `item.open`\n\t\t * for the initial render.\n\t\t *\n\t\t * @param {{ id: string, open?: boolean }} item Menu entry descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\tisItemOpen(item) {\n\t\t\tconst local = this.openState[item.id]\n\t\t\tif (local !== undefined) {\n\t\t\t\treturn local\n\t\t\t}\n\t\t\tif (this.hasActiveChild(item)) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn Boolean(item.open)\n\t\t},\n\n\t\t/**\n\t\t * Whether any of a group's visible children is the active route.\n\t\t * Drives auto-expansion of the parent group on page load.\n\t\t *\n\t\t * @param {object} item Menu entry descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\thasActiveChild(item) {\n\t\t\treturn this.visibleChildren(item).some((child) => this.isActive(child))\n\t\t},\n\n\t\t/**\n\t\t * Record a group's expand/collapse state. Bound to\n\t\t * NcAppNavigationItem's `@update:open` (chevron clicks) and\n\t\t * called from `onItemClick` for title clicks on route-less\n\t\t * group items.\n\t\t *\n\t\t * @param {{ id: string }} item Menu entry descriptor.\n\t\t * @param {boolean} value New open state.\n\t\t */\n\t\tsetItemOpen(item, value) {\n\t\t\tthis.openState[item.id] = value\n\t\t},\n\n\t\t/**\n\t\t * Pin open every group the active route just entered.\n\t\t *\n\t\t * Auto-expansion used to be read off the route alone, so a group\n\t\t * opened for a deep link collapsed the moment the route left it. A\n\t\t * group opened for you stays open until you close it. Only a group\n\t\t * the route ENTERS is pinned: one you closed while on one of its\n\t\t * children stays closed while you move between them.\n\t\t *\n\t\t * @param {string|null} previousRoute The active route before this change, or undefined at first render.\n\t\t */\n\t\tpinGroupsEntered(previousRoute) {\n\t\t\tfor (const item of this.visibleItems) {\n\t\t\t\tconst children = this.visibleChildren(item)\n\t\t\t\tif (children.length === 0 || !this.hasActiveChild(item)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst wasInside = children.some((child) => child.route === previousRoute)\n\t\t\t\tif (!wasInside || this.openState[item.id] === undefined) {\n\t\t\t\t\tthis.openState[item.id] = true\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Click handler. Dispatch order: action keyword → group\n\t\t * open/toggle. For `action: \"user-settings\"` invokes the injected\n\t\t * `cnOpenUserSettings` (provided by CnAppRoot) and prevents\n\t\t * default; `action: \"admin-settings\"` is a real link to\n\t\t * `/settings/admin/<appId>` (see `itemHref`) and is left to the\n\t\t * browser; for `action:\n\t\t * \"replay-walkthrough\"` invokes the injected\n\t\t * `cnReplayWalkthrough(item.tourId)` and prevents default. `href`\n\t\t * items with no children are NOT handled here — they render a real\n\t\t * anchor via `itemHref`, so the browser navigates natively\n\t\t * (external URLs open in a new tab, internal app paths in the same\n\t\t * tab).\n\t\t *\n\t\t * A group's children visibility on click depends on whether the\n\t\t * group ITSELF has a destination:\n\t\t * - Route-less, href-less: a pure group header, so its anchor is\n\t\t * a dead `#` link and the click's only job is to TOGGLE the\n\t\t * children open/closed (same effect as the collapse chevron).\n\t\t * - Carries a `route` or `href`: the click is a real navigation\n\t\t * (handled natively by `:to` / the anchor, not prevented here),\n\t\t * and this additionally forces the group OPEN — never closed —\n\t\t * so the reader lands on the group's own page without a second\n\t\t * click to see what else it holds. The collapse chevron is the\n\t\t * only control that can close such a group again.\n\t\t *\n\t\t * @param {object} item Menu item being clicked.\n\t\t * @param {Event} [event] Native click event (used to call\n\t\t * preventDefault for action / group links).\n\t\t */\n\t\tonItemClick(item, event) {\n\t\t\tif (item.action === 'user-settings') {\n\t\t\t\tif (event && typeof event.preventDefault === 'function') {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t}\n\t\t\t\tthis.cnOpenUserSettings()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (item.action === 'admin-settings') {\n\t\t\t\t// ADR-079: a real link to Nextcloud's own settings (see\n\t\t\t\t// itemHref), followed natively in a new tab. Without an app\n\t\t\t\t// id there is no href, and the click does nothing.\n\t\t\t\tif (!this.adminSettingsHref && event && typeof event.preventDefault === 'function') {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (item.action === 'replay-walkthrough') {\n\t\t\t\tif (event && typeof event.preventDefault === 'function') {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t}\n\t\t\t\tthis.cnReplayWalkthrough(item.tourId)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// An entry that shares its route is a plain link (see linkTo); a\n\t\t\t// plain click still navigates inside the app. A modified click\n\t\t\t// (new tab, new window) is left to the browser.\n\t\t\tif (this.appRouter() && this.sharesRoute(item) && event && !event.defaultPrevented\n\t\t\t\t&& !(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) && event.button !== 1) {\n\t\t\t\tconst to = this.itemTo(item)\n\t\t\t\tif (to) {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\tthis.appRouter().push(to).catch(() => {})\n\t\t\t\t}\n\t\t\t}\n\t\t\t// An entry left without a link (see itemTo) renders a `#` anchor;\n\t\t\t// following it would change the address, so the click goes nowhere.\n\t\t\tif (!item.href && this.unfilledRouteParam(item) && event && typeof event.preventDefault === 'function') {\n\t\t\t\tevent.preventDefault()\n\t\t\t}\n\t\t\tif (this.visibleChildren(item).length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!item.route && !item.href) {\n\t\t\t\tif (event && typeof event.preventDefault === 'function') {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t}\n\t\t\t\tthis.setItemOpen(item, !this.isItemOpen(item))\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// The item is ALSO a real destination: let the click navigate\n\t\t\t// natively and reveal the children alongside it.\n\t\t\tthis.setItemOpen(item, true)\n\t\t},\n\n\t\t/**\n\t\t * Click handler for the auto-prepended Personal-settings entry in\n\t\t * the settings foldout. Invokes the injected `cnOpenUserSettings`\n\t\t * (provided by CnAppRoot → opens the host's NcAppSettingsDialog).\n\t\t * No-op inject when mounted standalone.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonPersonalSettingsClick() {\n\t\t\tthis.cnOpenUserSettings()\n\t\t},\n\n\t\t/**\n\t\t * Click handler for the manifest-declared primary action. Emits\n\t\t * `@primary-action` AND the back-compat `@primary-action-click`\n\t\t * event for host-side handling. Navigation is the link's own: an\n\t\t * `href` or `route` action renders as a real link (see\n\t\t * `primaryActionLink`), so the browser or router follows it after\n\t\t * these events. Not invoked when the host overrides the\n\t\t * `#primary-action` slot (it provides its own handler).\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\t/**\n\t\t * Re-emit the object an `open-form` primary action created, so the\n\t\t * host can refresh a list or open the record.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-navigation-primary-action-runs-a-page-action\n\t\t * @param {object} created The created object.\n\t\t * @return {void}\n\t\t */\n\t\tonPrimaryActionCreated(created) {\n\t\t\t/**\n\t\t\t * @event primary-action-created Emitted after an `open-form` primary action saves. Payload: the created object.\n\t\t\t */\n\t\t\tthis.$emit('primary-action-created', created)\n\t\t},\n\n\t\t/**\n\t\t * A card link that is a button (an `action` id) emits `card-action`\n\t\t * with that id for the host to run; links and anchors navigate on\n\t\t * their own.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-the-navigation-carries-a-card-and-a-help-entry\n\t\t * @return {void}\n\t\t */\n\t\tonCardLinkClick() {\n\t\t\tconst card = this.resolvedCard\n\t\t\tif (card && card.action) {\n\t\t\t\t/**\n\t\t\t\t * @event card-action Emitted when the nav card's link is an action button. Payload: the action id.\n\t\t\t\t */\n\t\t\t\tthis.$emit('card-action', card.action)\n\t\t\t}\n\t\t},\n\n\t\tonPrimaryActionClick() {\n\t\t\tconst action = this.activePrimaryAction\n\t\t\tif (!action) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst payload = {\n\t\t\t\tid: action.id,\n\t\t\t\tlabel: action.label,\n\t\t\t\ticon: action.icon,\n\t\t\t\troute: action.route,\n\t\t\t\thref: action.href,\n\t\t\t\tpayload: action.payload,\n\t\t\t\tpage: this.$route?.name,\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event primary-action Emitted when the resolved primary-action button is clicked. Payload includes the action descriptor (`{ id, label, icon, route, href, payload }`) plus the current `page` (route name) for host dispatchers.\n\t\t\t * @type {{ id?: string, label: string, icon?: string, route?: string, href?: string, payload?: unknown, page?: string }}\n\t\t\t */\n\t\t\tthis.$emit('primary-action', payload)\n\t\t\t/**\n\t\t\t * @event primary-action-click Back-compat alias for `@primary-action`. Payload is the resolved primary action object as declared in the manifest.\n\t\t\t */\n\t\t\tthis.$emit('primary-action-click', action)\n\t\t},\n\t},\n}\n</script>\n\n<style>\n.cn-app-nav__hint {\n\tlist-style: none;\n\tpadding: 4px 12px 8px 16px;\n\tfont-size: 13px;\n\tline-height: 1.4;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n/* The emblem beside the app name (`nav.brand.emblem`). A theme sets\n --nldesign-emblem-url for `emblem: true`, and --cn-nav-emblem-size for both. */\n.cn-app-nav__brand-emblem {\n\tflex: none;\n\theight: var(--cn-nav-emblem-size, 34px);\n\twidth: auto;\n\tobject-fit: contain;\n}\n\n.cn-app-nav__brand-emblem--theme {\n\tdisplay: inline-block;\n\twidth: var(--cn-nav-emblem-size, 34px);\n\tbackground: var(--nldesign-emblem-url) center / contain no-repeat;\n}\n\n/* The solid primary action (`solid: true`, or an action that dispatches):\n one full-width primary button, as the board draws \"New case\". */\n.cn-app-nav__primary-action--solid .cn-action-buttons,\n.cn-app-nav__primary-action--solid .cn-action-buttons .button-vue,\n.cn-app-nav__primary-action--solid .button-vue {\n\twidth: 100%;\n\tjustify-content: center;\n}\n\n/* The card above the footer entries (`nav.card`). Theme hooks:\n --cn-nav-card-background and --cn-nav-card-radius. */\n.cn-app-nav__card {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: calc(2 * var(--default-grid-baseline));\n\tmargin: calc(2 * var(--default-grid-baseline));\n\tpadding: calc(4 * var(--default-grid-baseline));\n\tborder-radius: var(--cn-nav-card-radius, var(--border-radius-large));\n\tbackground: var(--cn-nav-card-background, var(--color-background-hover));\n}\n\n.cn-app-nav__card-title {\n\tcolor: var(--color-main-text);\n\tfont-weight: 700;\n}\n\n.cn-app-nav__card-text {\n\tcolor: var(--color-text-maxcontrast);\n\tline-height: 1.4;\n}\n\n.cn-app-nav__card-link {\n\talign-self: flex-start;\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tbackground: none;\n\tcolor: var(--color-primary-element);\n\tfont: inherit;\n\tfont-weight: 600;\n\ttext-decoration: none;\n\tcursor: pointer;\n}\n\n.cn-app-nav__card-link:hover,\n.cn-app-nav__card-link:focus-visible {\n\ttext-decoration: underline;\n}\n\n.cn-app-nav__card-link:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 2px;\n\tborder-radius: var(--border-radius-small, 4px);\n}\n\n/* The brand block at the top of the navigation. */\n.cn-app-nav__brand {\n\talign-items: center;\n\tdisplay: flex;\n\tgap: calc(2.5 * var(--default-grid-baseline));\n\tmin-width: 0;\n\tpadding: calc(2 * var(--default-grid-baseline)) calc(2 * var(--default-grid-baseline)) calc(3 * var(--default-grid-baseline));\n}\n\n.cn-app-nav__brand-logo {\n\tflex: none;\n\theight: 34px;\n\tmax-width: 50%;\n\tobject-fit: contain;\n\twidth: auto;\n}\n\n.cn-app-nav__brand-text {\n\tdisplay: flex;\n\tflex-direction: column;\n\tline-height: 1.15;\n\tmin-width: 0;\n}\n\n.cn-app-nav__brand-name {\n\tcolor: var(--color-main-text);\n\tfont-size: 1.2em;\n\tfont-weight: 700;\n\toverflow-wrap: anywhere;\n}\n\n.cn-app-nav__brand-caption {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.85em;\n\toverflow-wrap: anywhere;\n}\n\n/*\n * The legacy `icon-*` classes in Nextcloud render a background-image\n * with a hardcoded dark fill, so they stay grey when an entry becomes\n * active (text turns white against the primary-element background).\n * Force the icon to white in the active state to match the label.\n * Only applies when the icon is provided via the `icon` prop (CSS\n * class) — items using a `<template #icon>` MDI component already\n * inherit `currentColor`.\n */\n.app-navigation-entry.active .app-navigation-entry-icon[class*=\"icon-\"] {\n\tfilter: brightness(0) invert(1);\n}\n\n/* The link form of the primary action, matching NcAppNavigationNew's scoped layout. */\n.cn-app-nav__primary-action {\n\tdisplay: block;\n\tpadding: calc(var(--default-grid-baseline, 4px) * 2);\n}\n\n/*\n * The primary action never shrinks out of sight. NcAppNavigation renders it in\n * `.app-navigation__body`, a flex child with `overflow-y: scroll` (so its\n * minimum height is 0) beside a list of `height: 100%` and the footer. With a\n * card and footer entries below the list, the column overflows and the body\n * gives up its share of the shrink: \"New case\" showed as a 24px sliver of a\n * 42px button. All three forms carry `.app-navigation-new` (the solid and\n * link wrappers mirror NcAppNavigationNew's class), and the rule is scoped to\n * this component's navigation, so a navigation without a primary action lays\n * out exactly as before.\n */\n.app-navigation[data-testid=\"cn-nav\"] .app-navigation__body:has(> .app-navigation-new) {\n\tflex-shrink: 0;\n}\n\n/*\n * Footer-section items (section: \"footer\") render in NcAppNavigation's\n * #footer slot, outside the scroll container, so they stay visible above\n * the settings foldout regardless of menu length. (The interim\n * `pinned`-prop approach kept them inside the scrollable list, where\n * `margin-top: auto` only bottom-pins while the list does not overflow —\n * long menus showed Documentation / Features & roadmap mid-scroll.)\n *\n * No `padding` here on purpose: it comes from NcAppNavigationList's own\n * `var(--app-navigation-padding)`, so it stays in step with the main list.\n *\n * As a direct `> ul` child of `.app-navigation__content`, NC makes it a\n * shrinkable, scrollable flex item, and NcAppNavigationList adds\n * `overflow-y: auto` besides. That let a two-entry list be squeezed below its\n * content and grow a scrollbar on a short menu, so opt out of both.\n */\n.cn-app-nav__footer-list {\n\tlist-style: none;\n\tmargin: 0;\n\tflex-shrink: 0 !important;\n\toverflow: visible !important;\n}\n\n/*\n * A declared footer that names `settings` first (`nav.footer`) puts the\n * foldout above the footer list. The two are siblings in NcAppNavigation's\n * flex column, so `order` moves them without changing either's markup; the\n * card above keeps order 0 and stays first.\n */\n.cn-app-nav__settings--first {\n\torder: 1;\n}\n\n.cn-app-nav__footer-list--after-settings {\n\torder: 2;\n}\n\n/*\n * Align the settings foldout's items with the main/footer list items,\n * whose icons sit at a 16px inset. The foldout's items live in a bare\n * <ul> inside NcAppNavigationSettings' panel (`#app-settings`, padding\n * 3px), so without this they start ~5px further left and the icon\n * column looks ragged. (The native settings-toggle button sits ~1px\n * left of the 16px baseline, but NC owns that with an !important\n * shorthand — a sub-pixel difference we leave to the native component.)\n */\n.cn-app-nav__settings-list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding-inline-start: 5px;\n}\n</style>\n"],"names":["CnActionButtons","CnMenuItemIcon","MapMarkerPath","t"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnAppNav.vue2.js","sources":["../../../../src/components/CnAppNav/CnAppNav.vue"],"sourcesContent":["<!--\n CnAppNav — manifest-driven app navigation.\n\n Renders the manifest's `menu[]` array as a Nextcloud app navigation\n (NcAppNavigation + NcAppNavigationItem). One level of nested\n `children[]` is supported. Items are sorted by `order` at BOTH levels —\n top-level entries and a group's children — and items without an order\n render last. Items with a `permission` are filtered against\n the `permissions` prop — when the prop is omitted, all items render.\n\n An optional primary action renders above the main list as an\n NcAppNavigationNew button (e.g. a \"new\" button or an active-context\n switcher). Hosts supply it via the `#primary-action` slot (full\n control over dynamic content + click handling); a static\n `nav.primaryAction` ({ label, icon?, route?, href? }) manifest field\n is the declarative fallback. The slot wins when both are present;\n nothing renders when neither is.\n\n Items split into three RENDERED groups by `section`, plus one section\n this component deliberately renders nowhere:\n - `section: \"main\"` (default) — top of the navigation, scrollable.\n - `section: \"footer\"` — rendered in NcAppNavigation's `#footer` slot,\n OUTSIDE the scrollable list and directly above the settings foldout,\n so they stay visible regardless of how long the main menu is. (The\n earlier `pinned`-prop approach kept them inside the scroll container:\n `margin-top: auto` only bottom-pins while the list does not overflow,\n so apps with long menus showed them mid-scroll.) For always-visible,\n non-settings links: Documentation, Features & Roadmap, About.\n - `section: \"settings\"` — rendered INSIDE an NcAppNavigationSettings\n foldout (the NC-native gear-icon button that slides a panel open).\n A \"Personal settings\" entry is auto-prepended at the top of the\n foldout (opens the host app's NcAppSettingsDialog via\n cnOpenUserSettings); opt out with `nav.includePersonalSettings:\n false`. Right below it, an \"Admin settings\" entry is auto-prepended\n for INSTANCE ADMINS only — gated on the `isAdmin` prop (computed by\n CnAppRoot from `getCurrentUser()?.isAdmin`). It is a LINK to\n `/settings/admin/<appId>` that opens in a NEW TAB and carries an\n open-in-new marker (the destination is outside the app — the marker\n says so up front, the new tab keeps the app open), not a modal: per\n ADR-079 app-level\n configuration lives in Nextcloud's own settings framework, which\n authorizes it server-side. `isAdmin` gates VISIBILITY only and is\n never an authorization decision; it is also NOT interchangeable with\n `isOwner`, which means \"owns this app\" rather than \"administers this\n instance\" and keeps its own separate uses. The\n foldout mounts whenever there are settings items OR personal\n settings is enabled — so every app shows a Settings gear with at\n least Personal settings. It is only fully suppressed when there are\n no settings items AND `nav.includePersonalSettings: false`.\n - `section: \"integrations\"` — rendered by this component NOWHERE. Per\n ADR-110 these are the links that LEAVE this app for another one, and\n they belong in the Integrations section at the bottom of the per-user\n settings modal, which CnAppRoot owns. A link to another app cannot be\n the active route and carries no counter, so putting it in the nav\n makes another app's capability read as this app's feature. The one\n deep link that stays in the navigation is the auto-prepended Admin\n settings above — apps never declare that one themselves.\n\n Manifest and translate are injected from CnAppRoot by default but can\n also be passed as props for standalone use without CnAppRoot. Props\n win over inject when both are present.\n\n Items can opt out of routing in favour of a built-in action by\n setting `action` on the manifest entry. Supported keywords:\n `\"user-settings\"` invokes the `cnOpenUserSettings` provide-injected\n by CnAppRoot, which opens the host app's NcAppSettingsDialog modal;\n `\"admin-settings\"` opens `/settings/admin/<appId>` in a new tab (ADR-079);\n `\"replay-walkthrough\"` invokes `cnReplayWalkthrough` (optionally\n with the item's `tourId`) to re-run the product walkthrough from\n the first step (ADR-043). Both `route` and `href` are ignored when\n `action` is set. The injects default to a no-op so CnAppNav stays\n usable standalone (without a CnAppRoot ancestor).\n\n See REQ-JMR-004 of the json-manifest-renderer specification.\n-->\n<template>\n\t<NcAppNavigation :aria-label=\"ariaLabel\" data-testid=\"cn-nav\">\n\t\t<template v-if=\"$slots.search || $slots.brand || navBrand\" #search>\n\t\t\t<!--\n\t\t\t\t@slot brand\n\t\t\t\t@description Replace the brand block at the very top of the\n\t\t\t\tnavigation. Default content: the logo, name and caption from\n\t\t\t\tthe `brand` prop or the manifest's `nav.brand`. Renders\n\t\t\t\tnothing when neither is set.\n\t\t\t\t@binding {object|null} brand The resolved brand (`{ logo, name, caption, alt }`), or null.\n\t\t\t-->\n\t\t\t<slot name=\"brand\" :brand=\"resolvedBrand\">\n\t\t\t\t<div\n\t\t\t\t\tv-if=\"navBrand\"\n\t\t\t\t\tclass=\"cn-app-nav__brand\"\n\t\t\t\t\tdata-testid=\"cn-nav-brand\">\n\t\t\t\t\t<!-- Decorative beside a name: the name already says whose\n\t\t\t\t\t app this is, and an alt text would say it twice. A logo\n\t\t\t\t\t on its own carries the name as its alt text. -->\n\t\t\t\t\t<!-- An emblem (`nav.brand.emblem`) stands in for the logo:\n\t\t\t\t\t the municipality's mark beside the app name, distinct\n\t\t\t\t\t from the wordmark in the top bar. `true` draws the\n\t\t\t\t\t theme's emblem from --nldesign-emblem-url. -->\n\t\t\t\t\t<img\n\t\t\t\t\t\tv-if=\"typeof resolvedBrand.emblem === 'string' && resolvedBrand.emblem !== ''\"\n\t\t\t\t\t\tclass=\"cn-app-nav__brand-emblem\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-brand-emblem\"\n\t\t\t\t\t\t:src=\"resolvedBrand.emblem\"\n\t\t\t\t\t\t:alt=\"resolvedBrand.name ? '' : resolvedBrand.alt\">\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-else-if=\"resolvedBrand.emblem === true\"\n\t\t\t\t\t\tclass=\"cn-app-nav__brand-emblem cn-app-nav__brand-emblem--theme\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-brand-emblem\"\n\t\t\t\t\t\taria-hidden=\"true\" />\n\t\t\t\t\t<img\n\t\t\t\t\t\tv-else-if=\"resolvedBrand.logo\"\n\t\t\t\t\t\tclass=\"cn-app-nav__brand-logo\"\n\t\t\t\t\t\t:src=\"resolvedBrand.logo\"\n\t\t\t\t\t\t:alt=\"resolvedBrand.name ? '' : resolvedBrand.alt\">\n\t\t\t\t\t<span v-if=\"resolvedBrand.name || resolvedBrand.caption\" class=\"cn-app-nav__brand-text\">\n\t\t\t\t\t\t<strong v-if=\"resolvedBrand.name\" class=\"cn-app-nav__brand-name\">{{ resolvedBrand.name }}</strong>\n\t\t\t\t\t\t<span v-if=\"resolvedBrand.caption\" class=\"cn-app-nav__brand-caption\">{{ resolvedBrand.caption }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t</slot>\n\t\t\t<!--\n\t\t\t\t@slot search\n\t\t\t\t@description Forwarded into NcAppNavigation's #search slot.\n\t\t\t\tHosts mount NcAppNavigationSearch here. When unset, no search\n\t\t\t\tinput renders inside the navigation.\n\t\t\t-->\n\t\t\t<slot name=\"search\" />\n\t\t</template>\n\t\t<!-- @slot primary-action Optional primary action rendered above the\n\t\t main list as NcAppNavigation's top region (e.g. an app's \"new\"\n\t\t button or an active-context switcher). When provided, it takes\n\t\t precedence over the manifest-declared primaryAction (page-scoped\n\t\t OR nav root). Omitted entirely when neither the slot nor any\n\t\t resolvable primaryAction is present. -->\n\t\t<slot name=\"primary-action\">\n\t\t\t<!-- A primary action that carries an `action` runs a page action\n\t\t\t (open-form opens the create dialog, navigate pushes a route)\n\t\t\t through CnActionButtons, so \"New case\" can live in the\n\t\t\t navigation without a create page. Drawn as one solid,\n\t\t\t full-width primary button. -->\n\t\t\t<div\n\t\t\t\tv-if=\"activePrimaryAction && primaryDispatchEntry\"\n\t\t\t\tclass=\"app-navigation-new cn-app-nav__primary-action cn-app-nav__primary-action--solid\"\n\t\t\t\tdata-testid=\"cn-nav-primary-action\">\n\t\t\t\t<CnActionButtons\n\t\t\t\t\t:actions=\"[primaryDispatchEntry]\"\n\t\t\t\t\tdata-testid=\"cn-nav-primary-action-dispatch\"\n\t\t\t\t\t@created=\"onPrimaryActionCreated\" />\n\t\t\t</div>\n\t\t\t<!-- A primary action with an href or route is a real link.\n\t\t\t NcAppNavigationNew cannot render one, so this mirrors its\n\t\t\t wrapper and button. `solid: true` takes this same solid,\n\t\t\t full-width button for an action with neither. -->\n\t\t\t<div\n\t\t\t\tv-else-if=\"activePrimaryAction && (primaryActionLink || activePrimaryAction.solid === true)\"\n\t\t\t\tclass=\"app-navigation-new cn-app-nav__primary-action\"\n\t\t\t\t:class=\"{ 'cn-app-nav__primary-action--solid': activePrimaryAction.solid === true }\"\n\t\t\t\tdata-testid=\"cn-nav-primary-action\">\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\twide\n\t\t\t\t\tv-bind=\"primaryActionLink || {}\"\n\t\t\t\t\t@click=\"onPrimaryActionClick\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<component :is=\"primaryActionIconComponent\" :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ resolveLabel(activePrimaryAction) }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t\t<NcAppNavigationNew\n\t\t\t\tv-else-if=\"activePrimaryAction\"\n\t\t\t\t:text=\"resolveLabel(activePrimaryAction)\"\n\t\t\t\tdata-testid=\"cn-nav-primary-action\"\n\t\t\t\t@click=\"onPrimaryActionClick\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<component :is=\"primaryActionIconComponent\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t</NcAppNavigationNew>\n\t\t</slot>\n\t\t<template #list>\n\t\t\t<template v-for=\"item in mainItems\">\n\t\t\t\t<NcAppNavigationCaption\n\t\t\t\t\tv-if=\"isCaption(item)\"\n\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\t:name=\"resolveLabel(item)\"\n\t\t\t\t\t:data-testid=\"`cn-nav-caption-${item.id}`\">\n\t\t\t\t\t<template v-if=\"item.href || item.action === 'user-settings'\" #actions>\n\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\tv-if=\"item.href\"\n\t\t\t\t\t\t\t:href=\"item.href\"\n\t\t\t\t\t\t\t:aria-label=\"captionEditLabel(item)\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-nav-caption-edit-${item.id}`\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Pencil :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ captionEditLabel(item) }}\n\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t:aria-label=\"captionEditLabel(item)\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-nav-caption-edit-${item.id}`\"\n\t\t\t\t\t\t\t@click=\"cnOpenUserSettings()\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Pencil :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ captionEditLabel(item) }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t</template>\n\t\t\t\t</NcAppNavigationCaption>\n\t\t\t\t<!-- `type: \"hint\"`: a muted line, no link, as the empty \"My\n\t\t\t\t filters\" group says how to add a filter. -->\n\t\t\t\t<li\n\t\t\t\t\tv-else-if=\"item.type === 'hint'\"\n\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\tclass=\"cn-app-nav__hint\"\n\t\t\t\t\t:data-testid=\"`cn-nav-hint-${item.id}`\">\n\t\t\t\t\t{{ resolveLabel(item) }}\n\t\t\t\t</li>\n\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\tv-else\n\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\t:name=\"resolveLabel(item)\"\n\t\t\t\t\t:title=\"itemTooltip(item)\"\n\t\t\t\t\t:to=\"linkTo(item)\"\n\t\t\t\t\t:href=\"linkHref(item)\"\n\t\t\t\t\t:icon=\"cssIconClass(item)\"\n\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t:pinned=\"Boolean(item.pinned)\"\n\t\t\t\t\t:allowCollapse=\"visibleChildren(item).length > 0\"\n\t\t\t\t\t:open=\"isItemOpen(item)\"\n\t\t\t\t\t:data-testid=\"`cn-nav-entry-${item.id}`\"\n\t\t\t\t\t:data-cn-route=\"item.route\"\n\t\t\t\t\t@update:open=\"setItemOpen(item, $event)\"\n\t\t\t\t\t@click=\"onItemClick(item, $event)\">\n\t\t\t\t\t<template v-if=\"mdiIconComponent(item) || isRichIcon(item) || isRegistryIcon(item) || isUnresolvedIcon(item)\" #icon>\n\t\t\t\t\t\t<component :is=\"mdiIconComponent(item)\" v-if=\"mdiIconComponent(item)\" :size=\"20\" />\n\t\t\t\t\t\t<HelpCircleOutline v-else-if=\"isUnresolvedIcon(item)\" :size=\"20\" />\n\t\t\t\t\t\t<CnMenuItemIcon v-else :icon=\"item.icon\" :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t<template v-if=\"resolveCount(item)\" #counter>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tv-if=\"isBoard\"\n\t\t\t\t\t\t\tclass=\"cn-app-nav__count\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-app-nav__count--attention': isAttention(item) }\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-nav-count-${item.id}`\">\n\t\t\t\t\t\t\t{{ resolveCount(item) }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcCounterBubble\n\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t:count=\"resolveCount(item)\"\n\t\t\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t\t\t:type=\"isAttention(item) ? 'highlighted' : undefined\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t<template v-if=\"hasItemActionsSlot(item)\" #actions>\n\t\t\t\t\t\t<!--\n\t\t\t\t\t\t\t@slot `item-${item.id}-actions`\n\t\t\t\t\t\t\t@description Per-item scoped slot whose content lands inside\n\t\t\t\t\t\t\tthe NcAppNavigationItem's #actions slot for the menu entry\n\t\t\t\t\t\t\twith that id. Use it for inline NcActions menus (e.g. an\n\t\t\t\t\t\t\titem-level \"Pin\" button). Scope receives the menu item.\n\t\t\t\t\t\t\t@binding {object} item The menu item descriptor.\n\t\t\t\t\t\t-->\n\t\t\t\t\t\t<slot :name=\"`item-${item.id}-actions`\" :item=\"item\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\tv-for=\"child in visibleChildren(item)\"\n\t\t\t\t\t\t:key=\"child.id\"\n\t\t\t\t\t\t:name=\"resolveLabel(child)\"\n\t\t\t\t\t\t:to=\"linkTo(child)\"\n\t\t\t\t\t\t:href=\"linkHref(child)\"\n\t\t\t\t\t\t:icon=\"cssIconClass(child)\"\n\t\t\t\t\t\t:active=\"isActive(child)\"\n\t\t\t\t\t\t:pinned=\"Boolean(child.pinned)\"\n\t\t\t\t\t\t:data-testid=\"`cn-nav-entry-${child.id}`\"\n\t\t\t\t\t\t:data-cn-route=\"child.route\"\n\t\t\t\t\t\t@click=\"onItemClick(child, $event)\">\n\t\t\t\t\t\t<template v-if=\"mdiIconComponent(child) || isRichIcon(child) || isRegistryIcon(child) || isUnresolvedIcon(child)\" #icon>\n\t\t\t\t\t\t\t<component :is=\"mdiIconComponent(child)\" v-if=\"mdiIconComponent(child)\" :size=\"20\" />\n\t\t\t\t\t\t\t<HelpCircleOutline v-else-if=\"isUnresolvedIcon(child)\" :size=\"20\" />\n\t\t\t\t\t\t\t<CnMenuItemIcon v-else :icon=\"child.icon\" :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t<template v-if=\"resolveCount(child)\" #counter>\n\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\tv-if=\"isBoard\"\n\t\t\t\t\t\t\t\tclass=\"cn-app-nav__count\"\n\t\t\t\t\t\t\t\t:class=\"{ 'cn-app-nav__count--attention': isAttention(child) }\"\n\t\t\t\t\t\t\t\t:data-testid=\"`cn-nav-count-${child.id}`\">\n\t\t\t\t\t\t\t\t{{ resolveCount(child) }}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<NcCounterBubble\n\t\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t\t:count=\"resolveCount(child)\"\n\t\t\t\t\t\t\t\t:active=\"isActive(child)\"\n\t\t\t\t\t\t\t\t:type=\"isAttention(child) ? 'highlighted' : undefined\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t</NcAppNavigationItem>\n\t\t\t</template>\n\t\t</template>\n\t\t<template v-if=\"footerItems.length > 0 || showSettingsFoldout || resolvedCard || showsHelp\" #footer>\n\t\t\t<!--\n\t\t\t\t@slot card\n\t\t\t\t@description Replace the card above the footer entries\n\t\t\t\t(`nav.card`). Default content: a title, a line of text and one\n\t\t\t\tlink. Renders nothing when neither the slot nor `nav.card` is set.\n\t\t\t\t@binding {object|null} card The resolved card, or null.\n\t\t\t-->\n\t\t\t<slot name=\"card\" :card=\"resolvedCard\">\n\t\t\t\t<div\n\t\t\t\t\tv-if=\"resolvedCard\"\n\t\t\t\t\tclass=\"cn-app-nav__card\"\n\t\t\t\t\tdata-testid=\"cn-nav-card\">\n\t\t\t\t\t<strong class=\"cn-app-nav__card-title\">{{ resolvedCard.title }}</strong>\n\t\t\t\t\t<span v-if=\"resolvedCard.text\" class=\"cn-app-nav__card-text\">{{ resolvedCard.text }}</span>\n\t\t\t\t\t<component\n\t\t\t\t\t\t:is=\"resolvedCard.linkTag\"\n\t\t\t\t\t\tv-if=\"resolvedCard.linkTag\"\n\t\t\t\t\t\tclass=\"cn-app-nav__card-link\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-card-link\"\n\t\t\t\t\t\tv-bind=\"resolvedCard.linkAttrs\"\n\t\t\t\t\t\t@click=\"onCardLinkClick\">\n\t\t\t\t\t\t{{ resolvedCard.linkLabel }}\n\t\t\t\t\t</component>\n\t\t\t\t</div>\n\t\t\t</slot>\n\t\t\t<!-- Footer-section entries (Documentation, Features & Roadmap,\n\t\t\t About) live in NcAppNavigation's #footer slot — OUTSIDE the\n\t\t\t scrollable list — so they stay visible above the settings\n\t\t\t foldout no matter how long the main menu is. The pinned-prop\n\t\t\t approach only bottom-pinned while the list did not overflow.\n\n\t\t\t NcAppNavigationList, not a bare <ul>: its padding, gap and\n\t\t\t hover highlight are scoped to itself, so they survive being\n\t\t\t slotted. The main list's inset comes from NcAppNavigation's\n\t\t\t scope, which slot content does not carry. -->\n\t\t\t<NcAppNavigationList\n\t\t\t\tv-if=\"footerItems.length > 0 || showsHelp\"\n\t\t\t\tclass=\"cn-app-nav__footer-list\"\n\t\t\t\t:class=\"{ 'cn-app-nav__footer-list--after-settings': settingsFirst }\">\n\t\t\t\t<!-- The help entry (`nav.help`): a link to the app's own help\n\t\t\t\t with a help icon, above the footer entries (or after them,\n\t\t\t\t when a declared `nav.footer` names it last). -->\n\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\tv-if=\"showsHelp && !helpAfterItems\"\n\t\t\t\t\t:name=\"resolvedHelp.label\"\n\t\t\t\t\t:to=\"resolvedHelp.to\"\n\t\t\t\t\t:href=\"resolvedHelp.href\"\n\t\t\t\t\t:target=\"resolvedHelp.href ? '_blank' : undefined\"\n\t\t\t\t\tdata-testid=\"cn-nav-help\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<HelpCircleOutline :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\tv-for=\"item in footerItems\"\n\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\t:name=\"resolveLabel(item)\"\n\t\t\t\t\t:to=\"linkTo(item)\"\n\t\t\t\t\t:href=\"linkHref(item)\"\n\t\t\t\t\t:icon=\"cssIconClass(item)\"\n\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t:data-testid=\"`cn-nav-entry-${item.id}`\"\n\t\t\t\t\t:data-cn-route=\"item.route\"\n\t\t\t\t\t@click=\"onItemClick(item, $event)\">\n\t\t\t\t\t<template v-if=\"mdiIconComponent(item) || isRichIcon(item) || isRegistryIcon(item) || isUnresolvedIcon(item)\" #icon>\n\t\t\t\t\t\t<component :is=\"mdiIconComponent(item)\" v-if=\"mdiIconComponent(item)\" :size=\"20\" />\n\t\t\t\t\t\t<HelpCircleOutline v-else-if=\"isUnresolvedIcon(item)\" :size=\"20\" />\n\t\t\t\t\t\t<CnMenuItemIcon v-else :icon=\"item.icon\" :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t<template v-if=\"resolveCount(item)\" #counter>\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tv-if=\"isBoard\"\n\t\t\t\t\t\t\tclass=\"cn-app-nav__count\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-app-nav__count--attention': isAttention(item) }\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-nav-count-${item.id}`\">\n\t\t\t\t\t\t\t{{ resolveCount(item) }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcCounterBubble\n\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t:count=\"resolveCount(item)\"\n\t\t\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t\t\t:type=\"isAttention(item) ? 'highlighted' : undefined\" />\n\t\t\t\t\t</template>\n\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\tv-if=\"showsHelp && helpAfterItems\"\n\t\t\t\t\t:name=\"resolvedHelp.label\"\n\t\t\t\t\t:to=\"resolvedHelp.to\"\n\t\t\t\t\t:href=\"resolvedHelp.href\"\n\t\t\t\t\t:target=\"resolvedHelp.href ? '_blank' : undefined\"\n\t\t\t\t\tdata-testid=\"cn-nav-help\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<HelpCircleOutline :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t</NcAppNavigationItem>\n\t\t\t</NcAppNavigationList>\n\t\t\t<!-- Settings foldout (section: \"settings\" items). NC-native\n\t\t\t gear-icon button that slides open a panel; the first entry\n\t\t\t is an auto-prepended \"Personal settings\" that opens the\n\t\t\t host app's NcAppSettingsDialog via cnOpenUserSettings. -->\n\t\t\t<NcAppNavigationSettings\n\t\t\t\tv-if=\"showSettingsFoldout\"\n\t\t\t\t:name=\"settingsFoldoutLabel\"\n\t\t\t\t:class=\"{ 'cn-app-nav__settings--first': settingsFirst }\"\n\t\t\t\tdata-testid=\"cn-nav-settings\">\n\t\t\t\t<ul class=\"cn-app-nav__settings-list\">\n\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\tv-if=\"includePersonalSettings\"\n\t\t\t\t\t\t:name=\"personalSettingsLabel\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-personal-settings\"\n\t\t\t\t\t\t@click=\"onPersonalSettingsClick\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<Cog :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\tv-if=\"roadmapEntry\"\n\t\t\t\t\t\t:name=\"roadmapEntry.label\"\n\t\t\t\t\t\t:to=\"roadmapEntry.to\"\n\t\t\t\t\t\t:href=\"roadmapEntry.href\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-roadmap\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<MapMarkerPath :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\tv-if=\"documentationEntry\"\n\t\t\t\t\t\t:name=\"documentationEntry.label\"\n\t\t\t\t\t\t:href=\"documentationEntry.href\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-documentation\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<BookOpenVariant :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t\t<!-- The target is Nextcloud's OWN settings area, not an\n\t\t\t\t\t in-app route: a new tab keeps the app open, and the\n\t\t\t\t\t trailing open-in-new marker tells the user they are\n\t\t\t\t\t leaving the app before they click. The new tab comes\n\t\t\t\t\t from the href being ABSOLUTE (see adminSettingsHref) —\n\t\t\t\t\t NcAppNavigationItem ignores a `target` attr and only\n\t\t\t\t\t sets target=\"_blank\" for scheme-prefixed hrefs. -->\n\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\tv-if=\"showAdminSettingsLink\"\n\t\t\t\t\t\t:name=\"adminSettingsLabel\"\n\t\t\t\t\t\t:href=\"adminSettingsHref\"\n\t\t\t\t\t\tdata-testid=\"cn-nav-admin-settings\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<ShieldAccountOutline :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t<template #counter>\n\t\t\t\t\t\t\t<OpenInNew :size=\"16\" :title=\"opensInNewTabHint\" data-testid=\"cn-nav-admin-settings-external\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t\t<template v-for=\"item in settingsItems\">\n\t\t\t\t\t\t<NcAppNavigationCaption\n\t\t\t\t\t\t\tv-if=\"isCaption(item)\"\n\t\t\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\t\t\t:name=\"resolveLabel(item)\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-nav-caption-${item.id}`\">\n\t\t\t\t\t\t\t<template v-if=\"item.href || item.action === 'user-settings'\" #actions>\n\t\t\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\t\t\tv-if=\"item.href\"\n\t\t\t\t\t\t\t\t\t:href=\"item.href\"\n\t\t\t\t\t\t\t\t\t:aria-label=\"captionEditLabel(item)\"\n\t\t\t\t\t\t\t\t\t:data-testid=\"`cn-nav-caption-edit-${item.id}`\">\n\t\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t\t<Pencil :size=\"20\" />\n\t\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t\t{{ captionEditLabel(item) }}\n\t\t\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t\t\t:aria-label=\"captionEditLabel(item)\"\n\t\t\t\t\t\t\t\t\t:data-testid=\"`cn-nav-caption-edit-${item.id}`\"\n\t\t\t\t\t\t\t\t\t@click=\"cnOpenUserSettings()\">\n\t\t\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t\t\t<Pencil :size=\"20\" />\n\t\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t\t{{ captionEditLabel(item) }}\n\t\t\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcAppNavigationCaption>\n\t\t\t\t\t\t<NcAppNavigationItem\n\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t:key=\"item.id\"\n\t\t\t\t\t\t\t:name=\"resolveLabel(item)\"\n\t\t\t\t\t\t\t:to=\"linkTo(item)\"\n\t\t\t\t\t\t\t:href=\"linkHref(item)\"\n\t\t\t\t\t\t\t:icon=\"cssIconClass(item)\"\n\t\t\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t\t\t:data-cn-route=\"item.route\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-nav-entry-${item.id}`\"\n\t\t\t\t\t\t\t@click=\"onItemClick(item, $event)\">\n\t\t\t\t\t\t\t<template v-if=\"mdiIconComponent(item) || isRichIcon(item) || isRegistryIcon(item) || isUnresolvedIcon(item)\" #icon>\n\t\t\t\t\t\t\t\t<component :is=\"mdiIconComponent(item)\" v-if=\"mdiIconComponent(item)\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<HelpCircleOutline v-else-if=\"isUnresolvedIcon(item)\" :size=\"20\" />\n\t\t\t\t\t\t\t\t<CnMenuItemIcon v-else :icon=\"item.icon\" :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t<template v-if=\"resolveCount(item)\" #counter>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tv-if=\"isBoard\"\n\t\t\t\t\t\t\t\t\tclass=\"cn-app-nav__count\"\n\t\t\t\t\t\t\t\t\t:class=\"{ 'cn-app-nav__count--attention': isAttention(item) }\"\n\t\t\t\t\t\t\t\t\t:data-testid=\"`cn-nav-count-${item.id}`\">\n\t\t\t\t\t\t\t\t\t{{ resolveCount(item) }}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<NcCounterBubble\n\t\t\t\t\t\t\t\t\tv-else\n\t\t\t\t\t\t\t\t\t:count=\"resolveCount(item)\"\n\t\t\t\t\t\t\t\t\t:active=\"isActive(item)\"\n\t\t\t\t\t\t\t\t\t:type=\"isAttention(item) ? 'highlighted' : undefined\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcAppNavigationItem>\n\t\t\t\t\t</template>\n\t\t\t\t</ul>\n\t\t\t</NcAppNavigationSettings>\n\t\t</template>\n\t</NcAppNavigation>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcActionButton, NcActionLink, NcAppNavigation, NcAppNavigationCaption, NcAppNavigationItem, NcAppNavigationList, NcAppNavigationNew, NcAppNavigationSettings, NcButton, NcCounterBubble } from '@nextcloud/vue'\nimport { toRaw } from 'vue'\nimport BookOpenVariant from 'vue-material-design-icons/BookOpenVariant.vue'\nimport Cog from 'vue-material-design-icons/Cog.vue'\n// ADR-077 rule 4: visible fallback for an unresolvable icon name.\nimport HelpCircleOutline from 'vue-material-design-icons/HelpCircleOutline.vue'\nimport MapMarkerPath from 'vue-material-design-icons/MapMarkerPath.vue'\nimport OpenInNew from 'vue-material-design-icons/OpenInNew.vue'\nimport Pencil from 'vue-material-design-icons/Pencil.vue'\nimport Plus from 'vue-material-design-icons/Plus.vue'\nimport ShieldAccountOutline from 'vue-material-design-icons/ShieldAccountOutline.vue'\nimport { ICON_MAP } from '../CnIcon/CnIcon.vue'\nimport CnMenuItemIcon from '../CnMenuWidget/CnMenuItemIcon.vue'\nimport { useLook } from '../../composables/useLook.js'\nimport { isAppInstalled } from '../../utils/appInstalled.js'\nimport { isSvgPath } from '../../utils/iconUtils.js'\nimport { resolveBrand } from '../../utils/resolveBrand.js'\nimport { passesContextPredicates } from '../../utils/visibleIfContext.js'\nimport { CnActionButtons } from '../CnActionButtons/index.js'\n// The legacy `icon-*` → MDI bridge lives beside CnIcon now, so the menu EDITOR\n// resolves a seeded `icon-comment` the same way this nav does. It used to be a\n// map local to this file, which is why the nav drew a proper glyph and the\n// editor drew a help-circle \"?\" for the very same manifest value.\nimport { bridgedMdiForCssIcon } from '../CnIcon/cssIconBridge.js'\nimport { getSemanticIconComponent } from '../CnIcon/semanticIcons.js'\nimport { hasRegistryIcon, isCustomIconUrl } from '../CnWidgetGrid/widgetIcons.js'\n\n/**\n * Order two menu entries by their manifest `order`.\n *\n * Entries carrying an `order` come first, ascending; entries without one render\n * last and keep their relative order. Used at BOTH nav levels so a group's\n * children obey the same rule as the top-level list.\n *\n * @param {object} a First entry.\n * @param {object} b Second entry.\n * @return {number} Comparator result.\n */\nfunction byManifestOrder(a, b) {\n\tconst aHas = typeof a.order === 'number'\n\tconst bHas = typeof b.order === 'number'\n\tif (aHas && !bHas) {\n\t\treturn -1\n\t}\n\tif (!aHas && bHas) {\n\t\treturn 1\n\t}\n\tif (!aHas && !bHas) {\n\t\treturn 0\n\t}\n\treturn a.order - b.order\n}\n\n/** A `:name` page-path segment: name, optional `(regexp)`, optional modifier. */\nconst PARAM_SEGMENT = /^:(\\w+)(\\([^)]*\\))?([?*+])?$/\n\n/**\n * Whether a `PARAM_SEGMENT` match may be left out (`?` or `*`).\n *\n * @param {Array<string>} param The match.\n * @return {boolean} True for an optional segment.\n */\nfunction isOptionalParam(param) {\n\treturn param[3] === '?' || param[3] === '*'\n}\n\n/**\n * Whether a route param value fills its segment.\n *\n * @param {unknown} value The value.\n * @return {boolean} False for undefined, null and the empty string.\n */\nfunction isFilled(value) {\n\treturn value !== undefined && value !== null && value !== ''\n}\n\n/**\n * Decode one percent-encoded path segment, or keep it as is when it is not\n * valid percent-encoding.\n *\n * @param {string} segment The segment.\n * @return {string} The decoded segment.\n */\nfunction decodeSegment(segment) {\n\ttry {\n\t\treturn decodeURIComponent(segment)\n\t} catch {\n\t\treturn segment\n\t}\n}\n\nexport default {\n\tname: 'CnAppNav',\n\n\tcomponents: {\n\t\tNcActionButton,\n\t\tNcActionLink,\n\t\tPencil,\n\t\tNcAppNavigation,\n\t\tNcAppNavigationCaption,\n\t\tNcAppNavigationItem,\n\t\tNcAppNavigationList,\n\t\tNcAppNavigationNew,\n\t\tNcAppNavigationSettings,\n\t\tNcButton,\n\t\tNcCounterBubble,\n\t\tCnActionButtons,\n\t\tCnMenuItemIcon,\n\t\tCog,\n\t\tHelpCircleOutline,\n\t\tShieldAccountOutline,\n\t\tMapMarkerPath,\n\t\tBookOpenVariant,\n\t\tOpenInNew,\n\t},\n\n\tinject: {\n\t\tcnManifest: { default: null },\n\t\t/**\n\t\t * Provided by CnAppRoot as true while the board look draws the brand\n\t\t * block in Nextcloud's header (screens-brand-block-top-bar): the\n\t\t * navigation then skips its own.\n\t\t */\n\t\tcnBrandInHeader: { default: false },\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/**\n\t\t * Provided by CnAppRoot — opens the host app's\n\t\t * NcAppSettingsDialog. Defaults to a no-op so CnAppNav is\n\t\t * still usable when mounted outside a CnAppRoot ancestor;\n\t\t * the click silently does nothing in that case rather than\n\t\t * throwing.\n\t\t */\n\t\tcnOpenUserSettings: { default: () => () => {} },\n\t\t/**\n\t\t * Provided by CnAppRoot — the consuming app's slug, used to build\n\t\t * the \"Admin settings\" link target `/settings/admin/<appId>`.\n\t\t * Overridden by the explicit `appId` prop when both are present.\n\t\t * Null outside a CnAppRoot ancestor, in which case the link is\n\t\t * suppressed (ADR-079 §2).\n\t\t */\n\t\tcnAppId: { default: null },\n\t\t/**\n\t\t * Provided by CnAppRoot — restarts the product walkthrough (ADR-043)\n\t\t * from the first step. Bound to menu entries declaring\n\t\t * `action: \"replay-walkthrough\"` (optionally with a `tourId`).\n\t\t * Defaults to a no-op so CnAppNav stays usable standalone.\n\t\t */\n\t\tcnReplayWalkthrough: { default: () => () => {} },\n\t\t/**\n\t\t * Provided by CnAppRoot — reactive `{ [register]: { [schema]: number } }`\n\t\t * map populated from `useObjectStore().totals` for every\n\t\t * `count: \"auto\"` menu entry whose resolved page is `type: \"index\"`\n\t\t * with `register + schema` in its config. Defaults to an empty\n\t\t * object so `resolveCount` returns `null` (no badge) when CnAppNav\n\t\t * is mounted outside a CnAppRoot ancestor.\n\t\t *\n\t\t * @type {{ [register: string]: { [schema: string]: number } }}\n\t\t */\n\t\tcnMenuCounts: { default: () => ({}) },\n\t\t/**\n\t\t * Provided by CnAppRoot — reactive `{ [menuItemId]: number }` totals\n\t\t * for every menu entry whose `count` is an object\n\t\t * (`{ register, schema, filter? }`): the total of that filtered\n\t\t * list, fetched under the entry's own key so an index page's\n\t\t * whole-schema total is left alone. Empty outside a CnAppRoot.\n\t\t *\n\t\t * @type {{ [itemId: string]: number }}\n\t\t */\n\t\tcnMenuItemCounts: { default: () => ({}) },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The look the navigation is drawn in: `board` or `nextcloud`. Empty\n\t\t * follows the `cnLook` that CnAppRoot provides. Under `board` the\n\t\t * navigation takes the anatomy of the screens (264px, 42px entries,\n\t\t * attention counts, Help before Advanced).\n\t\t *\n\t\t * @spec openspec/changes/screens-chrome-parity/specs/layout-components/spec.md#requirement-the-navigation-takes-the-board-anatomy\n\t\t */\n\t\tlook: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Manifest object. Falls back to injected `cnManifest`. Provide\n\t\t * explicitly when mounting CnAppNav outside of CnAppRoot.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tmanifest: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Translate function. Falls back to injected `cnTranslate`,\n\t\t * which itself defaults to an identity function.\n\t\t *\n\t\t * @type {((key: string) => string)|null}\n\t\t */\n\t\ttranslate: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * List of permission strings the current user holds. Items\n\t\t * declaring a `permission` only render when their permission\n\t\t * appears in this list. When the prop is omitted (or empty),\n\t\t * all items are visible regardless of their permission field.\n\t\t *\n\t\t * @type {Array<string>}\n\t\t */\n\t\tpermissions: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * Whether the current user is an OWNER of this app\n\t\t * (admin-settings-owner-gating capability). Computed by CnAppRoot\n\t\t * from `currentUserGroups` ∩ `permissions.owners` and/or a manifest\n\t\t * `runtime.user` owner signal — deliberately NOT `OC.isUserAdmin()`.\n\t\t * Read by nothing in this component: the auto-included \"Admin\n\t\t * settings\" entry is gated on `isAdmin` alone (see the file header\n\t\t * and `showAdminSettingsLink`). The prop stays because CnAppRoot\n\t\t * binds it as published API and owner-gating is its own question,\n\t\t * not the instance-admin one.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tisOwner: { // eslint-disable-line vue/no-unused-properties -- published prop bound by CnAppRoot; owner-gating is decided upstream, not here\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Whether the current user administers this Nextcloud instance.\n\t\t * Computed by CnAppRoot from `getCurrentUser()?.isAdmin`\n\t\t * (`@nextcloud/auth`) — NOT the legacy `OC.isUserAdmin()` global,\n\t\t * and NOT interchangeable with `isOwner`, which is about owning a\n\t\t * given app rather than administering the instance (ADR-079 §3).\n\t\t *\n\t\t * Gates VISIBILITY of the \"Admin settings\" link only. It is not an\n\t\t * authorization decision and MUST NOT be used as one: the boundary\n\t\t * is Nextcloud's settings framework, which refuses\n\t\t * `/settings/admin/<app>` server-side for non-admins. Defaults to\n\t\t * `false` so CnAppNav mounted standalone never shows the link.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tisAdmin: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * App id used to build the \"Admin settings\" link target\n\t\t * (`/settings/admin/<appId>`). Falls back to the injected\n\t\t * `cnAppId` provided by CnAppRoot. With neither available the\n\t\t * link is suppressed rather than pointing at a broken URL.\n\t\t *\n\t\t * @type {string|null}\n\t\t */\n\t\tappId: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Accessible name for the navigation landmark, forwarded to\n\t\t * `NcAppNavigation`'s `aria-label`.\n\t\t *\n\t\t * `@nextcloud/vue` 9 requires `ariaLabel` or `ariaLabelledby` and warns\n\t\t * when neither is set: a `<nav>` with no accessible name is announced as\n\t\t * an unlabelled landmark, so a screen-reader user tabbing the landmark\n\t\t * list cannot tell it from any other nav on the page (WCAG 2.4.6 /\n\t\t * 1.3.1). The default covers every consumer without a code change; pass\n\t\t * your own when an app shows more than one navigation, since the point\n\t\t * of the name is to tell them apart.\n\t\t *\n\t\t * @type {string}\n\t\t */\n\t\tariaLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Main navigation'),\n\t\t},\n\n\t\t/**\n\t\t * The brand block at the top of the navigation:\n\t\t * `{ logo?, name?, caption?, alt? }`. `logo` is an image URL, `name`\n\t\t * the app or organisation name, `caption` a line under it. Falls back\n\t\t * to the manifest's `nav.brand`. `null` (the default) with no manifest\n\t\t * brand renders nothing.\n\t\t *\n\t\t * @type {{logo?: string, name?: string, caption?: string, alt?: string}|null}\n\t\t */\n\t\tbrand: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: ['primary-action', 'primary-action-click', 'primary-action-created', 'card-action'],\n\n\tsetup(props) {\n\t\tconst { isBoard } = useLook(props)\n\t\treturn { isBoard }\n\t},\n\n\t/**\n\t * The navigation's own state: which groups are open, and which entry\n\t * of a route the reader last used.\n\t *\n\t * @return {object} The state.\n\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t */\n\tdata() {\n\t\treturn {\n\t\t\t/**\n\t\t\t * Per-item expand/collapse state for menu groups, keyed by\n\t\t\t * item id. Seeded lazily from the manifest's `item.open` by\n\t\t\t * `isItemOpen`; written by the collapse chevron (via\n\t\t\t * `@update:open`), by title clicks on route-less group items\n\t\t\t * (which TOGGLE open/closed), and by title clicks on a group\n\t\t\t * that ALSO carries a route or href (which force it OPEN,\n\t\t\t * alongside the navigation — see `onItemClick`).\n\t\t\t */\n\t\t\topenState: {},\n\n\t\t\t/**\n\t\t\t * Per route name, the key of the entry that was last active on\n\t\t\t * that route in this session. Read by `subRouteParent` to keep\n\t\t\t * \"the list I came from\" marked on a page below it. In memory\n\t\t\t * only: a reload starts empty and falls back to menu order.\n\t\t\t *\n\t\t\t * @type {Record<string, string>}\n\t\t\t */\n\t\t\tlastActiveEntryByRoute: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\teffectiveManifest() {\n\t\t\treturn this.manifest ?? this.cnManifest\n\t\t},\n\n\t\teffectiveTranslate() {\n\t\t\treturn this.translate ?? this.cnTranslate\n\t\t},\n\n\t\t/**\n\t\t * The brand the navigation draws itself: the resolved brand, or null\n\t\t * while the app's top bar draws it.\n\t\t *\n\t\t * @spec openspec/changes/screens-brand-block-top-bar/specs/layout-components/spec.md#requirement-the-navigation-does-not-draw-a-brand-block-the-bar-already-draws\n\t\t * @return {object|null}\n\t\t */\n\t\tnavBrand() {\n\t\t\treturn this.cnBrandInHeader ? null : this.resolvedBrand\n\t\t},\n\n\t\t/**\n\t\t * The brand to draw: the `brand` prop, else the manifest's\n\t\t * `nav.brand`. Name and caption go through the translate function,\n\t\t * like every other manifest label. Null when there is nothing to\n\t\t * show, which is what keeps the block out of a navigation that\n\t\t * declares no brand.\n\t\t *\n\t\t * @return {{logo: string, name: string, caption: string, alt: string}|null} The brand, or null.\n\t\t * @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-navigation-brand\n\t\t */\n\t\tresolvedBrand() {\n\t\t\treturn resolveBrand(this.brand ?? this.effectiveManifest?.nav?.brand, (value) => this.effectiveTranslate(value))\n\t\t},\n\n\t\t/**\n\t\t * The card above the footer entries (`nav.card`): `{ title, text?,\n\t\t * link?: { label, route?, params?, href?, action? } }`. Title, text\n\t\t * and link label go through the translate function. The link is a\n\t\t * router link for a `route` (with a router), an anchor for an\n\t\t * `href`, and a button emitting `card-action` with the `action` id\n\t\t * otherwise. Null without a title.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-the-navigation-carries-a-card-and-a-help-entry\n\t\t * @return {object|null}\n\t\t */\n\t\tresolvedCard() {\n\t\t\tconst declared = this.effectiveManifest?.nav?.card\n\t\t\tif (!declared || typeof declared !== 'object' || typeof declared.title !== 'string' || declared.title === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst text = (value) => (typeof value === 'string' && value !== '' ? this.effectiveTranslate(value) : '')\n\t\t\tconst card = { title: text(declared.title), text: text(declared.text), linkTag: '', linkAttrs: {}, linkLabel: '', action: '' }\n\t\t\tconst link = declared.link\n\t\t\tif (link && typeof link === 'object' && typeof link.label === 'string' && link.label !== '') {\n\t\t\t\tcard.linkLabel = text(link.label)\n\t\t\t\tif (link.route && this.$router) {\n\t\t\t\t\tcard.linkTag = 'router-link'\n\t\t\t\t\tcard.linkAttrs = { to: { name: link.route, ...(link.params && typeof link.params === 'object' ? { params: link.params } : {}) } }\n\t\t\t\t} else if (typeof link.href === 'string' && link.href !== '') {\n\t\t\t\t\tcard.linkTag = 'a'\n\t\t\t\t\tcard.linkAttrs = { href: link.href }\n\t\t\t\t} else if (typeof link.action === 'string' && link.action !== '') {\n\t\t\t\t\tcard.linkTag = 'button'\n\t\t\t\t\tcard.linkAttrs = { type: 'button' }\n\t\t\t\t\tcard.action = link.action\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn card\n\t\t},\n\n\t\t/**\n\t\t * The help entry (`nav.help`): `{ label, route?, href? }` rendered as\n\t\t * a footer entry with a help icon. Null without a label or a target.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-the-navigation-carries-a-card-and-a-help-entry\n\t\t * @return {{label: string, to?: object, href?: string}|null}\n\t\t */\n\t\tresolvedHelp() {\n\t\t\tconst declared = this.effectiveManifest?.nav?.help\n\t\t\tif (!declared || typeof declared !== 'object' || typeof declared.label !== 'string' || declared.label === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (declared.route && this.$router) {\n\t\t\t\treturn { label: this.effectiveTranslate(declared.label), to: { name: declared.route }, href: undefined }\n\t\t\t}\n\t\t\tif (typeof declared.href === 'string' && declared.href !== '') {\n\t\t\t\treturn { label: this.effectiveTranslate(declared.label), to: undefined, href: declared.href }\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Manifest-declared root-level primary action (`nav.primaryAction`)\n\t\t * — retained for backwards compatibility with code that reads this\n\t\t * computed. New code SHOULD read `activePrimaryAction` instead,\n\t\t * which also handles the page-scoped override.\n\t\t *\n\t\t * @return {object|null} `{ label, icon?, route?, href?, id?, payload? }` or null.\n\t\t */\n\t\tprimaryAction() {\n\t\t\treturn this.effectiveManifest?.nav?.primaryAction ?? null\n\t\t},\n\n\t\t/**\n\t\t * Resolved primary action for the current route. Resolution order:\n\t\t * 1. The current route's matching `pages[].primaryAction`\n\t\t * 2. `manifest.nav.primaryAction` as app-wide default\n\t\t * 3. `null` — no primary-action button renders\n\t\t *\n\t\t * Page-scoped declarations always win over the nav-root default. An\n\t\t * action declaring `permission` or `visibleIf` is gated like a menu\n\t\t * entry.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-navigation-primary-action-runs-a-page-action\n\t\t * @return {object|null}\n\t\t */\n\t\tactivePrimaryAction() {\n\t\t\tconst pages = this.effectiveManifest?.pages ?? []\n\t\t\tconst routeName = this.$route?.name\n\t\t\t// The same `permission` / `visibleIf` gate a menu entry has: an\n\t\t\t// action the reader may not take, or that a condition hides, is\n\t\t\t// not drawn. A gated-out page action falls back to the nav one.\n\t\t\tconst gated = (action) => (action && this.passesPermission(action) && this.passesVisibleIf(action) ? action : null)\n\t\t\tif (routeName) {\n\t\t\t\tconst page = pages.find((p) => p.id === routeName)\n\t\t\t\tif (page && page.primaryAction) {\n\t\t\t\t\tconst pageAction = gated(page.primaryAction)\n\t\t\t\t\tif (pageAction) {\n\t\t\t\t\t\treturn pageAction\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn gated(this.effectiveManifest?.nav?.primaryAction ?? null)\n\t\t},\n\n\t\t/**\n\t\t * MDI icon component for the resolved primary action. Honors the\n\t\t * action's `icon` field when set; falls back to the canonical\n\t\t * `Plus` icon to match NC's NcAppNavigationNew default styling.\n\t\t *\n\t\t * @return {import('vue').Component}\n\t\t */\n\t\tprimaryActionIconComponent() {\n\t\t\treturn this.mdiIconComponent(this.activePrimaryAction) ?? Plus\n\t\t},\n\n\t\t/**\n\t\t * The CnActionButtons entry for a primary action that carries an\n\t\t * `action` (`$defs/action`: open-form, navigate, api-call, ...):\n\t\t * the action with the primary action's `id`, `label` and `icon`\n\t\t * folded in and `variant: \"primary\"`. Null for a plain primary\n\t\t * action, which keeps its link or button.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-navigation-primary-action-runs-a-page-action\n\t\t * @return {object|null}\n\t\t */\n\t\tprimaryDispatchEntry() {\n\t\t\tconst action = this.activePrimaryAction\n\t\t\tconst inner = action && action.action\n\t\t\tif (!inner || typeof inner !== 'object' || typeof inner.type !== 'string') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn {\n\t\t\t\ticon: action.icon || 'Plus',\n\t\t\t\t...inner,\n\t\t\t\tid: inner.id || action.id || 'primary-action',\n\t\t\t\tlabel: action.label,\n\t\t\t\tvariant: 'primary',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Link props for the primary action's button: an `href` opens in a\n\t\t * new tab, a `route` is a router link. Null when the action is\n\t\t * neither (or there is no router), so it stays a plain button.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tprimaryActionLink() {\n\t\t\tconst action = this.activePrimaryAction\n\t\t\tif (!action) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (action.href) {\n\t\t\t\treturn { href: action.href, target: '_blank' }\n\t\t\t}\n\t\t\tif (action.route && this.$router) {\n\t\t\t\treturn { to: { name: action.route } }\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * All visible items (filtered by permission and visibleIf conditions,\n\t\t * sorted by order). Retained for backwards-compat with the previous\n\t\t * public API and tests that read this computed; new code should use\n\t\t * `mainItems` / `settingsItems` instead.\n\t\t */\n\t\tvisibleItems() {\n\t\t\treturn (this.effectiveManifest?.menu ?? [])\n\t\t\t\t.filter((item) => this.passesPermission(item) && this.passesVisibleIf(item))\n\t\t\t\t.slice()\n\t\t\t\t.sort(byManifestOrder)\n\t\t},\n\n\t\t/**\n\t\t * Items that render in the top list (default placement).\n\t\t *\n\t\t * Note the `=== 'main'` rather than a negated list: an entry whose\n\t\t * section this component does not render must fall through to\n\t\t * NOTHING, not to the main list. `section: \"integrations\"` is\n\t\t * exactly that case — those entries render in CnAppRoot's\n\t\t * per-user settings modal, not in the navigation (ADR-110) — and a\n\t\t * `!== 'footer' && !== 'settings'` test would have quietly put\n\t\t * every one of them back in the nav this contract removes them\n\t\t * from.\n\t\t */\n\t\tmainItems() {\n\t\t\treturn this.visibleItems.filter((item) => (item.section ?? 'main') === 'main')\n\t\t},\n\n\t\t/**\n\t\t * Items pinned to the bottom of the navigation (section:\n\t\t * \"footer\") — rendered as flat NcAppNavigationItems above the\n\t\t * settings foldout. For always-visible, non-settings entries:\n\t\t * Documentation, Features & Roadmap, About.\n\t\t */\n\t\tfooterItems() {\n\t\t\tconst footer = this.visibleItems.filter((item) => item.section === 'footer')\n\t\t\tconst declared = this.declaredFooter\n\t\t\tif (declared === null) {\n\t\t\t\treturn footer\n\t\t\t}\n\t\t\t// A declared footer (`nav.footer`) keeps only the entries it names,\n\t\t\t// in the order it names them.\n\t\t\treturn declared\n\t\t\t\t.map((id) => footer.find((item) => item.id === id))\n\t\t\t\t.filter(Boolean)\n\t\t},\n\n\t\t/**\n\t\t * The footer the manifest declares (`nav.footer`): an ordered list of\n\t\t * menu entry ids plus the reserved ids `help` (the `nav.help` entry)\n\t\t * and `settings` (the settings foldout). Null when the manifest\n\t\t * declares none, which keeps today's footer: the help entry, then\n\t\t * every `section: \"footer\"` entry, then the foldout.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {Array<string>|null}\n\t\t */\n\t\tdeclaredFooter() {\n\t\t\tconst declared = this.effectiveManifest?.nav?.footer\n\t\t\tif (!Array.isArray(declared)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn declared.filter((id) => typeof id === 'string' && id !== '')\n\t\t},\n\n\t\t/**\n\t\t * Footer-section entries a declared footer leaves out. They move into\n\t\t * the settings foldout rather than disappearing, so a page such as\n\t\t * Store or Reports stays reachable. Empty without `nav.footer`.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {Array<object>}\n\t\t */\n\t\tundeclaredFooterItems() {\n\t\t\tconst declared = this.declaredFooter\n\t\t\tif (declared === null) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn this.visibleItems.filter((item) => item.section === 'footer' && !declared.includes(item.id))\n\t\t},\n\n\t\t/**\n\t\t * Whether the help entry renders: whenever it resolves, unless a\n\t\t * declared footer leaves `help` out.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {boolean}\n\t\t */\n\t\tshowsHelp() {\n\t\t\tif (!this.resolvedHelp) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn this.declaredFooter === null || this.declaredFooter.includes('help')\n\t\t},\n\n\t\t/**\n\t\t * Whether the help entry goes AFTER the footer entries. Only a declared\n\t\t * footer that names an entry before `help` puts it there; by default\n\t\t * it leads the list.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {boolean}\n\t\t */\n\t\thelpAfterItems() {\n\t\t\tconst declared = this.declaredFooter\n\t\t\tif (declared === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst help = declared.indexOf('help')\n\t\t\treturn this.footerItems.some((item) => declared.indexOf(item.id) < help)\n\t\t},\n\n\t\t/**\n\t\t * Whether the settings foldout goes ABOVE the footer list: only when a\n\t\t * declared footer names `settings` before every other entry\n\t\t * (`[\"settings\", \"help\"]`, the board's \"Instellingen\" then \"Hulp en\n\t\t * uitleg\"). Done with CSS `order` on the two siblings, so the markup\n\t\t * of both stays as it is.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {boolean}\n\t\t */\n\t\tsettingsFirst() {\n\t\t\t// Under the board look Help always comes first and Advanced last,\n\t\t\t// whatever order the manifest declares.\n\t\t\tif (this.isBoard) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst declared = this.declaredFooter\n\t\t\treturn declared !== null && declared.indexOf('settings') === 0\n\t\t},\n\n\t\t/**\n\t\t * Items that render INSIDE the NcAppNavigationSettings foldout\n\t\t * (section: \"settings\"). The foldout is the NC-native gear-icon\n\t\t * button that slides a panel open; these entries are app-level\n\t\t * configuration pages (Forms, Pipelines, Automations, …). A declared\n\t\t * footer (`nav.footer`) adds the footer entries it leaves out.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-the-navigation-footer-can-be-declared\n\t\t * @return {Array<object>}\n\t\t */\n\t\tsettingsItems() {\n\t\t\treturn [\n\t\t\t\t...this.visibleItems.filter((item) => item.section === 'settings'),\n\t\t\t\t...this.undeclaredFooterItems,\n\t\t\t]\n\t\t},\n\n\t\t/**\n\t\t * Whether the settings foldout mounts. Mounts when there is at\n\t\t * least one `section: \"settings\"` item OR personal settings is\n\t\t * enabled — so every app shows a Settings gear with at least the\n\t\t * auto-prepended \"Personal settings\" entry. Only fully suppressed\n\t\t * when there are no settings items AND `nav.includePersonalSettings`\n\t\t * is explicitly `false`.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tshowSettingsFoldout() {\n\t\t\treturn this.settingsItems.length > 0 || this.includePersonalSettings\n\t\t\t\t|| this.roadmapEntry !== null || this.documentationEntry !== null\n\t\t},\n\n\t\t/**\n\t\t * Whether to auto-prepend the \"Personal settings\" entry at the top\n\t\t * of the foldout. On by default; opt out with\n\t\t * `manifest.nav.includePersonalSettings: false` (e.g. when the app\n\t\t * has no per-user NcAppSettingsDialog wired through\n\t\t * cnOpenUserSettings).\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tincludePersonalSettings() {\n\t\t\treturn this.effectiveManifest?.nav?.includePersonalSettings !== false\n\t\t},\n\n\t\t/**\n\t\t * Label for the foldout's gear button. Manifest override:\n\t\t * `nav.settingsLabel`; defaults to \"Advanced\".\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tsettingsFoldoutLabel() {\n\t\t\tconst custom = this.effectiveManifest?.nav?.settingsLabel\n\t\t\tif (typeof custom === 'string' && custom.length > 0) {\n\t\t\t\treturn this.effectiveTranslate(custom)\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'Advanced')\n\t\t},\n\n\t\t/**\n\t\t * Label for the auto-prepended Personal-settings entry.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tpersonalSettingsLabel() {\n\t\t\treturn t('nextcloud-vue', 'Personal settings')\n\t\t},\n\n\t\t/**\n\t\t * Optional \"Features & roadmap\" foldout entry. Enabled via\n\t\t * `nav.includeRoadmap`; `nav.roadmapUrl` is treated as an external link\n\t\t * when it looks like a URL, otherwise as an in-app router target.\n\t\t *\n\t\t * @return {{label: string, to: (string|null), href: (string|null)}|null}\n\t\t */\n\t\troadmapEntry() {\n\t\t\tconst nav = this.effectiveManifest?.nav\n\t\t\tif (!nav || nav.includeRoadmap !== true) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst label = (typeof nav.roadmapLabel === 'string' && nav.roadmapLabel)\n\t\t\t\t? this.effectiveTranslate(nav.roadmapLabel)\n\t\t\t\t: t('nextcloud-vue', 'Features & roadmap')\n\t\t\tconst target = typeof nav.roadmapUrl === 'string' ? nav.roadmapUrl.trim() : ''\n\t\t\tconst external = /^(https?:)?\\/\\//.test(target)\n\t\t\treturn { label, to: (target && !external) ? target : null, href: external ? target : null }\n\t\t},\n\n\t\t/**\n\t\t * Optional \"Documentation\" foldout entry. Enabled via\n\t\t * `nav.includeDocumentation`; always an external link (`nav.documentationUrl`).\n\t\t *\n\t\t * @return {{label: string, href: string}|null}\n\t\t */\n\t\tdocumentationEntry() {\n\t\t\tconst nav = this.effectiveManifest?.nav\n\t\t\tif (!nav || nav.includeDocumentation !== true) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst target = typeof nav.documentationUrl === 'string' ? nav.documentationUrl.trim() : ''\n\t\t\tif (!target) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst label = (typeof nav.documentationLabel === 'string' && nav.documentationLabel)\n\t\t\t\t? this.effectiveTranslate(nav.documentationLabel)\n\t\t\t\t: t('nextcloud-vue', 'Documentation')\n\t\t\treturn { label, href: target }\n\t\t},\n\n\t\t/**\n\t\t * Label for the auto-prepended Admin-settings entry.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tadminSettingsLabel() {\n\t\t\treturn t('nextcloud-vue', 'Admin settings')\n\t\t},\n\n\t\t/**\n\t\t * Accessible name (and hover tooltip) of the open-in-new marker on\n\t\t * the Admin-settings entry — the visual cue that the link leaves\n\t\t * the app for Nextcloud's own settings area.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\topensInNewTabHint() {\n\t\t\treturn t('nextcloud-vue', 'Opens in a new tab')\n\t\t},\n\n\t\t/**\n\t\t * Resolved app id for the Admin-settings link — the explicit\n\t\t * `appId` prop, else the `cnAppId` provided by CnAppRoot.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\teffectiveAppId() {\n\t\t\tconst id = this.appId || this.cnAppId\n\t\t\treturn (typeof id === 'string' && id.trim()) ? id.trim() : ''\n\t\t},\n\n\t\t/**\n\t\t * Target of the Admin-settings entry: the app's section in\n\t\t * Nextcloud's own admin settings (ADR-079 §1). This is a LINK, not\n\t\t * a modal — the app never re-implements the settings surface, and\n\t\t * the destination is authorized server-side by the settings\n\t\t * framework.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tadminSettingsHref() {\n\t\t\tif (!this.effectiveAppId) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\t// ABSOLUTE (same-origin) on purpose: NcAppNavigationItem renders\n\t\t\t// target=\"_blank\" only for hrefs its isExternal() deems external\n\t\t\t// (scheme-prefixed) and ignores a passed `target` — a relative\n\t\t\t// path therefore always opens in the SAME tab. The absolute form\n\t\t\t// gets the new tab while keeping native anchor semantics\n\t\t\t// (middle-click, copy link).\n\t\t\tconst path = generateUrl('/settings/admin/{appId}', { appId: this.effectiveAppId })\n\t\t\tconst origin = (typeof window !== 'undefined' && window.location && window.location.origin) || ''\n\t\t\treturn origin + path\n\t\t},\n\n\t\t/**\n\t\t * Whether to show the Admin-settings link: the user administers the\n\t\t * instance AND we can build a target. Visibility only — see the\n\t\t * `isAdmin` prop docs; the access check lives in Nextcloud.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tshowAdminSettingsLink() {\n\t\t\treturn this.isAdmin === true && this.adminSettingsHref !== ''\n\t\t},\n\n\t\t/**\n\t\t * Route name of the menu item that best matches the current route.\n\t\t * A direct match (current route name IS a menu target) wins;\n\t\t * otherwise the current path is matched against each item's page\n\t\t * path and the LONGEST prefix wins, so detail / nested routes (e.g.\n\t\t * `/expenses/:id`) light up — and auto-expand — their index entry\n\t\t * even though the detail route name is not in the menu. Longest\n\t\t * prefix disambiguates nested namespaces (e.g. `/pos` vs\n\t\t * `/pos/refunds`). An entry with `params` matches by its page path\n\t\t * with those params filled in (see `pageMatchDepth`). Returns null\n\t\t * when nothing matches.\n\t\t *\n\t\t * @return {string|null}\n\t\t */\n\t\tactiveRouteName() {\n\t\t\tconst routeName = this.$route?.name\n\t\t\tconst path = this.$route?.path\n\t\t\tconst flat = []\n\t\t\tfor (const item of this.visibleItems) {\n\t\t\t\tflat.push(item)\n\t\t\t\tfor (const child of this.visibleChildren(item)) {\n\t\t\t\t\tflat.push(child)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (routeName && flat.some((it) => it.route === routeName)) {\n\t\t\t\treturn routeName\n\t\t\t}\n\t\t\tif (!path) {\n\t\t\t\treturn routeName ?? null\n\t\t\t}\n\t\t\tlet best = null\n\t\t\tlet bestDepth = 0\n\t\t\tfor (const it of flat) {\n\t\t\t\tif (!it.route) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst depth = this.pageMatchDepth(it, path)\n\t\t\t\tif (depth > bestDepth) {\n\t\t\t\t\tbest = it.route\n\t\t\t\t\tbestDepth = depth\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn best ?? routeName ?? null\n\t\t},\n\n\t\t/**\n\t\t * Every visible entry and child, flat, in menu order.\n\t\t *\n\t\t * @return {Array<object>} The entries.\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tflatEntries() {\n\t\t\tconst flat = []\n\t\t\tfor (const item of this.visibleItems) {\n\t\t\t\tflat.push(item, ...this.visibleChildren(item))\n\t\t\t}\n\t\t\treturn flat\n\t\t},\n\n\t\t/**\n\t\t * The entry the query rule marks while the reader is on a menu\n\t\t * route itself (not on a page below it). Watched, so the nav can\n\t\t * remember which entry of a route the reader last used.\n\t\t *\n\t\t * @return {object|null} The entry, or null on a page below a route.\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tentryActiveOnOwnRoute() {\n\t\t\tconst routeName = this.$route?.name\n\t\t\tif (!routeName || routeName !== this.activeRouteName) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.flatEntries.find((entry) => this.isActiveByRule(entry)) ?? null\n\t\t},\n\n\t\t/**\n\t\t * The one entry to mark on a page BELOW a menu route when the query\n\t\t * rule marks none.\n\t\t *\n\t\t * On a detail page (`/cases/123`) the active route is found by path\n\t\t * prefix, and the address carries the detail page's query, not the\n\t\t * list's. When every entry on that list has a `query` (\"My work\",\n\t\t * \"Queue\"), none of them matched and the menu showed no place at\n\t\t * all. Marking all of them is the defect the query rule ended, so\n\t\t * this picks exactly one: the entry the reader last had active on\n\t\t * that route, else the first in menu order.\n\t\t *\n\t\t * Null whenever the existing rule already marks an entry, so a list\n\t\t * with an entry without a `query` behaves as it did. An entry with\n\t\t * `params` is a candidate only when the current path sits below its\n\t\t * own filled-in page path, so another param value is never marked.\n\t\t *\n\t\t * @return {object|null} The entry to mark, or null.\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tsubRouteParent() {\n\t\t\tconst active = this.activeRouteName\n\t\t\tif (!active || this.$route?.name === active) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst path = this.$route?.path\n\t\t\tconst entries = this.flatEntries.filter((entry) => !entry.href && entry.route === active\n\t\t\t\t&& (!this.hasParams(entry) || this.pageMatchDepth(entry, path) > 0))\n\t\t\tif (entries.length === 0 || entries.some((entry) => this.isActiveByRule(entry))) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst remembered = this.lastActiveEntryByRoute[active]\n\t\t\treturn entries.find((entry) => this.entryKey(entry) === remembered) ?? entries[0]\n\t\t},\n\t},\n\n\twatch: {\n\t\tactiveRouteName: {\n\t\t\timmediate: true,\n\t\t\thandler(_current, previous) {\n\t\t\t\tthis.pinGroupsEntered(previous)\n\t\t\t},\n\t\t},\n\n\t\t// The manifest can arrive after the route did.\n\t\tvisibleItems() {\n\t\t\tthis.pinGroupsEntered(this.activeRouteName)\n\t\t},\n\n\t\tentryActiveOnOwnRoute: {\n\t\t\timmediate: true,\n\t\t\t/**\n\t\t\t * Remember which entry of a route the reader used, for\n\t\t\t * `subRouteParent`.\n\t\t\t *\n\t\t\t * @param {object|null} entry The entry active on its own route.\n\t\t\t * @return {void}\n\t\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t\t */\n\t\t\thandler(entry) {\n\t\t\t\tif (entry && entry.route) {\n\t\t\t\t\tthis.lastActiveEntryByRoute[entry.route] = this.entryKey(entry)\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tcreated() {\n\t\t// Non-reactive one-shot latch for warnAutoCountMisconfigured(). It has\n\t\t// to be seeded here rather than lazily on first use: `resolveCount()`\n\t\t// runs DURING RENDER, and Vue 3's instance proxy emits\n\t\t// \"Property \"_autoCountWarned\" was accessed during render but is not\n\t\t// defined on instance\" for the first read of an unset instance field\n\t\t// (Vue 2 read it back as plain `undefined`, silently). It deliberately\n\t\t// stays out of `data()`: a reactive Set mutated inside render would\n\t\t// re-trigger the render effect.\n\t\tthis._autoCountWarned = new Set()\n\t\t// Same latch, for warnUnfilledRouteParam() (`itemTo()` runs during render).\n\t\tthis._unfilledParamWarned = new Set()\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Whether an entry's count asks for attention (`counterVariant:\n\t\t * \"attention\"`): the red pill under the board look, the counter\n\t\t * bubble's highlighted state without it.\n\t\t *\n\t\t * @spec openspec/changes/screens-chrome-parity/specs/layout-components/spec.md#requirement-a-navigation-count-can-ask-for-attention\n\t\t * @param {object} item Menu entry descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\tisAttention(item) {\n\t\t\treturn item?.counterVariant === 'attention'\n\t\t},\n\n\t\t/**\n\t\t * Resolve a menu item's `icon` string to an MDI Vue component. MDI names\n\t\t * resolve via the per-app `registerIcons()` registry; legacy Nextcloud\n\t\t * `icon-*` class names resolve via the shared `cssIconBridge` so they\n\t\t * render monochrome (fill:currentColor) like every other glyph.\n\t\t * Returns `null` (→ the `:icon=\"cssIconClass(item)\"` CSS-class fallback)\n\t\t * for unbridged `icon-*` names and unknown MDI names.\n\t\t *\n\t\t * @param {{ icon?: string }} item Menu item descriptor.\n\t\t * @return {import('vue').Component|null}\n\t\t */\n\t\t/**\n\t\t * The tooltip of a menu entry: its `description` (a saved view's, say),\n\t\t * else null, which leaves NcAppNavigationItem's own (the name).\n\t\t *\n\t\t * @param {{ description?: string }} item Menu item descriptor.\n\t\t * @return {string|null}\n\t\t * @spec openspec/changes/saved-view-icon-description-count/specs/saved-view-icon-description-count/spec.md#requirement-a-saved-view-has-an-icon-and-a-description\n\t\t */\n\t\titemTooltip(item) {\n\t\t\treturn typeof item?.description === 'string' && item.description !== '' ? item.description : null\n\t\t},\n\n\t\tmdiIconComponent(item) {\n\t\t\tconst icon = item?.icon\n\t\t\tif (typeof icon !== 'string' || icon.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (icon.startsWith('icon-')) {\n\t\t\t\treturn bridgedMdiForCssIcon(icon) || null\n\t\t\t}\n\t\t\t// ADR-077: the app's own registerIcons() entries win (so an app can\n\t\t\t// override), then the shared semantic vocabulary — which resolves\n\t\t\t// WITHOUT the app having registered anything. Before the vocabulary\n\t\t\t// existed, a name the app forgot to register resolved to null here\n\t\t\t// and the entry rendered with no icon at all.\n\t\t\treturn ICON_MAP[icon] || getSemanticIconComponent(icon) || null\n\t\t},\n\n\t\t/**\n\t\t * Whether the item declares an icon that NOTHING can resolve — not the\n\t\t * app registry, not the semantic vocabulary, not the widget registry, and\n\t\t * not a URL / SVG path.\n\t\t *\n\t\t * ADR-077 rule 4: such an icon MUST degrade to a visible fallback glyph.\n\t\t * Historically it rendered as empty space, which is indistinguishable\n\t\t * from a deliberate no-icon design choice — 29 of hrmq's 72 nav entries\n\t\t * were silently blank this way. A visible \"?\" is discoverable; blank is\n\t\t * not.\n\t\t *\n\t\t * `icon-*` values are excluded: those have their own CSS-class fallback\n\t\t * path via the `cssIconClass` method.\n\t\t *\n\t\t * @param {{ icon?: string }} item Menu item descriptor.\n\t\t * @return {boolean} true when the declared icon resolves to nothing.\n\t\t */\n\t\tisUnresolvedIcon(item) {\n\t\t\tconst icon = item?.icon\n\t\t\tif (typeof icon !== 'string' || icon.length === 0) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif (icon.startsWith('icon-')) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !this.mdiIconComponent(item)\n\t\t\t\t&& !this.isRichIcon(item)\n\t\t\t\t&& !this.isRegistryIcon(item)\n\t\t},\n\n\t\t/**\n\t\t * Whether the item's icon is a raw SVG path or an image URL (incl. the\n\t\t * `data:` URIs the bundled NL-government sets emit) — neither of which is a\n\t\t * component, so `ICON_MAP` can't resolve it and the `#icon` slot must\n\t\t * render it through CnMenuItemIcon instead.\n\t\t *\n\t\t * Without this, an icon picked from CnIconBrowser's Gemeente / Den Haag /\n\t\t * RVO tabs would simply not appear in the navigation.\n\t\t *\n\t\t * @param {{ icon?: string }} item Menu item descriptor.\n\t\t * @return {boolean} true for path/URL icons.\n\t\t */\n\t\tisRichIcon(item) {\n\t\t\tconst icon = item?.icon\n\t\t\tif (typeof icon !== 'string' || icon.length === 0 || icon.startsWith('icon-')) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn isCustomIconUrl(icon) || isSvgPath(icon)\n\t\t},\n\n\t\t/**\n\t\t * Whether the item's icon is a plain MDI *name* that the shared widget-icon\n\t\t * registry can render (e.g. \"Heart\", \"Home\" — what CnIconBrowser emits from\n\t\t * its component-name sources).\n\t\t *\n\t\t * `ICON_MAP` only holds what the consuming app passed to `registerIcons()`,\n\t\t * and an app rendering USER-AUTHORED manifests cannot pre-register whatever\n\t\t * icon a user might pick — Buildiq registers none at all. So a picked name\n\t\t * failed `mdiIconComponent` (not registered) AND `isRichIcon` (not a URL or\n\t\t * SVG path), the `#icon` slot was skipped entirely, and the menu item rendered\n\t\t * with NO icon — even though CnMenuItemIcon → CnWidgetIcon could resolve it.\n\t\t *\n\t\t * Gate on the registry actually HAVING the name: `getIconComponent` answers\n\t\t * the default icon for anything unknown, so gating on it would render a wrong\n\t\t * (but plausible) icon for a typo instead of none.\n\t\t *\n\t\t * @param {{ icon?: string }} item Menu item descriptor.\n\t\t * @return {boolean} true when the widget-icon registry can render this name.\n\t\t */\n\t\tisRegistryIcon(item) {\n\t\t\treturn hasRegistryIcon(item?.icon)\n\t\t},\n\n\t\t/**\n\t\t * Pass-through for the `:icon` prop on NcAppNavigationItem when\n\t\t * the manifest declares a Nextcloud CSS-class icon (`icon-*`).\n\t\t * Returns an empty string when the icon is an MDI name OR a bridged\n\t\t * `icon-*` (rendered via the `#icon` slot instead), so NcAppNavigationItem\n\t\t * doesn't also paint a CSS-class background-image.\n\t\t *\n\t\t * @param {{ icon?: string }} item Menu item descriptor.\n\t\t * @return {string}\n\t\t */\n\t\tcssIconClass(item) {\n\t\t\tconst icon = item?.icon\n\t\t\tif (typeof icon !== 'string' || icon.length === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (!icon.startsWith('icon-')) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn bridgedMdiForCssIcon(icon) ? '' : icon\n\t\t},\n\n\t\tpassesPermission(item) {\n\t\t\tif (!item.permission) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tif (!this.permissions || this.permissions.length === 0) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn this.permissions.includes(item.permission)\n\t\t},\n\n\t\t/**\n\t\t * Evaluate a menu item's `visibleIf` condition block.\n\t\t *\n\t\t * Returns `true` (visible) when:\n\t\t * - No `visibleIf` is declared (backwards-compatible default).\n\t\t * - `visibleIf.appInstalled` is set AND the named app is\n\t\t * installed / enabled (checked via `OC.appswebroots` then the\n\t\t * capabilities fallback, cached per page load by `isAppInstalled`).\n\t\t * - Context-path predicates (any key that is a dot-separated path\n\t\t * into `manifest.runtime`) all pass against the current runtime\n\t\t * data. Predicates are evaluated by `passesContextPredicates`.\n\t\t * Example: `{ \"user.primaryRole\": { \"in\": [\"hr\", \"compliance\"] } }`\n\t\t * hides the entry unless `manifest.runtime.user.primaryRole` is\n\t\t * `\"hr\"` or `\"compliance\"`. When the runtime block is absent the\n\t\t * entry is hidden (fail-safe: never show role-gated items to\n\t\t * unidentified users).\n\t\t *\n\t\t * All conditions are combined with implicit AND — every condition\n\t\t * must pass for the item to render. Returns `false` when any fails.\n\t\t *\n\t\t * @param {object} item Menu item (or child) to evaluate.\n\t\t * @return {boolean} Whether the item should render.\n\t\t */\n\t\tpassesVisibleIf(item) {\n\t\t\tconst condition = item.visibleIf\n\t\t\tif (!condition || typeof condition !== 'object') {\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\t// Specialised condition: appInstalled.\n\t\t\tif (condition.appInstalled) {\n\t\t\t\tif (!isAppInstalled(condition.appInstalled)) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Context-path predicates: any non-reserved key is a dot-path\n\t\t\t// into manifest.runtime evaluated by passesContextPredicates.\n\t\t\tconst runtime = this.effectiveManifest?.runtime ?? null\n\t\t\tif (!passesContextPredicates(condition, runtime)) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t},\n\n\t\t/**\n\t\t * A group's visible children, in `order`.\n\t\t *\n\t\t * The SORT is the fix for a silent no-op: this used to filter only, so\n\t\t * `order` on a child was accepted, documented and ignored. It bites\n\t\t * hardest on relocated leaves, because `applyMenuRelocations()` walks\n\t\t * the menu backwards and appends each move, which lands a group's\n\t\t * children in REVERSE manifest order — an order nobody wrote down and\n\t\t * no app can influence except by reordering `manifest.json` itself.\n\t\t * Pipelinq's Customer Support group read \"Projecten, My Work, Queue,\n\t\t * Tasks, All tickets\" against declared orders of 55, 20, 10, 60, 50.\n\t\t *\n\t\t * Same comparator as the top level, so one rule governs both: items\n\t\t * without an `order` render last, in their existing relative order\n\t\t * (Array.prototype.sort is stable).\n\t\t *\n\t\t * @param {object} item The group whose children to render.\n\t\t * @return {Array<object>} Visible children, ordered.\n\t\t */\n\t\tvisibleChildren(item) {\n\t\t\tif (!Array.isArray(item.children)) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn item.children\n\t\t\t\t.filter((c) => this.passesPermission(c) && this.passesVisibleIf(c))\n\t\t\t\t.sort(byManifestOrder)\n\t\t},\n\n\t\t/**\n\t\t * The label an entry shows: run through the translate function, or\n\t\t * as written when the entry sets `translateLabel: false` (a\n\t\t * user-authored title that may equal a translation key). Every\n\t\t * place the nav shows an entry's label reads it from here.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {string} The label to render as text.\n\t\t */\n\t\tresolveLabel(item) {\n\t\t\tif (item.translateLabel === false) {\n\t\t\t\treturn item.label\n\t\t\t}\n\t\t\treturn this.effectiveTranslate(item.label)\n\t\t},\n\n\t\t/**\n\t\t * Whether a menu entry is the page the reader is on.\n\t\t *\n\t\t * Two entries may share a route and differ only in `query` (\"My\n\t\t * work\" and \"Queue\" on one list). The route name alone lit both. An\n\t\t * entry with a `query` is active only when the address carries that\n\t\t * query; an entry without one steps back when a sibling's query\n\t\t * matches, so exactly one of them is marked. `params` work the\n\t\t * same way against the route's params, so of several entries on a\n\t\t * `/items/:slug` route only the one whose `slug` is in the address\n\t\t * is marked.\n\t\t *\n\t\t * On a page below a list where that rule marks nothing, the one\n\t\t * entry `subRouteParent` picks is active instead.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {boolean} True when the entry is the current page.\n\t\t * @spec openspec/changes/link-cards-page/specs/link-cards-page/spec.md#requirement-menu-entries-that-differ-in-query\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tisActive(item) {\n\t\t\tif (this.isActiveByRule(item)) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tconst parent = this.subRouteParent\n\t\t\treturn parent !== null && toRaw(parent) === toRaw(item)\n\t\t},\n\n\t\t/**\n\t\t * The route, query and params rule on its own, without the fallback\n\t\t * for a page below a list. `subRouteParent` asks this to see whether\n\t\t * the rule already marks an entry.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {boolean} True when the rule marks the entry.\n\t\t * @spec openspec/changes/link-cards-page/specs/link-cards-page/spec.md#requirement-menu-entries-that-differ-in-query\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tisActiveByRule(item) {\n\t\t\tif (item.href || !item.route) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif (item.route !== this.activeRouteName) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tif (this.isNarrowed(item)) {\n\t\t\t\treturn this.narrowingMatches(item)\n\t\t\t}\n\t\t\treturn !this.flatEntries.some((entry) => entry !== item\n\t\t\t\t&& entry.route === item.route\n\t\t\t\t&& this.isNarrowed(entry)\n\t\t\t\t&& this.narrowingMatches(entry))\n\t\t},\n\n\t\t/**\n\t\t * Whether an entry narrows its route with a `query` or `params`.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {boolean} True when the entry declares either.\n\t\t */\n\t\tisNarrowed(item) {\n\t\t\treturn Boolean(item.query && typeof item.query === 'object') || this.hasParams(item)\n\t\t},\n\n\t\t/**\n\t\t * Whether the address carries every `query` key and every `params`\n\t\t * key the entry declares.\n\t\t *\n\t\t * @param {object} item Menu entry that narrows its route.\n\t\t * @return {boolean} True when everything it declares matches.\n\t\t */\n\t\tnarrowingMatches(item) {\n\t\t\tconst queryOk = !(item.query && typeof item.query === 'object') || this.queryMatches(item)\n\t\t\tconst paramsOk = !this.hasParams(item) || this.paramsMatch(item)\n\t\t\treturn queryOk && paramsOk\n\t\t},\n\n\t\t/**\n\t\t * Whether an entry declares a non-empty `params` object.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {boolean} True when it has route params.\n\t\t */\n\t\thasParams(item) {\n\t\t\treturn Boolean(item?.params) && typeof item.params === 'object' && Object.keys(item.params).length > 0\n\t\t},\n\n\t\t/**\n\t\t * Whether the route's params carry every key of an entry's\n\t\t * `params`. Values are compared as strings.\n\t\t *\n\t\t * @param {object} item Menu entry with `params`.\n\t\t * @return {boolean} True when every declared key matches.\n\t\t */\n\t\tparamsMatch(item) {\n\t\t\tconst current = this.$route?.params ?? {}\n\t\t\treturn Object.keys(item.params).every((key) => String(current[key] ?? '') === String(item.params[key]))\n\t\t},\n\n\t\t/**\n\t\t * The segments of an entry's page path with its `params` filled in,\n\t\t * as plain values. A missing optional `:name?` segment is dropped;\n\t\t * null when a required one has no param, or without a page.\n\t\t *\n\t\t * @param {object} item Menu entry with `params`.\n\t\t * @return {Array<string>|null} The segments, or null.\n\t\t */\n\t\tfilledPageSegments(item) {\n\t\t\tconst pagePath = this.pageForItem(item)?.route\n\t\t\tif (!pagePath) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst segments = []\n\t\t\tfor (const part of pagePath.split('/').filter(Boolean)) {\n\t\t\t\tconst param = PARAM_SEGMENT.exec(part)\n\t\t\t\tif (!param) {\n\t\t\t\t\tsegments.push(part)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst value = item.params?.[param[1]]\n\t\t\t\tif (isFilled(value)) {\n\t\t\t\t\tsegments.push(String(value))\n\t\t\t\t} else if (!isOptionalParam(param)) {\n\t\t\t\t\treturn null\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn segments\n\t\t},\n\n\t\t/**\n\t\t * The required route param the router cannot fill when it resolves\n\t\t * an entry's link on its manifest page. vue-router fills a named\n\t\t * link's required params from the current route, then overlays every\n\t\t * key the entry declares, empty or null included. So a declared key\n\t\t * decides on its own value, and only an undeclared one falls back\n\t\t * to the current route. Null without a known page, or when every\n\t\t * required segment is filled. Reads `$route`, so it follows\n\t\t * navigation.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {string|null} The param name, or null.\n\t\t */\n\t\tunfilledRouteParam(item) {\n\t\t\tconst pagePath = this.pageForItem(item)?.route\n\t\t\tif (!pagePath) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst declared = item.params && typeof item.params === 'object' ? item.params : {}\n\t\t\tconst current = this.$route?.params ?? {}\n\t\t\tfor (const part of pagePath.split('/')) {\n\t\t\t\tconst param = PARAM_SEGMENT.exec(part)\n\t\t\t\tif (!param || isOptionalParam(param)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst value = param[1] in declared ? declared[param[1]] : current[param[1]]\n\t\t\t\tif (!isFilled(value)) {\n\t\t\t\t\treturn param[1]\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * How deep a path sits on an entry's page path: the page path's\n\t\t * segment count when the path is that page or below it, else 0.\n\t\t * A `/` page path, or one with an unfilled `:name`, never matches.\n\t\t *\n\t\t * Without `params` the page path is compared as written. With\n\t\t * `params`, segments are compared decoded, because the router\n\t\t * percent-encodes param values in the path and the entry holds them\n\t\t * plain.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @param {string|undefined} path The path to test.\n\t\t * @return {number} The depth of the match, or 0.\n\t\t */\n\t\tpageMatchDepth(item, path) {\n\t\t\tif (!path) {\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\tif (!this.hasParams(item)) {\n\t\t\t\tconst pagePath = this.pageForItem(item)?.route\n\t\t\t\tif (!pagePath || pagePath === '/' || pagePath.includes(':')) {\n\t\t\t\t\treturn 0\n\t\t\t\t}\n\t\t\t\tconst below = path === pagePath || path.startsWith(pagePath + '/')\n\t\t\t\treturn below ? pagePath.split('/').filter(Boolean).length : 0\n\t\t\t}\n\t\t\tconst segments = this.filledPageSegments(item)\n\t\t\tif (!segments || segments.length === 0) {\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\tconst current = path.split('/').filter(Boolean).map(decodeSegment)\n\t\t\treturn segments.every((segment, index) => current[index] === segment) ? segments.length : 0\n\t\t},\n\n\t\t/**\n\t\t * What an entry is remembered by: its `id`, else its label.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {string} The key.\n\t\t * @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry\n\t\t */\n\t\tentryKey(item) {\n\t\t\treturn String(item.id ?? item.label ?? '')\n\t\t},\n\n\t\t/**\n\t\t * Whether the address carries every key of an entry's `query`.\n\t\t * Values are compared as strings, since an address has no numbers.\n\t\t *\n\t\t * @param {object} item Menu entry with a `query`.\n\t\t * @return {boolean} True when every declared key matches.\n\t\t * @spec openspec/changes/link-cards-page/specs/link-cards-page/spec.md#requirement-menu-entries-that-differ-in-query\n\t\t */\n\t\tqueryMatches(item) {\n\t\t\tconst current = this.$route?.query ?? {}\n\t\t\tconst keys = Object.keys(item.query)\n\t\t\treturn keys.length > 0 && keys.every((key) => String(current[key] ?? '') === String(item.query[key]))\n\t\t},\n\n\t\t/**\n\t\t * Whether a menu entry renders as a `NcAppNavigationCaption`\n\t\t * (`type: \"caption\"`) rather than a clickable\n\t\t * `NcAppNavigationItem`. Caption entries ignore `route`, `action`,\n\t\t * `icon`, `count`, `children`, and `pinned`. A caption's `href` is\n\t\t * drawn as a pencil link beside the heading: the place where what\n\t\t * stands under it is changed (a user's own choice of entries, say).\n\t\t * `action: \"user-settings\"` draws the same pencil as a button that\n\t\t * opens the user settings dialog.\n\t\t *\n\t\t * @param {{ type?: string }} item Menu entry descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\tisCaption(item) {\n\t\t\treturn item?.type === 'caption'\n\t\t},\n\n\t\t/**\n\t\t * The accessible name of a caption's pencil link.\n\t\t *\n\t\t * @param {object} item The caption entry.\n\t\t * @return {string} \"Change {caption}\", translated.\n\t\t */\n\t\tcaptionEditLabel(item) {\n\t\t\treturn t('nextcloud-vue', 'Change {name}', { name: this.resolveLabel(item) })\n\t\t},\n\n\t\t/**\n\t\t * Whether the host has registered a scoped slot named\n\t\t * `item-${id}-actions` for this menu item. Used to gate template\n\t\t * rendering of the per-item `#actions` slot pass-through so items\n\t\t * without a matching slot don't render an empty `<template #actions>`.\n\t\t *\n\t\t * @param {{ id: string }} item Menu entry descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\thasItemActionsSlot(item) {\n\t\t\tif (!item?.id) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst name = `item-${item.id}-actions`\n\t\t\treturn Boolean((this.$slots && this.$slots[name])\n\t\t\t\t|| (this.$slots && this.$slots[name]))\n\t\t},\n\n\t\t/**\n\t\t * Resolve the count value to render in this entry's\n\t\t * `NcCounterBubble` (in the `#counter` slot of\n\t\t * `NcAppNavigationItem`).\n\t\t *\n\t\t * - Literal positive integer in `item.count` → return as-is.\n\t\t * - `item.count` is an object (`{ register, schema, filter? }`) →\n\t\t * `cnMenuItemCounts[item.id] ?? null`, the filtered total CnAppRoot\n\t\t * fetched for this entry.\n\t\t * - `item.count === \"auto\"` → look up the entry's resolved page;\n\t\t * when that page is `type: \"index\"` with a `register`/`schema`\n\t\t * in its `config`, return\n\t\t * `cnMenuCounts[register][schema] ?? null`.\n\t\t *\n\t\t * Returns `null` (no badge) when:\n\t\t * - `item.count` is unset or falsy\n\t\t * - The literal value is `0`\n\t\t * - `count === \"auto\"` but no matching index page resolves\n\t\t * (also emits a one-shot `console.warn`)\n\t\t * - The store has no entry for the resolved `(register, schema)`\n\t\t *\n\t\t * @param {object} item Menu entry descriptor.\n\t\t * @return {number|null} Count to render, or null for no badge.\n\t\t */\n\t\tresolveCount(item) {\n\t\t\tconst raw = item?.count\n\t\t\tif (raw === undefined || raw === null) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (typeof raw === 'number') {\n\t\t\t\treturn raw > 0 ? raw : null\n\t\t\t}\n\t\t\tif (raw && typeof raw === 'object') {\n\t\t\t\t// A filtered count: CnAppRoot fetched it per entry id.\n\t\t\t\tconst value = this.cnMenuItemCounts?.[item.id]\n\t\t\t\treturn (typeof value === 'number' && value > 0) ? value : null\n\t\t\t}\n\t\t\tif (raw !== 'auto') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst page = this.pageForItem(item)\n\t\t\tconst register = page?.config?.register\n\t\t\tconst schema = page?.config?.schema\n\t\t\tif (page?.type !== 'index' || !register || !schema) {\n\t\t\t\tthis.warnAutoCountMisconfigured(item)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst value = this.cnMenuCounts?.[register]?.[schema]\n\t\t\tif (typeof value !== 'number' || value <= 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn value\n\t\t},\n\n\t\t/**\n\t\t * One-shot `console.warn` per menu-item id for misconfigured\n\t\t * `count: \"auto\"` entries (no resolvable index page). Keeps the\n\t\t * console quiet on re-renders.\n\t\t *\n\t\t * @param {{ id: string }} item Menu entry descriptor.\n\t\t * @return {void}\n\t\t * @private\n\t\t */\n\t\twarnAutoCountMisconfigured(item) {\n\t\t\tif (this._autoCountWarned.has(item.id)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis._autoCountWarned.add(item.id)\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[CnAppNav] Menu entry \"${item.id}\" declares count: \"auto\" but has no resolvable index-type page with register + schema config — no badge will render.`)\n\t\t},\n\n\t\t/**\n\t\t * One-shot `console.warn` per menu entry whose link cannot fill a\n\t\t * required route param. Keyed by `id`, else route and label, so\n\t\t * entries without an id each get their own warning.\n\t\t *\n\t\t * @param {{ id?: string, route: string, label?: string }} item Menu entry descriptor.\n\t\t * @param {string} param The unfilled param name.\n\t\t * @return {void}\n\t\t * @private\n\t\t */\n\t\twarnUnfilledRouteParam(item, param) {\n\t\t\tconst key = item.id ?? `${item.route}|${item.label ?? ''}`\n\t\t\tif (this._unfilledParamWarned.has(key)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis._unfilledParamWarned.add(key)\n\t\t\tconst name = item.id ?? item.label ?? item.route\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[CnAppNav] Menu entry \"${name}\" cannot fill the required route param \"${param}\" of page \"${item.route}\" from its params or the current route — the entry renders without a link.`)\n\t\t},\n\n\t\t/**\n\t\t * Look up an item's resolved page (`pages[]` entry whose `id`\n\t\t * matches the menu item's `route`) — used to decide whether the\n\t\t * NcAppNavigationItem should match its router-link `exact`.\n\t\t *\n\t\t * @param {object} item Menu item to resolve.\n\t\t * @return {object|null} Matching page entry, or null when the item\n\t\t * has no `route` or no page matches.\n\t\t */\n\t\tpageForItem(item) {\n\t\t\tif (!item.route) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst pages = this.effectiveManifest?.pages ?? []\n\t\t\treturn pages.find((p) => p.id === item.route) ?? null\n\t\t},\n\n\t\t/**\n\t\t * Build the `:to` value for an `NcAppNavigationItem`. Action\n\t\t * items (`action: \"user-settings\"`) and `href` items return\n\t\t * `null` so the entry is NOT a vue-router link: action items\n\t\t * fall through to the click handler, `href` items render a real\n\t\t * anchor via `itemHref`. Route items return a named route that\n\t\t * carries the item's `params` and `query` when it declares them.\n\t\t *\n\t\t * An item whose manifest page has a required segment that neither\n\t\t * its `params` nor the current route fill also returns null, with a\n\t\t * one-time warning: the router throws resolving such a link, which\n\t\t * would take the whole navigation down rather than that one entry.\n\t\t *\n\t\t * @param {object} item Menu item being rendered.\n\t\t * @return {object|null} A `{ name, params?, query? }` route object,\n\t\t * or null for action / href / route-less / unfillable items.\n\t\t */\n\t\titemTo(item) {\n\t\t\tif (item.action) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (item.href) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (!item.route) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst unfilled = this.unfilledRouteParam(item)\n\t\t\tif (unfilled) {\n\t\t\t\tthis.warnUnfilledRouteParam(item, unfilled)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst to = { name: item.route }\n\t\t\t// Params fill a parameterised route (one entry per catalog →\n\t\t\t// /catalogs/:slug); query deep-links to a pre-filtered index page\n\t\t\t// (one entry per case type → Cases?caseType=…).\n\t\t\tif (this.hasParams(item)) {\n\t\t\t\tto.params = item.params\n\t\t\t}\n\t\t\tif (item.query) {\n\t\t\t\tto.query = item.query\n\t\t\t}\n\t\t\treturn to\n\t\t},\n\n\t\t/**\n\t\t * Whether another visible entry links to the same route, so the two\n\t\t * differ only in `query` or `params` (\"All cases\" and \"Woo requests\"\n\t\t * on one list).\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {boolean} True when the route is shared.\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active\n\t\t */\n\t\tsharesRoute(item) {\n\t\t\tif (!item || item.href || item.action || !item.route) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn this.flatEntries.some((entry) => entry !== item && !entry.href && !entry.action && entry.route === item.route)\n\t\t},\n\n\t\t/**\n\t\t * The app's router, or null when the nav is mounted without one. Read\n\t\t * from the app's global properties: `this.$router` warns during render\n\t\t * on an instance that has none.\n\t\t *\n\t\t * @return {object|null} The router.\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active\n\t\t */\n\t\tappRouter() {\n\t\t\treturn this.$?.appContext?.config?.globalProperties?.$router ?? null\n\t\t},\n\n\t\t/**\n\t\t * The `:to` an entry renders with. An entry that shares its route\n\t\t * renders as a plain link instead (see `linkHref`): NcAppNavigationItem\n\t\t * marks a router link active whenever vue-router calls it active, and\n\t\t * vue-router ignores the query, so \"Woo requests\" lit up beside \"All\n\t\t * cases\" on the unfiltered list. As a plain link only `isActive`\n\t\t * decides, which marks the entry that matches best.\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {object|null} The router target, or null.\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active\n\t\t */\n\t\tlinkTo(item) {\n\t\t\tif (this.appRouter() && this.sharesRoute(item)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn this.itemTo(item)\n\t\t},\n\n\t\t/**\n\t\t * The `:href` an entry renders with: `itemHref`, or for an entry that\n\t\t * shares its route the address vue-router resolves its target to (a\n\t\t * click on it is still routed in the app, see `onItemClick`).\n\t\t *\n\t\t * @param {object} item Menu entry.\n\t\t * @return {string|null} The address, or null.\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active\n\t\t */\n\t\tlinkHref(item) {\n\t\t\tconst own = this.itemHref(item)\n\t\t\tconst router = this.appRouter()\n\t\t\tif (own || !router || !this.sharesRoute(item)) {\n\t\t\t\treturn own\n\t\t\t}\n\t\t\tconst to = this.itemTo(item)\n\t\t\treturn to ? router.resolve(to).href : null\n\t\t},\n\n\t\t/**\n\t\t * Build the `:href` value for an `NcAppNavigationItem`. Returns\n\t\t * the item's `href` so the entry renders as a real anchor whose\n\t\t * destination is visible on hover and which gets the native link\n\t\t * cursor. `NcAppNavigationItem` adds `target=\"_blank\"` itself for\n\t\t * external (`scheme://`) URLs, so those open in a new tab while\n\t\t * internal app paths (e.g. `/index.php/apps/foo/`) navigate in the\n\t\t * same tab — no `window.open` interception. The `admin-settings`\n\t\t * action links to `adminSettingsHref` (absolute, so it opens in a\n\t\t * new tab); other action items carry no href. Returns `null` for\n\t\t * non-href items so the entry stays a router-link / button.\n\t\t *\n\t\t * @param {object} item Menu item being rendered.\n\t\t * @return {string|null} The destination URL, or null.\n\t\t */\n\t\titemHref(item) {\n\t\t\tif (item.action === 'admin-settings') {\n\t\t\t\treturn this.adminSettingsHref || null\n\t\t\t}\n\t\t\tif (item.action) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn item.href || null\n\t\t},\n\n\t\t/**\n\t\t * Whether a menu group renders expanded. Local `openState` (set\n\t\t * by the chevron, a title click, or `pinGroupsEntered`) wins;\n\t\t * otherwise the group auto-expands when it contains the active\n\t\t * route — so deep-linking to a child page reveals which group it\n\t\t * lives in — and finally falls back to the manifest's `item.open`\n\t\t * for the initial render.\n\t\t *\n\t\t * @param {{ id: string, open?: boolean }} item Menu entry descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\tisItemOpen(item) {\n\t\t\tconst local = this.openState[item.id]\n\t\t\tif (local !== undefined) {\n\t\t\t\treturn local\n\t\t\t}\n\t\t\tif (this.hasActiveChild(item)) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\treturn Boolean(item.open)\n\t\t},\n\n\t\t/**\n\t\t * Whether any of a group's visible children is the active route.\n\t\t * Drives auto-expansion of the parent group on page load.\n\t\t *\n\t\t * @param {object} item Menu entry descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\thasActiveChild(item) {\n\t\t\treturn this.visibleChildren(item).some((child) => this.isActive(child))\n\t\t},\n\n\t\t/**\n\t\t * Record a group's expand/collapse state. Bound to\n\t\t * NcAppNavigationItem's `@update:open` (chevron clicks) and\n\t\t * called from `onItemClick` for title clicks on route-less\n\t\t * group items.\n\t\t *\n\t\t * @param {{ id: string }} item Menu entry descriptor.\n\t\t * @param {boolean} value New open state.\n\t\t */\n\t\tsetItemOpen(item, value) {\n\t\t\tthis.openState[item.id] = value\n\t\t},\n\n\t\t/**\n\t\t * Pin open every group the active route just entered.\n\t\t *\n\t\t * Auto-expansion used to be read off the route alone, so a group\n\t\t * opened for a deep link collapsed the moment the route left it. A\n\t\t * group opened for you stays open until you close it. Only a group\n\t\t * the route ENTERS is pinned: one you closed while on one of its\n\t\t * children stays closed while you move between them.\n\t\t *\n\t\t * @param {string|null} previousRoute The active route before this change, or undefined at first render.\n\t\t */\n\t\tpinGroupsEntered(previousRoute) {\n\t\t\tfor (const item of this.visibleItems) {\n\t\t\t\tconst children = this.visibleChildren(item)\n\t\t\t\tif (children.length === 0 || !this.hasActiveChild(item)) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst wasInside = children.some((child) => child.route === previousRoute)\n\t\t\t\tif (!wasInside || this.openState[item.id] === undefined) {\n\t\t\t\t\tthis.openState[item.id] = true\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Click handler. Dispatch order: action keyword → group\n\t\t * open/toggle. For `action: \"user-settings\"` invokes the injected\n\t\t * `cnOpenUserSettings` (provided by CnAppRoot) and prevents\n\t\t * default; `action: \"admin-settings\"` is a real link to\n\t\t * `/settings/admin/<appId>` (see `itemHref`) and is left to the\n\t\t * browser; for `action:\n\t\t * \"replay-walkthrough\"` invokes the injected\n\t\t * `cnReplayWalkthrough(item.tourId)` and prevents default. `href`\n\t\t * items with no children are NOT handled here — they render a real\n\t\t * anchor via `itemHref`, so the browser navigates natively\n\t\t * (external URLs open in a new tab, internal app paths in the same\n\t\t * tab).\n\t\t *\n\t\t * A group's children visibility on click depends on whether the\n\t\t * group ITSELF has a destination:\n\t\t * - Route-less, href-less: a pure group header, so its anchor is\n\t\t * a dead `#` link and the click's only job is to TOGGLE the\n\t\t * children open/closed (same effect as the collapse chevron).\n\t\t * - Carries a `route` or `href`: the click is a real navigation\n\t\t * (handled natively by `:to` / the anchor, not prevented here),\n\t\t * and this additionally forces the group OPEN — never closed —\n\t\t * so the reader lands on the group's own page without a second\n\t\t * click to see what else it holds. The collapse chevron is the\n\t\t * only control that can close such a group again.\n\t\t *\n\t\t * @param {object} item Menu item being clicked.\n\t\t * @param {Event} [event] Native click event (used to call\n\t\t * preventDefault for action / group links).\n\t\t */\n\t\tonItemClick(item, event) {\n\t\t\tif (item.action === 'user-settings') {\n\t\t\t\tif (event && typeof event.preventDefault === 'function') {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t}\n\t\t\t\tthis.cnOpenUserSettings()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (item.action === 'admin-settings') {\n\t\t\t\t// ADR-079: a real link to Nextcloud's own settings (see\n\t\t\t\t// itemHref), followed natively in a new tab. Without an app\n\t\t\t\t// id there is no href, and the click does nothing.\n\t\t\t\tif (!this.adminSettingsHref && event && typeof event.preventDefault === 'function') {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (item.action === 'replay-walkthrough') {\n\t\t\t\tif (event && typeof event.preventDefault === 'function') {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t}\n\t\t\t\tthis.cnReplayWalkthrough(item.tourId)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// An entry that shares its route is a plain link (see linkTo); a\n\t\t\t// plain click still navigates inside the app. A modified click\n\t\t\t// (new tab, new window) is left to the browser.\n\t\t\tif (this.appRouter() && this.sharesRoute(item) && event && !event.defaultPrevented\n\t\t\t\t&& !(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) && event.button !== 1) {\n\t\t\t\tconst to = this.itemTo(item)\n\t\t\t\tif (to) {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t\tthis.appRouter().push(to).catch(() => {})\n\t\t\t\t}\n\t\t\t}\n\t\t\t// An entry left without a link (see itemTo) renders a `#` anchor;\n\t\t\t// following it would change the address, so the click goes nowhere.\n\t\t\tif (!item.href && this.unfilledRouteParam(item) && event && typeof event.preventDefault === 'function') {\n\t\t\t\tevent.preventDefault()\n\t\t\t}\n\t\t\tif (this.visibleChildren(item).length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!item.route && !item.href) {\n\t\t\t\tif (event && typeof event.preventDefault === 'function') {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t}\n\t\t\t\tthis.setItemOpen(item, !this.isItemOpen(item))\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// The item is ALSO a real destination: let the click navigate\n\t\t\t// natively and reveal the children alongside it.\n\t\t\tthis.setItemOpen(item, true)\n\t\t},\n\n\t\t/**\n\t\t * Click handler for the auto-prepended Personal-settings entry in\n\t\t * the settings foldout. Invokes the injected `cnOpenUserSettings`\n\t\t * (provided by CnAppRoot → opens the host's NcAppSettingsDialog).\n\t\t * No-op inject when mounted standalone.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonPersonalSettingsClick() {\n\t\t\tthis.cnOpenUserSettings()\n\t\t},\n\n\t\t/**\n\t\t * Click handler for the manifest-declared primary action. Emits\n\t\t * `@primary-action` AND the back-compat `@primary-action-click`\n\t\t * event for host-side handling. Navigation is the link's own: an\n\t\t * `href` or `route` action renders as a real link (see\n\t\t * `primaryActionLink`), so the browser or router follows it after\n\t\t * these events. Not invoked when the host overrides the\n\t\t * `#primary-action` slot (it provides its own handler).\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\t/**\n\t\t * Re-emit the object an `open-form` primary action created, so the\n\t\t * host can refresh a list or open the record.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-navigation-primary-action-runs-a-page-action\n\t\t * @param {object} created The created object.\n\t\t * @return {void}\n\t\t */\n\t\tonPrimaryActionCreated(created) {\n\t\t\t/**\n\t\t\t * @event primary-action-created Emitted after an `open-form` primary action saves. Payload: the created object.\n\t\t\t */\n\t\t\tthis.$emit('primary-action-created', created)\n\t\t},\n\n\t\t/**\n\t\t * A card link that is a button (an `action` id) emits `card-action`\n\t\t * with that id for the host to run; links and anchors navigate on\n\t\t * their own.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-the-navigation-carries-a-card-and-a-help-entry\n\t\t * @return {void}\n\t\t */\n\t\tonCardLinkClick() {\n\t\t\tconst card = this.resolvedCard\n\t\t\tif (card && card.action) {\n\t\t\t\t/**\n\t\t\t\t * @event card-action Emitted when the nav card's link is an action button. Payload: the action id.\n\t\t\t\t */\n\t\t\t\tthis.$emit('card-action', card.action)\n\t\t\t}\n\t\t},\n\n\t\tonPrimaryActionClick() {\n\t\t\tconst action = this.activePrimaryAction\n\t\t\tif (!action) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst payload = {\n\t\t\t\tid: action.id,\n\t\t\t\tlabel: action.label,\n\t\t\t\ticon: action.icon,\n\t\t\t\troute: action.route,\n\t\t\t\thref: action.href,\n\t\t\t\tpayload: action.payload,\n\t\t\t\tpage: this.$route?.name,\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event primary-action Emitted when the resolved primary-action button is clicked. Payload includes the action descriptor (`{ id, label, icon, route, href, payload }`) plus the current `page` (route name) for host dispatchers.\n\t\t\t * @type {{ id?: string, label: string, icon?: string, route?: string, href?: string, payload?: unknown, page?: string }}\n\t\t\t */\n\t\t\tthis.$emit('primary-action', payload)\n\t\t\t/**\n\t\t\t * @event primary-action-click Back-compat alias for `@primary-action`. Payload is the resolved primary action object as declared in the manifest.\n\t\t\t */\n\t\t\tthis.$emit('primary-action-click', action)\n\t\t},\n\t},\n}\n</script>\n\n<style>\n.cn-app-nav__hint {\n\tlist-style: none;\n\tpadding: 4px 12px 8px 16px;\n\tfont-size: 13px;\n\tline-height: 1.4;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n/* The emblem beside the app name (`nav.brand.emblem`). A theme sets\n --nldesign-emblem-url for `emblem: true`, and --cn-nav-emblem-size for both. */\n.cn-app-nav__brand-emblem {\n\tflex: none;\n\theight: var(--cn-nav-emblem-size, 34px);\n\twidth: auto;\n\tobject-fit: contain;\n}\n\n.cn-app-nav__brand-emblem--theme {\n\tdisplay: inline-block;\n\twidth: var(--cn-nav-emblem-size, 34px);\n\tbackground: var(--nldesign-emblem-url) center / contain no-repeat;\n}\n\n/* The solid primary action (`solid: true`, or an action that dispatches):\n one full-width primary button, as the board draws \"New case\". */\n.cn-app-nav__primary-action--solid .cn-action-buttons,\n.cn-app-nav__primary-action--solid .cn-action-buttons .button-vue,\n.cn-app-nav__primary-action--solid .button-vue {\n\twidth: 100%;\n\tjustify-content: center;\n}\n\n/* The card above the footer entries (`nav.card`). Theme hooks:\n --cn-nav-card-background and --cn-nav-card-radius. */\n.cn-app-nav__card {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: calc(2 * var(--default-grid-baseline));\n\tmargin: calc(2 * var(--default-grid-baseline));\n\tpadding: calc(4 * var(--default-grid-baseline));\n\tborder-radius: var(--cn-nav-card-radius, var(--border-radius-large));\n\tbackground: var(--cn-nav-card-background, var(--color-background-hover));\n}\n\n.cn-app-nav__card-title {\n\tcolor: var(--color-main-text);\n\tfont-weight: 700;\n}\n\n.cn-app-nav__card-text {\n\tcolor: var(--color-text-maxcontrast);\n\tline-height: 1.4;\n}\n\n.cn-app-nav__card-link {\n\talign-self: flex-start;\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tbackground: none;\n\tcolor: var(--color-primary-element);\n\tfont: inherit;\n\tfont-weight: 600;\n\ttext-decoration: none;\n\tcursor: pointer;\n}\n\n.cn-app-nav__card-link:hover,\n.cn-app-nav__card-link:focus-visible {\n\ttext-decoration: underline;\n}\n\n.cn-app-nav__card-link:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 2px;\n\tborder-radius: var(--border-radius-small, 4px);\n}\n\n/* The brand block at the top of the navigation. */\n.cn-app-nav__brand {\n\talign-items: center;\n\tdisplay: flex;\n\tgap: calc(2.5 * var(--default-grid-baseline));\n\tmin-width: 0;\n\tpadding: calc(2 * var(--default-grid-baseline)) calc(2 * var(--default-grid-baseline)) calc(3 * var(--default-grid-baseline));\n}\n\n.cn-app-nav__brand-logo {\n\tflex: none;\n\theight: 34px;\n\tmax-width: 50%;\n\tobject-fit: contain;\n\twidth: auto;\n}\n\n.cn-app-nav__brand-text {\n\tdisplay: flex;\n\tflex-direction: column;\n\tline-height: 1.15;\n\tmin-width: 0;\n}\n\n.cn-app-nav__brand-name {\n\tcolor: var(--color-main-text);\n\tfont-size: 1.2em;\n\tfont-weight: 700;\n\toverflow-wrap: anywhere;\n}\n\n.cn-app-nav__brand-caption {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.85em;\n\toverflow-wrap: anywhere;\n}\n\n/*\n * The legacy `icon-*` classes in Nextcloud render a background-image\n * with a hardcoded dark fill, so they stay grey when an entry becomes\n * active (text turns white against the primary-element background).\n * Force the icon to white in the active state to match the label.\n * Only applies when the icon is provided via the `icon` prop (CSS\n * class) — items using a `<template #icon>` MDI component already\n * inherit `currentColor`.\n */\n.app-navigation-entry.active .app-navigation-entry-icon[class*=\"icon-\"] {\n\tfilter: brightness(0) invert(1);\n}\n\n/* The link form of the primary action, matching NcAppNavigationNew's scoped layout. */\n.cn-app-nav__primary-action {\n\tdisplay: block;\n\tpadding: calc(var(--default-grid-baseline, 4px) * 2);\n}\n\n/*\n * The primary action never shrinks out of sight. NcAppNavigation renders it in\n * `.app-navigation__body`, a flex child with `overflow-y: scroll` (so its\n * minimum height is 0) beside a list of `height: 100%` and the footer. With a\n * card and footer entries below the list, the column overflows and the body\n * gives up its share of the shrink: \"New case\" showed as a 24px sliver of a\n * 42px button. All three forms carry `.app-navigation-new` (the solid and\n * link wrappers mirror NcAppNavigationNew's class), and the rule is scoped to\n * this component's navigation, so a navigation without a primary action lays\n * out exactly as before.\n */\n.app-navigation[data-testid=\"cn-nav\"] .app-navigation__body:has(> .app-navigation-new) {\n\tflex-shrink: 0;\n}\n\n/*\n * Footer-section items (section: \"footer\") render in NcAppNavigation's\n * #footer slot, outside the scroll container, so they stay visible above\n * the settings foldout regardless of menu length. (The interim\n * `pinned`-prop approach kept them inside the scrollable list, where\n * `margin-top: auto` only bottom-pins while the list does not overflow —\n * long menus showed Documentation / Features & roadmap mid-scroll.)\n *\n * No `padding` here on purpose: it comes from NcAppNavigationList's own\n * `var(--app-navigation-padding)`, so it stays in step with the main list.\n *\n * As a direct `> ul` child of `.app-navigation__content`, NC makes it a\n * shrinkable, scrollable flex item, and NcAppNavigationList adds\n * `overflow-y: auto` besides. That let a two-entry list be squeezed below its\n * content and grow a scrollbar on a short menu, so opt out of both.\n */\n.cn-app-nav__footer-list {\n\tlist-style: none;\n\tmargin: 0;\n\tflex-shrink: 0 !important;\n\toverflow: visible !important;\n}\n\n/*\n * A declared footer that names `settings` first (`nav.footer`) puts the\n * foldout above the footer list. The two are siblings in NcAppNavigation's\n * flex column, so `order` moves them without changing either's markup; the\n * card above keeps order 0 and stays first.\n */\n.cn-app-nav__settings--first {\n\torder: 1;\n}\n\n.cn-app-nav__footer-list--after-settings {\n\torder: 2;\n}\n\n/*\n * Align the settings foldout's items with the main/footer list items,\n * whose icons sit at a 16px inset. The foldout's items live in a bare\n * <ul> inside NcAppNavigationSettings' panel (`#app-settings`, padding\n * 3px), so without this they start ~5px further left and the icon\n * column looks ragged. (The native settings-toggle button sits ~1px\n * left of the 16px baseline, but NC owns that with an !important\n * shorthand — a sub-pixel difference we leave to the native component.)\n */\n.cn-app-nav__settings-list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding-inline-start: 5px;\n}\n</style>\n"],"names":["CnActionButtons","CnMenuItemIcon","MapMarkerPath","t"],"mappings":"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"}
|