@conduction/nextcloud-vue 2.92.0 → 2.93.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +57 -4
  2. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  3. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +44 -17
  4. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  5. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue.js +1 -1
  6. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js +44 -2
  7. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
  8. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js +140 -59
  9. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
  10. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
  11. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +20 -6
  12. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  13. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +3 -2
  14. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  15. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +2 -36
  16. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  17. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  18. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +5 -3
  19. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  20. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  21. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
  22. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +6 -4
  23. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  24. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  25. package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue2.js +46 -0
  26. package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue2.js.map +1 -1
  27. package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue3.js +6 -2
  28. package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue3.js.map +1 -1
  29. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue.js +1 -1
  30. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js +82 -9
  31. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js.map +1 -1
  32. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js +104 -90
  33. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js.map +1 -1
  34. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue.js +9 -0
  35. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue.js.map +1 -0
  36. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js +355 -0
  37. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js.map +1 -0
  38. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js +462 -0
  39. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js.map +1 -0
  40. package/dist/esm/components/CnFormDialog/CnFormDialog.vue.js +1 -1
  41. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +21 -0
  42. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  43. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +402 -391
  44. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  45. package/dist/esm/components/CnIcon/semanticIcons.js +2 -2
  46. package/dist/esm/components/CnIcon/semanticIcons.js.map +1 -1
  47. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue.js +1 -1
  48. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js +22 -1
  49. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js.map +1 -1
  50. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js +20 -14
  51. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js.map +1 -1
  52. package/dist/esm/components/CnNotificationPreferences/CnNotificationPreferences.vue.js +1 -1
  53. package/dist/esm/components/CnNotificationPreferences/CnNotificationPreferences.vue2.js +2 -0
  54. package/dist/esm/components/CnNotificationPreferences/CnNotificationPreferences.vue2.js.map +1 -1
  55. package/dist/esm/components/CnNotificationPreferences/CnNotificationPreferences.vue3.js +15 -5
  56. package/dist/esm/components/CnNotificationPreferences/CnNotificationPreferences.vue3.js.map +1 -1
  57. package/dist/esm/components/CnRoadmapTab/CnRoadmapTab.vue.js +1 -1
  58. package/dist/esm/components/CnRoadmapTab/CnRoadmapTab.vue2.js +8 -30
  59. package/dist/esm/components/CnRoadmapTab/CnRoadmapTab.vue2.js.map +1 -1
  60. package/dist/esm/components/CnRoadmapTab/CnRoadmapTab.vue3.js.map +1 -1
  61. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js +9 -0
  62. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js.map +1 -0
  63. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js +164 -0
  64. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js.map +1 -0
  65. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js +93 -0
  66. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js.map +1 -0
  67. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue.js +1 -1
  68. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +12 -0
  69. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
  70. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
  71. package/dist/esm/l10n/en.json.js +24 -1
  72. package/dist/esm/l10n/en.json.js.map +1 -1
  73. package/dist/esm/l10n/nl.json.js +24 -1
  74. package/dist/esm/l10n/nl.json.js.map +1 -1
  75. package/dist/esm/library-style.js +1 -1
  76. package/dist/esm/nextcloud-vue.css +887 -247
  77. package/dist/esm/utils/featureCatalog.js +135 -0
  78. package/dist/esm/utils/featureCatalog.js.map +1 -0
  79. package/dist/esm/utils/fillTemplate.js +74 -3
  80. package/dist/esm/utils/fillTemplate.js.map +1 -1
  81. package/dist/esm/utils/headerMeta.js +62 -12
  82. package/dist/esm/utils/headerMeta.js.map +1 -1
  83. package/dist/esm/utils/roadmapIssues.js +86 -0
  84. package/dist/esm/utils/roadmapIssues.js.map +1 -0
  85. package/dist/esm/utils/userDisplayName.js +47 -0
  86. package/dist/esm/utils/userDisplayName.js.map +1 -0
  87. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  88. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  89. package/dist/nextcloud-vue.cjs.js +14820 -12966
  90. package/dist/nextcloud-vue.cjs.js.map +2 -2
  91. package/dist/nextcloud-vue.css +887 -247
  92. package/l10n/en.json +24 -1
  93. package/l10n/nl.json +24 -1
  94. package/package.json +1 -1
  95. package/src/components/CnAppRoot/CnAppRoot.md +2 -0
  96. package/src/components/CnAppRoot/CnAppRoot.vue +66 -5
  97. package/src/components/CnChoiceCards/CnChoiceCards.md +27 -0
  98. package/src/components/CnChoiceCards/CnChoiceCards.vue +168 -3
  99. package/src/components/CnDashboardPage/CnDashboardPage.vue +45 -6
  100. package/src/components/CnDataTable/CnDataTable.vue +2 -36
  101. package/src/components/CnDetailPage/CnDetailPage.vue +5 -3
  102. package/src/components/CnFactsWidget/CnFactsWidget.vue +6 -4
  103. package/src/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue +51 -1
  104. package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +98 -13
  105. package/src/components/CnFeaturesBoard/CnFeaturesBoard.vue +1053 -0
  106. package/src/components/CnFormDialog/CnFormDialog.vue +606 -562
  107. package/src/components/CnNcWidgetWidget/CnNcWidgetWidget.vue +23 -2
  108. package/src/components/CnNotificationPreferences/CnNotificationPreferences.vue +5 -0
  109. package/src/components/CnRoadmapTab/CnRoadmapTab.vue +6 -28
  110. package/src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue +305 -0
  111. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +12 -0
  112. package/src/css/dialog.css +47 -0
  113. package/src/css/look-board-detail.css +8 -0
  114. package/src/css/look-board.css +33 -0
  115. package/src/schemas/app-manifest-v2.schema.json +9 -3
  116. package/src/utils/featureCatalog.js +132 -0
  117. package/src/utils/fillTemplate.js +73 -2
  118. package/src/utils/headerMeta.js +62 -12
  119. package/src/utils/roadmapIssues.js +82 -0
  120. package/src/utils/userDisplayName.js +54 -0
  121. package/src/utils/validateManifestV2.compiled.js +3 -3
@@ -94,7 +94,7 @@ import HandshakeOutlineIcon from 'vue-material-design-icons/HandshakeOutline.vue
94
94
  import History from 'vue-material-design-icons/History.vue';
95
95
  import ImageOutlineIcon from 'vue-material-design-icons/ImageOutline.vue';
96
96
  import InformationOutline from 'vue-material-design-icons/InformationOutline.vue';
97
- import KeyOutlineIcon from 'vue-material-design-icons/KeyOutline.vue';
97
+ import KeyOutline from 'vue-material-design-icons/KeyOutline.vue';
98
98
  import LayersOutlineIcon from 'vue-material-design-icons/LayersOutline.vue';
99
99
  import LinkVariant from 'vue-material-design-icons/LinkVariant.vue';
100
100
  import LockOutline from 'vue-material-design-icons/LockOutline.vue';
@@ -494,7 +494,7 @@ const SEMANTIC_ICON_COMPONENTS = Object.freeze({
494
494
  History: History,
495
495
  ImageOutline: ImageOutlineIcon,
496
496
  InformationOutline: InformationOutline,
497
- KeyOutline: KeyOutlineIcon,
497
+ KeyOutline: KeyOutline,
498
498
  LayersOutline: LayersOutlineIcon,
499
499
  LinkVariant: LinkVariant,
500
500
  LockOutline: LockOutline,
@@ -1 +1 @@
1
- {"version":3,"file":"semanticIcons.js","sources":["../../../../src/components/CnIcon/semanticIcons.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * semanticIcons — the fleet-wide semantic icon vocabulary (ADR-077).\n *\n * One concept, one icon. A manifest `icon` field holds an MDI PascalCase name;\n * this table is what makes the same concept read the same way in every\n * Conduction app (Store is always StoreOutline, Dashboard is always\n * ViewDashboardOutline). The mapping is a BIJECTION — no concept has two\n * icons and no icon serves two concepts — which is what stops the historical\n * overloading (one glyph standing for 18 unrelated things).\n *\n * Tier A is universal chrome every app has and MUST match. Tier B is the\n * shared domain vocabulary an app SHOULD use when it has the concept.\n *\n * WHY THIS IS A PURE EXPORT AND NOT AN import-time `registerIcons()` CALL:\n * the published dist's `sideEffects` allowlist has previously tree-shaken\n * import-time side effects out of consumer bundles, which fails SILENTLY\n * (nothing renders, no error). So the rendering components import\n * {@link SEMANTIC_ICON_COMPONENTS} and consult it directly — resolution is\n * guaranteed by the component that needs it, with no side-effect ordering to\n * get wrong and nothing for a bundler to drop.\n *\n * Every name below is verified to exist in `vue-material-design-icons` by\n * tests/components/semanticIcons.spec.js — the check that caught invented\n * names like `LedgerOutline` and `FileSignOutline` already live in manifests.\n *\n * Each icon is imported individually (no wildcard / barrel) so the bundle\n * stays tree-shake-friendly.\n *\n * @spec openspec/architecture/adr-077-semantic-icon-vocabulary.md\n */\n\nimport AccountArrowRightOutlineIcon from 'vue-material-design-icons/AccountArrowRightOutline.vue'\nimport AccountBoxOutlineIcon from 'vue-material-design-icons/AccountBoxOutline.vue'\nimport AccountGroupOutlineIcon from 'vue-material-design-icons/AccountGroupOutline.vue'\nimport AccountKeyOutlineIcon from 'vue-material-design-icons/AccountKeyOutline.vue'\nimport AccountMinusOutlineIcon from 'vue-material-design-icons/AccountMinusOutline.vue'\nimport AccountMultipleOutlineIcon from 'vue-material-design-icons/AccountMultipleOutline.vue'\nimport AccountOutlineIcon from 'vue-material-design-icons/AccountOutline.vue'\nimport AccountPlusOutlineIcon from 'vue-material-design-icons/AccountPlusOutline.vue'\nimport AccountSchoolOutlineIcon from 'vue-material-design-icons/AccountSchoolOutline.vue'\nimport AccountSearchOutlineIcon from 'vue-material-design-icons/AccountSearchOutline.vue'\nimport AccountStarOutlineIcon from 'vue-material-design-icons/AccountStarOutline.vue'\nimport AccountSwitchOutlineIcon from 'vue-material-design-icons/AccountSwitchOutline.vue'\nimport AccountTieOutlineIcon from 'vue-material-design-icons/AccountTieOutline.vue'\nimport AlertCircleOutlineIcon from 'vue-material-design-icons/AlertCircleOutline.vue'\nimport ApiIcon from 'vue-material-design-icons/Api.vue'\nimport ApplicationOutlineIcon from 'vue-material-design-icons/ApplicationOutline.vue'\nimport BankOutlineIcon from 'vue-material-design-icons/BankOutline.vue'\nimport BankTransferIcon from 'vue-material-design-icons/BankTransfer.vue'\nimport BellOutlineIcon from 'vue-material-design-icons/BellOutline.vue'\nimport BookOpenPageVariantOutlineIcon from 'vue-material-design-icons/BookOpenPageVariantOutline.vue'\nimport BookOpenVariantOutlineIcon from 'vue-material-design-icons/BookOpenVariantOutline.vue'\nimport BookshelfIcon from 'vue-material-design-icons/Bookshelf.vue'\nimport BrainIcon from 'vue-material-design-icons/Brain.vue'\nimport BriefcaseOutlineIcon from 'vue-material-design-icons/BriefcaseOutline.vue'\nimport CalculatorVariantOutlineIcon from 'vue-material-design-icons/CalculatorVariantOutline.vue'\nimport CalendarAccountOutlineIcon from 'vue-material-design-icons/CalendarAccountOutline.vue'\nimport CalendarClockOutlineIcon from 'vue-material-design-icons/CalendarClockOutline.vue'\nimport CalendarOutlineIcon from 'vue-material-design-icons/CalendarOutline.vue'\nimport CalendarRemoveOutlineIcon from 'vue-material-design-icons/CalendarRemoveOutline.vue'\nimport CalendarTextOutlineIcon from 'vue-material-design-icons/CalendarTextOutline.vue'\nimport CalendarWeekendOutlineIcon from 'vue-material-design-icons/CalendarWeekendOutline.vue'\nimport CarOutlineIcon from 'vue-material-design-icons/CarOutline.vue'\nimport CartArrowDownIcon from 'vue-material-design-icons/CartArrowDown.vue'\nimport CartOutlineIcon from 'vue-material-design-icons/CartOutline.vue'\nimport CashSyncIcon from 'vue-material-design-icons/CashSync.vue'\nimport CertificateOutlineIcon from 'vue-material-design-icons/CertificateOutline.vue'\nimport ChartBarIcon from 'vue-material-design-icons/ChartBar.vue'\nimport ChartBoxOutlineIcon from 'vue-material-design-icons/ChartBoxOutline.vue'\nimport ChartLineVariantIcon from 'vue-material-design-icons/ChartLineVariant.vue'\nimport ChartSankeyIcon from 'vue-material-design-icons/ChartSankey.vue'\nimport ChartTimelineVariantIcon from 'vue-material-design-icons/ChartTimelineVariant.vue'\nimport CheckboxMarkedCircleOutlineIcon from 'vue-material-design-icons/CheckboxMarkedCircleOutline.vue'\nimport CheckCircleOutlineIcon from 'vue-material-design-icons/CheckCircleOutline.vue'\nimport CheckDecagramOutlineIcon from 'vue-material-design-icons/CheckDecagramOutline.vue'\nimport ClipboardAccountOutlineIcon from 'vue-material-design-icons/ClipboardAccountOutline.vue'\nimport ClipboardCheckOutlineIcon from 'vue-material-design-icons/ClipboardCheckOutline.vue'\nimport ClipboardListOutlineIcon from 'vue-material-design-icons/ClipboardListOutline.vue'\nimport ClipboardPulseOutlineIcon from 'vue-material-design-icons/ClipboardPulseOutline.vue'\nimport ClipboardTextOutlineIcon from 'vue-material-design-icons/ClipboardTextOutline.vue'\nimport ClockAlertOutlineIcon from 'vue-material-design-icons/ClockAlertOutline.vue'\nimport ClockCheckOutlineIcon from 'vue-material-design-icons/ClockCheckOutline.vue'\nimport ClockOutlineIcon from 'vue-material-design-icons/ClockOutline.vue'\nimport CloseCircleOutlineIcon from 'vue-material-design-icons/CloseCircleOutline.vue'\nimport CloudUploadOutlineIcon from 'vue-material-design-icons/CloudUploadOutline.vue'\nimport CogOutlineIcon from 'vue-material-design-icons/CogOutline.vue'\nimport CommentOutlineIcon from 'vue-material-design-icons/CommentOutline.vue'\nimport CommentQuestionOutlineIcon from 'vue-material-design-icons/CommentQuestionOutline.vue'\nimport ContentCopyIcon from 'vue-material-design-icons/ContentCopy.vue'\nimport ContentSaveIcon from 'vue-material-design-icons/ContentSave.vue'\nimport CreditCardOutlineIcon from 'vue-material-design-icons/CreditCardOutline.vue'\nimport CubeOutlineIcon from 'vue-material-design-icons/CubeOutline.vue'\nimport CurrencyEurIcon from 'vue-material-design-icons/CurrencyEur.vue'\nimport DatabaseArrowRightOutlineIcon from 'vue-material-design-icons/DatabaseArrowRightOutline.vue'\nimport DatabaseExportOutlineIcon from 'vue-material-design-icons/DatabaseExportOutline.vue'\nimport DatabaseImportOutlineIcon from 'vue-material-design-icons/DatabaseImportOutline.vue'\nimport DatabaseOutlineIcon from 'vue-material-design-icons/DatabaseOutline.vue'\nimport DeleteOutlineIcon from 'vue-material-design-icons/DeleteOutline.vue'\nimport DesktopTowerMonitorIcon from 'vue-material-design-icons/DesktopTowerMonitor.vue'\nimport DomainIcon from 'vue-material-design-icons/Domain.vue'\nimport DotsHorizontalIcon from 'vue-material-design-icons/DotsHorizontal.vue'\nimport DownloadIcon from 'vue-material-design-icons/Download.vue'\nimport EmailOutlineIcon from 'vue-material-design-icons/EmailOutline.vue'\nimport EyeOffOutlineIcon from 'vue-material-design-icons/EyeOffOutline.vue'\nimport EyeOutlineIcon from 'vue-material-design-icons/EyeOutline.vue'\nimport FileAlertOutlineIcon from 'vue-material-design-icons/FileAlertOutline.vue'\nimport FileChartOutlineIcon from 'vue-material-design-icons/FileChartOutline.vue'\nimport FileCheckOutlineIcon from 'vue-material-design-icons/FileCheckOutline.vue'\nimport FileDocumentMultipleOutlineIcon from 'vue-material-design-icons/FileDocumentMultipleOutline.vue'\nimport FileDocumentOutlineIcon from 'vue-material-design-icons/FileDocumentOutline.vue'\nimport FileLockOutlineIcon from 'vue-material-design-icons/FileLockOutline.vue'\nimport FileReplaceOutlineIcon from 'vue-material-design-icons/FileReplaceOutline.vue'\nimport FileSignIcon from 'vue-material-design-icons/FileSign.vue'\nimport FileTreeOutlineIcon from 'vue-material-design-icons/FileTreeOutline.vue'\nimport FilterVariantIcon from 'vue-material-design-icons/FilterVariant.vue'\nimport FolderAccountOutlineIcon from 'vue-material-design-icons/FolderAccountOutline.vue'\nimport FolderCogOutlineIcon from 'vue-material-design-icons/FolderCogOutline.vue'\nimport FolderOutlineIcon from 'vue-material-design-icons/FolderOutline.vue'\nimport FormatListChecksIcon from 'vue-material-design-icons/FormatListChecks.vue'\nimport ForumOutlineIcon from 'vue-material-design-icons/ForumOutline.vue'\nimport GaugeIcon from 'vue-material-design-icons/Gauge.vue'\nimport GavelIcon from 'vue-material-design-icons/Gavel.vue'\nimport HandHeartOutlineIcon from 'vue-material-design-icons/HandHeartOutline.vue'\nimport HandshakeOutlineIcon from 'vue-material-design-icons/HandshakeOutline.vue'\nimport HistoryIcon from 'vue-material-design-icons/History.vue'\nimport ImageOutlineIcon from 'vue-material-design-icons/ImageOutline.vue'\nimport InformationOutlineIcon from 'vue-material-design-icons/InformationOutline.vue'\nimport KeyOutlineIcon from 'vue-material-design-icons/KeyOutline.vue'\nimport LayersOutlineIcon from 'vue-material-design-icons/LayersOutline.vue'\nimport LinkVariantIcon from 'vue-material-design-icons/LinkVariant.vue'\nimport LockOutlineIcon from 'vue-material-design-icons/LockOutline.vue'\nimport MagnifyIcon from 'vue-material-design-icons/Magnify.vue'\nimport MapMarkerOutlineIcon from 'vue-material-design-icons/MapMarkerOutline.vue'\nimport MapMarkerPathIcon from 'vue-material-design-icons/MapMarkerPath.vue'\nimport MapOutlineIcon from 'vue-material-design-icons/MapOutline.vue'\nimport MedalOutlineIcon from 'vue-material-design-icons/MedalOutline.vue'\nimport MessageTextOutlineIcon from 'vue-material-design-icons/MessageTextOutline.vue'\nimport NotebookOutlineIcon from 'vue-material-design-icons/NotebookOutline.vue'\nimport OfficeBuildingOutlineIcon from 'vue-material-design-icons/OfficeBuildingOutline.vue'\nimport OpenInNewIcon from 'vue-material-design-icons/OpenInNew.vue'\nimport PackageVariantClosedIcon from 'vue-material-design-icons/PackageVariantClosed.vue'\nimport PaperclipIcon from 'vue-material-design-icons/Paperclip.vue'\nimport PencilOutlineIcon from 'vue-material-design-icons/PencilOutline.vue'\nimport PercentOutlineIcon from 'vue-material-design-icons/PercentOutline.vue'\nimport PlayCircleOutlineIcon from 'vue-material-design-icons/PlayCircleOutline.vue'\nimport PlayOutlineIcon from 'vue-material-design-icons/PlayOutline.vue'\nimport PlusIcon from 'vue-material-design-icons/Plus.vue'\nimport PrinterOutlineIcon from 'vue-material-design-icons/PrinterOutline.vue'\nimport PulseIcon from 'vue-material-design-icons/Pulse.vue'\nimport PuzzleOutlineIcon from 'vue-material-design-icons/PuzzleOutline.vue'\nimport ReceiptOutlineIcon from 'vue-material-design-icons/ReceiptOutline.vue'\nimport ReceiptTextOutlineIcon from 'vue-material-design-icons/ReceiptTextOutline.vue'\nimport RefreshIcon from 'vue-material-design-icons/Refresh.vue'\nimport RobotOutlineIcon from 'vue-material-design-icons/RobotOutline.vue'\nimport ScaleBalanceIcon from 'vue-material-design-icons/ScaleBalance.vue'\nimport SchoolOutlineIcon from 'vue-material-design-icons/SchoolOutline.vue'\nimport ShareVariantOutlineIcon from 'vue-material-design-icons/ShareVariantOutline.vue'\nimport ShieldAccountOutlineIcon from 'vue-material-design-icons/ShieldAccountOutline.vue'\nimport ShieldAlertOutlineIcon from 'vue-material-design-icons/ShieldAlertOutline.vue'\nimport ShieldCheckOutlineIcon from 'vue-material-design-icons/ShieldCheckOutline.vue'\nimport ShieldCrownOutlineIcon from 'vue-material-design-icons/ShieldCrownOutline.vue'\nimport ShieldKeyOutlineIcon from 'vue-material-design-icons/ShieldKeyOutline.vue'\nimport ShieldLockOutlineIcon from 'vue-material-design-icons/ShieldLockOutline.vue'\nimport ShieldOutlineIcon from 'vue-material-design-icons/ShieldOutline.vue'\nimport SignatureFreehandIcon from 'vue-material-design-icons/SignatureFreehand.vue'\nimport SitemapOutlineIcon from 'vue-material-design-icons/SitemapOutline.vue'\nimport SourceBranchIcon from 'vue-material-design-icons/SourceBranch.vue'\nimport SpeedometerIcon from 'vue-material-design-icons/Speedometer.vue'\nimport StoreOutlineIcon from 'vue-material-design-icons/StoreOutline.vue'\nimport SwapHorizontalIcon from 'vue-material-design-icons/SwapHorizontal.vue'\nimport TableClockIcon from 'vue-material-design-icons/TableClock.vue'\nimport TagOutlineIcon from 'vue-material-design-icons/TagOutline.vue'\nimport TextBoxOutlineIcon from 'vue-material-design-icons/TextBoxOutline.vue'\nimport ToolboxOutlineIcon from 'vue-material-design-icons/ToolboxOutline.vue'\nimport TransitConnectionVariantIcon from 'vue-material-design-icons/TransitConnectionVariant.vue'\nimport TrayFullIcon from 'vue-material-design-icons/TrayFull.vue'\nimport TrendingUpIcon from 'vue-material-design-icons/TrendingUp.vue'\nimport UploadIcon from 'vue-material-design-icons/Upload.vue'\nimport VectorPolylinePlusIcon from 'vue-material-design-icons/VectorPolylinePlus.vue'\nimport ViewColumnOutlineIcon from 'vue-material-design-icons/ViewColumnOutline.vue'\nimport ViewDashboardOutlineIcon from 'vue-material-design-icons/ViewDashboardOutline.vue'\nimport ViewGridOutlineIcon from 'vue-material-design-icons/ViewGridOutline.vue'\nimport WarehouseIcon from 'vue-material-design-icons/Warehouse.vue'\nimport WebhookIcon from 'vue-material-design-icons/Webhook.vue'\n\n/**\n * Tier A — universal chrome. An app that has the concept MUST use this icon.\n *\n * @type {Readonly<Record<string, string>>}\n */\nexport const SEMANTIC_ICONS_TIER_A = Object.freeze({\n\tdashboard: 'ViewDashboardOutline',\n\tdocumentation: 'BookOpenVariantOutline',\n\t'features-roadmap': 'MapMarkerPath',\n\tsettings: 'CogOutline',\n\tadmin: 'ShieldAccountOutline',\n\tsearch: 'Magnify',\n\tstore: 'StoreOutline',\n\ttutorial: 'PlayCircleOutline',\n\tabout: 'InformationOutline',\n\tnotifications: 'BellOutline',\n\tactivity: 'Pulse',\n\t'audit-trail': 'History',\n\t'my-work': 'ClipboardAccountOutline',\n})\n\n/**\n * Tier B — shared domain vocabulary. An app SHOULD use this icon when it has\n * the concept; a genuinely new concept is added here, never invented locally.\n *\n * @type {Readonly<Record<string, string>>}\n */\nexport const SEMANTIC_ICONS_TIER_B = Object.freeze({\n\t// data & records\n\tdata: 'DatabaseOutline',\n\tschema: 'FileTreeOutline',\n\trecord: 'CubeOutline',\n\t'data-quality': 'ClipboardPulseOutline',\n\timport: 'DatabaseImportOutline',\n\texport: 'DatabaseExportOutline',\n\tmigration: 'DatabaseArrowRightOutline',\n\tmapping: 'SwapHorizontal',\n\tlog: 'TextBoxOutline',\n\tjob: 'ClockOutline',\n\t// documents & files\n\tdocument: 'FileDocumentOutline',\n\tdocuments: 'FileDocumentMultipleOutline',\n\tfolder: 'FolderOutline',\n\ttemplate: 'FileReplaceOutline',\n\tcatalogue: 'Bookshelf',\n\tsigning: 'SignatureFreehand',\n\tcontract: 'FileSign',\n\tcorrespondence: 'EmailOutline',\n\tattachment: 'Paperclip',\n\t// cases & process\n\tcase: 'FolderAccountOutline',\n\t'case-type': 'FolderCogOutline',\n\ttask: 'CheckboxMarkedCircleOutline',\n\ttasks: 'FormatListChecks',\n\tworkflow: 'SitemapOutline',\n\tboard: 'ViewColumnOutline',\n\tapproval: 'CheckDecagramOutline',\n\tdecision: 'Gavel',\n\tqueue: 'TrayFull',\n\tdeadline: 'ClockAlertOutline',\n\tobjection: 'FileAlertOutline',\n\tappeal: 'ScaleBalance',\n\t// communication\n\tchat: 'MessageTextOutline',\n\tcomment: 'CommentOutline',\n\tmeeting: 'CalendarAccountOutline',\n\tagenda: 'CalendarTextOutline',\n\tappointment: 'CalendarClockOutline',\n\tcalendar: 'CalendarOutline',\n\tconsultation: 'CommentQuestionOutline',\n\tforum: 'ForumOutline',\n\t// people & organisations\n\tperson: 'AccountOutline',\n\tpeople: 'AccountMultipleOutline',\n\tgroup: 'AccountGroupOutline',\n\trole: 'AccountKeyOutline',\n\torganisation: 'OfficeBuildingOutline',\n\t'organisation-unit': 'Domain',\n\tpartner: 'HandshakeOutline',\n\tclient: 'AccountStarOutline',\n\temployee: 'AccountTieOutline',\n\tlead: 'AccountArrowRightOutline',\n\tprospect: 'AccountSearchOutline',\n\tsubstitution: 'AccountSwitchOutline',\n\t// commerce & finance\n\tsales: 'CartOutline',\n\tpurchasing: 'CartArrowDown',\n\tproduct: 'PackageVariantClosed',\n\tinventory: 'Warehouse',\n\torder: 'ClipboardListOutline',\n\tinvoice: 'ReceiptTextOutline',\n\tpayment: 'CreditCardOutline',\n\tpayroll: 'CashSync',\n\texpense: 'ReceiptOutline',\n\tbank: 'BankOutline',\n\t'bank-transaction': 'BankTransfer',\n\tbookkeeping: 'NotebookOutline',\n\ttax: 'PercentOutline',\n\tbudget: 'CalculatorVariantOutline',\n\tforecast: 'ChartTimelineVariant',\n\trevenue: 'CurrencyEur',\n\tpricing: 'TagOutline',\n\tsubsidy: 'HandHeartOutline',\n\t// reporting & monitoring\n\treport: 'FileChartOutline',\n\treporting: 'ChartBoxOutline',\n\tanalytics: 'ChartLineVariant',\n\tkpi: 'Speedometer',\n\tmonitoring: 'Gauge',\n\tstatistics: 'ChartBar',\n\t'process-mining': 'ChartSankey',\n\t// security & compliance\n\tsecurity: 'ShieldOutline',\n\tcompliance: 'ClipboardCheckOutline',\n\tpolicy: 'ShieldCheckOutline',\n\tvulnerability: 'ShieldAlertOutline',\n\tcertificate: 'CertificateOutline',\n\tvault: 'LockOutline',\n\tkey: 'KeyOutline',\n\tauthorization: 'ShieldKeyOutline',\n\tprivacy: 'ShieldLockOutline',\n\tanonymization: 'EyeOffOutline',\n\tconsent: 'FileCheckOutline',\n\tconfidentiality: 'FileLockOutline',\n\tretention: 'CalendarRemoveOutline',\n\tgovernance: 'ShieldCrownOutline',\n\t// integration & technology\n\tintegration: 'Api',\n\tconnection: 'TransitConnectionVariant',\n\twebhook: 'Webhook',\n\tautomation: 'VectorPolylinePlus',\n\tagent: 'RobotOutline',\n\tai: 'Brain',\n\ttool: 'ToolboxOutline',\n\tapps: 'ViewGridOutline',\n\tmodule: 'PuzzleOutline',\n\tsource: 'SourceBranch',\n\t// location & geo\n\tlocation: 'MapMarkerOutline',\n\tmap: 'MapOutline',\n\t'map-layer': 'LayersOutline',\n\t// learning\n\tcourse: 'BookOpenPageVariantOutline',\n\tlearning: 'SchoolOutline',\n\tcompetency: 'MedalOutline',\n\ttimetable: 'TableClock',\n\tprogress: 'TrendingUp',\n\tportfolio: 'BriefcaseOutline',\n\texam: 'ClipboardTextOutline',\n\tstudent: 'AccountSchoolOutline',\n\t// Publish, Test connection).\n\tview: 'EyeOutline',\n\tcreate: 'Plus',\n\tedit: 'PencilOutline',\n\tdelete: 'DeleteOutline',\n\trun: 'PlayOutline',\n\ttest: 'CheckCircleOutline',\n\tupload: 'Upload',\n\tpublish: 'CloudUploadOutline',\n\tdownload: 'Download',\n\trefresh: 'Refresh',\n\t'open-external': 'OpenInNew',\n\tcopy: 'ContentCopy',\n\tshare: 'ShareVariantOutline',\n\tfilter: 'FilterVariant',\n\tprint: 'PrinterOutline',\n\timage: 'ImageOutline',\n\tlink: 'LinkVariant',\n\tmore: 'DotsHorizontal',\n\tsave: 'ContentSave',\n\tcancel: 'CloseCircleOutline',\n\talert: 'AlertCircleOutline',\n\t// hr\n\tleave: 'CalendarWeekendOutline',\n\thours: 'ClockCheckOutline',\n\tonboarding: 'AccountPlusOutline',\n\toffboarding: 'AccountMinusOutline',\n\tvacancy: 'AccountBoxOutline',\n\tasset: 'DesktopTowerMonitor',\n\tfleet: 'CarOutline',\n})\n\n/**\n * The whole vocabulary — concept slug to canonical MDI name.\n *\n * @type {Readonly<Record<string, string>>}\n */\nexport const SEMANTIC_ICONS = Object.freeze({\n\t...SEMANTIC_ICONS_TIER_A,\n\t...SEMANTIC_ICONS_TIER_B,\n})\n\n/**\n * Which tier a concept belongs to — `'A'` (MUST) or `'B'` (SHOULD). Consumed by\n * hydra's icon-vocabulary gate to decide hard-fail vs warn.\n *\n * @type {Readonly<Record<string, 'A'|'B'>>}\n */\nexport const SEMANTIC_ICON_TIERS = Object.freeze(Object.fromEntries([\n\t...Object.keys(SEMANTIC_ICONS_TIER_A).map((c) => [c, 'A']),\n\t...Object.keys(SEMANTIC_ICONS_TIER_B).map((c) => [c, 'B']),\n]))\n\n/**\n * Canonical MDI name to its Vue component, for every icon in the vocabulary.\n * The rendering components consult this so an app never has to register a\n * vocabulary icon itself.\n *\n * @type {Readonly<Record<string, object>>}\n */\nexport const SEMANTIC_ICON_COMPONENTS = Object.freeze({\n\tAccountArrowRightOutline: AccountArrowRightOutlineIcon,\n\tAccountBoxOutline: AccountBoxOutlineIcon,\n\tAccountGroupOutline: AccountGroupOutlineIcon,\n\tAccountKeyOutline: AccountKeyOutlineIcon,\n\tAccountMinusOutline: AccountMinusOutlineIcon,\n\tAccountMultipleOutline: AccountMultipleOutlineIcon,\n\tAccountOutline: AccountOutlineIcon,\n\tAccountPlusOutline: AccountPlusOutlineIcon,\n\tAccountSchoolOutline: AccountSchoolOutlineIcon,\n\tAccountSearchOutline: AccountSearchOutlineIcon,\n\tAccountStarOutline: AccountStarOutlineIcon,\n\tAccountSwitchOutline: AccountSwitchOutlineIcon,\n\tAccountTieOutline: AccountTieOutlineIcon,\n\tAlertCircleOutline: AlertCircleOutlineIcon,\n\tApi: ApiIcon,\n\tApplicationOutline: ApplicationOutlineIcon,\n\tBankOutline: BankOutlineIcon,\n\tBankTransfer: BankTransferIcon,\n\tBellOutline: BellOutlineIcon,\n\tBookOpenPageVariantOutline: BookOpenPageVariantOutlineIcon,\n\tBookOpenVariantOutline: BookOpenVariantOutlineIcon,\n\tBookshelf: BookshelfIcon,\n\tBrain: BrainIcon,\n\tBriefcaseOutline: BriefcaseOutlineIcon,\n\tCalculatorVariantOutline: CalculatorVariantOutlineIcon,\n\tCalendarAccountOutline: CalendarAccountOutlineIcon,\n\tCalendarClockOutline: CalendarClockOutlineIcon,\n\tCalendarOutline: CalendarOutlineIcon,\n\tCalendarRemoveOutline: CalendarRemoveOutlineIcon,\n\tCalendarTextOutline: CalendarTextOutlineIcon,\n\tCalendarWeekendOutline: CalendarWeekendOutlineIcon,\n\tCarOutline: CarOutlineIcon,\n\tCartArrowDown: CartArrowDownIcon,\n\tCartOutline: CartOutlineIcon,\n\tCashSync: CashSyncIcon,\n\tCertificateOutline: CertificateOutlineIcon,\n\tChartBar: ChartBarIcon,\n\tChartBoxOutline: ChartBoxOutlineIcon,\n\tChartLineVariant: ChartLineVariantIcon,\n\tChartSankey: ChartSankeyIcon,\n\tChartTimelineVariant: ChartTimelineVariantIcon,\n\tCheckCircleOutline: CheckCircleOutlineIcon,\n\tCheckDecagramOutline: CheckDecagramOutlineIcon,\n\tCheckboxMarkedCircleOutline: CheckboxMarkedCircleOutlineIcon,\n\tClipboardAccountOutline: ClipboardAccountOutlineIcon,\n\tClipboardCheckOutline: ClipboardCheckOutlineIcon,\n\tClipboardListOutline: ClipboardListOutlineIcon,\n\tClipboardPulseOutline: ClipboardPulseOutlineIcon,\n\tClipboardTextOutline: ClipboardTextOutlineIcon,\n\tClockAlertOutline: ClockAlertOutlineIcon,\n\tClockCheckOutline: ClockCheckOutlineIcon,\n\tClockOutline: ClockOutlineIcon,\n\tCloseCircleOutline: CloseCircleOutlineIcon,\n\tCloudUploadOutline: CloudUploadOutlineIcon,\n\tCogOutline: CogOutlineIcon,\n\tCommentOutline: CommentOutlineIcon,\n\tCommentQuestionOutline: CommentQuestionOutlineIcon,\n\tContentCopy: ContentCopyIcon,\n\tContentSave: ContentSaveIcon,\n\tCreditCardOutline: CreditCardOutlineIcon,\n\tCubeOutline: CubeOutlineIcon,\n\tCurrencyEur: CurrencyEurIcon,\n\tDatabaseArrowRightOutline: DatabaseArrowRightOutlineIcon,\n\tDatabaseExportOutline: DatabaseExportOutlineIcon,\n\tDatabaseImportOutline: DatabaseImportOutlineIcon,\n\tDatabaseOutline: DatabaseOutlineIcon,\n\tDeleteOutline: DeleteOutlineIcon,\n\tDesktopTowerMonitor: DesktopTowerMonitorIcon,\n\tDomain: DomainIcon,\n\tDotsHorizontal: DotsHorizontalIcon,\n\tDownload: DownloadIcon,\n\tEmailOutline: EmailOutlineIcon,\n\tEyeOffOutline: EyeOffOutlineIcon,\n\tEyeOutline: EyeOutlineIcon,\n\tFileAlertOutline: FileAlertOutlineIcon,\n\tFileChartOutline: FileChartOutlineIcon,\n\tFileCheckOutline: FileCheckOutlineIcon,\n\tFileDocumentMultipleOutline: FileDocumentMultipleOutlineIcon,\n\tFileDocumentOutline: FileDocumentOutlineIcon,\n\tFileLockOutline: FileLockOutlineIcon,\n\tFileReplaceOutline: FileReplaceOutlineIcon,\n\tFileSign: FileSignIcon,\n\tFileTreeOutline: FileTreeOutlineIcon,\n\tFilterVariant: FilterVariantIcon,\n\tFolderAccountOutline: FolderAccountOutlineIcon,\n\tFolderCogOutline: FolderCogOutlineIcon,\n\tFolderOutline: FolderOutlineIcon,\n\tFormatListChecks: FormatListChecksIcon,\n\tForumOutline: ForumOutlineIcon,\n\tGauge: GaugeIcon,\n\tGavel: GavelIcon,\n\tHandHeartOutline: HandHeartOutlineIcon,\n\tHandshakeOutline: HandshakeOutlineIcon,\n\tHistory: HistoryIcon,\n\tImageOutline: ImageOutlineIcon,\n\tInformationOutline: InformationOutlineIcon,\n\tKeyOutline: KeyOutlineIcon,\n\tLayersOutline: LayersOutlineIcon,\n\tLinkVariant: LinkVariantIcon,\n\tLockOutline: LockOutlineIcon,\n\tMagnify: MagnifyIcon,\n\tMapMarkerOutline: MapMarkerOutlineIcon,\n\tMapMarkerPath: MapMarkerPathIcon,\n\tMapOutline: MapOutlineIcon,\n\tMedalOutline: MedalOutlineIcon,\n\tMessageTextOutline: MessageTextOutlineIcon,\n\tNotebookOutline: NotebookOutlineIcon,\n\tOfficeBuildingOutline: OfficeBuildingOutlineIcon,\n\tOpenInNew: OpenInNewIcon,\n\tPackageVariantClosed: PackageVariantClosedIcon,\n\tPaperclip: PaperclipIcon,\n\tPencilOutline: PencilOutlineIcon,\n\tPercentOutline: PercentOutlineIcon,\n\tPlayCircleOutline: PlayCircleOutlineIcon,\n\tPlayOutline: PlayOutlineIcon,\n\tPlus: PlusIcon,\n\tPrinterOutline: PrinterOutlineIcon,\n\tPulse: PulseIcon,\n\tPuzzleOutline: PuzzleOutlineIcon,\n\tReceiptOutline: ReceiptOutlineIcon,\n\tReceiptTextOutline: ReceiptTextOutlineIcon,\n\tRefresh: RefreshIcon,\n\tRobotOutline: RobotOutlineIcon,\n\tScaleBalance: ScaleBalanceIcon,\n\tSchoolOutline: SchoolOutlineIcon,\n\tShareVariantOutline: ShareVariantOutlineIcon,\n\tShieldAccountOutline: ShieldAccountOutlineIcon,\n\tShieldAlertOutline: ShieldAlertOutlineIcon,\n\tShieldCheckOutline: ShieldCheckOutlineIcon,\n\tShieldCrownOutline: ShieldCrownOutlineIcon,\n\tShieldKeyOutline: ShieldKeyOutlineIcon,\n\tShieldLockOutline: ShieldLockOutlineIcon,\n\tShieldOutline: ShieldOutlineIcon,\n\tSignatureFreehand: SignatureFreehandIcon,\n\tSitemapOutline: SitemapOutlineIcon,\n\tSourceBranch: SourceBranchIcon,\n\tSpeedometer: SpeedometerIcon,\n\tStoreOutline: StoreOutlineIcon,\n\tSwapHorizontal: SwapHorizontalIcon,\n\tTableClock: TableClockIcon,\n\tTagOutline: TagOutlineIcon,\n\tTextBoxOutline: TextBoxOutlineIcon,\n\tToolboxOutline: ToolboxOutlineIcon,\n\tTransitConnectionVariant: TransitConnectionVariantIcon,\n\tTrayFull: TrayFullIcon,\n\tTrendingUp: TrendingUpIcon,\n\tUpload: UploadIcon,\n\tVectorPolylinePlus: VectorPolylinePlusIcon,\n\tViewColumnOutline: ViewColumnOutlineIcon,\n\tViewDashboardOutline: ViewDashboardOutlineIcon,\n\tViewGridOutline: ViewGridOutlineIcon,\n\tWarehouse: WarehouseIcon,\n\tWebhook: WebhookIcon,\n})\n\n/**\n * Reverse lookup — the concept a canonical icon name stands for.\n *\n * @param {string} name Canonical MDI icon name.\n * @return {string|null} The concept slug, or null when the name is not in the\n * vocabulary.\n */\nexport function conceptForIcon(name) {\n\tfor (const [concept, icon] of Object.entries(SEMANTIC_ICONS)) {\n\t\tif (icon === name) {\n\t\t\treturn concept\n\t\t}\n\t}\n\treturn null\n}\n\n/**\n * Resolve a vocabulary icon name to its component.\n *\n * @param {string|null|undefined} name Canonical MDI icon name.\n * @return {object|null} The Vue component, or null when not in the vocabulary.\n */\nexport function getSemanticIconComponent(name) {\n\tif (typeof name !== 'string' || name.length === 0) {\n\t\treturn null\n\t}\n\treturn SEMANTIC_ICON_COMPONENTS[name] ?? null\n}\n"],"names":["AccountGroupOutlineIcon","AccountOutlineIcon","AlertCircleOutlineIcon","BellOutlineIcon","BriefcaseOutlineIcon","CalendarClockOutlineIcon","CalendarOutlineIcon","ChartBarIcon","CheckCircleOutlineIcon","ClipboardCheckOutlineIcon","ClipboardListOutlineIcon","ClockOutlineIcon","CloseCircleOutlineIcon","CogOutlineIcon","CommentOutlineIcon","ContentCopyIcon","ContentSaveIcon","CurrencyEurIcon","DatabaseOutlineIcon","DomainIcon","DotsHorizontalIcon","DownloadIcon","EmailOutlineIcon","EyeOutlineIcon","FileDocumentOutlineIcon","FolderAccountOutlineIcon","FolderOutlineIcon","FormatListChecksIcon","HistoryIcon","InformationOutlineIcon","LinkVariantIcon","LockOutlineIcon","MagnifyIcon","MapMarkerOutlineIcon","MapOutlineIcon","OpenInNewIcon","PackageVariantClosedIcon","PaperclipIcon","PlayCircleOutlineIcon","PlusIcon","PulseIcon","RefreshIcon","ShareVariantOutlineIcon","ShieldAccountOutlineIcon","ShieldKeyOutlineIcon","ShieldOutlineIcon","SitemapOutlineIcon","TagOutlineIcon","UploadIcon","ViewColumnOutlineIcon","ViewDashboardOutlineIcon","ViewGridOutlineIcon"],"mappings":"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"}
1
+ {"version":3,"file":"semanticIcons.js","sources":["../../../../src/components/CnIcon/semanticIcons.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * semanticIcons — the fleet-wide semantic icon vocabulary (ADR-077).\n *\n * One concept, one icon. A manifest `icon` field holds an MDI PascalCase name;\n * this table is what makes the same concept read the same way in every\n * Conduction app (Store is always StoreOutline, Dashboard is always\n * ViewDashboardOutline). The mapping is a BIJECTION — no concept has two\n * icons and no icon serves two concepts — which is what stops the historical\n * overloading (one glyph standing for 18 unrelated things).\n *\n * Tier A is universal chrome every app has and MUST match. Tier B is the\n * shared domain vocabulary an app SHOULD use when it has the concept.\n *\n * WHY THIS IS A PURE EXPORT AND NOT AN import-time `registerIcons()` CALL:\n * the published dist's `sideEffects` allowlist has previously tree-shaken\n * import-time side effects out of consumer bundles, which fails SILENTLY\n * (nothing renders, no error). So the rendering components import\n * {@link SEMANTIC_ICON_COMPONENTS} and consult it directly — resolution is\n * guaranteed by the component that needs it, with no side-effect ordering to\n * get wrong and nothing for a bundler to drop.\n *\n * Every name below is verified to exist in `vue-material-design-icons` by\n * tests/components/semanticIcons.spec.js — the check that caught invented\n * names like `LedgerOutline` and `FileSignOutline` already live in manifests.\n *\n * Each icon is imported individually (no wildcard / barrel) so the bundle\n * stays tree-shake-friendly.\n *\n * @spec openspec/architecture/adr-077-semantic-icon-vocabulary.md\n */\n\nimport AccountArrowRightOutlineIcon from 'vue-material-design-icons/AccountArrowRightOutline.vue'\nimport AccountBoxOutlineIcon from 'vue-material-design-icons/AccountBoxOutline.vue'\nimport AccountGroupOutlineIcon from 'vue-material-design-icons/AccountGroupOutline.vue'\nimport AccountKeyOutlineIcon from 'vue-material-design-icons/AccountKeyOutline.vue'\nimport AccountMinusOutlineIcon from 'vue-material-design-icons/AccountMinusOutline.vue'\nimport AccountMultipleOutlineIcon from 'vue-material-design-icons/AccountMultipleOutline.vue'\nimport AccountOutlineIcon from 'vue-material-design-icons/AccountOutline.vue'\nimport AccountPlusOutlineIcon from 'vue-material-design-icons/AccountPlusOutline.vue'\nimport AccountSchoolOutlineIcon from 'vue-material-design-icons/AccountSchoolOutline.vue'\nimport AccountSearchOutlineIcon from 'vue-material-design-icons/AccountSearchOutline.vue'\nimport AccountStarOutlineIcon from 'vue-material-design-icons/AccountStarOutline.vue'\nimport AccountSwitchOutlineIcon from 'vue-material-design-icons/AccountSwitchOutline.vue'\nimport AccountTieOutlineIcon from 'vue-material-design-icons/AccountTieOutline.vue'\nimport AlertCircleOutlineIcon from 'vue-material-design-icons/AlertCircleOutline.vue'\nimport ApiIcon from 'vue-material-design-icons/Api.vue'\nimport ApplicationOutlineIcon from 'vue-material-design-icons/ApplicationOutline.vue'\nimport BankOutlineIcon from 'vue-material-design-icons/BankOutline.vue'\nimport BankTransferIcon from 'vue-material-design-icons/BankTransfer.vue'\nimport BellOutlineIcon from 'vue-material-design-icons/BellOutline.vue'\nimport BookOpenPageVariantOutlineIcon from 'vue-material-design-icons/BookOpenPageVariantOutline.vue'\nimport BookOpenVariantOutlineIcon from 'vue-material-design-icons/BookOpenVariantOutline.vue'\nimport BookshelfIcon from 'vue-material-design-icons/Bookshelf.vue'\nimport BrainIcon from 'vue-material-design-icons/Brain.vue'\nimport BriefcaseOutlineIcon from 'vue-material-design-icons/BriefcaseOutline.vue'\nimport CalculatorVariantOutlineIcon from 'vue-material-design-icons/CalculatorVariantOutline.vue'\nimport CalendarAccountOutlineIcon from 'vue-material-design-icons/CalendarAccountOutline.vue'\nimport CalendarClockOutlineIcon from 'vue-material-design-icons/CalendarClockOutline.vue'\nimport CalendarOutlineIcon from 'vue-material-design-icons/CalendarOutline.vue'\nimport CalendarRemoveOutlineIcon from 'vue-material-design-icons/CalendarRemoveOutline.vue'\nimport CalendarTextOutlineIcon from 'vue-material-design-icons/CalendarTextOutline.vue'\nimport CalendarWeekendOutlineIcon from 'vue-material-design-icons/CalendarWeekendOutline.vue'\nimport CarOutlineIcon from 'vue-material-design-icons/CarOutline.vue'\nimport CartArrowDownIcon from 'vue-material-design-icons/CartArrowDown.vue'\nimport CartOutlineIcon from 'vue-material-design-icons/CartOutline.vue'\nimport CashSyncIcon from 'vue-material-design-icons/CashSync.vue'\nimport CertificateOutlineIcon from 'vue-material-design-icons/CertificateOutline.vue'\nimport ChartBarIcon from 'vue-material-design-icons/ChartBar.vue'\nimport ChartBoxOutlineIcon from 'vue-material-design-icons/ChartBoxOutline.vue'\nimport ChartLineVariantIcon from 'vue-material-design-icons/ChartLineVariant.vue'\nimport ChartSankeyIcon from 'vue-material-design-icons/ChartSankey.vue'\nimport ChartTimelineVariantIcon from 'vue-material-design-icons/ChartTimelineVariant.vue'\nimport CheckboxMarkedCircleOutlineIcon from 'vue-material-design-icons/CheckboxMarkedCircleOutline.vue'\nimport CheckCircleOutlineIcon from 'vue-material-design-icons/CheckCircleOutline.vue'\nimport CheckDecagramOutlineIcon from 'vue-material-design-icons/CheckDecagramOutline.vue'\nimport ClipboardAccountOutlineIcon from 'vue-material-design-icons/ClipboardAccountOutline.vue'\nimport ClipboardCheckOutlineIcon from 'vue-material-design-icons/ClipboardCheckOutline.vue'\nimport ClipboardListOutlineIcon from 'vue-material-design-icons/ClipboardListOutline.vue'\nimport ClipboardPulseOutlineIcon from 'vue-material-design-icons/ClipboardPulseOutline.vue'\nimport ClipboardTextOutlineIcon from 'vue-material-design-icons/ClipboardTextOutline.vue'\nimport ClockAlertOutlineIcon from 'vue-material-design-icons/ClockAlertOutline.vue'\nimport ClockCheckOutlineIcon from 'vue-material-design-icons/ClockCheckOutline.vue'\nimport ClockOutlineIcon from 'vue-material-design-icons/ClockOutline.vue'\nimport CloseCircleOutlineIcon from 'vue-material-design-icons/CloseCircleOutline.vue'\nimport CloudUploadOutlineIcon from 'vue-material-design-icons/CloudUploadOutline.vue'\nimport CogOutlineIcon from 'vue-material-design-icons/CogOutline.vue'\nimport CommentOutlineIcon from 'vue-material-design-icons/CommentOutline.vue'\nimport CommentQuestionOutlineIcon from 'vue-material-design-icons/CommentQuestionOutline.vue'\nimport ContentCopyIcon from 'vue-material-design-icons/ContentCopy.vue'\nimport ContentSaveIcon from 'vue-material-design-icons/ContentSave.vue'\nimport CreditCardOutlineIcon from 'vue-material-design-icons/CreditCardOutline.vue'\nimport CubeOutlineIcon from 'vue-material-design-icons/CubeOutline.vue'\nimport CurrencyEurIcon from 'vue-material-design-icons/CurrencyEur.vue'\nimport DatabaseArrowRightOutlineIcon from 'vue-material-design-icons/DatabaseArrowRightOutline.vue'\nimport DatabaseExportOutlineIcon from 'vue-material-design-icons/DatabaseExportOutline.vue'\nimport DatabaseImportOutlineIcon from 'vue-material-design-icons/DatabaseImportOutline.vue'\nimport DatabaseOutlineIcon from 'vue-material-design-icons/DatabaseOutline.vue'\nimport DeleteOutlineIcon from 'vue-material-design-icons/DeleteOutline.vue'\nimport DesktopTowerMonitorIcon from 'vue-material-design-icons/DesktopTowerMonitor.vue'\nimport DomainIcon from 'vue-material-design-icons/Domain.vue'\nimport DotsHorizontalIcon from 'vue-material-design-icons/DotsHorizontal.vue'\nimport DownloadIcon from 'vue-material-design-icons/Download.vue'\nimport EmailOutlineIcon from 'vue-material-design-icons/EmailOutline.vue'\nimport EyeOffOutlineIcon from 'vue-material-design-icons/EyeOffOutline.vue'\nimport EyeOutlineIcon from 'vue-material-design-icons/EyeOutline.vue'\nimport FileAlertOutlineIcon from 'vue-material-design-icons/FileAlertOutline.vue'\nimport FileChartOutlineIcon from 'vue-material-design-icons/FileChartOutline.vue'\nimport FileCheckOutlineIcon from 'vue-material-design-icons/FileCheckOutline.vue'\nimport FileDocumentMultipleOutlineIcon from 'vue-material-design-icons/FileDocumentMultipleOutline.vue'\nimport FileDocumentOutlineIcon from 'vue-material-design-icons/FileDocumentOutline.vue'\nimport FileLockOutlineIcon from 'vue-material-design-icons/FileLockOutline.vue'\nimport FileReplaceOutlineIcon from 'vue-material-design-icons/FileReplaceOutline.vue'\nimport FileSignIcon from 'vue-material-design-icons/FileSign.vue'\nimport FileTreeOutlineIcon from 'vue-material-design-icons/FileTreeOutline.vue'\nimport FilterVariantIcon from 'vue-material-design-icons/FilterVariant.vue'\nimport FolderAccountOutlineIcon from 'vue-material-design-icons/FolderAccountOutline.vue'\nimport FolderCogOutlineIcon from 'vue-material-design-icons/FolderCogOutline.vue'\nimport FolderOutlineIcon from 'vue-material-design-icons/FolderOutline.vue'\nimport FormatListChecksIcon from 'vue-material-design-icons/FormatListChecks.vue'\nimport ForumOutlineIcon from 'vue-material-design-icons/ForumOutline.vue'\nimport GaugeIcon from 'vue-material-design-icons/Gauge.vue'\nimport GavelIcon from 'vue-material-design-icons/Gavel.vue'\nimport HandHeartOutlineIcon from 'vue-material-design-icons/HandHeartOutline.vue'\nimport HandshakeOutlineIcon from 'vue-material-design-icons/HandshakeOutline.vue'\nimport HistoryIcon from 'vue-material-design-icons/History.vue'\nimport ImageOutlineIcon from 'vue-material-design-icons/ImageOutline.vue'\nimport InformationOutlineIcon from 'vue-material-design-icons/InformationOutline.vue'\nimport KeyOutlineIcon from 'vue-material-design-icons/KeyOutline.vue'\nimport LayersOutlineIcon from 'vue-material-design-icons/LayersOutline.vue'\nimport LinkVariantIcon from 'vue-material-design-icons/LinkVariant.vue'\nimport LockOutlineIcon from 'vue-material-design-icons/LockOutline.vue'\nimport MagnifyIcon from 'vue-material-design-icons/Magnify.vue'\nimport MapMarkerOutlineIcon from 'vue-material-design-icons/MapMarkerOutline.vue'\nimport MapMarkerPathIcon from 'vue-material-design-icons/MapMarkerPath.vue'\nimport MapOutlineIcon from 'vue-material-design-icons/MapOutline.vue'\nimport MedalOutlineIcon from 'vue-material-design-icons/MedalOutline.vue'\nimport MessageTextOutlineIcon from 'vue-material-design-icons/MessageTextOutline.vue'\nimport NotebookOutlineIcon from 'vue-material-design-icons/NotebookOutline.vue'\nimport OfficeBuildingOutlineIcon from 'vue-material-design-icons/OfficeBuildingOutline.vue'\nimport OpenInNewIcon from 'vue-material-design-icons/OpenInNew.vue'\nimport PackageVariantClosedIcon from 'vue-material-design-icons/PackageVariantClosed.vue'\nimport PaperclipIcon from 'vue-material-design-icons/Paperclip.vue'\nimport PencilOutlineIcon from 'vue-material-design-icons/PencilOutline.vue'\nimport PercentOutlineIcon from 'vue-material-design-icons/PercentOutline.vue'\nimport PlayCircleOutlineIcon from 'vue-material-design-icons/PlayCircleOutline.vue'\nimport PlayOutlineIcon from 'vue-material-design-icons/PlayOutline.vue'\nimport PlusIcon from 'vue-material-design-icons/Plus.vue'\nimport PrinterOutlineIcon from 'vue-material-design-icons/PrinterOutline.vue'\nimport PulseIcon from 'vue-material-design-icons/Pulse.vue'\nimport PuzzleOutlineIcon from 'vue-material-design-icons/PuzzleOutline.vue'\nimport ReceiptOutlineIcon from 'vue-material-design-icons/ReceiptOutline.vue'\nimport ReceiptTextOutlineIcon from 'vue-material-design-icons/ReceiptTextOutline.vue'\nimport RefreshIcon from 'vue-material-design-icons/Refresh.vue'\nimport RobotOutlineIcon from 'vue-material-design-icons/RobotOutline.vue'\nimport ScaleBalanceIcon from 'vue-material-design-icons/ScaleBalance.vue'\nimport SchoolOutlineIcon from 'vue-material-design-icons/SchoolOutline.vue'\nimport ShareVariantOutlineIcon from 'vue-material-design-icons/ShareVariantOutline.vue'\nimport ShieldAccountOutlineIcon from 'vue-material-design-icons/ShieldAccountOutline.vue'\nimport ShieldAlertOutlineIcon from 'vue-material-design-icons/ShieldAlertOutline.vue'\nimport ShieldCheckOutlineIcon from 'vue-material-design-icons/ShieldCheckOutline.vue'\nimport ShieldCrownOutlineIcon from 'vue-material-design-icons/ShieldCrownOutline.vue'\nimport ShieldKeyOutlineIcon from 'vue-material-design-icons/ShieldKeyOutline.vue'\nimport ShieldLockOutlineIcon from 'vue-material-design-icons/ShieldLockOutline.vue'\nimport ShieldOutlineIcon from 'vue-material-design-icons/ShieldOutline.vue'\nimport SignatureFreehandIcon from 'vue-material-design-icons/SignatureFreehand.vue'\nimport SitemapOutlineIcon from 'vue-material-design-icons/SitemapOutline.vue'\nimport SourceBranchIcon from 'vue-material-design-icons/SourceBranch.vue'\nimport SpeedometerIcon from 'vue-material-design-icons/Speedometer.vue'\nimport StoreOutlineIcon from 'vue-material-design-icons/StoreOutline.vue'\nimport SwapHorizontalIcon from 'vue-material-design-icons/SwapHorizontal.vue'\nimport TableClockIcon from 'vue-material-design-icons/TableClock.vue'\nimport TagOutlineIcon from 'vue-material-design-icons/TagOutline.vue'\nimport TextBoxOutlineIcon from 'vue-material-design-icons/TextBoxOutline.vue'\nimport ToolboxOutlineIcon from 'vue-material-design-icons/ToolboxOutline.vue'\nimport TransitConnectionVariantIcon from 'vue-material-design-icons/TransitConnectionVariant.vue'\nimport TrayFullIcon from 'vue-material-design-icons/TrayFull.vue'\nimport TrendingUpIcon from 'vue-material-design-icons/TrendingUp.vue'\nimport UploadIcon from 'vue-material-design-icons/Upload.vue'\nimport VectorPolylinePlusIcon from 'vue-material-design-icons/VectorPolylinePlus.vue'\nimport ViewColumnOutlineIcon from 'vue-material-design-icons/ViewColumnOutline.vue'\nimport ViewDashboardOutlineIcon from 'vue-material-design-icons/ViewDashboardOutline.vue'\nimport ViewGridOutlineIcon from 'vue-material-design-icons/ViewGridOutline.vue'\nimport WarehouseIcon from 'vue-material-design-icons/Warehouse.vue'\nimport WebhookIcon from 'vue-material-design-icons/Webhook.vue'\n\n/**\n * Tier A — universal chrome. An app that has the concept MUST use this icon.\n *\n * @type {Readonly<Record<string, string>>}\n */\nexport const SEMANTIC_ICONS_TIER_A = Object.freeze({\n\tdashboard: 'ViewDashboardOutline',\n\tdocumentation: 'BookOpenVariantOutline',\n\t'features-roadmap': 'MapMarkerPath',\n\tsettings: 'CogOutline',\n\tadmin: 'ShieldAccountOutline',\n\tsearch: 'Magnify',\n\tstore: 'StoreOutline',\n\ttutorial: 'PlayCircleOutline',\n\tabout: 'InformationOutline',\n\tnotifications: 'BellOutline',\n\tactivity: 'Pulse',\n\t'audit-trail': 'History',\n\t'my-work': 'ClipboardAccountOutline',\n})\n\n/**\n * Tier B — shared domain vocabulary. An app SHOULD use this icon when it has\n * the concept; a genuinely new concept is added here, never invented locally.\n *\n * @type {Readonly<Record<string, string>>}\n */\nexport const SEMANTIC_ICONS_TIER_B = Object.freeze({\n\t// data & records\n\tdata: 'DatabaseOutline',\n\tschema: 'FileTreeOutline',\n\trecord: 'CubeOutline',\n\t'data-quality': 'ClipboardPulseOutline',\n\timport: 'DatabaseImportOutline',\n\texport: 'DatabaseExportOutline',\n\tmigration: 'DatabaseArrowRightOutline',\n\tmapping: 'SwapHorizontal',\n\tlog: 'TextBoxOutline',\n\tjob: 'ClockOutline',\n\t// documents & files\n\tdocument: 'FileDocumentOutline',\n\tdocuments: 'FileDocumentMultipleOutline',\n\tfolder: 'FolderOutline',\n\ttemplate: 'FileReplaceOutline',\n\tcatalogue: 'Bookshelf',\n\tsigning: 'SignatureFreehand',\n\tcontract: 'FileSign',\n\tcorrespondence: 'EmailOutline',\n\tattachment: 'Paperclip',\n\t// cases & process\n\tcase: 'FolderAccountOutline',\n\t'case-type': 'FolderCogOutline',\n\ttask: 'CheckboxMarkedCircleOutline',\n\ttasks: 'FormatListChecks',\n\tworkflow: 'SitemapOutline',\n\tboard: 'ViewColumnOutline',\n\tapproval: 'CheckDecagramOutline',\n\tdecision: 'Gavel',\n\tqueue: 'TrayFull',\n\tdeadline: 'ClockAlertOutline',\n\tobjection: 'FileAlertOutline',\n\tappeal: 'ScaleBalance',\n\t// communication\n\tchat: 'MessageTextOutline',\n\tcomment: 'CommentOutline',\n\tmeeting: 'CalendarAccountOutline',\n\tagenda: 'CalendarTextOutline',\n\tappointment: 'CalendarClockOutline',\n\tcalendar: 'CalendarOutline',\n\tconsultation: 'CommentQuestionOutline',\n\tforum: 'ForumOutline',\n\t// people & organisations\n\tperson: 'AccountOutline',\n\tpeople: 'AccountMultipleOutline',\n\tgroup: 'AccountGroupOutline',\n\trole: 'AccountKeyOutline',\n\torganisation: 'OfficeBuildingOutline',\n\t'organisation-unit': 'Domain',\n\tpartner: 'HandshakeOutline',\n\tclient: 'AccountStarOutline',\n\temployee: 'AccountTieOutline',\n\tlead: 'AccountArrowRightOutline',\n\tprospect: 'AccountSearchOutline',\n\tsubstitution: 'AccountSwitchOutline',\n\t// commerce & finance\n\tsales: 'CartOutline',\n\tpurchasing: 'CartArrowDown',\n\tproduct: 'PackageVariantClosed',\n\tinventory: 'Warehouse',\n\torder: 'ClipboardListOutline',\n\tinvoice: 'ReceiptTextOutline',\n\tpayment: 'CreditCardOutline',\n\tpayroll: 'CashSync',\n\texpense: 'ReceiptOutline',\n\tbank: 'BankOutline',\n\t'bank-transaction': 'BankTransfer',\n\tbookkeeping: 'NotebookOutline',\n\ttax: 'PercentOutline',\n\tbudget: 'CalculatorVariantOutline',\n\tforecast: 'ChartTimelineVariant',\n\trevenue: 'CurrencyEur',\n\tpricing: 'TagOutline',\n\tsubsidy: 'HandHeartOutline',\n\t// reporting & monitoring\n\treport: 'FileChartOutline',\n\treporting: 'ChartBoxOutline',\n\tanalytics: 'ChartLineVariant',\n\tkpi: 'Speedometer',\n\tmonitoring: 'Gauge',\n\tstatistics: 'ChartBar',\n\t'process-mining': 'ChartSankey',\n\t// security & compliance\n\tsecurity: 'ShieldOutline',\n\tcompliance: 'ClipboardCheckOutline',\n\tpolicy: 'ShieldCheckOutline',\n\tvulnerability: 'ShieldAlertOutline',\n\tcertificate: 'CertificateOutline',\n\tvault: 'LockOutline',\n\tkey: 'KeyOutline',\n\tauthorization: 'ShieldKeyOutline',\n\tprivacy: 'ShieldLockOutline',\n\tanonymization: 'EyeOffOutline',\n\tconsent: 'FileCheckOutline',\n\tconfidentiality: 'FileLockOutline',\n\tretention: 'CalendarRemoveOutline',\n\tgovernance: 'ShieldCrownOutline',\n\t// integration & technology\n\tintegration: 'Api',\n\tconnection: 'TransitConnectionVariant',\n\twebhook: 'Webhook',\n\tautomation: 'VectorPolylinePlus',\n\tagent: 'RobotOutline',\n\tai: 'Brain',\n\ttool: 'ToolboxOutline',\n\tapps: 'ViewGridOutline',\n\tmodule: 'PuzzleOutline',\n\tsource: 'SourceBranch',\n\t// location & geo\n\tlocation: 'MapMarkerOutline',\n\tmap: 'MapOutline',\n\t'map-layer': 'LayersOutline',\n\t// learning\n\tcourse: 'BookOpenPageVariantOutline',\n\tlearning: 'SchoolOutline',\n\tcompetency: 'MedalOutline',\n\ttimetable: 'TableClock',\n\tprogress: 'TrendingUp',\n\tportfolio: 'BriefcaseOutline',\n\texam: 'ClipboardTextOutline',\n\tstudent: 'AccountSchoolOutline',\n\t// Publish, Test connection).\n\tview: 'EyeOutline',\n\tcreate: 'Plus',\n\tedit: 'PencilOutline',\n\tdelete: 'DeleteOutline',\n\trun: 'PlayOutline',\n\ttest: 'CheckCircleOutline',\n\tupload: 'Upload',\n\tpublish: 'CloudUploadOutline',\n\tdownload: 'Download',\n\trefresh: 'Refresh',\n\t'open-external': 'OpenInNew',\n\tcopy: 'ContentCopy',\n\tshare: 'ShareVariantOutline',\n\tfilter: 'FilterVariant',\n\tprint: 'PrinterOutline',\n\timage: 'ImageOutline',\n\tlink: 'LinkVariant',\n\tmore: 'DotsHorizontal',\n\tsave: 'ContentSave',\n\tcancel: 'CloseCircleOutline',\n\talert: 'AlertCircleOutline',\n\t// hr\n\tleave: 'CalendarWeekendOutline',\n\thours: 'ClockCheckOutline',\n\tonboarding: 'AccountPlusOutline',\n\toffboarding: 'AccountMinusOutline',\n\tvacancy: 'AccountBoxOutline',\n\tasset: 'DesktopTowerMonitor',\n\tfleet: 'CarOutline',\n})\n\n/**\n * The whole vocabulary — concept slug to canonical MDI name.\n *\n * @type {Readonly<Record<string, string>>}\n */\nexport const SEMANTIC_ICONS = Object.freeze({\n\t...SEMANTIC_ICONS_TIER_A,\n\t...SEMANTIC_ICONS_TIER_B,\n})\n\n/**\n * Which tier a concept belongs to — `'A'` (MUST) or `'B'` (SHOULD). Consumed by\n * hydra's icon-vocabulary gate to decide hard-fail vs warn.\n *\n * @type {Readonly<Record<string, 'A'|'B'>>}\n */\nexport const SEMANTIC_ICON_TIERS = Object.freeze(Object.fromEntries([\n\t...Object.keys(SEMANTIC_ICONS_TIER_A).map((c) => [c, 'A']),\n\t...Object.keys(SEMANTIC_ICONS_TIER_B).map((c) => [c, 'B']),\n]))\n\n/**\n * Canonical MDI name to its Vue component, for every icon in the vocabulary.\n * The rendering components consult this so an app never has to register a\n * vocabulary icon itself.\n *\n * @type {Readonly<Record<string, object>>}\n */\nexport const SEMANTIC_ICON_COMPONENTS = Object.freeze({\n\tAccountArrowRightOutline: AccountArrowRightOutlineIcon,\n\tAccountBoxOutline: AccountBoxOutlineIcon,\n\tAccountGroupOutline: AccountGroupOutlineIcon,\n\tAccountKeyOutline: AccountKeyOutlineIcon,\n\tAccountMinusOutline: AccountMinusOutlineIcon,\n\tAccountMultipleOutline: AccountMultipleOutlineIcon,\n\tAccountOutline: AccountOutlineIcon,\n\tAccountPlusOutline: AccountPlusOutlineIcon,\n\tAccountSchoolOutline: AccountSchoolOutlineIcon,\n\tAccountSearchOutline: AccountSearchOutlineIcon,\n\tAccountStarOutline: AccountStarOutlineIcon,\n\tAccountSwitchOutline: AccountSwitchOutlineIcon,\n\tAccountTieOutline: AccountTieOutlineIcon,\n\tAlertCircleOutline: AlertCircleOutlineIcon,\n\tApi: ApiIcon,\n\tApplicationOutline: ApplicationOutlineIcon,\n\tBankOutline: BankOutlineIcon,\n\tBankTransfer: BankTransferIcon,\n\tBellOutline: BellOutlineIcon,\n\tBookOpenPageVariantOutline: BookOpenPageVariantOutlineIcon,\n\tBookOpenVariantOutline: BookOpenVariantOutlineIcon,\n\tBookshelf: BookshelfIcon,\n\tBrain: BrainIcon,\n\tBriefcaseOutline: BriefcaseOutlineIcon,\n\tCalculatorVariantOutline: CalculatorVariantOutlineIcon,\n\tCalendarAccountOutline: CalendarAccountOutlineIcon,\n\tCalendarClockOutline: CalendarClockOutlineIcon,\n\tCalendarOutline: CalendarOutlineIcon,\n\tCalendarRemoveOutline: CalendarRemoveOutlineIcon,\n\tCalendarTextOutline: CalendarTextOutlineIcon,\n\tCalendarWeekendOutline: CalendarWeekendOutlineIcon,\n\tCarOutline: CarOutlineIcon,\n\tCartArrowDown: CartArrowDownIcon,\n\tCartOutline: CartOutlineIcon,\n\tCashSync: CashSyncIcon,\n\tCertificateOutline: CertificateOutlineIcon,\n\tChartBar: ChartBarIcon,\n\tChartBoxOutline: ChartBoxOutlineIcon,\n\tChartLineVariant: ChartLineVariantIcon,\n\tChartSankey: ChartSankeyIcon,\n\tChartTimelineVariant: ChartTimelineVariantIcon,\n\tCheckCircleOutline: CheckCircleOutlineIcon,\n\tCheckDecagramOutline: CheckDecagramOutlineIcon,\n\tCheckboxMarkedCircleOutline: CheckboxMarkedCircleOutlineIcon,\n\tClipboardAccountOutline: ClipboardAccountOutlineIcon,\n\tClipboardCheckOutline: ClipboardCheckOutlineIcon,\n\tClipboardListOutline: ClipboardListOutlineIcon,\n\tClipboardPulseOutline: ClipboardPulseOutlineIcon,\n\tClipboardTextOutline: ClipboardTextOutlineIcon,\n\tClockAlertOutline: ClockAlertOutlineIcon,\n\tClockCheckOutline: ClockCheckOutlineIcon,\n\tClockOutline: ClockOutlineIcon,\n\tCloseCircleOutline: CloseCircleOutlineIcon,\n\tCloudUploadOutline: CloudUploadOutlineIcon,\n\tCogOutline: CogOutlineIcon,\n\tCommentOutline: CommentOutlineIcon,\n\tCommentQuestionOutline: CommentQuestionOutlineIcon,\n\tContentCopy: ContentCopyIcon,\n\tContentSave: ContentSaveIcon,\n\tCreditCardOutline: CreditCardOutlineIcon,\n\tCubeOutline: CubeOutlineIcon,\n\tCurrencyEur: CurrencyEurIcon,\n\tDatabaseArrowRightOutline: DatabaseArrowRightOutlineIcon,\n\tDatabaseExportOutline: DatabaseExportOutlineIcon,\n\tDatabaseImportOutline: DatabaseImportOutlineIcon,\n\tDatabaseOutline: DatabaseOutlineIcon,\n\tDeleteOutline: DeleteOutlineIcon,\n\tDesktopTowerMonitor: DesktopTowerMonitorIcon,\n\tDomain: DomainIcon,\n\tDotsHorizontal: DotsHorizontalIcon,\n\tDownload: DownloadIcon,\n\tEmailOutline: EmailOutlineIcon,\n\tEyeOffOutline: EyeOffOutlineIcon,\n\tEyeOutline: EyeOutlineIcon,\n\tFileAlertOutline: FileAlertOutlineIcon,\n\tFileChartOutline: FileChartOutlineIcon,\n\tFileCheckOutline: FileCheckOutlineIcon,\n\tFileDocumentMultipleOutline: FileDocumentMultipleOutlineIcon,\n\tFileDocumentOutline: FileDocumentOutlineIcon,\n\tFileLockOutline: FileLockOutlineIcon,\n\tFileReplaceOutline: FileReplaceOutlineIcon,\n\tFileSign: FileSignIcon,\n\tFileTreeOutline: FileTreeOutlineIcon,\n\tFilterVariant: FilterVariantIcon,\n\tFolderAccountOutline: FolderAccountOutlineIcon,\n\tFolderCogOutline: FolderCogOutlineIcon,\n\tFolderOutline: FolderOutlineIcon,\n\tFormatListChecks: FormatListChecksIcon,\n\tForumOutline: ForumOutlineIcon,\n\tGauge: GaugeIcon,\n\tGavel: GavelIcon,\n\tHandHeartOutline: HandHeartOutlineIcon,\n\tHandshakeOutline: HandshakeOutlineIcon,\n\tHistory: HistoryIcon,\n\tImageOutline: ImageOutlineIcon,\n\tInformationOutline: InformationOutlineIcon,\n\tKeyOutline: KeyOutlineIcon,\n\tLayersOutline: LayersOutlineIcon,\n\tLinkVariant: LinkVariantIcon,\n\tLockOutline: LockOutlineIcon,\n\tMagnify: MagnifyIcon,\n\tMapMarkerOutline: MapMarkerOutlineIcon,\n\tMapMarkerPath: MapMarkerPathIcon,\n\tMapOutline: MapOutlineIcon,\n\tMedalOutline: MedalOutlineIcon,\n\tMessageTextOutline: MessageTextOutlineIcon,\n\tNotebookOutline: NotebookOutlineIcon,\n\tOfficeBuildingOutline: OfficeBuildingOutlineIcon,\n\tOpenInNew: OpenInNewIcon,\n\tPackageVariantClosed: PackageVariantClosedIcon,\n\tPaperclip: PaperclipIcon,\n\tPencilOutline: PencilOutlineIcon,\n\tPercentOutline: PercentOutlineIcon,\n\tPlayCircleOutline: PlayCircleOutlineIcon,\n\tPlayOutline: PlayOutlineIcon,\n\tPlus: PlusIcon,\n\tPrinterOutline: PrinterOutlineIcon,\n\tPulse: PulseIcon,\n\tPuzzleOutline: PuzzleOutlineIcon,\n\tReceiptOutline: ReceiptOutlineIcon,\n\tReceiptTextOutline: ReceiptTextOutlineIcon,\n\tRefresh: RefreshIcon,\n\tRobotOutline: RobotOutlineIcon,\n\tScaleBalance: ScaleBalanceIcon,\n\tSchoolOutline: SchoolOutlineIcon,\n\tShareVariantOutline: ShareVariantOutlineIcon,\n\tShieldAccountOutline: ShieldAccountOutlineIcon,\n\tShieldAlertOutline: ShieldAlertOutlineIcon,\n\tShieldCheckOutline: ShieldCheckOutlineIcon,\n\tShieldCrownOutline: ShieldCrownOutlineIcon,\n\tShieldKeyOutline: ShieldKeyOutlineIcon,\n\tShieldLockOutline: ShieldLockOutlineIcon,\n\tShieldOutline: ShieldOutlineIcon,\n\tSignatureFreehand: SignatureFreehandIcon,\n\tSitemapOutline: SitemapOutlineIcon,\n\tSourceBranch: SourceBranchIcon,\n\tSpeedometer: SpeedometerIcon,\n\tStoreOutline: StoreOutlineIcon,\n\tSwapHorizontal: SwapHorizontalIcon,\n\tTableClock: TableClockIcon,\n\tTagOutline: TagOutlineIcon,\n\tTextBoxOutline: TextBoxOutlineIcon,\n\tToolboxOutline: ToolboxOutlineIcon,\n\tTransitConnectionVariant: TransitConnectionVariantIcon,\n\tTrayFull: TrayFullIcon,\n\tTrendingUp: TrendingUpIcon,\n\tUpload: UploadIcon,\n\tVectorPolylinePlus: VectorPolylinePlusIcon,\n\tViewColumnOutline: ViewColumnOutlineIcon,\n\tViewDashboardOutline: ViewDashboardOutlineIcon,\n\tViewGridOutline: ViewGridOutlineIcon,\n\tWarehouse: WarehouseIcon,\n\tWebhook: WebhookIcon,\n})\n\n/**\n * Reverse lookup — the concept a canonical icon name stands for.\n *\n * @param {string} name Canonical MDI icon name.\n * @return {string|null} The concept slug, or null when the name is not in the\n * vocabulary.\n */\nexport function conceptForIcon(name) {\n\tfor (const [concept, icon] of Object.entries(SEMANTIC_ICONS)) {\n\t\tif (icon === name) {\n\t\t\treturn concept\n\t\t}\n\t}\n\treturn null\n}\n\n/**\n * Resolve a vocabulary icon name to its component.\n *\n * @param {string|null|undefined} name Canonical MDI icon name.\n * @return {object|null} The Vue component, or null when not in the vocabulary.\n */\nexport function getSemanticIconComponent(name) {\n\tif (typeof name !== 'string' || name.length === 0) {\n\t\treturn null\n\t}\n\treturn SEMANTIC_ICON_COMPONENTS[name] ?? null\n}\n"],"names":["AccountGroupOutlineIcon","AccountOutlineIcon","AlertCircleOutlineIcon","BellOutlineIcon","BriefcaseOutlineIcon","CalendarClockOutlineIcon","CalendarOutlineIcon","ChartBarIcon","CheckCircleOutlineIcon","ClipboardCheckOutlineIcon","ClipboardListOutlineIcon","ClockOutlineIcon","CloseCircleOutlineIcon","CogOutlineIcon","CommentOutlineIcon","ContentCopyIcon","ContentSaveIcon","CurrencyEurIcon","DatabaseOutlineIcon","DomainIcon","DotsHorizontalIcon","DownloadIcon","EmailOutlineIcon","EyeOutlineIcon","FileDocumentOutlineIcon","FolderAccountOutlineIcon","FolderOutlineIcon","FormatListChecksIcon","HistoryIcon","InformationOutlineIcon","KeyOutlineIcon","LinkVariantIcon","LockOutlineIcon","MagnifyIcon","MapMarkerOutlineIcon","MapOutlineIcon","OpenInNewIcon","PackageVariantClosedIcon","PaperclipIcon","PlayCircleOutlineIcon","PlusIcon","PulseIcon","RefreshIcon","ShareVariantOutlineIcon","ShieldAccountOutlineIcon","ShieldKeyOutlineIcon","ShieldOutlineIcon","SitemapOutlineIcon","TagOutlineIcon","UploadIcon","ViewColumnOutlineIcon","ViewDashboardOutlineIcon","ViewGridOutlineIcon"],"mappings":"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"}
@@ -2,7 +2,7 @@ import script from './CnNcWidgetWidget.vue2.js';
2
2
  import { render } from './CnNcWidgetWidget.vue3.js';
3
3
 
4
4
  script.render = render;
5
- script.__scopeId = "data-v-04be70f3";
5
+ script.__scopeId = "data-v-f553a198";
6
6
  const __sfc_main = script;
7
7
 
8
8
  export { __sfc_main as default };
@@ -39,9 +39,16 @@ function getDashboardGlobal() {
39
39
  var script = {
40
40
  name: 'CnNcWidgetWidget',
41
41
 
42
+ inject: {
43
+ /** Whether the hosting card draws a title row (CnWidgetWrapper). */
44
+ cnWidgetTitled: { default: null },
45
+ },
46
+
42
47
  props: {
43
48
  /**
44
- * Persisted widget content `{widgetId, displayMode, limit?, showAllUrl?, showAllLabel?}`.
49
+ * Persisted widget content `{widgetId, displayMode, limit?, showAllUrl?, showAllLabel?, showHeader?}`.
50
+ * `showHeader: false` drops the widget's own header (icon and title);
51
+ * it is dropped too when the hosting card draws a title row.
45
52
  * `limit` is the most items shown (the list then comes from the items
46
53
  * API, so it fits its cell); `showAllUrl` / `showAllLabel` the link to
47
54
  * the rest (default the widget's own page and "Show all").
@@ -116,6 +123,20 @@ var script = {
116
123
  return null
117
124
  },
118
125
 
126
+ /**
127
+ * Whether the widget draws its own header: not with
128
+ * `content.showHeader: false`, nor inside a card that draws a title.
129
+ *
130
+ * @spec openspec/changes/nc-widget-header/specs/nc-widget-header/spec.md#requirement-a-nextcloud-widget-draws-no-second-heading
131
+ * @return {boolean}
132
+ */
133
+ showsHeader() {
134
+ if (this.content && this.content.showHeader === false) {
135
+ return false
136
+ }
137
+ return !(typeof this.cnWidgetTitled === 'function' && this.cnWidgetTitled())
138
+ },
139
+
119
140
  /**
120
141
  * The header title.
121
142
  *
@@ -1 +1 @@
1
- {"version":3,"file":"CnNcWidgetWidget.vue2.js","sources":["../../../../src/components/CnNcWidgetWidget/CnNcWidgetWidget.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-nc-widget-widget\" :class=\"{ 'cn-nc-widget-widget--horizontal': displayMode === 'horizontal' }\">\n\t\t<header class=\"cn-nc-widget-widget__header\">\n\t\t\t<img\n\t\t\t\tv-if=\"widgetIconUrl\"\n\t\t\t\tclass=\"cn-nc-widget-widget__header-icon\"\n\t\t\t\t:src=\"widgetIconUrl\"\n\t\t\t\talt=\"\">\n\t\t\t<span class=\"cn-nc-widget-widget__header-title\">{{ widgetTitle }}</span>\n\t\t</header>\n\n\t\t<!--\n\t\t\tNative callback container — always present but hidden until the\n\t\t\tOCA.Dashboard callback mounts into it. Keeping it mounted avoids a\n\t\t\tflicker when the native path wins after the API list has painted.\n\n\t\t\tThe `--horizontal` reskin class lives on the ROOT element, not here:\n\t\t\tnative widget callbacks mount via `new Vue(...).$mount(el)`, which\n\t\t\tREPLACES this element in the live DOM with the callback's own root\n\t\t\tnode — any class we put directly on it is discarded along with the\n\t\t\telement itself, so it can never appear in the rendered page.\n\t\t-->\n\t\t<div\n\t\t\tv-show=\"mode === 'native'\"\n\t\t\tref=\"nativeContainer\"\n\t\t\tclass=\"cn-nc-widget-widget__native\" />\n\n\t\t<div\n\t\t\tv-if=\"mode !== 'native'\"\n\t\t\tclass=\"cn-nc-widget-widget__body\"\n\t\t\t:class=\"bodyClass\">\n\t\t\t<div v-if=\"loading\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'Loading…') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"!widgetId\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'No widget selected') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"unsupported\" class=\"cn-nc-widget-widget__state\" data-testid=\"nc-widget-unsupported\">\n\t\t\t\t{{ t('nextcloud-vue', 'This widget can only be shown on the Nextcloud dashboard itself.') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"items.length === 0\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'No items available') }}\n\t\t\t</div>\n\n\t\t\t<template v-else>\n\t\t\t\t<a\n\t\t\t\t\tv-for=\"(item, idx) in shownItems\"\n\t\t\t\t\t:key=\"item.sinceId || item.id || idx\"\n\t\t\t\t\tclass=\"cn-nc-widget-widget__item\"\n\t\t\t\t\t:class=\"itemClass\"\n\t\t\t\t\t:href=\"item.link || '#'\"\n\t\t\t\t\t:title=\"item.title\">\n\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-icon-wrap\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"item.iconUrl\"\n\t\t\t\t\t\t\tclass=\"cn-nc-widget-widget__item-icon\"\n\t\t\t\t\t\t\t:src=\"item.iconUrl\"\n\t\t\t\t\t\t\talt=\"\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"item.overlayIconUrl\"\n\t\t\t\t\t\t\tclass=\"cn-nc-widget-widget__item-overlay\"\n\t\t\t\t\t\t\t:src=\"item.overlayIconUrl\"\n\t\t\t\t\t\t\talt=\"\">\n\t\t\t\t\t</span>\n\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-text\">\n\t\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-title\">{{ item.title }}</span>\n\t\t\t\t\t\t<span v-if=\"item.subtitle\" class=\"cn-nc-widget-widget__item-subtitle\">{{ item.subtitle }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t</a>\n\t\t\t\t<!-- With a `limit`, the rest is one link away (`showAllUrl`, else the widget's own page). -->\n\t\t\t\t<a\n\t\t\t\t\tv-if=\"showAllHref\"\n\t\t\t\t\tclass=\"cn-nc-widget-widget__show-all\"\n\t\t\t\t\tdata-testid=\"nc-widget-show-all\"\n\t\t\t\t\t:href=\"showAllHref\">\n\t\t\t\t\t{{ showAllLabel }}\n\t\t\t\t</a>\n\t\t\t</template>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateOcsUrl } from '@nextcloud/router'\n\nconst API_ITEM_LIMIT = 7\n\n/**\n * Read the global `OCA.Dashboard` registry without assuming it exists.\n *\n * @return {object|null} the `OCA.Dashboard` object, or `null` when absent.\n */\nfunction getDashboardGlobal() {\n\tif (typeof window === 'undefined') {\n\t\treturn null\n\t}\n\tconst oca = window.OCA\n\treturn oca && oca.Dashboard ? oca.Dashboard : null\n}\n\n/**\n * CnNcWidgetWidget — proxies any native Nextcloud Dashboard widget into a\n * dashboard grid cell.\n *\n * Two-mode rendering (decoupling seam — reads NC directly, no app bridge):\n * - **native** — when the widget bundle has registered a callback on the\n * global `OCA.Dashboard` (`getWidget(id)` / `widgets[id]`), the callback is\n * handed the render container and paints itself (native fast-path).\n * - **api** — otherwise the OCS Dashboard endpoint\n * `/apps/dashboard/api/v{1,2}/widget-items` is fetched directly via\n * `@nextcloud/axios` and a flat item list is rendered.\n *\n * The header title + icon come from the dashboard widget metadata\n * (`OCA.Dashboard` registry, falling back to the configured `widgetId`). When\n * no `widgetId` is configured the widget renders an empty state and never hits\n * the network.\n *\n * @spec openspec/changes/cn-widget-library/specs/cn-widget-library/spec.md\n */\nexport default {\n\tname: 'CnNcWidgetWidget',\n\n\tprops: {\n\t\t/**\n\t\t * Persisted widget content `{widgetId, displayMode, limit?, showAllUrl?, showAllLabel?}`.\n\t\t * `limit` is the most items shown (the list then comes from the items\n\t\t * API, so it fits its cell); `showAllUrl` / `showAllLabel` the link to\n\t\t * the rest (default the widget's own page and \"Show all\").\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\t/** @type {'pending'|'native'|'api'} the resolved mounting mode. */\n\t\t\tmode: 'pending',\n\t\t\t/**\n\t\t\t * Whether the items API has no entry for this widget at all.\n\t\t\t *\n\t\t\t * Not the same as an empty list. A widget whose provider implements\n\t\t\t * only `IWidget` (no `IAPIWidget`/`IAPIWidgetV2`) declares\n\t\t\t * `itemApiVersions: []` and is simply ABSENT from the widget-items\n\t\t\t * response, while a widget with nothing to show right now comes\n\t\t\t * back as its own key holding an empty list. The Tasks app's widget\n\t\t\t * is the first kind: with no native callback registered on the page\n\t\t\t * it can never render a single item here, and saying \"No items\n\t\t\t * available\" under it told the reader their task list was empty.\n\t\t\t *\n\t\t\t * @type {boolean}\n\t\t\t */\n\t\t\tunsupported: false,\n\t\t\tloading: false,\n\t\t\titems: [],\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The configured native widget id.\n\t\t *\n\t\t * @return {string} the widget id (empty when unset).\n\t\t */\n\t\twidgetId() {\n\t\t\treturn typeof (this.content && this.content.widgetId) === 'string' ? this.content.widgetId : ''\n\t\t},\n\n\t\t/**\n\t\t * The item list orientation.\n\t\t *\n\t\t * @return {string} `horizontal` or `vertical`.\n\t\t */\n\t\tdisplayMode() {\n\t\t\treturn (this.content && this.content.displayMode) === 'horizontal' ? 'horizontal' : 'vertical'\n\t\t},\n\n\t\t/**\n\t\t * The native widget metadata from the `OCA.Dashboard` global.\n\t\t *\n\t\t * @return {object|null} the widget metadata, or `null`.\n\t\t */\n\t\twidgetMeta() {\n\t\t\tconst dashboard = getDashboardGlobal()\n\t\t\tif (!dashboard || !this.widgetId) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (typeof dashboard.getWidget === 'function') {\n\t\t\t\treturn dashboard.getWidget(this.widgetId) || null\n\t\t\t}\n\t\t\tif (dashboard.widgets && typeof dashboard.widgets === 'object') {\n\t\t\t\treturn dashboard.widgets[this.widgetId] || null\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * The header title.\n\t\t *\n\t\t * @return {string} the title.\n\t\t */\n\t\twidgetTitle() {\n\t\t\treturn (this.widgetMeta && this.widgetMeta.title) || this.widgetId || t('nextcloud-vue', 'Widget')\n\t\t},\n\n\t\t/**\n\t\t * The header icon URL.\n\t\t *\n\t\t * @return {string} the icon URL (empty when none).\n\t\t */\n\t\twidgetIconUrl() {\n\t\t\treturn (this.widgetMeta && this.widgetMeta.iconUrl) || ''\n\t\t},\n\n\t\t/**\n\t\t * The most items the list shows (`content.limit`), or 0 for no limit.\n\t\t * A limit lets the widget fit a dashboard cell instead of scrolling\n\t\t * inside it.\n\t\t *\n\t\t * @spec openspec/changes/screens-nc-widget-limit/specs/nc-widget/spec.md#requirement-a-nextcloud-widget-shows-at-most-its-limit\n\t\t * @return {number} the limit.\n\t\t */\n\t\titemLimit() {\n\t\t\tconst limit = Number(this.content && this.content.limit)\n\t\t\treturn Number.isInteger(limit) && limit > 0 ? limit : 0\n\t\t},\n\n\t\t/**\n\t\t * The items drawn: at most `itemLimit`.\n\t\t *\n\t\t * @return {object[]} the items.\n\t\t */\n\t\tshownItems() {\n\t\t\treturn this.itemLimit > 0 ? this.items.slice(0, this.itemLimit) : this.items\n\t\t},\n\n\t\t/**\n\t\t * Where \"Show all\" goes: `content.showAllUrl`, else the page the widget\n\t\t * names itself (its `url`). Only with a limit; '' for no link.\n\t\t *\n\t\t * @spec openspec/changes/screens-nc-widget-limit/specs/nc-widget/spec.md#requirement-a-nextcloud-widget-shows-at-most-its-limit\n\t\t * @return {string} the URL.\n\t\t */\n\t\tshowAllHref() {\n\t\t\tif (this.itemLimit === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst own = this.content && typeof this.content.showAllUrl === 'string' ? this.content.showAllUrl : ''\n\t\t\treturn own || (this.widgetMeta && typeof this.widgetMeta.url === 'string' ? this.widgetMeta.url : '')\n\t\t},\n\n\t\t/**\n\t\t * The \"Show all\" text (`content.showAllLabel`, else the library's).\n\t\t *\n\t\t * @return {string} the label.\n\t\t */\n\t\tshowAllLabel() {\n\t\t\tconst label = this.content && this.content.showAllLabel\n\t\t\treturn typeof label === 'string' && label !== '' ? label : t('nextcloud-vue', 'Show all')\n\t\t},\n\n\t\t/**\n\t\t * The body orientation CSS modifier class.\n\t\t *\n\t\t * @return {string} the body class.\n\t\t */\n\t\tbodyClass() {\n\t\t\treturn `cn-nc-widget-widget__body--${this.displayMode}`\n\t\t},\n\n\t\t/**\n\t\t * The item orientation CSS modifier class.\n\t\t *\n\t\t * @return {string} the item class.\n\t\t */\n\t\titemClass() {\n\t\t\treturn `cn-nc-widget-widget__item--${this.displayMode}`\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.tryMount()\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Resolve the mounting mode. Prefers the native `OCA.Dashboard`\n\t\t * callback fast-path; otherwise falls back to the OCS item list.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\ttryMount() {\n\t\t\tif (!this.widgetId) {\n\t\t\t\tthis.mode = 'api'\n\t\t\t\tthis.items = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// The native callback paints its own opaque markup, so `displayMode`\n\t\t\t// (bodyClass/itemClass below) has no effect on it — only the API\n\t\t\t// item list honours the vertical/horizontal setting. Horizontal mode\n\t\t\t// must therefore skip the native fast-path, or the \"Horizontal\n\t\t\t// (cards)\" option would silently do nothing for the (common) case\n\t\t\t// where the widget has a registered native callback.\n\t\t\t// A `limit` also takes the API list first: the native callback paints\n\t\t\t// as many items as it likes. Its fallback to native stays.\n\t\t\tif (this.displayMode !== 'horizontal' && this.itemLimit === 0) {\n\t\t\t\tconst callback = this.resolveNativeCallback()\n\t\t\t\tif (typeof callback === 'function') {\n\t\t\t\t\tthis.mountNative(callback)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.mode = 'api'\n\t\t\tthis.loadApiItems()\n\t\t},\n\n\t\t/**\n\t\t * Look up a native render callback on the `OCA.Dashboard` global.\n\t\t *\n\t\t * @return {((el: HTMLElement, ctx: {widget: object}) => unknown)|null} the callback, or `null` when none is registered.\n\t\t */\n\t\tresolveNativeCallback() {\n\t\t\tconst dashboard = getDashboardGlobal()\n\t\t\tif (!dashboard) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (this.widgetMeta && typeof this.widgetMeta.callback === 'function') {\n\t\t\t\treturn this.widgetMeta.callback\n\t\t\t}\n\t\t\tif (dashboard.callbacks && typeof dashboard.callbacks[this.widgetId] === 'function') {\n\t\t\t\treturn dashboard.callbacks[this.widgetId]\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Mount the widget natively by invoking its registered callback with\n\t\t * our render container.\n\t\t *\n\t\t * @param {(el: HTMLElement, ctx: {widget: object}) => unknown} callback the native render callback.\n\t\t * @return {void}\n\t\t */\n\t\tmountNative(callback) {\n\t\t\tthis.mode = 'native'\n\t\t\tthis.$nextTick(() => {\n\t\t\t\tconst container = this.$refs.nativeContainer\n\t\t\t\tif (!container) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// Native callback failed — fall back to the API list.\n\t\t\t\tconst fallback = () => {\n\t\t\t\t\tthis.mode = 'api'\n\t\t\t\t\tthis.loadApiItems()\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\t// NC dashboard widgets are registered as\n\t\t\t\t\t// `register(id, (el, { widget }) => …)` — the second argument\n\t\t\t\t\t// MUST be the `{ widget }` envelope, not the bare metadata, or\n\t\t\t\t\t// the widget destructures `widget` as undefined and throws on\n\t\t\t\t\t// first use (e.g. `widget.title`).\n\t\t\t\t\tconst result = callback(container, { widget: this.widgetMeta || {} })\n\t\t\t\t\t// Most widget callbacks are async; a synchronous try/catch\n\t\t\t\t\t// can't see a rejected promise, so wire the fallback to it too.\n\t\t\t\t\tif (result && typeof result.then === 'function') {\n\t\t\t\t\t\tresult.catch(fallback)\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\tfallback()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Fetch the API fallback list directly from the OCS Dashboard\n\t\t * endpoint. Malformed or failed responses collapse to an empty list\n\t\t * (the empty state) instead of throwing.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadApiItems() {\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\t// The v2 widget-items API only returns an entry for widgets\n\t\t\t\t// whose server-side provider implements `IAPIWidgetV2` — plenty\n\t\t\t\t// of native dashboard widgets are JS-callback-only (`IWidget`)\n\t\t\t\t// and never appear in this response at all, which looks\n\t\t\t\t// identical to \"0 items\" from here. extractItems() tolerates\n\t\t\t\t// both the flat-array (older providers) and `{items}` (v2) shapes.\n\t\t\t\tconst url = generateOcsUrl('/apps/dashboard/api/v2/widget-items')\n\t\t\t\tconst response = await axios.get(url, {\n\t\t\t\t\tparams: { widgets: [this.widgetId], limit: this.itemLimit > 0 ? this.itemLimit : API_ITEM_LIMIT },\n\t\t\t\t})\n\t\t\t\tconst data = response && response.data && response.data.ocs ? response.data.ocs.data : null\n\t\t\t\tconst widgetData = data ? data[this.widgetId] : null\n\t\t\t\tthis.items = this.extractItems(widgetData)\n\t\t\t\t// Only a SUCCESSFUL response can say the widget is absent. A\n\t\t\t\t// failed request says nothing about the widget, so it keeps\n\t\t\t\t// the ordinary empty state rather than a claim about the app.\n\t\t\t\tthis.unsupported = data !== null && (widgetData === null || widgetData === undefined)\n\t\t\t} catch {\n\t\t\t\tthis.items = []\n\t\t\t\tthis.unsupported = false\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\n\t\t\t// Horizontal mode deliberately skips the native fast-path (see\n\t\t\t// tryMount()) to get the styled card layout. But when the API has\n\t\t\t// no entry for this widget at all — no `IAPIWidgetV2` support, not\n\t\t\t// \"no items right now\" — that would render a false empty state for\n\t\t\t// a widget that actually has content. Fall back to native\n\t\t\t// rendering rather than lying about there being nothing to show.\n\t\t\tif (this.items.length === 0) {\n\t\t\t\tconst callback = this.resolveNativeCallback()\n\t\t\t\tif (typeof callback === 'function') {\n\t\t\t\t\tthis.mountNative(callback)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Normalise a per-widget OCS payload to an items array, tolerating both\n\t\t * the flat array and the `{items}` envelope shapes.\n\t\t *\n\t\t * @param {unknown} widgetData the per-widget payload.\n\t\t * @return {object[]} the items array (possibly empty).\n\t\t */\n\t\textractItems(widgetData) {\n\t\t\tif (!widgetData) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tif (Array.isArray(widgetData)) {\n\t\t\t\treturn widgetData\n\t\t\t}\n\t\t\tif (Array.isArray(widgetData.items)) {\n\t\t\t\treturn widgetData.items\n\t\t\t}\n\t\t\tif (widgetData.items && typeof widgetData.items === 'object') {\n\t\t\t\treturn Object.values(widgetData.items)\n\t\t\t}\n\t\t\treturn []\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-nc-widget-widget {\n\tdisplay: flex;\n\tflex-direction: column;\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n}\n\n/*\n * Header + content match the native Nextcloud Dashboard panel (apps/dashboard)\n * exactly — this component's whole job is rendering NC dashboard widgets, so it\n * should look native by default: 16px header, 32px leading icon with a 16px\n * gap, a 20px/700 title, and the native panel content inset (16px sides +\n * bottom, flush to the header on top). Same design tokens as core; overridable\n * via the host's CnWidgetWrapper styleConfig / nldesign.\n */\n.cn-nc-widget-widget__header {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 16px;\n\tpadding: 16px;\n\tfont-weight: 700;\n}\n\n.cn-nc-widget-widget__header-icon {\n\twidth: 32px;\n\theight: 32px;\n\tflex: 0 0 auto;\n}\n\n.cn-nc-widget-widget__header-title {\n\tflex: 1;\n\tfont-size: 20px;\n\tfont-weight: 700;\n\tline-height: 24px;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-nc-widget-widget__show-all {\n\talign-self: flex-start;\n\tpadding: 8px 0 0;\n\tcolor: var(--color-primary-element);\n\tfont-weight: 600;\n\ttext-decoration: none;\n}\n\n.cn-nc-widget-widget__show-all:hover,\n.cn-nc-widget-widget__show-all:focus-visible {\n\ttext-decoration: underline;\n}\n\n.cn-nc-widget-widget__native {\n\tflex: 1;\n\toverflow: auto;\n\tpadding: 0 16px 16px;\n}\n\n/*\n * The native `OCA.Dashboard` callback paints its own markup we don't control\n * — for first-party widgets that's almost always `@nextcloud/vue`'s\n * `NcDashboardWidget` / `NcDashboardWidgetItem` (`.dashboard-widget` wrapping\n * a bare `<ul>`/`<li>` list, each item a `.item-list__entry`).\n *\n * Only the LIST CONTAINER is retiled into a grid here — `.item-list__entry`'s\n * own internal layout is left untouched. An earlier version of this override\n * also forced `.item-list__entry` from row to column, but its icon-overlay\n * badge (`.item-icon`, see @nextcloud/vue's NcDashboardWidgetItem CSS) is\n * positioned with negative margins calibrated for the row layout, so\n * flipping to column made items visually overlap. Tiling the `<li>`s into a\n * grid while each entry keeps its normal icon+text row reads as a grid of\n * card tiles without touching that internal math.\n *\n * Scoped from `.cn-nc-widget-widget--horizontal` on the ROOT element, not\n * `.cn-nc-widget-widget__native`: the callback mounts via `.$mount(el)`,\n * which replaces `nativeContainer` in the live DOM outright, so any class\n * placed directly on it never survives to be selectable.\n *\n * The 250px column floor matches `.item-list__entry`'s own natural minimum\n * width (avatar + padding + its un-truncatable-below-this content) — a grid\n * track narrower than that squeezes the entry below its real minimum and it\n * overflows into the neighbouring cell. `min-width: 0` on the `<li>` alone\n * isn't enough to shrink it further: the item's own internal flex layout\n * still claims that much room regardless of the grid track size, so the\n * track itself must not go below it.\n */\n.cn-nc-widget-widget--horizontal :deep(.dashboard-widget > ul) {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n\tgap: 8px;\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-nc-widget-widget--horizontal :deep(.dashboard-widget > ul > li) {\n\twidth: auto;\n\tmin-width: 0;\n}\n\n.cn-nc-widget-widget--horizontal :deep(.item-list__entry) {\n\theight: 100%;\n\tmargin: 0;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large);\n}\n\n.cn-nc-widget-widget__body {\n\tflex: 1;\n\toverflow: auto;\n\tpadding: 0 16px 16px;\n}\n\n.cn-nc-widget-widget__body--vertical {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n}\n\n.cn-nc-widget-widget__body--horizontal {\n\tdisplay: flex;\n\tflex-direction: row;\n\tflex-wrap: wrap;\n\tgap: 12px;\n}\n\n.cn-nc-widget-widget__state {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tflex: 1;\n\tmin-height: 64px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-style: italic;\n}\n\n.cn-nc-widget-widget__item {\n\tdisplay: flex;\n\ttext-decoration: none;\n\tcolor: var(--color-main-text);\n\tborder-radius: var(--border-radius);\n\tpadding: 4px;\n}\n\n.cn-nc-widget-widget__item:hover {\n\tbackground-color: var(--color-background-hover);\n}\n\n.cn-nc-widget-widget__item--vertical {\n\tflex-direction: row;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-nc-widget-widget__item--horizontal {\n\tflex-direction: column;\n\talign-items: center;\n\twidth: 120px;\n\ttext-align: center;\n}\n\n.cn-nc-widget-widget__item-icon-wrap {\n\twidth: 32px;\n\theight: 32px;\n\tflex: 0 0 32px;\n\tposition: relative;\n}\n\n.cn-nc-widget-widget__item-icon {\n\twidth: 32px;\n\theight: 32px;\n\tobject-fit: cover;\n\tborder-radius: 50%;\n}\n\n.cn-nc-widget-widget__item-overlay {\n\tposition: absolute;\n\tright: -2px;\n\tbottom: -2px;\n\twidth: 14px;\n\theight: 14px;\n}\n\n.cn-nc-widget-widget__item-text {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 0;\n\tflex: 1;\n}\n\n.cn-nc-widget-widget__item-title {\n\tfont-weight: 600;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-nc-widget-widget__item-subtitle {\n\tfont-size: 0.85em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n</style>\n"],"names":["t","axios"],"mappings":"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"}
1
+ {"version":3,"file":"CnNcWidgetWidget.vue2.js","sources":["../../../../src/components/CnNcWidgetWidget/CnNcWidgetWidget.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-nc-widget-widget\" :class=\"{ 'cn-nc-widget-widget--horizontal': displayMode === 'horizontal' }\">\n\t\t<header v-if=\"showsHeader\" class=\"cn-nc-widget-widget__header\" data-testid=\"cn-nc-widget-header\">\n\t\t\t<img\n\t\t\t\tv-if=\"widgetIconUrl\"\n\t\t\t\tclass=\"cn-nc-widget-widget__header-icon\"\n\t\t\t\t:src=\"widgetIconUrl\"\n\t\t\t\talt=\"\">\n\t\t\t<span class=\"cn-nc-widget-widget__header-title\">{{ widgetTitle }}</span>\n\t\t</header>\n\n\t\t<!--\n\t\t\tNative callback container — always present but hidden until the\n\t\t\tOCA.Dashboard callback mounts into it. Keeping it mounted avoids a\n\t\t\tflicker when the native path wins after the API list has painted.\n\n\t\t\tThe `--horizontal` reskin class lives on the ROOT element, not here:\n\t\t\tnative widget callbacks mount via `new Vue(...).$mount(el)`, which\n\t\t\tREPLACES this element in the live DOM with the callback's own root\n\t\t\tnode — any class we put directly on it is discarded along with the\n\t\t\telement itself, so it can never appear in the rendered page.\n\t\t-->\n\t\t<div\n\t\t\tv-show=\"mode === 'native'\"\n\t\t\tref=\"nativeContainer\"\n\t\t\tclass=\"cn-nc-widget-widget__native\" />\n\n\t\t<div\n\t\t\tv-if=\"mode !== 'native'\"\n\t\t\tclass=\"cn-nc-widget-widget__body\"\n\t\t\t:class=\"bodyClass\">\n\t\t\t<div v-if=\"loading\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'Loading…') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"!widgetId\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'No widget selected') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"unsupported\" class=\"cn-nc-widget-widget__state\" data-testid=\"nc-widget-unsupported\">\n\t\t\t\t{{ t('nextcloud-vue', 'This widget can only be shown on the Nextcloud dashboard itself.') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"items.length === 0\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'No items available') }}\n\t\t\t</div>\n\n\t\t\t<template v-else>\n\t\t\t\t<a\n\t\t\t\t\tv-for=\"(item, idx) in shownItems\"\n\t\t\t\t\t:key=\"item.sinceId || item.id || idx\"\n\t\t\t\t\tclass=\"cn-nc-widget-widget__item\"\n\t\t\t\t\t:class=\"itemClass\"\n\t\t\t\t\t:href=\"item.link || '#'\"\n\t\t\t\t\t:title=\"item.title\">\n\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-icon-wrap\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"item.iconUrl\"\n\t\t\t\t\t\t\tclass=\"cn-nc-widget-widget__item-icon\"\n\t\t\t\t\t\t\t:src=\"item.iconUrl\"\n\t\t\t\t\t\t\talt=\"\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"item.overlayIconUrl\"\n\t\t\t\t\t\t\tclass=\"cn-nc-widget-widget__item-overlay\"\n\t\t\t\t\t\t\t:src=\"item.overlayIconUrl\"\n\t\t\t\t\t\t\talt=\"\">\n\t\t\t\t\t</span>\n\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-text\">\n\t\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-title\">{{ item.title }}</span>\n\t\t\t\t\t\t<span v-if=\"item.subtitle\" class=\"cn-nc-widget-widget__item-subtitle\">{{ item.subtitle }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t</a>\n\t\t\t\t<!-- With a `limit`, the rest is one link away (`showAllUrl`, else the widget's own page). -->\n\t\t\t\t<a\n\t\t\t\t\tv-if=\"showAllHref\"\n\t\t\t\t\tclass=\"cn-nc-widget-widget__show-all\"\n\t\t\t\t\tdata-testid=\"nc-widget-show-all\"\n\t\t\t\t\t:href=\"showAllHref\">\n\t\t\t\t\t{{ showAllLabel }}\n\t\t\t\t</a>\n\t\t\t</template>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateOcsUrl } from '@nextcloud/router'\n\nconst API_ITEM_LIMIT = 7\n\n/**\n * Read the global `OCA.Dashboard` registry without assuming it exists.\n *\n * @return {object|null} the `OCA.Dashboard` object, or `null` when absent.\n */\nfunction getDashboardGlobal() {\n\tif (typeof window === 'undefined') {\n\t\treturn null\n\t}\n\tconst oca = window.OCA\n\treturn oca && oca.Dashboard ? oca.Dashboard : null\n}\n\n/**\n * CnNcWidgetWidget — proxies any native Nextcloud Dashboard widget into a\n * dashboard grid cell.\n *\n * Two-mode rendering (decoupling seam — reads NC directly, no app bridge):\n * - **native** — when the widget bundle has registered a callback on the\n * global `OCA.Dashboard` (`getWidget(id)` / `widgets[id]`), the callback is\n * handed the render container and paints itself (native fast-path).\n * - **api** — otherwise the OCS Dashboard endpoint\n * `/apps/dashboard/api/v{1,2}/widget-items` is fetched directly via\n * `@nextcloud/axios` and a flat item list is rendered.\n *\n * The header title + icon come from the dashboard widget metadata\n * (`OCA.Dashboard` registry, falling back to the configured `widgetId`). When\n * no `widgetId` is configured the widget renders an empty state and never hits\n * the network.\n *\n * @spec openspec/changes/cn-widget-library/specs/cn-widget-library/spec.md\n */\nexport default {\n\tname: 'CnNcWidgetWidget',\n\n\tinject: {\n\t\t/** Whether the hosting card draws a title row (CnWidgetWrapper). */\n\t\tcnWidgetTitled: { default: null },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * Persisted widget content `{widgetId, displayMode, limit?, showAllUrl?, showAllLabel?, showHeader?}`.\n\t\t * `showHeader: false` drops the widget's own header (icon and title);\n\t\t * it is dropped too when the hosting card draws a title row.\n\t\t * `limit` is the most items shown (the list then comes from the items\n\t\t * API, so it fits its cell); `showAllUrl` / `showAllLabel` the link to\n\t\t * the rest (default the widget's own page and \"Show all\").\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\t/** @type {'pending'|'native'|'api'} the resolved mounting mode. */\n\t\t\tmode: 'pending',\n\t\t\t/**\n\t\t\t * Whether the items API has no entry for this widget at all.\n\t\t\t *\n\t\t\t * Not the same as an empty list. A widget whose provider implements\n\t\t\t * only `IWidget` (no `IAPIWidget`/`IAPIWidgetV2`) declares\n\t\t\t * `itemApiVersions: []` and is simply ABSENT from the widget-items\n\t\t\t * response, while a widget with nothing to show right now comes\n\t\t\t * back as its own key holding an empty list. The Tasks app's widget\n\t\t\t * is the first kind: with no native callback registered on the page\n\t\t\t * it can never render a single item here, and saying \"No items\n\t\t\t * available\" under it told the reader their task list was empty.\n\t\t\t *\n\t\t\t * @type {boolean}\n\t\t\t */\n\t\t\tunsupported: false,\n\t\t\tloading: false,\n\t\t\titems: [],\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The configured native widget id.\n\t\t *\n\t\t * @return {string} the widget id (empty when unset).\n\t\t */\n\t\twidgetId() {\n\t\t\treturn typeof (this.content && this.content.widgetId) === 'string' ? this.content.widgetId : ''\n\t\t},\n\n\t\t/**\n\t\t * The item list orientation.\n\t\t *\n\t\t * @return {string} `horizontal` or `vertical`.\n\t\t */\n\t\tdisplayMode() {\n\t\t\treturn (this.content && this.content.displayMode) === 'horizontal' ? 'horizontal' : 'vertical'\n\t\t},\n\n\t\t/**\n\t\t * The native widget metadata from the `OCA.Dashboard` global.\n\t\t *\n\t\t * @return {object|null} the widget metadata, or `null`.\n\t\t */\n\t\twidgetMeta() {\n\t\t\tconst dashboard = getDashboardGlobal()\n\t\t\tif (!dashboard || !this.widgetId) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (typeof dashboard.getWidget === 'function') {\n\t\t\t\treturn dashboard.getWidget(this.widgetId) || null\n\t\t\t}\n\t\t\tif (dashboard.widgets && typeof dashboard.widgets === 'object') {\n\t\t\t\treturn dashboard.widgets[this.widgetId] || null\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Whether the widget draws its own header: not with\n\t\t * `content.showHeader: false`, nor inside a card that draws a title.\n\t\t *\n\t\t * @spec openspec/changes/nc-widget-header/specs/nc-widget-header/spec.md#requirement-a-nextcloud-widget-draws-no-second-heading\n\t\t * @return {boolean}\n\t\t */\n\t\tshowsHeader() {\n\t\t\tif (this.content && this.content.showHeader === false) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !(typeof this.cnWidgetTitled === 'function' && this.cnWidgetTitled())\n\t\t},\n\n\t\t/**\n\t\t * The header title.\n\t\t *\n\t\t * @return {string} the title.\n\t\t */\n\t\twidgetTitle() {\n\t\t\treturn (this.widgetMeta && this.widgetMeta.title) || this.widgetId || t('nextcloud-vue', 'Widget')\n\t\t},\n\n\t\t/**\n\t\t * The header icon URL.\n\t\t *\n\t\t * @return {string} the icon URL (empty when none).\n\t\t */\n\t\twidgetIconUrl() {\n\t\t\treturn (this.widgetMeta && this.widgetMeta.iconUrl) || ''\n\t\t},\n\n\t\t/**\n\t\t * The most items the list shows (`content.limit`), or 0 for no limit.\n\t\t * A limit lets the widget fit a dashboard cell instead of scrolling\n\t\t * inside it.\n\t\t *\n\t\t * @spec openspec/changes/screens-nc-widget-limit/specs/nc-widget/spec.md#requirement-a-nextcloud-widget-shows-at-most-its-limit\n\t\t * @return {number} the limit.\n\t\t */\n\t\titemLimit() {\n\t\t\tconst limit = Number(this.content && this.content.limit)\n\t\t\treturn Number.isInteger(limit) && limit > 0 ? limit : 0\n\t\t},\n\n\t\t/**\n\t\t * The items drawn: at most `itemLimit`.\n\t\t *\n\t\t * @return {object[]} the items.\n\t\t */\n\t\tshownItems() {\n\t\t\treturn this.itemLimit > 0 ? this.items.slice(0, this.itemLimit) : this.items\n\t\t},\n\n\t\t/**\n\t\t * Where \"Show all\" goes: `content.showAllUrl`, else the page the widget\n\t\t * names itself (its `url`). Only with a limit; '' for no link.\n\t\t *\n\t\t * @spec openspec/changes/screens-nc-widget-limit/specs/nc-widget/spec.md#requirement-a-nextcloud-widget-shows-at-most-its-limit\n\t\t * @return {string} the URL.\n\t\t */\n\t\tshowAllHref() {\n\t\t\tif (this.itemLimit === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst own = this.content && typeof this.content.showAllUrl === 'string' ? this.content.showAllUrl : ''\n\t\t\treturn own || (this.widgetMeta && typeof this.widgetMeta.url === 'string' ? this.widgetMeta.url : '')\n\t\t},\n\n\t\t/**\n\t\t * The \"Show all\" text (`content.showAllLabel`, else the library's).\n\t\t *\n\t\t * @return {string} the label.\n\t\t */\n\t\tshowAllLabel() {\n\t\t\tconst label = this.content && this.content.showAllLabel\n\t\t\treturn typeof label === 'string' && label !== '' ? label : t('nextcloud-vue', 'Show all')\n\t\t},\n\n\t\t/**\n\t\t * The body orientation CSS modifier class.\n\t\t *\n\t\t * @return {string} the body class.\n\t\t */\n\t\tbodyClass() {\n\t\t\treturn `cn-nc-widget-widget__body--${this.displayMode}`\n\t\t},\n\n\t\t/**\n\t\t * The item orientation CSS modifier class.\n\t\t *\n\t\t * @return {string} the item class.\n\t\t */\n\t\titemClass() {\n\t\t\treturn `cn-nc-widget-widget__item--${this.displayMode}`\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.tryMount()\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Resolve the mounting mode. Prefers the native `OCA.Dashboard`\n\t\t * callback fast-path; otherwise falls back to the OCS item list.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\ttryMount() {\n\t\t\tif (!this.widgetId) {\n\t\t\t\tthis.mode = 'api'\n\t\t\t\tthis.items = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// The native callback paints its own opaque markup, so `displayMode`\n\t\t\t// (bodyClass/itemClass below) has no effect on it — only the API\n\t\t\t// item list honours the vertical/horizontal setting. Horizontal mode\n\t\t\t// must therefore skip the native fast-path, or the \"Horizontal\n\t\t\t// (cards)\" option would silently do nothing for the (common) case\n\t\t\t// where the widget has a registered native callback.\n\t\t\t// A `limit` also takes the API list first: the native callback paints\n\t\t\t// as many items as it likes. Its fallback to native stays.\n\t\t\tif (this.displayMode !== 'horizontal' && this.itemLimit === 0) {\n\t\t\t\tconst callback = this.resolveNativeCallback()\n\t\t\t\tif (typeof callback === 'function') {\n\t\t\t\t\tthis.mountNative(callback)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.mode = 'api'\n\t\t\tthis.loadApiItems()\n\t\t},\n\n\t\t/**\n\t\t * Look up a native render callback on the `OCA.Dashboard` global.\n\t\t *\n\t\t * @return {((el: HTMLElement, ctx: {widget: object}) => unknown)|null} the callback, or `null` when none is registered.\n\t\t */\n\t\tresolveNativeCallback() {\n\t\t\tconst dashboard = getDashboardGlobal()\n\t\t\tif (!dashboard) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (this.widgetMeta && typeof this.widgetMeta.callback === 'function') {\n\t\t\t\treturn this.widgetMeta.callback\n\t\t\t}\n\t\t\tif (dashboard.callbacks && typeof dashboard.callbacks[this.widgetId] === 'function') {\n\t\t\t\treturn dashboard.callbacks[this.widgetId]\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Mount the widget natively by invoking its registered callback with\n\t\t * our render container.\n\t\t *\n\t\t * @param {(el: HTMLElement, ctx: {widget: object}) => unknown} callback the native render callback.\n\t\t * @return {void}\n\t\t */\n\t\tmountNative(callback) {\n\t\t\tthis.mode = 'native'\n\t\t\tthis.$nextTick(() => {\n\t\t\t\tconst container = this.$refs.nativeContainer\n\t\t\t\tif (!container) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// Native callback failed — fall back to the API list.\n\t\t\t\tconst fallback = () => {\n\t\t\t\t\tthis.mode = 'api'\n\t\t\t\t\tthis.loadApiItems()\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\t// NC dashboard widgets are registered as\n\t\t\t\t\t// `register(id, (el, { widget }) => …)` — the second argument\n\t\t\t\t\t// MUST be the `{ widget }` envelope, not the bare metadata, or\n\t\t\t\t\t// the widget destructures `widget` as undefined and throws on\n\t\t\t\t\t// first use (e.g. `widget.title`).\n\t\t\t\t\tconst result = callback(container, { widget: this.widgetMeta || {} })\n\t\t\t\t\t// Most widget callbacks are async; a synchronous try/catch\n\t\t\t\t\t// can't see a rejected promise, so wire the fallback to it too.\n\t\t\t\t\tif (result && typeof result.then === 'function') {\n\t\t\t\t\t\tresult.catch(fallback)\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\tfallback()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Fetch the API fallback list directly from the OCS Dashboard\n\t\t * endpoint. Malformed or failed responses collapse to an empty list\n\t\t * (the empty state) instead of throwing.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadApiItems() {\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\t// The v2 widget-items API only returns an entry for widgets\n\t\t\t\t// whose server-side provider implements `IAPIWidgetV2` — plenty\n\t\t\t\t// of native dashboard widgets are JS-callback-only (`IWidget`)\n\t\t\t\t// and never appear in this response at all, which looks\n\t\t\t\t// identical to \"0 items\" from here. extractItems() tolerates\n\t\t\t\t// both the flat-array (older providers) and `{items}` (v2) shapes.\n\t\t\t\tconst url = generateOcsUrl('/apps/dashboard/api/v2/widget-items')\n\t\t\t\tconst response = await axios.get(url, {\n\t\t\t\t\tparams: { widgets: [this.widgetId], limit: this.itemLimit > 0 ? this.itemLimit : API_ITEM_LIMIT },\n\t\t\t\t})\n\t\t\t\tconst data = response && response.data && response.data.ocs ? response.data.ocs.data : null\n\t\t\t\tconst widgetData = data ? data[this.widgetId] : null\n\t\t\t\tthis.items = this.extractItems(widgetData)\n\t\t\t\t// Only a SUCCESSFUL response can say the widget is absent. A\n\t\t\t\t// failed request says nothing about the widget, so it keeps\n\t\t\t\t// the ordinary empty state rather than a claim about the app.\n\t\t\t\tthis.unsupported = data !== null && (widgetData === null || widgetData === undefined)\n\t\t\t} catch {\n\t\t\t\tthis.items = []\n\t\t\t\tthis.unsupported = false\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\n\t\t\t// Horizontal mode deliberately skips the native fast-path (see\n\t\t\t// tryMount()) to get the styled card layout. But when the API has\n\t\t\t// no entry for this widget at all — no `IAPIWidgetV2` support, not\n\t\t\t// \"no items right now\" — that would render a false empty state for\n\t\t\t// a widget that actually has content. Fall back to native\n\t\t\t// rendering rather than lying about there being nothing to show.\n\t\t\tif (this.items.length === 0) {\n\t\t\t\tconst callback = this.resolveNativeCallback()\n\t\t\t\tif (typeof callback === 'function') {\n\t\t\t\t\tthis.mountNative(callback)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Normalise a per-widget OCS payload to an items array, tolerating both\n\t\t * the flat array and the `{items}` envelope shapes.\n\t\t *\n\t\t * @param {unknown} widgetData the per-widget payload.\n\t\t * @return {object[]} the items array (possibly empty).\n\t\t */\n\t\textractItems(widgetData) {\n\t\t\tif (!widgetData) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tif (Array.isArray(widgetData)) {\n\t\t\t\treturn widgetData\n\t\t\t}\n\t\t\tif (Array.isArray(widgetData.items)) {\n\t\t\t\treturn widgetData.items\n\t\t\t}\n\t\t\tif (widgetData.items && typeof widgetData.items === 'object') {\n\t\t\t\treturn Object.values(widgetData.items)\n\t\t\t}\n\t\t\treturn []\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-nc-widget-widget {\n\tdisplay: flex;\n\tflex-direction: column;\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n}\n\n/*\n * Header + content match the native Nextcloud Dashboard panel (apps/dashboard)\n * exactly — this component's whole job is rendering NC dashboard widgets, so it\n * should look native by default: 16px header, 32px leading icon with a 16px\n * gap, a 20px/700 title, and the native panel content inset (16px sides +\n * bottom, flush to the header on top). Same design tokens as core; overridable\n * via the host's CnWidgetWrapper styleConfig / nldesign.\n */\n.cn-nc-widget-widget__header {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 16px;\n\tpadding: 16px;\n\tfont-weight: 700;\n}\n\n.cn-nc-widget-widget__header-icon {\n\twidth: 32px;\n\theight: 32px;\n\tflex: 0 0 auto;\n}\n\n.cn-nc-widget-widget__header-title {\n\tflex: 1;\n\tfont-size: 20px;\n\tfont-weight: 700;\n\tline-height: 24px;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-nc-widget-widget__show-all {\n\talign-self: flex-start;\n\tpadding: 8px 0 0;\n\tcolor: var(--color-primary-element);\n\tfont-weight: 600;\n\ttext-decoration: none;\n}\n\n.cn-nc-widget-widget__show-all:hover,\n.cn-nc-widget-widget__show-all:focus-visible {\n\ttext-decoration: underline;\n}\n\n.cn-nc-widget-widget__native {\n\tflex: 1;\n\toverflow: auto;\n\tpadding: 0 16px 16px;\n}\n\n/*\n * The native `OCA.Dashboard` callback paints its own markup we don't control\n * — for first-party widgets that's almost always `@nextcloud/vue`'s\n * `NcDashboardWidget` / `NcDashboardWidgetItem` (`.dashboard-widget` wrapping\n * a bare `<ul>`/`<li>` list, each item a `.item-list__entry`).\n *\n * Only the LIST CONTAINER is retiled into a grid here — `.item-list__entry`'s\n * own internal layout is left untouched. An earlier version of this override\n * also forced `.item-list__entry` from row to column, but its icon-overlay\n * badge (`.item-icon`, see @nextcloud/vue's NcDashboardWidgetItem CSS) is\n * positioned with negative margins calibrated for the row layout, so\n * flipping to column made items visually overlap. Tiling the `<li>`s into a\n * grid while each entry keeps its normal icon+text row reads as a grid of\n * card tiles without touching that internal math.\n *\n * Scoped from `.cn-nc-widget-widget--horizontal` on the ROOT element, not\n * `.cn-nc-widget-widget__native`: the callback mounts via `.$mount(el)`,\n * which replaces `nativeContainer` in the live DOM outright, so any class\n * placed directly on it never survives to be selectable.\n *\n * The 250px column floor matches `.item-list__entry`'s own natural minimum\n * width (avatar + padding + its un-truncatable-below-this content) — a grid\n * track narrower than that squeezes the entry below its real minimum and it\n * overflows into the neighbouring cell. `min-width: 0` on the `<li>` alone\n * isn't enough to shrink it further: the item's own internal flex layout\n * still claims that much room regardless of the grid track size, so the\n * track itself must not go below it.\n */\n.cn-nc-widget-widget--horizontal :deep(.dashboard-widget > ul) {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n\tgap: 8px;\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-nc-widget-widget--horizontal :deep(.dashboard-widget > ul > li) {\n\twidth: auto;\n\tmin-width: 0;\n}\n\n.cn-nc-widget-widget--horizontal :deep(.item-list__entry) {\n\theight: 100%;\n\tmargin: 0;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large);\n}\n\n.cn-nc-widget-widget__body {\n\tflex: 1;\n\toverflow: auto;\n\tpadding: 0 16px 16px;\n}\n\n.cn-nc-widget-widget__body--vertical {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n}\n\n.cn-nc-widget-widget__body--horizontal {\n\tdisplay: flex;\n\tflex-direction: row;\n\tflex-wrap: wrap;\n\tgap: 12px;\n}\n\n.cn-nc-widget-widget__state {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tflex: 1;\n\tmin-height: 64px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-style: italic;\n}\n\n.cn-nc-widget-widget__item {\n\tdisplay: flex;\n\ttext-decoration: none;\n\tcolor: var(--color-main-text);\n\tborder-radius: var(--border-radius);\n\tpadding: 4px;\n}\n\n.cn-nc-widget-widget__item:hover {\n\tbackground-color: var(--color-background-hover);\n}\n\n.cn-nc-widget-widget__item--vertical {\n\tflex-direction: row;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-nc-widget-widget__item--horizontal {\n\tflex-direction: column;\n\talign-items: center;\n\twidth: 120px;\n\ttext-align: center;\n}\n\n.cn-nc-widget-widget__item-icon-wrap {\n\twidth: 32px;\n\theight: 32px;\n\tflex: 0 0 32px;\n\tposition: relative;\n}\n\n.cn-nc-widget-widget__item-icon {\n\twidth: 32px;\n\theight: 32px;\n\tobject-fit: cover;\n\tborder-radius: 50%;\n}\n\n.cn-nc-widget-widget__item-overlay {\n\tposition: absolute;\n\tright: -2px;\n\tbottom: -2px;\n\twidth: 14px;\n\theight: 14px;\n}\n\n.cn-nc-widget-widget__item-text {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 0;\n\tflex: 1;\n}\n\n.cn-nc-widget-widget__item-title {\n\tfont-weight: 600;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-nc-widget-widget__item-subtitle {\n\tfont-size: 0.85em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n</style>\n"],"names":["t","axios"],"mappings":"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"}
@@ -1,6 +1,10 @@
1
- import { openBlock, createElementBlock, normalizeClass, createElementVNode, createCommentVNode, toDisplayString, withDirectives, vShow, Fragment, renderList } from 'vue';
1
+ import { openBlock, createElementBlock, normalizeClass, createCommentVNode, createElementVNode, toDisplayString, withDirectives, vShow, Fragment, renderList } from 'vue';
2
2
 
3
- const _hoisted_1 = { class: "cn-nc-widget-widget__header" };
3
+ const _hoisted_1 = {
4
+ key: 0,
5
+ class: "cn-nc-widget-widget__header",
6
+ "data-testid": "cn-nc-widget-header"
7
+ };
4
8
  const _hoisted_2 = ["src"];
5
9
  const _hoisted_3 = { class: "cn-nc-widget-widget__header-title" };
6
10
  const _hoisted_4 = {
@@ -40,23 +44,25 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
40
44
  return (openBlock(), createElementBlock("div", {
41
45
  class: normalizeClass(["cn-nc-widget-widget", { 'cn-nc-widget-widget--horizontal': $options.displayMode === 'horizontal' }])
42
46
  }, [
43
- createElementVNode("header", _hoisted_1, [
44
- ($options.widgetIconUrl)
45
- ? (openBlock(), createElementBlock("img", {
46
- key: 0,
47
- class: "cn-nc-widget-widget__header-icon",
48
- src: $options.widgetIconUrl,
49
- alt: ""
50
- }, null, 8 /* PROPS */, _hoisted_2))
51
- : createCommentVNode("v-if", true),
52
- createElementVNode("span", _hoisted_3, toDisplayString($options.widgetTitle), 1 /* TEXT */)
53
- ]),
47
+ ($options.showsHeader)
48
+ ? (openBlock(), createElementBlock("header", _hoisted_1, [
49
+ ($options.widgetIconUrl)
50
+ ? (openBlock(), createElementBlock("img", {
51
+ key: 0,
52
+ class: "cn-nc-widget-widget__header-icon",
53
+ src: $options.widgetIconUrl,
54
+ alt: ""
55
+ }, null, 8 /* PROPS */, _hoisted_2))
56
+ : createCommentVNode("v-if", true),
57
+ createElementVNode("span", _hoisted_3, toDisplayString($options.widgetTitle), 1 /* TEXT */)
58
+ ]))
59
+ : createCommentVNode("v-if", true),
54
60
  withDirectives(createElementVNode("div", _hoisted_4, null, 512 /* NEED_PATCH */), [
55
61
  [vShow, $data.mode === 'native']
56
62
  ]),
57
63
  ($data.mode !== 'native')
58
64
  ? (openBlock(), createElementBlock("div", {
59
- key: 0,
65
+ key: 1,
60
66
  class: normalizeClass(["cn-nc-widget-widget__body", $options.bodyClass])
61
67
  }, [
62
68
  ($data.loading)
@@ -1 +1 @@
1
- {"version":3,"file":"CnNcWidgetWidget.vue3.js","sources":["../../../../src/components/CnNcWidgetWidget/CnNcWidgetWidget.vue?vue&type=template&id=04be70f3&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-nc-widget-widget\" :class=\"{ 'cn-nc-widget-widget--horizontal': displayMode === 'horizontal' }\">\n\t\t<header class=\"cn-nc-widget-widget__header\">\n\t\t\t<img\n\t\t\t\tv-if=\"widgetIconUrl\"\n\t\t\t\tclass=\"cn-nc-widget-widget__header-icon\"\n\t\t\t\t:src=\"widgetIconUrl\"\n\t\t\t\talt=\"\">\n\t\t\t<span class=\"cn-nc-widget-widget__header-title\">{{ widgetTitle }}</span>\n\t\t</header>\n\n\t\t<!--\n\t\t\tNative callback container — always present but hidden until the\n\t\t\tOCA.Dashboard callback mounts into it. Keeping it mounted avoids a\n\t\t\tflicker when the native path wins after the API list has painted.\n\n\t\t\tThe `--horizontal` reskin class lives on the ROOT element, not here:\n\t\t\tnative widget callbacks mount via `new Vue(...).$mount(el)`, which\n\t\t\tREPLACES this element in the live DOM with the callback's own root\n\t\t\tnode — any class we put directly on it is discarded along with the\n\t\t\telement itself, so it can never appear in the rendered page.\n\t\t-->\n\t\t<div\n\t\t\tv-show=\"mode === 'native'\"\n\t\t\tref=\"nativeContainer\"\n\t\t\tclass=\"cn-nc-widget-widget__native\" />\n\n\t\t<div\n\t\t\tv-if=\"mode !== 'native'\"\n\t\t\tclass=\"cn-nc-widget-widget__body\"\n\t\t\t:class=\"bodyClass\">\n\t\t\t<div v-if=\"loading\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'Loading…') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"!widgetId\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'No widget selected') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"unsupported\" class=\"cn-nc-widget-widget__state\" data-testid=\"nc-widget-unsupported\">\n\t\t\t\t{{ t('nextcloud-vue', 'This widget can only be shown on the Nextcloud dashboard itself.') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"items.length === 0\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'No items available') }}\n\t\t\t</div>\n\n\t\t\t<template v-else>\n\t\t\t\t<a\n\t\t\t\t\tv-for=\"(item, idx) in shownItems\"\n\t\t\t\t\t:key=\"item.sinceId || item.id || idx\"\n\t\t\t\t\tclass=\"cn-nc-widget-widget__item\"\n\t\t\t\t\t:class=\"itemClass\"\n\t\t\t\t\t:href=\"item.link || '#'\"\n\t\t\t\t\t:title=\"item.title\">\n\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-icon-wrap\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"item.iconUrl\"\n\t\t\t\t\t\t\tclass=\"cn-nc-widget-widget__item-icon\"\n\t\t\t\t\t\t\t:src=\"item.iconUrl\"\n\t\t\t\t\t\t\talt=\"\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"item.overlayIconUrl\"\n\t\t\t\t\t\t\tclass=\"cn-nc-widget-widget__item-overlay\"\n\t\t\t\t\t\t\t:src=\"item.overlayIconUrl\"\n\t\t\t\t\t\t\talt=\"\">\n\t\t\t\t\t</span>\n\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-text\">\n\t\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-title\">{{ item.title }}</span>\n\t\t\t\t\t\t<span v-if=\"item.subtitle\" class=\"cn-nc-widget-widget__item-subtitle\">{{ item.subtitle }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t</a>\n\t\t\t\t<!-- With a `limit`, the rest is one link away (`showAllUrl`, else the widget's own page). -->\n\t\t\t\t<a\n\t\t\t\t\tv-if=\"showAllHref\"\n\t\t\t\t\tclass=\"cn-nc-widget-widget__show-all\"\n\t\t\t\t\tdata-testid=\"nc-widget-show-all\"\n\t\t\t\t\t:href=\"showAllHref\">\n\t\t\t\t\t{{ showAllLabel }}\n\t\t\t\t</a>\n\t\t\t</template>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateOcsUrl } from '@nextcloud/router'\n\nconst API_ITEM_LIMIT = 7\n\n/**\n * Read the global `OCA.Dashboard` registry without assuming it exists.\n *\n * @return {object|null} the `OCA.Dashboard` object, or `null` when absent.\n */\nfunction getDashboardGlobal() {\n\tif (typeof window === 'undefined') {\n\t\treturn null\n\t}\n\tconst oca = window.OCA\n\treturn oca && oca.Dashboard ? oca.Dashboard : null\n}\n\n/**\n * CnNcWidgetWidget — proxies any native Nextcloud Dashboard widget into a\n * dashboard grid cell.\n *\n * Two-mode rendering (decoupling seam — reads NC directly, no app bridge):\n * - **native** — when the widget bundle has registered a callback on the\n * global `OCA.Dashboard` (`getWidget(id)` / `widgets[id]`), the callback is\n * handed the render container and paints itself (native fast-path).\n * - **api** — otherwise the OCS Dashboard endpoint\n * `/apps/dashboard/api/v{1,2}/widget-items` is fetched directly via\n * `@nextcloud/axios` and a flat item list is rendered.\n *\n * The header title + icon come from the dashboard widget metadata\n * (`OCA.Dashboard` registry, falling back to the configured `widgetId`). When\n * no `widgetId` is configured the widget renders an empty state and never hits\n * the network.\n *\n * @spec openspec/changes/cn-widget-library/specs/cn-widget-library/spec.md\n */\nexport default {\n\tname: 'CnNcWidgetWidget',\n\n\tprops: {\n\t\t/**\n\t\t * Persisted widget content `{widgetId, displayMode, limit?, showAllUrl?, showAllLabel?}`.\n\t\t * `limit` is the most items shown (the list then comes from the items\n\t\t * API, so it fits its cell); `showAllUrl` / `showAllLabel` the link to\n\t\t * the rest (default the widget's own page and \"Show all\").\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\t/** @type {'pending'|'native'|'api'} the resolved mounting mode. */\n\t\t\tmode: 'pending',\n\t\t\t/**\n\t\t\t * Whether the items API has no entry for this widget at all.\n\t\t\t *\n\t\t\t * Not the same as an empty list. A widget whose provider implements\n\t\t\t * only `IWidget` (no `IAPIWidget`/`IAPIWidgetV2`) declares\n\t\t\t * `itemApiVersions: []` and is simply ABSENT from the widget-items\n\t\t\t * response, while a widget with nothing to show right now comes\n\t\t\t * back as its own key holding an empty list. The Tasks app's widget\n\t\t\t * is the first kind: with no native callback registered on the page\n\t\t\t * it can never render a single item here, and saying \"No items\n\t\t\t * available\" under it told the reader their task list was empty.\n\t\t\t *\n\t\t\t * @type {boolean}\n\t\t\t */\n\t\t\tunsupported: false,\n\t\t\tloading: false,\n\t\t\titems: [],\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The configured native widget id.\n\t\t *\n\t\t * @return {string} the widget id (empty when unset).\n\t\t */\n\t\twidgetId() {\n\t\t\treturn typeof (this.content && this.content.widgetId) === 'string' ? this.content.widgetId : ''\n\t\t},\n\n\t\t/**\n\t\t * The item list orientation.\n\t\t *\n\t\t * @return {string} `horizontal` or `vertical`.\n\t\t */\n\t\tdisplayMode() {\n\t\t\treturn (this.content && this.content.displayMode) === 'horizontal' ? 'horizontal' : 'vertical'\n\t\t},\n\n\t\t/**\n\t\t * The native widget metadata from the `OCA.Dashboard` global.\n\t\t *\n\t\t * @return {object|null} the widget metadata, or `null`.\n\t\t */\n\t\twidgetMeta() {\n\t\t\tconst dashboard = getDashboardGlobal()\n\t\t\tif (!dashboard || !this.widgetId) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (typeof dashboard.getWidget === 'function') {\n\t\t\t\treturn dashboard.getWidget(this.widgetId) || null\n\t\t\t}\n\t\t\tif (dashboard.widgets && typeof dashboard.widgets === 'object') {\n\t\t\t\treturn dashboard.widgets[this.widgetId] || null\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * The header title.\n\t\t *\n\t\t * @return {string} the title.\n\t\t */\n\t\twidgetTitle() {\n\t\t\treturn (this.widgetMeta && this.widgetMeta.title) || this.widgetId || t('nextcloud-vue', 'Widget')\n\t\t},\n\n\t\t/**\n\t\t * The header icon URL.\n\t\t *\n\t\t * @return {string} the icon URL (empty when none).\n\t\t */\n\t\twidgetIconUrl() {\n\t\t\treturn (this.widgetMeta && this.widgetMeta.iconUrl) || ''\n\t\t},\n\n\t\t/**\n\t\t * The most items the list shows (`content.limit`), or 0 for no limit.\n\t\t * A limit lets the widget fit a dashboard cell instead of scrolling\n\t\t * inside it.\n\t\t *\n\t\t * @spec openspec/changes/screens-nc-widget-limit/specs/nc-widget/spec.md#requirement-a-nextcloud-widget-shows-at-most-its-limit\n\t\t * @return {number} the limit.\n\t\t */\n\t\titemLimit() {\n\t\t\tconst limit = Number(this.content && this.content.limit)\n\t\t\treturn Number.isInteger(limit) && limit > 0 ? limit : 0\n\t\t},\n\n\t\t/**\n\t\t * The items drawn: at most `itemLimit`.\n\t\t *\n\t\t * @return {object[]} the items.\n\t\t */\n\t\tshownItems() {\n\t\t\treturn this.itemLimit > 0 ? this.items.slice(0, this.itemLimit) : this.items\n\t\t},\n\n\t\t/**\n\t\t * Where \"Show all\" goes: `content.showAllUrl`, else the page the widget\n\t\t * names itself (its `url`). Only with a limit; '' for no link.\n\t\t *\n\t\t * @spec openspec/changes/screens-nc-widget-limit/specs/nc-widget/spec.md#requirement-a-nextcloud-widget-shows-at-most-its-limit\n\t\t * @return {string} the URL.\n\t\t */\n\t\tshowAllHref() {\n\t\t\tif (this.itemLimit === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst own = this.content && typeof this.content.showAllUrl === 'string' ? this.content.showAllUrl : ''\n\t\t\treturn own || (this.widgetMeta && typeof this.widgetMeta.url === 'string' ? this.widgetMeta.url : '')\n\t\t},\n\n\t\t/**\n\t\t * The \"Show all\" text (`content.showAllLabel`, else the library's).\n\t\t *\n\t\t * @return {string} the label.\n\t\t */\n\t\tshowAllLabel() {\n\t\t\tconst label = this.content && this.content.showAllLabel\n\t\t\treturn typeof label === 'string' && label !== '' ? label : t('nextcloud-vue', 'Show all')\n\t\t},\n\n\t\t/**\n\t\t * The body orientation CSS modifier class.\n\t\t *\n\t\t * @return {string} the body class.\n\t\t */\n\t\tbodyClass() {\n\t\t\treturn `cn-nc-widget-widget__body--${this.displayMode}`\n\t\t},\n\n\t\t/**\n\t\t * The item orientation CSS modifier class.\n\t\t *\n\t\t * @return {string} the item class.\n\t\t */\n\t\titemClass() {\n\t\t\treturn `cn-nc-widget-widget__item--${this.displayMode}`\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.tryMount()\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Resolve the mounting mode. Prefers the native `OCA.Dashboard`\n\t\t * callback fast-path; otherwise falls back to the OCS item list.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\ttryMount() {\n\t\t\tif (!this.widgetId) {\n\t\t\t\tthis.mode = 'api'\n\t\t\t\tthis.items = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// The native callback paints its own opaque markup, so `displayMode`\n\t\t\t// (bodyClass/itemClass below) has no effect on it — only the API\n\t\t\t// item list honours the vertical/horizontal setting. Horizontal mode\n\t\t\t// must therefore skip the native fast-path, or the \"Horizontal\n\t\t\t// (cards)\" option would silently do nothing for the (common) case\n\t\t\t// where the widget has a registered native callback.\n\t\t\t// A `limit` also takes the API list first: the native callback paints\n\t\t\t// as many items as it likes. Its fallback to native stays.\n\t\t\tif (this.displayMode !== 'horizontal' && this.itemLimit === 0) {\n\t\t\t\tconst callback = this.resolveNativeCallback()\n\t\t\t\tif (typeof callback === 'function') {\n\t\t\t\t\tthis.mountNative(callback)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.mode = 'api'\n\t\t\tthis.loadApiItems()\n\t\t},\n\n\t\t/**\n\t\t * Look up a native render callback on the `OCA.Dashboard` global.\n\t\t *\n\t\t * @return {((el: HTMLElement, ctx: {widget: object}) => unknown)|null} the callback, or `null` when none is registered.\n\t\t */\n\t\tresolveNativeCallback() {\n\t\t\tconst dashboard = getDashboardGlobal()\n\t\t\tif (!dashboard) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (this.widgetMeta && typeof this.widgetMeta.callback === 'function') {\n\t\t\t\treturn this.widgetMeta.callback\n\t\t\t}\n\t\t\tif (dashboard.callbacks && typeof dashboard.callbacks[this.widgetId] === 'function') {\n\t\t\t\treturn dashboard.callbacks[this.widgetId]\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Mount the widget natively by invoking its registered callback with\n\t\t * our render container.\n\t\t *\n\t\t * @param {(el: HTMLElement, ctx: {widget: object}) => unknown} callback the native render callback.\n\t\t * @return {void}\n\t\t */\n\t\tmountNative(callback) {\n\t\t\tthis.mode = 'native'\n\t\t\tthis.$nextTick(() => {\n\t\t\t\tconst container = this.$refs.nativeContainer\n\t\t\t\tif (!container) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// Native callback failed — fall back to the API list.\n\t\t\t\tconst fallback = () => {\n\t\t\t\t\tthis.mode = 'api'\n\t\t\t\t\tthis.loadApiItems()\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\t// NC dashboard widgets are registered as\n\t\t\t\t\t// `register(id, (el, { widget }) => …)` — the second argument\n\t\t\t\t\t// MUST be the `{ widget }` envelope, not the bare metadata, or\n\t\t\t\t\t// the widget destructures `widget` as undefined and throws on\n\t\t\t\t\t// first use (e.g. `widget.title`).\n\t\t\t\t\tconst result = callback(container, { widget: this.widgetMeta || {} })\n\t\t\t\t\t// Most widget callbacks are async; a synchronous try/catch\n\t\t\t\t\t// can't see a rejected promise, so wire the fallback to it too.\n\t\t\t\t\tif (result && typeof result.then === 'function') {\n\t\t\t\t\t\tresult.catch(fallback)\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\tfallback()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Fetch the API fallback list directly from the OCS Dashboard\n\t\t * endpoint. Malformed or failed responses collapse to an empty list\n\t\t * (the empty state) instead of throwing.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadApiItems() {\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\t// The v2 widget-items API only returns an entry for widgets\n\t\t\t\t// whose server-side provider implements `IAPIWidgetV2` — plenty\n\t\t\t\t// of native dashboard widgets are JS-callback-only (`IWidget`)\n\t\t\t\t// and never appear in this response at all, which looks\n\t\t\t\t// identical to \"0 items\" from here. extractItems() tolerates\n\t\t\t\t// both the flat-array (older providers) and `{items}` (v2) shapes.\n\t\t\t\tconst url = generateOcsUrl('/apps/dashboard/api/v2/widget-items')\n\t\t\t\tconst response = await axios.get(url, {\n\t\t\t\t\tparams: { widgets: [this.widgetId], limit: this.itemLimit > 0 ? this.itemLimit : API_ITEM_LIMIT },\n\t\t\t\t})\n\t\t\t\tconst data = response && response.data && response.data.ocs ? response.data.ocs.data : null\n\t\t\t\tconst widgetData = data ? data[this.widgetId] : null\n\t\t\t\tthis.items = this.extractItems(widgetData)\n\t\t\t\t// Only a SUCCESSFUL response can say the widget is absent. A\n\t\t\t\t// failed request says nothing about the widget, so it keeps\n\t\t\t\t// the ordinary empty state rather than a claim about the app.\n\t\t\t\tthis.unsupported = data !== null && (widgetData === null || widgetData === undefined)\n\t\t\t} catch {\n\t\t\t\tthis.items = []\n\t\t\t\tthis.unsupported = false\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\n\t\t\t// Horizontal mode deliberately skips the native fast-path (see\n\t\t\t// tryMount()) to get the styled card layout. But when the API has\n\t\t\t// no entry for this widget at all — no `IAPIWidgetV2` support, not\n\t\t\t// \"no items right now\" — that would render a false empty state for\n\t\t\t// a widget that actually has content. Fall back to native\n\t\t\t// rendering rather than lying about there being nothing to show.\n\t\t\tif (this.items.length === 0) {\n\t\t\t\tconst callback = this.resolveNativeCallback()\n\t\t\t\tif (typeof callback === 'function') {\n\t\t\t\t\tthis.mountNative(callback)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Normalise a per-widget OCS payload to an items array, tolerating both\n\t\t * the flat array and the `{items}` envelope shapes.\n\t\t *\n\t\t * @param {unknown} widgetData the per-widget payload.\n\t\t * @return {object[]} the items array (possibly empty).\n\t\t */\n\t\textractItems(widgetData) {\n\t\t\tif (!widgetData) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tif (Array.isArray(widgetData)) {\n\t\t\t\treturn widgetData\n\t\t\t}\n\t\t\tif (Array.isArray(widgetData.items)) {\n\t\t\t\treturn widgetData.items\n\t\t\t}\n\t\t\tif (widgetData.items && typeof widgetData.items === 'object') {\n\t\t\t\treturn Object.values(widgetData.items)\n\t\t\t}\n\t\t\treturn []\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-nc-widget-widget {\n\tdisplay: flex;\n\tflex-direction: column;\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n}\n\n/*\n * Header + content match the native Nextcloud Dashboard panel (apps/dashboard)\n * exactly — this component's whole job is rendering NC dashboard widgets, so it\n * should look native by default: 16px header, 32px leading icon with a 16px\n * gap, a 20px/700 title, and the native panel content inset (16px sides +\n * bottom, flush to the header on top). Same design tokens as core; overridable\n * via the host's CnWidgetWrapper styleConfig / nldesign.\n */\n.cn-nc-widget-widget__header {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 16px;\n\tpadding: 16px;\n\tfont-weight: 700;\n}\n\n.cn-nc-widget-widget__header-icon {\n\twidth: 32px;\n\theight: 32px;\n\tflex: 0 0 auto;\n}\n\n.cn-nc-widget-widget__header-title {\n\tflex: 1;\n\tfont-size: 20px;\n\tfont-weight: 700;\n\tline-height: 24px;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-nc-widget-widget__show-all {\n\talign-self: flex-start;\n\tpadding: 8px 0 0;\n\tcolor: var(--color-primary-element);\n\tfont-weight: 600;\n\ttext-decoration: none;\n}\n\n.cn-nc-widget-widget__show-all:hover,\n.cn-nc-widget-widget__show-all:focus-visible {\n\ttext-decoration: underline;\n}\n\n.cn-nc-widget-widget__native {\n\tflex: 1;\n\toverflow: auto;\n\tpadding: 0 16px 16px;\n}\n\n/*\n * The native `OCA.Dashboard` callback paints its own markup we don't control\n * — for first-party widgets that's almost always `@nextcloud/vue`'s\n * `NcDashboardWidget` / `NcDashboardWidgetItem` (`.dashboard-widget` wrapping\n * a bare `<ul>`/`<li>` list, each item a `.item-list__entry`).\n *\n * Only the LIST CONTAINER is retiled into a grid here — `.item-list__entry`'s\n * own internal layout is left untouched. An earlier version of this override\n * also forced `.item-list__entry` from row to column, but its icon-overlay\n * badge (`.item-icon`, see @nextcloud/vue's NcDashboardWidgetItem CSS) is\n * positioned with negative margins calibrated for the row layout, so\n * flipping to column made items visually overlap. Tiling the `<li>`s into a\n * grid while each entry keeps its normal icon+text row reads as a grid of\n * card tiles without touching that internal math.\n *\n * Scoped from `.cn-nc-widget-widget--horizontal` on the ROOT element, not\n * `.cn-nc-widget-widget__native`: the callback mounts via `.$mount(el)`,\n * which replaces `nativeContainer` in the live DOM outright, so any class\n * placed directly on it never survives to be selectable.\n *\n * The 250px column floor matches `.item-list__entry`'s own natural minimum\n * width (avatar + padding + its un-truncatable-below-this content) — a grid\n * track narrower than that squeezes the entry below its real minimum and it\n * overflows into the neighbouring cell. `min-width: 0` on the `<li>` alone\n * isn't enough to shrink it further: the item's own internal flex layout\n * still claims that much room regardless of the grid track size, so the\n * track itself must not go below it.\n */\n.cn-nc-widget-widget--horizontal :deep(.dashboard-widget > ul) {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n\tgap: 8px;\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-nc-widget-widget--horizontal :deep(.dashboard-widget > ul > li) {\n\twidth: auto;\n\tmin-width: 0;\n}\n\n.cn-nc-widget-widget--horizontal :deep(.item-list__entry) {\n\theight: 100%;\n\tmargin: 0;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large);\n}\n\n.cn-nc-widget-widget__body {\n\tflex: 1;\n\toverflow: auto;\n\tpadding: 0 16px 16px;\n}\n\n.cn-nc-widget-widget__body--vertical {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n}\n\n.cn-nc-widget-widget__body--horizontal {\n\tdisplay: flex;\n\tflex-direction: row;\n\tflex-wrap: wrap;\n\tgap: 12px;\n}\n\n.cn-nc-widget-widget__state {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tflex: 1;\n\tmin-height: 64px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-style: italic;\n}\n\n.cn-nc-widget-widget__item {\n\tdisplay: flex;\n\ttext-decoration: none;\n\tcolor: var(--color-main-text);\n\tborder-radius: var(--border-radius);\n\tpadding: 4px;\n}\n\n.cn-nc-widget-widget__item:hover {\n\tbackground-color: var(--color-background-hover);\n}\n\n.cn-nc-widget-widget__item--vertical {\n\tflex-direction: row;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-nc-widget-widget__item--horizontal {\n\tflex-direction: column;\n\talign-items: center;\n\twidth: 120px;\n\ttext-align: center;\n}\n\n.cn-nc-widget-widget__item-icon-wrap {\n\twidth: 32px;\n\theight: 32px;\n\tflex: 0 0 32px;\n\tposition: relative;\n}\n\n.cn-nc-widget-widget__item-icon {\n\twidth: 32px;\n\theight: 32px;\n\tobject-fit: cover;\n\tborder-radius: 50%;\n}\n\n.cn-nc-widget-widget__item-overlay {\n\tposition: absolute;\n\tright: -2px;\n\tbottom: -2px;\n\twidth: 14px;\n\theight: 14px;\n}\n\n.cn-nc-widget-widget__item-text {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 0;\n\tflex: 1;\n}\n\n.cn-nc-widget-widget__item-title {\n\tfont-weight: 600;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-nc-widget-widget__item-subtitle {\n\tfont-size: 0.85em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_createElementVNode","_toDisplayString","_withDirectives","_openBlock","_Fragment","_renderList"],"mappings":";;AAYU,MAAA,UAAA,GAAA,EAAA,KAAA,EAAA,6BAAA,GAAA;;AAMD,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,mCAAmC,GAAA;;AAgB/C,EAAA,GAAG,EAAC,iBAAiB;AACrB,EAAA,KAAK,EAAC,6BAAY;;;;AAME,EAAA,KAAK,8BAAqB;;;;AAInB,EAAA,KAAK,EAAC,4BAA4B;;;;AAIhC,EAAA,KAAK,EAAC,4BAAW;AAAA,EAAA,aAAA,EAAA,uBAAA;;;;AAI5C,EAAA,KAAA,EAAA,4BAAA;;;AAYM,MAAA,WAAA,GAAA,EAAA,KAAE,EAAA,qCAAA,GAAA;;;AAYF,MAAA,WAAA,GAAA,EAAA,KAAK,EAAC,gCAAgC,GAAA;AAC5C,MAAA,WAAA,GAAA,EAAA,KAAA,EAAA,iCAAA,GAAA;;;AACiB,EAAA,KAAA,EAAA,oCAAA;;;;;uBApElBA;IAAE,KAAK,EAAAC,cAAA,CAAA,CAAC,qBAAW,EAAA,EAAA,iCAAA,EAAA,QAAA,CAAA,WAAA,KAAA,YAAA,EAAA,CAAA,CAAA;;AACnB,IAAAC,kBAAA,CAOO,UAPP,UAOO,EAAA;OALD,QAAA,CAAA,aAAA;wBADPF,kBAIQ,CAAA,KAAA,EAAA;;;AADN,YAAA,GAAA,EAAA,QAAA,CAAA,aAAA;AACD,YAAA,GAAG,EAAC,EAAE;;;MACPE,kBAAiE,CAAA,MAAA,EAAjE,UAAiE,EAAAC,eAAA,CAAd,QAAW,CAAA,WAAA,CAAA,EAAA,CAAA,YAAA;;AAc/D,IAAAC,cAAA,CAAAF,kBAAA,CAGmB,OAHnB,UAGmB,EAAA,IAAA,EAAA,GAAA,kBAAA,EAAA;cAFV,KAAI,CAAA,IAAA,KAAA,QAAA,CAAA;;KAKP,KAAA,CAAA,IAAA,KAAA,QAAA;sBADJF;;8DAGO,QAAS,CAAA,SAAA,CAAA,CAAA;;WACN,KAAO,CAAA,OAAA;4BAAjBA,0BAAA,4BACG,QAAC,CAAA,CAAA,CAAA,eAAA,EAAA,UAAA,CAAA,CAAA,EAAA,CAAA,YAAA;gBAGY,QAAQ,CAAA,QAAA;8BAAxBA,0BAAA,4BACG,QAAC,CAAA,CAAA,CAAA,eAAA,EAAA,oBAAA,CAAA,CAAA,EAAA,CAAA,YAAA;iBAGW,KAAW,CAAA,WAAA;gCAA1BA,0BAAA,4BACG,QAAC,CAAA,CAAA,CAAA,eAAA,EAAA,kEAAA,CAAA,CAAA,EAAA,CAAA,YAAA;AAGH,kBAAA,CAAA,KAAA,CAAA,KAAA,CAAA,MAAA,KAAA,CAAA;oDAEI,CAAA,KAAA,YAAA,EAAAG,eAAA,CADF,QAAC,CAAA,CAAA,CAAA,eAAA,EAAA,oBAAA,CAAA,CAAA,EAAA,CAAA,YAAA;kCAGHH;AACA,uBAAAK,SAAA,CAAA,IAAA,CAAA,EAAAL,kBAAA,CAuBGM,QAtBgB,EAAA,IAAA,EAAAC,UAAA,CAAA,QAAA,CAAA,UAAA,EAAX,CAAA,IAAI,EAAE,GAAG,KAAA;6CADjBP,kBAuBG,CAAA,GAAA,EAAA;0BArBF,GAAG,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,EAAE,IAAI,GAAG;0BACnC,KAAG,EAAAC,cAAA,CAAA,CAAA,2BAAA,EACI,QAAS,CAAA,SAAA,CAAA,CAAA;0BACf,IAAG,EAAE,IAAI,CAAC,IAAI,IAAA,GAAA;0BACd,KAAI,EAAE,IAAI,CAAC,KAAK;;AAChB,0BAAAC,kBAAA,CAWA,QAXA,WAWA,EAAA;AATM,4BAAA,CAAA,IAAI,CAAC,OAAO;8CADnBF,kBAIO,CAAA,KAAA,EAAA;;AAFN,kCAAA,KAAK,EAAC,gCAAgC;kCACrC,GAAG,EAAE,IAAI,CAAC,OAAO;AAClB,kCAAA,GAAG,EAAC,EAAE;;;AAEA,4BAAA,CAAA,IAAI,CAAC,cAAc;8CAD1BA,kBAIK,CAAA,KAAA,EAAA;;AAFJ,kCAAA,KAAK,EAAC,mCAAmC;kCACxC,KAAK,IAAI,CAAC;AACX,kCAAA,GAAG,EAAC,EAAA;;;;AAEN,0BAAAE,kBAAA,CAGO,QAHP,WAGO,EAAA;AAFP,4BAAAA,kBAAA,CAAA,MAAA,EAAA,WAAA,EAAAC,eAAA,CAAA,IAAA,CAAA,KAAA,CAAA,EAAA,CAAA,YAAA;AACa,4BAAA,CAAA,IAAI,CAAA,QAAA;AAAhB,iCAAAE,SAAA,EAAA,EAAAL,kBAAA,CAAgB,MAAhB,EAAA,WAAgB,EAAAG,eAAA,CAAA,IAAA,CAAA,QAAA,CAAA,EAAA,CAAA,YAAA;;;;;uBAKf,QAAA,CAAA,WAAA;wCADFH;;AAEA,4BAAA,KAAK,EAAC,+BAAE;AACR,4BAAA,aAAE,EAAA,oBAAA;AACD,4BAAA,IAAA,EAAA,QAAA,CAAA,WAAA;;;;;;;;;;;"}
1
+ {"version":3,"file":"CnNcWidgetWidget.vue3.js","sources":["../../../../src/components/CnNcWidgetWidget/CnNcWidgetWidget.vue?vue&type=template&id=f553a198&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-nc-widget-widget\" :class=\"{ 'cn-nc-widget-widget--horizontal': displayMode === 'horizontal' }\">\n\t\t<header v-if=\"showsHeader\" class=\"cn-nc-widget-widget__header\" data-testid=\"cn-nc-widget-header\">\n\t\t\t<img\n\t\t\t\tv-if=\"widgetIconUrl\"\n\t\t\t\tclass=\"cn-nc-widget-widget__header-icon\"\n\t\t\t\t:src=\"widgetIconUrl\"\n\t\t\t\talt=\"\">\n\t\t\t<span class=\"cn-nc-widget-widget__header-title\">{{ widgetTitle }}</span>\n\t\t</header>\n\n\t\t<!--\n\t\t\tNative callback container — always present but hidden until the\n\t\t\tOCA.Dashboard callback mounts into it. Keeping it mounted avoids a\n\t\t\tflicker when the native path wins after the API list has painted.\n\n\t\t\tThe `--horizontal` reskin class lives on the ROOT element, not here:\n\t\t\tnative widget callbacks mount via `new Vue(...).$mount(el)`, which\n\t\t\tREPLACES this element in the live DOM with the callback's own root\n\t\t\tnode — any class we put directly on it is discarded along with the\n\t\t\telement itself, so it can never appear in the rendered page.\n\t\t-->\n\t\t<div\n\t\t\tv-show=\"mode === 'native'\"\n\t\t\tref=\"nativeContainer\"\n\t\t\tclass=\"cn-nc-widget-widget__native\" />\n\n\t\t<div\n\t\t\tv-if=\"mode !== 'native'\"\n\t\t\tclass=\"cn-nc-widget-widget__body\"\n\t\t\t:class=\"bodyClass\">\n\t\t\t<div v-if=\"loading\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'Loading…') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"!widgetId\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'No widget selected') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"unsupported\" class=\"cn-nc-widget-widget__state\" data-testid=\"nc-widget-unsupported\">\n\t\t\t\t{{ t('nextcloud-vue', 'This widget can only be shown on the Nextcloud dashboard itself.') }}\n\t\t\t</div>\n\n\t\t\t<div v-else-if=\"items.length === 0\" class=\"cn-nc-widget-widget__state\">\n\t\t\t\t{{ t('nextcloud-vue', 'No items available') }}\n\t\t\t</div>\n\n\t\t\t<template v-else>\n\t\t\t\t<a\n\t\t\t\t\tv-for=\"(item, idx) in shownItems\"\n\t\t\t\t\t:key=\"item.sinceId || item.id || idx\"\n\t\t\t\t\tclass=\"cn-nc-widget-widget__item\"\n\t\t\t\t\t:class=\"itemClass\"\n\t\t\t\t\t:href=\"item.link || '#'\"\n\t\t\t\t\t:title=\"item.title\">\n\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-icon-wrap\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"item.iconUrl\"\n\t\t\t\t\t\t\tclass=\"cn-nc-widget-widget__item-icon\"\n\t\t\t\t\t\t\t:src=\"item.iconUrl\"\n\t\t\t\t\t\t\talt=\"\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"item.overlayIconUrl\"\n\t\t\t\t\t\t\tclass=\"cn-nc-widget-widget__item-overlay\"\n\t\t\t\t\t\t\t:src=\"item.overlayIconUrl\"\n\t\t\t\t\t\t\talt=\"\">\n\t\t\t\t\t</span>\n\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-text\">\n\t\t\t\t\t\t<span class=\"cn-nc-widget-widget__item-title\">{{ item.title }}</span>\n\t\t\t\t\t\t<span v-if=\"item.subtitle\" class=\"cn-nc-widget-widget__item-subtitle\">{{ item.subtitle }}</span>\n\t\t\t\t\t</span>\n\t\t\t\t</a>\n\t\t\t\t<!-- With a `limit`, the rest is one link away (`showAllUrl`, else the widget's own page). -->\n\t\t\t\t<a\n\t\t\t\t\tv-if=\"showAllHref\"\n\t\t\t\t\tclass=\"cn-nc-widget-widget__show-all\"\n\t\t\t\t\tdata-testid=\"nc-widget-show-all\"\n\t\t\t\t\t:href=\"showAllHref\">\n\t\t\t\t\t{{ showAllLabel }}\n\t\t\t\t</a>\n\t\t\t</template>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateOcsUrl } from '@nextcloud/router'\n\nconst API_ITEM_LIMIT = 7\n\n/**\n * Read the global `OCA.Dashboard` registry without assuming it exists.\n *\n * @return {object|null} the `OCA.Dashboard` object, or `null` when absent.\n */\nfunction getDashboardGlobal() {\n\tif (typeof window === 'undefined') {\n\t\treturn null\n\t}\n\tconst oca = window.OCA\n\treturn oca && oca.Dashboard ? oca.Dashboard : null\n}\n\n/**\n * CnNcWidgetWidget — proxies any native Nextcloud Dashboard widget into a\n * dashboard grid cell.\n *\n * Two-mode rendering (decoupling seam — reads NC directly, no app bridge):\n * - **native** — when the widget bundle has registered a callback on the\n * global `OCA.Dashboard` (`getWidget(id)` / `widgets[id]`), the callback is\n * handed the render container and paints itself (native fast-path).\n * - **api** — otherwise the OCS Dashboard endpoint\n * `/apps/dashboard/api/v{1,2}/widget-items` is fetched directly via\n * `@nextcloud/axios` and a flat item list is rendered.\n *\n * The header title + icon come from the dashboard widget metadata\n * (`OCA.Dashboard` registry, falling back to the configured `widgetId`). When\n * no `widgetId` is configured the widget renders an empty state and never hits\n * the network.\n *\n * @spec openspec/changes/cn-widget-library/specs/cn-widget-library/spec.md\n */\nexport default {\n\tname: 'CnNcWidgetWidget',\n\n\tinject: {\n\t\t/** Whether the hosting card draws a title row (CnWidgetWrapper). */\n\t\tcnWidgetTitled: { default: null },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * Persisted widget content `{widgetId, displayMode, limit?, showAllUrl?, showAllLabel?, showHeader?}`.\n\t\t * `showHeader: false` drops the widget's own header (icon and title);\n\t\t * it is dropped too when the hosting card draws a title row.\n\t\t * `limit` is the most items shown (the list then comes from the items\n\t\t * API, so it fits its cell); `showAllUrl` / `showAllLabel` the link to\n\t\t * the rest (default the widget's own page and \"Show all\").\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\t/** @type {'pending'|'native'|'api'} the resolved mounting mode. */\n\t\t\tmode: 'pending',\n\t\t\t/**\n\t\t\t * Whether the items API has no entry for this widget at all.\n\t\t\t *\n\t\t\t * Not the same as an empty list. A widget whose provider implements\n\t\t\t * only `IWidget` (no `IAPIWidget`/`IAPIWidgetV2`) declares\n\t\t\t * `itemApiVersions: []` and is simply ABSENT from the widget-items\n\t\t\t * response, while a widget with nothing to show right now comes\n\t\t\t * back as its own key holding an empty list. The Tasks app's widget\n\t\t\t * is the first kind: with no native callback registered on the page\n\t\t\t * it can never render a single item here, and saying \"No items\n\t\t\t * available\" under it told the reader their task list was empty.\n\t\t\t *\n\t\t\t * @type {boolean}\n\t\t\t */\n\t\t\tunsupported: false,\n\t\t\tloading: false,\n\t\t\titems: [],\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The configured native widget id.\n\t\t *\n\t\t * @return {string} the widget id (empty when unset).\n\t\t */\n\t\twidgetId() {\n\t\t\treturn typeof (this.content && this.content.widgetId) === 'string' ? this.content.widgetId : ''\n\t\t},\n\n\t\t/**\n\t\t * The item list orientation.\n\t\t *\n\t\t * @return {string} `horizontal` or `vertical`.\n\t\t */\n\t\tdisplayMode() {\n\t\t\treturn (this.content && this.content.displayMode) === 'horizontal' ? 'horizontal' : 'vertical'\n\t\t},\n\n\t\t/**\n\t\t * The native widget metadata from the `OCA.Dashboard` global.\n\t\t *\n\t\t * @return {object|null} the widget metadata, or `null`.\n\t\t */\n\t\twidgetMeta() {\n\t\t\tconst dashboard = getDashboardGlobal()\n\t\t\tif (!dashboard || !this.widgetId) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (typeof dashboard.getWidget === 'function') {\n\t\t\t\treturn dashboard.getWidget(this.widgetId) || null\n\t\t\t}\n\t\t\tif (dashboard.widgets && typeof dashboard.widgets === 'object') {\n\t\t\t\treturn dashboard.widgets[this.widgetId] || null\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Whether the widget draws its own header: not with\n\t\t * `content.showHeader: false`, nor inside a card that draws a title.\n\t\t *\n\t\t * @spec openspec/changes/nc-widget-header/specs/nc-widget-header/spec.md#requirement-a-nextcloud-widget-draws-no-second-heading\n\t\t * @return {boolean}\n\t\t */\n\t\tshowsHeader() {\n\t\t\tif (this.content && this.content.showHeader === false) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !(typeof this.cnWidgetTitled === 'function' && this.cnWidgetTitled())\n\t\t},\n\n\t\t/**\n\t\t * The header title.\n\t\t *\n\t\t * @return {string} the title.\n\t\t */\n\t\twidgetTitle() {\n\t\t\treturn (this.widgetMeta && this.widgetMeta.title) || this.widgetId || t('nextcloud-vue', 'Widget')\n\t\t},\n\n\t\t/**\n\t\t * The header icon URL.\n\t\t *\n\t\t * @return {string} the icon URL (empty when none).\n\t\t */\n\t\twidgetIconUrl() {\n\t\t\treturn (this.widgetMeta && this.widgetMeta.iconUrl) || ''\n\t\t},\n\n\t\t/**\n\t\t * The most items the list shows (`content.limit`), or 0 for no limit.\n\t\t * A limit lets the widget fit a dashboard cell instead of scrolling\n\t\t * inside it.\n\t\t *\n\t\t * @spec openspec/changes/screens-nc-widget-limit/specs/nc-widget/spec.md#requirement-a-nextcloud-widget-shows-at-most-its-limit\n\t\t * @return {number} the limit.\n\t\t */\n\t\titemLimit() {\n\t\t\tconst limit = Number(this.content && this.content.limit)\n\t\t\treturn Number.isInteger(limit) && limit > 0 ? limit : 0\n\t\t},\n\n\t\t/**\n\t\t * The items drawn: at most `itemLimit`.\n\t\t *\n\t\t * @return {object[]} the items.\n\t\t */\n\t\tshownItems() {\n\t\t\treturn this.itemLimit > 0 ? this.items.slice(0, this.itemLimit) : this.items\n\t\t},\n\n\t\t/**\n\t\t * Where \"Show all\" goes: `content.showAllUrl`, else the page the widget\n\t\t * names itself (its `url`). Only with a limit; '' for no link.\n\t\t *\n\t\t * @spec openspec/changes/screens-nc-widget-limit/specs/nc-widget/spec.md#requirement-a-nextcloud-widget-shows-at-most-its-limit\n\t\t * @return {string} the URL.\n\t\t */\n\t\tshowAllHref() {\n\t\t\tif (this.itemLimit === 0) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst own = this.content && typeof this.content.showAllUrl === 'string' ? this.content.showAllUrl : ''\n\t\t\treturn own || (this.widgetMeta && typeof this.widgetMeta.url === 'string' ? this.widgetMeta.url : '')\n\t\t},\n\n\t\t/**\n\t\t * The \"Show all\" text (`content.showAllLabel`, else the library's).\n\t\t *\n\t\t * @return {string} the label.\n\t\t */\n\t\tshowAllLabel() {\n\t\t\tconst label = this.content && this.content.showAllLabel\n\t\t\treturn typeof label === 'string' && label !== '' ? label : t('nextcloud-vue', 'Show all')\n\t\t},\n\n\t\t/**\n\t\t * The body orientation CSS modifier class.\n\t\t *\n\t\t * @return {string} the body class.\n\t\t */\n\t\tbodyClass() {\n\t\t\treturn `cn-nc-widget-widget__body--${this.displayMode}`\n\t\t},\n\n\t\t/**\n\t\t * The item orientation CSS modifier class.\n\t\t *\n\t\t * @return {string} the item class.\n\t\t */\n\t\titemClass() {\n\t\t\treturn `cn-nc-widget-widget__item--${this.displayMode}`\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.tryMount()\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Resolve the mounting mode. Prefers the native `OCA.Dashboard`\n\t\t * callback fast-path; otherwise falls back to the OCS item list.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\ttryMount() {\n\t\t\tif (!this.widgetId) {\n\t\t\t\tthis.mode = 'api'\n\t\t\t\tthis.items = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// The native callback paints its own opaque markup, so `displayMode`\n\t\t\t// (bodyClass/itemClass below) has no effect on it — only the API\n\t\t\t// item list honours the vertical/horizontal setting. Horizontal mode\n\t\t\t// must therefore skip the native fast-path, or the \"Horizontal\n\t\t\t// (cards)\" option would silently do nothing for the (common) case\n\t\t\t// where the widget has a registered native callback.\n\t\t\t// A `limit` also takes the API list first: the native callback paints\n\t\t\t// as many items as it likes. Its fallback to native stays.\n\t\t\tif (this.displayMode !== 'horizontal' && this.itemLimit === 0) {\n\t\t\t\tconst callback = this.resolveNativeCallback()\n\t\t\t\tif (typeof callback === 'function') {\n\t\t\t\t\tthis.mountNative(callback)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.mode = 'api'\n\t\t\tthis.loadApiItems()\n\t\t},\n\n\t\t/**\n\t\t * Look up a native render callback on the `OCA.Dashboard` global.\n\t\t *\n\t\t * @return {((el: HTMLElement, ctx: {widget: object}) => unknown)|null} the callback, or `null` when none is registered.\n\t\t */\n\t\tresolveNativeCallback() {\n\t\t\tconst dashboard = getDashboardGlobal()\n\t\t\tif (!dashboard) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (this.widgetMeta && typeof this.widgetMeta.callback === 'function') {\n\t\t\t\treturn this.widgetMeta.callback\n\t\t\t}\n\t\t\tif (dashboard.callbacks && typeof dashboard.callbacks[this.widgetId] === 'function') {\n\t\t\t\treturn dashboard.callbacks[this.widgetId]\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Mount the widget natively by invoking its registered callback with\n\t\t * our render container.\n\t\t *\n\t\t * @param {(el: HTMLElement, ctx: {widget: object}) => unknown} callback the native render callback.\n\t\t * @return {void}\n\t\t */\n\t\tmountNative(callback) {\n\t\t\tthis.mode = 'native'\n\t\t\tthis.$nextTick(() => {\n\t\t\t\tconst container = this.$refs.nativeContainer\n\t\t\t\tif (!container) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t// Native callback failed — fall back to the API list.\n\t\t\t\tconst fallback = () => {\n\t\t\t\t\tthis.mode = 'api'\n\t\t\t\t\tthis.loadApiItems()\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\t// NC dashboard widgets are registered as\n\t\t\t\t\t// `register(id, (el, { widget }) => …)` — the second argument\n\t\t\t\t\t// MUST be the `{ widget }` envelope, not the bare metadata, or\n\t\t\t\t\t// the widget destructures `widget` as undefined and throws on\n\t\t\t\t\t// first use (e.g. `widget.title`).\n\t\t\t\t\tconst result = callback(container, { widget: this.widgetMeta || {} })\n\t\t\t\t\t// Most widget callbacks are async; a synchronous try/catch\n\t\t\t\t\t// can't see a rejected promise, so wire the fallback to it too.\n\t\t\t\t\tif (result && typeof result.then === 'function') {\n\t\t\t\t\t\tresult.catch(fallback)\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\tfallback()\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Fetch the API fallback list directly from the OCS Dashboard\n\t\t * endpoint. Malformed or failed responses collapse to an empty list\n\t\t * (the empty state) instead of throwing.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadApiItems() {\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\t// The v2 widget-items API only returns an entry for widgets\n\t\t\t\t// whose server-side provider implements `IAPIWidgetV2` — plenty\n\t\t\t\t// of native dashboard widgets are JS-callback-only (`IWidget`)\n\t\t\t\t// and never appear in this response at all, which looks\n\t\t\t\t// identical to \"0 items\" from here. extractItems() tolerates\n\t\t\t\t// both the flat-array (older providers) and `{items}` (v2) shapes.\n\t\t\t\tconst url = generateOcsUrl('/apps/dashboard/api/v2/widget-items')\n\t\t\t\tconst response = await axios.get(url, {\n\t\t\t\t\tparams: { widgets: [this.widgetId], limit: this.itemLimit > 0 ? this.itemLimit : API_ITEM_LIMIT },\n\t\t\t\t})\n\t\t\t\tconst data = response && response.data && response.data.ocs ? response.data.ocs.data : null\n\t\t\t\tconst widgetData = data ? data[this.widgetId] : null\n\t\t\t\tthis.items = this.extractItems(widgetData)\n\t\t\t\t// Only a SUCCESSFUL response can say the widget is absent. A\n\t\t\t\t// failed request says nothing about the widget, so it keeps\n\t\t\t\t// the ordinary empty state rather than a claim about the app.\n\t\t\t\tthis.unsupported = data !== null && (widgetData === null || widgetData === undefined)\n\t\t\t} catch {\n\t\t\t\tthis.items = []\n\t\t\t\tthis.unsupported = false\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\n\t\t\t// Horizontal mode deliberately skips the native fast-path (see\n\t\t\t// tryMount()) to get the styled card layout. But when the API has\n\t\t\t// no entry for this widget at all — no `IAPIWidgetV2` support, not\n\t\t\t// \"no items right now\" — that would render a false empty state for\n\t\t\t// a widget that actually has content. Fall back to native\n\t\t\t// rendering rather than lying about there being nothing to show.\n\t\t\tif (this.items.length === 0) {\n\t\t\t\tconst callback = this.resolveNativeCallback()\n\t\t\t\tif (typeof callback === 'function') {\n\t\t\t\t\tthis.mountNative(callback)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Normalise a per-widget OCS payload to an items array, tolerating both\n\t\t * the flat array and the `{items}` envelope shapes.\n\t\t *\n\t\t * @param {unknown} widgetData the per-widget payload.\n\t\t * @return {object[]} the items array (possibly empty).\n\t\t */\n\t\textractItems(widgetData) {\n\t\t\tif (!widgetData) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tif (Array.isArray(widgetData)) {\n\t\t\t\treturn widgetData\n\t\t\t}\n\t\t\tif (Array.isArray(widgetData.items)) {\n\t\t\t\treturn widgetData.items\n\t\t\t}\n\t\t\tif (widgetData.items && typeof widgetData.items === 'object') {\n\t\t\t\treturn Object.values(widgetData.items)\n\t\t\t}\n\t\t\treturn []\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-nc-widget-widget {\n\tdisplay: flex;\n\tflex-direction: column;\n\twidth: 100%;\n\theight: 100%;\n\toverflow: hidden;\n}\n\n/*\n * Header + content match the native Nextcloud Dashboard panel (apps/dashboard)\n * exactly — this component's whole job is rendering NC dashboard widgets, so it\n * should look native by default: 16px header, 32px leading icon with a 16px\n * gap, a 20px/700 title, and the native panel content inset (16px sides +\n * bottom, flush to the header on top). Same design tokens as core; overridable\n * via the host's CnWidgetWrapper styleConfig / nldesign.\n */\n.cn-nc-widget-widget__header {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 16px;\n\tpadding: 16px;\n\tfont-weight: 700;\n}\n\n.cn-nc-widget-widget__header-icon {\n\twidth: 32px;\n\theight: 32px;\n\tflex: 0 0 auto;\n}\n\n.cn-nc-widget-widget__header-title {\n\tflex: 1;\n\tfont-size: 20px;\n\tfont-weight: 700;\n\tline-height: 24px;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-nc-widget-widget__show-all {\n\talign-self: flex-start;\n\tpadding: 8px 0 0;\n\tcolor: var(--color-primary-element);\n\tfont-weight: 600;\n\ttext-decoration: none;\n}\n\n.cn-nc-widget-widget__show-all:hover,\n.cn-nc-widget-widget__show-all:focus-visible {\n\ttext-decoration: underline;\n}\n\n.cn-nc-widget-widget__native {\n\tflex: 1;\n\toverflow: auto;\n\tpadding: 0 16px 16px;\n}\n\n/*\n * The native `OCA.Dashboard` callback paints its own markup we don't control\n * — for first-party widgets that's almost always `@nextcloud/vue`'s\n * `NcDashboardWidget` / `NcDashboardWidgetItem` (`.dashboard-widget` wrapping\n * a bare `<ul>`/`<li>` list, each item a `.item-list__entry`).\n *\n * Only the LIST CONTAINER is retiled into a grid here — `.item-list__entry`'s\n * own internal layout is left untouched. An earlier version of this override\n * also forced `.item-list__entry` from row to column, but its icon-overlay\n * badge (`.item-icon`, see @nextcloud/vue's NcDashboardWidgetItem CSS) is\n * positioned with negative margins calibrated for the row layout, so\n * flipping to column made items visually overlap. Tiling the `<li>`s into a\n * grid while each entry keeps its normal icon+text row reads as a grid of\n * card tiles without touching that internal math.\n *\n * Scoped from `.cn-nc-widget-widget--horizontal` on the ROOT element, not\n * `.cn-nc-widget-widget__native`: the callback mounts via `.$mount(el)`,\n * which replaces `nativeContainer` in the live DOM outright, so any class\n * placed directly on it never survives to be selectable.\n *\n * The 250px column floor matches `.item-list__entry`'s own natural minimum\n * width (avatar + padding + its un-truncatable-below-this content) — a grid\n * track narrower than that squeezes the entry below its real minimum and it\n * overflows into the neighbouring cell. `min-width: 0` on the `<li>` alone\n * isn't enough to shrink it further: the item's own internal flex layout\n * still claims that much room regardless of the grid track size, so the\n * track itself must not go below it.\n */\n.cn-nc-widget-widget--horizontal :deep(.dashboard-widget > ul) {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n\tgap: 8px;\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-nc-widget-widget--horizontal :deep(.dashboard-widget > ul > li) {\n\twidth: auto;\n\tmin-width: 0;\n}\n\n.cn-nc-widget-widget--horizontal :deep(.item-list__entry) {\n\theight: 100%;\n\tmargin: 0;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large);\n}\n\n.cn-nc-widget-widget__body {\n\tflex: 1;\n\toverflow: auto;\n\tpadding: 0 16px 16px;\n}\n\n.cn-nc-widget-widget__body--vertical {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n}\n\n.cn-nc-widget-widget__body--horizontal {\n\tdisplay: flex;\n\tflex-direction: row;\n\tflex-wrap: wrap;\n\tgap: 12px;\n}\n\n.cn-nc-widget-widget__state {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tflex: 1;\n\tmin-height: 64px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-style: italic;\n}\n\n.cn-nc-widget-widget__item {\n\tdisplay: flex;\n\ttext-decoration: none;\n\tcolor: var(--color-main-text);\n\tborder-radius: var(--border-radius);\n\tpadding: 4px;\n}\n\n.cn-nc-widget-widget__item:hover {\n\tbackground-color: var(--color-background-hover);\n}\n\n.cn-nc-widget-widget__item--vertical {\n\tflex-direction: row;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-nc-widget-widget__item--horizontal {\n\tflex-direction: column;\n\talign-items: center;\n\twidth: 120px;\n\ttext-align: center;\n}\n\n.cn-nc-widget-widget__item-icon-wrap {\n\twidth: 32px;\n\theight: 32px;\n\tflex: 0 0 32px;\n\tposition: relative;\n}\n\n.cn-nc-widget-widget__item-icon {\n\twidth: 32px;\n\theight: 32px;\n\tobject-fit: cover;\n\tborder-radius: 50%;\n}\n\n.cn-nc-widget-widget__item-overlay {\n\tposition: absolute;\n\tright: -2px;\n\tbottom: -2px;\n\twidth: 14px;\n\theight: 14px;\n}\n\n.cn-nc-widget-widget__item-text {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 0;\n\tflex: 1;\n}\n\n.cn-nc-widget-widget__item-title {\n\tfont-weight: 600;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-nc-widget-widget__item-subtitle {\n\tfont-size: 0.85em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_openBlock","_createElementVNode","_toDisplayString","_withDirectives","_Fragment","_renderList"],"mappings":"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"}