@conduction/nextcloud-vue 2.56.0-beta.11 → 2.56.0-beta.12

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 (100) hide show
  1. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +154 -7
  2. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
  3. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +119 -42
  4. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
  5. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +87 -0
  6. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  7. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +26 -24
  8. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  9. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +61 -16
  10. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js.map +1 -1
  11. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js.map +1 -1
  12. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js +20 -0
  13. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js.map +1 -1
  14. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js +3 -2
  15. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js.map +1 -1
  16. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +33 -2
  17. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  18. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  19. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +29 -0
  20. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  21. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +150 -133
  22. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  23. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +37 -1
  24. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  25. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +12 -4
  26. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  27. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +66 -14
  28. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  29. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +23 -14
  30. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  31. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js +81 -4
  32. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js.map +1 -1
  33. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js +22 -5
  34. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js.map +1 -1
  35. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +30 -0
  36. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  37. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +2 -2
  38. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  39. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +5 -1
  40. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  41. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +4 -2
  42. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  43. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +63 -2
  44. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
  45. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js +96 -37
  46. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
  47. package/dist/esm/components/CnStagesWidget/stagesModel.js +5 -2
  48. package/dist/esm/components/CnStagesWidget/stagesModel.js.map +1 -1
  49. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +52 -2
  50. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  51. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +6 -6
  52. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  53. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +14 -2
  54. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  55. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +2 -1
  56. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  57. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +73 -1
  58. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
  59. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js +14 -2
  60. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
  61. package/dist/esm/l10n/en.json.js +2 -1
  62. package/dist/esm/l10n/en.json.js.map +1 -1
  63. package/dist/esm/l10n/nl.json.js +2 -1
  64. package/dist/esm/l10n/nl.json.js.map +1 -1
  65. package/dist/esm/nextcloud-vue.css +331 -81
  66. package/dist/esm/utils/schemaRefSlug.js +19 -3
  67. package/dist/esm/utils/schemaRefSlug.js.map +1 -1
  68. package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
  69. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  70. package/dist/nextcloud-vue.cjs.js +6933 -5958
  71. package/dist/nextcloud-vue.cjs.js.map +2 -2
  72. package/dist/nextcloud-vue.css +331 -81
  73. package/l10n/en.json +2 -0
  74. package/l10n/nl.json +2 -0
  75. package/package.json +1 -1
  76. package/src/components/CnAppNav/CnAppNav.vue +297 -11
  77. package/src/components/CnAppRoot/CnAppRoot.md +4 -0
  78. package/src/components/CnAppRoot/CnAppRoot.vue +94 -1
  79. package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +61 -16
  80. package/src/components/CnAuditTrailWidget/CnAuditTrailWidget.vue +22 -1
  81. package/src/components/CnCellRenderer/CnCellRenderer.vue +33 -2
  82. package/src/components/CnDashboardPage/CnDashboardPage.vue +43 -2
  83. package/src/components/CnDataTable/CnDataTable.vue +45 -1
  84. package/src/components/CnDetailPage/CnDetailPage.md +4 -0
  85. package/src/components/CnDetailPage/CnDetailPage.vue +60 -1
  86. package/src/components/CnHeaderWidget/CnHeaderWidget.vue +116 -6
  87. package/src/components/CnIndexPage/CnIndexPage.vue +32 -2
  88. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +7 -1
  89. package/src/components/CnStagesWidget/CnStagesWidget.vue +180 -2
  90. package/src/components/CnStagesWidget/stagesModel.js +5 -2
  91. package/src/components/CnStatWidget/CnStatWidget.vue +57 -3
  92. package/src/components/CnTabsWidget/CnTabsWidget.vue +15 -2
  93. package/src/components/CnWidgetWrapper/CnWidgetWrapper.md +4 -0
  94. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +107 -1
  95. package/src/css/detail-page.css +10 -4
  96. package/src/css/kpi-card.css +24 -1
  97. package/src/css/table.css +18 -6
  98. package/src/schemas/app-manifest-v2.schema.json +113 -3
  99. package/src/utils/schemaRefSlug.js +19 -3
  100. package/src/utils/validateManifestV2.compiled.js +2 -2
@@ -10,10 +10,11 @@ import OpenInNew from 'vue-material-design-icons/OpenInNew.vue';
10
10
  import Plus from 'vue-material-design-icons/Plus.vue';
11
11
  import ShieldAccountOutline from 'vue-material-design-icons/ShieldAccountOutline.vue';
12
12
  import '../CnIcon/CnIcon.vue.js';
13
- import __sfc_main from '../CnMenuWidget/CnMenuItemIcon.vue.js';
13
+ import __sfc_main$1 from '../CnMenuWidget/CnMenuItemIcon.vue.js';
14
14
  import { isAppInstalled } from '../../utils/appInstalled.js';
15
15
  import { isSvgPath } from '../../utils/iconUtils.js';
16
16
  import { passesContextPredicates } from '../../utils/visibleIfContext.js';
17
+ import __sfc_main from '../CnActionButtons/CnActionButtons.vue.js';
17
18
  import { bridgedMdiForCssIcon } from '../CnIcon/cssIconBridge.js';
18
19
  import { getSemanticIconComponent } from '../CnIcon/semanticIcons.js';
19
20
  import { isCustomIconUrl, hasRegistryIcon } from '../CnWidgetGrid/widgetIcons.js';
@@ -95,7 +96,8 @@ var script = {
95
96
  NcAppNavigationSettings,
96
97
  NcButton,
97
98
  NcCounterBubble,
98
- CnMenuItemIcon: __sfc_main,
99
+ CnActionButtons: __sfc_main,
100
+ CnMenuItemIcon: __sfc_main$1,
99
101
  Cog,
100
102
  HelpCircleOutline,
101
103
  ShieldAccountOutline,
@@ -141,6 +143,16 @@ var script = {
141
143
  * @type {{ [register: string]: { [schema: string]: number } }}
142
144
  */
143
145
  cnMenuCounts: { default: () => ({}) },
146
+ /**
147
+ * Provided by CnAppRoot — reactive `{ [menuItemId]: number }` totals
148
+ * for every menu entry whose `count` is an object
149
+ * (`{ register, schema, filter? }`): the total of that filtered
150
+ * list, fetched under the entry's own key so an index page's
151
+ * whole-schema total is left alone. Empty outside a CnAppRoot.
152
+ *
153
+ * @type {{ [itemId: string]: number }}
154
+ */
155
+ cnMenuItemCounts: { default: () => ({}) },
144
156
  },
145
157
 
146
158
  props: {
@@ -264,7 +276,7 @@ var script = {
264
276
  },
265
277
  },
266
278
 
267
- emits: ['primary-action', 'primary-action-click'],
279
+ emits: ['primary-action', 'primary-action-click', 'primary-action-created', 'card-action'],
268
280
 
269
281
  /**
270
282
  * The navigation's own state: which groups are open, and which entry
@@ -325,11 +337,70 @@ var script = {
325
337
  const text = (value) => (typeof value === 'string' && value !== '' ? this.effectiveTranslate(value) : '');
326
338
  const brand = {
327
339
  logo: typeof declared.logo === 'string' ? declared.logo : '',
340
+ // A URL, or `true` for the theme's emblem (--nldesign-emblem-url).
341
+ emblem: declared.emblem === true ? true : (typeof declared.emblem === 'string' ? declared.emblem : ''),
328
342
  name: text(declared.name),
329
343
  caption: text(declared.caption),
330
344
  alt: text(declared.alt),
331
345
  };
332
- return (brand.logo || brand.name || brand.caption) ? brand : null
346
+ return (brand.logo || brand.emblem || brand.name || brand.caption) ? brand : null
347
+ },
348
+
349
+ /**
350
+ * The card above the footer entries (`nav.card`): `{ title, text?,
351
+ * link?: { label, route?, params?, href?, action? } }`. Title, text
352
+ * and link label go through the translate function. The link is a
353
+ * router link for a `route` (with a router), an anchor for an
354
+ * `href`, and a button emitting `card-action` with the `action` id
355
+ * otherwise. Null without a title.
356
+ *
357
+ * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-the-navigation-carries-a-card-and-a-help-entry
358
+ * @return {object|null}
359
+ */
360
+ resolvedCard() {
361
+ const declared = this.effectiveManifest?.nav?.card;
362
+ if (!declared || typeof declared !== 'object' || typeof declared.title !== 'string' || declared.title === '') {
363
+ return null
364
+ }
365
+ const text = (value) => (typeof value === 'string' && value !== '' ? this.effectiveTranslate(value) : '');
366
+ const card = { title: text(declared.title), text: text(declared.text), linkTag: '', linkAttrs: {}, linkLabel: '', action: '' };
367
+ const link = declared.link;
368
+ if (link && typeof link === 'object' && typeof link.label === 'string' && link.label !== '') {
369
+ card.linkLabel = text(link.label);
370
+ if (link.route && this.$router) {
371
+ card.linkTag = 'router-link';
372
+ card.linkAttrs = { to: { name: link.route, ...(link.params && typeof link.params === 'object' ? { params: link.params } : {}) } };
373
+ } else if (typeof link.href === 'string' && link.href !== '') {
374
+ card.linkTag = 'a';
375
+ card.linkAttrs = { href: link.href };
376
+ } else if (typeof link.action === 'string' && link.action !== '') {
377
+ card.linkTag = 'button';
378
+ card.linkAttrs = { type: 'button' };
379
+ card.action = link.action;
380
+ }
381
+ }
382
+ return card
383
+ },
384
+
385
+ /**
386
+ * The help entry (`nav.help`): `{ label, route?, href? }` rendered as
387
+ * a footer entry with a help icon. Null without a label or a target.
388
+ *
389
+ * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-the-navigation-carries-a-card-and-a-help-entry
390
+ * @return {{label: string, to?: object, href?: string}|null}
391
+ */
392
+ resolvedHelp() {
393
+ const declared = this.effectiveManifest?.nav?.help;
394
+ if (!declared || typeof declared !== 'object' || typeof declared.label !== 'string' || declared.label === '') {
395
+ return null
396
+ }
397
+ if (declared.route && this.$router) {
398
+ return { label: this.effectiveTranslate(declared.label), to: { name: declared.route }, href: undefined }
399
+ }
400
+ if (typeof declared.href === 'string' && declared.href !== '') {
401
+ return { label: this.effectiveTranslate(declared.label), to: undefined, href: declared.href }
402
+ }
403
+ return null
333
404
  },
334
405
 
335
406
  /**
@@ -350,20 +421,30 @@ var script = {
350
421
  * 2. `manifest.nav.primaryAction` as app-wide default
351
422
  * 3. `null` — no primary-action button renders
352
423
  *
353
- * Page-scoped declarations always win over the nav-root default.
424
+ * Page-scoped declarations always win over the nav-root default. An
425
+ * action declaring `permission` or `visibleIf` is gated like a menu
426
+ * entry.
354
427
  *
428
+ * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-navigation-primary-action-runs-a-page-action
355
429
  * @return {object|null}
356
430
  */
357
431
  activePrimaryAction() {
358
432
  const pages = this.effectiveManifest?.pages ?? [];
359
433
  const routeName = this.$route?.name;
434
+ // The same `permission` / `visibleIf` gate a menu entry has: an
435
+ // action the reader may not take, or that a condition hides, is
436
+ // not drawn. A gated-out page action falls back to the nav one.
437
+ const gated = (action) => (action && this.passesPermission(action) && this.passesVisibleIf(action) ? action : null);
360
438
  if (routeName) {
361
439
  const page = pages.find((p) => p.id === routeName);
362
440
  if (page && page.primaryAction) {
363
- return page.primaryAction
441
+ const pageAction = gated(page.primaryAction);
442
+ if (pageAction) {
443
+ return pageAction
444
+ }
364
445
  }
365
446
  }
366
- return this.effectiveManifest?.nav?.primaryAction ?? null
447
+ return gated(this.effectiveManifest?.nav?.primaryAction ?? null)
367
448
  },
368
449
 
369
450
  /**
@@ -377,6 +458,31 @@ var script = {
377
458
  return this.mdiIconComponent(this.activePrimaryAction) ?? Plus
378
459
  },
379
460
 
461
+ /**
462
+ * The CnActionButtons entry for a primary action that carries an
463
+ * `action` (`$defs/action`: open-form, navigate, api-call, ...):
464
+ * the action with the primary action's `id`, `label` and `icon`
465
+ * folded in and `variant: "primary"`. Null for a plain primary
466
+ * action, which keeps its link or button.
467
+ *
468
+ * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-navigation-primary-action-runs-a-page-action
469
+ * @return {object|null}
470
+ */
471
+ primaryDispatchEntry() {
472
+ const action = this.activePrimaryAction;
473
+ const inner = action && action.action;
474
+ if (!inner || typeof inner !== 'object' || typeof inner.type !== 'string') {
475
+ return null
476
+ }
477
+ return {
478
+ icon: action.icon || 'Plus',
479
+ ...inner,
480
+ id: inner.id || action.id || 'primary-action',
481
+ label: action.label,
482
+ variant: 'primary',
483
+ }
484
+ },
485
+
380
486
  /**
381
487
  * Link props for the primary action's button: an `href` opens in a
382
488
  * new tab, a `route` is a router link. Null when the action is
@@ -1241,6 +1347,9 @@ var script = {
1241
1347
  * `NcAppNavigationItem`).
1242
1348
  *
1243
1349
  * - Literal positive integer in `item.count` → return as-is.
1350
+ * - `item.count` is an object (`{ register, schema, filter? }`) →
1351
+ * `cnMenuItemCounts[item.id] ?? null`, the filtered total CnAppRoot
1352
+ * fetched for this entry.
1244
1353
  * - `item.count === "auto"` → look up the entry's resolved page;
1245
1354
  * when that page is `type: "index"` with a `register`/`schema`
1246
1355
  * in its `config`, return
@@ -1264,6 +1373,11 @@ var script = {
1264
1373
  if (typeof raw === 'number') {
1265
1374
  return raw > 0 ? raw : null
1266
1375
  }
1376
+ if (raw && typeof raw === 'object') {
1377
+ // A filtered count: CnAppRoot fetched it per entry id.
1378
+ const value = this.cnMenuItemCounts?.[item.id];
1379
+ return (typeof value === 'number' && value > 0) ? value : null
1380
+ }
1267
1381
  if (raw !== 'auto') {
1268
1382
  return null
1269
1383
  }
@@ -1574,6 +1688,39 @@ var script = {
1574
1688
  *
1575
1689
  * @return {void}
1576
1690
  */
1691
+ /**
1692
+ * Re-emit the object an `open-form` primary action created, so the
1693
+ * host can refresh a list or open the record.
1694
+ *
1695
+ * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-navigation-primary-action-runs-a-page-action
1696
+ * @param {object} created The created object.
1697
+ * @return {void}
1698
+ */
1699
+ onPrimaryActionCreated(created) {
1700
+ /**
1701
+ * @event primary-action-created Emitted after an `open-form` primary action saves. Payload: the created object.
1702
+ */
1703
+ this.$emit('primary-action-created', created);
1704
+ },
1705
+
1706
+ /**
1707
+ * A card link that is a button (an `action` id) emits `card-action`
1708
+ * with that id for the host to run; links and anchors navigate on
1709
+ * their own.
1710
+ *
1711
+ * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-the-navigation-carries-a-card-and-a-help-entry
1712
+ * @return {void}
1713
+ */
1714
+ onCardLinkClick() {
1715
+ const card = this.resolvedCard;
1716
+ if (card && card.action) {
1717
+ /**
1718
+ * @event card-action Emitted when the nav card's link is an action button. Payload: the action id.
1719
+ */
1720
+ this.$emit('card-action', card.action);
1721
+ }
1722
+ },
1723
+
1577
1724
  onPrimaryActionClick() {
1578
1725
  const action = this.activePrimaryAction;
1579
1726
  if (!action) {