@conduction/nextcloud-vue 2.67.0 → 2.68.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 (55) hide show
  1. package/dist/esm/components/CnContextMenu/CnContextMenu.vue2.js +37 -26
  2. package/dist/esm/components/CnContextMenu/CnContextMenu.vue2.js.map +1 -1
  3. package/dist/esm/components/CnContextMenu/CnContextMenu.vue3.js +3 -3
  4. package/dist/esm/components/CnContextMenu/CnContextMenu.vue3.js.map +1 -1
  5. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +87 -18
  6. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  7. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +6 -1
  8. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  9. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +58 -48
  10. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  11. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +2 -2
  12. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  13. package/dist/esm/components/CnIndexPage/defaultActions.js +6 -7
  14. package/dist/esm/components/CnIndexPage/defaultActions.js.map +1 -1
  15. package/dist/esm/components/CnRowActions/CnRowActions.vue2.js +33 -34
  16. package/dist/esm/components/CnRowActions/CnRowActions.vue2.js.map +1 -1
  17. package/dist/esm/components/CnRowActions/CnRowActions.vue3.js +3 -3
  18. package/dist/esm/components/CnRowActions/CnRowActions.vue3.js.map +1 -1
  19. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +8 -2
  20. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
  21. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
  22. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +3 -2
  23. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -1
  24. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -1
  25. package/dist/esm/composables/useContextMenu.js +4 -2
  26. package/dist/esm/composables/useContextMenu.js.map +1 -1
  27. package/dist/esm/utils/resolveRowActions.js +130 -0
  28. package/dist/esm/utils/resolveRowActions.js.map +1 -0
  29. package/dist/esm/utils/rowActionItem.js +104 -0
  30. package/dist/esm/utils/rowActionItem.js.map +1 -0
  31. package/dist/esm/utils/timelineEvents.js +44 -1
  32. package/dist/esm/utils/timelineEvents.js.map +1 -1
  33. package/dist/esm/utils/validateManifest.js +59 -3
  34. package/dist/esm/utils/validateManifest.js.map +1 -1
  35. package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
  36. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  37. package/dist/nextcloud-vue.cjs.js +575 -151
  38. package/dist/nextcloud-vue.cjs.js.map +2 -2
  39. package/package.json +1 -1
  40. package/scripts/.jsdoc-baselines.json +2 -2
  41. package/src/components/CnContextMenu/CnContextMenu.vue +40 -29
  42. package/src/components/CnFormDialog/CnFormDialog.vue +92 -18
  43. package/src/components/CnIndexPage/CnIndexPage.md +21 -0
  44. package/src/components/CnIndexPage/CnIndexPage.vue +61 -51
  45. package/src/components/CnIndexPage/defaultActions.js +6 -7
  46. package/src/components/CnRowActions/CnRowActions.vue +36 -37
  47. package/src/components/CnSetupWizard/CnSetupWizard.vue +8 -2
  48. package/src/components/CnTimelineWidget/CnTimelineWidget.vue +3 -2
  49. package/src/composables/useContextMenu.js +4 -2
  50. package/src/schemas/app-manifest-v2.schema.json +46 -8
  51. package/src/utils/resolveRowActions.js +127 -0
  52. package/src/utils/rowActionItem.js +100 -0
  53. package/src/utils/timelineEvents.js +43 -0
  54. package/src/utils/validateManifest.js +60 -3
  55. package/src/utils/validateManifestV2.compiled.js +2 -2
@@ -23,8 +23,10 @@ import { resolveClaimedTeams, splitViewsIntoTabs, viewAsTab, resolveClaimTokens,
23
23
  import { LIST_SHORTCUTS, listPaletteCommands, shortcutFor } from '../../utils/listShortcuts.js';
24
24
  import { multiKeySort } from '../../utils/multiKeySort.js';
25
25
  import { resolveDeepTokens, resolveFilterValue } from '../../utils/resolveFilterTokens.js';
26
+ import { resolveRowActions } from '../../utils/resolveRowActions.js';
26
27
  import { resolveFilterMap } from '../../utils/routeFilters.js';
27
28
  import { DEFAULT_ROW_ACTION_FIELD, availableRowActions, refusalReasonFor, undeclaredRowActions } from '../../utils/rowActionAvailability.js';
29
+ import { isRowActionVisible, rowActionPayload } from '../../utils/rowActionItem.js';
28
30
  import { isNewTabClick, preventMiddleClickAutoscroll, isRowMiddleClick, isNewTabHandled, markNewTabHandled } from '../../utils/rowAuxClick.js';
29
31
  import { DEFAULT_ROW_INDICATOR_CAP } from '../../utils/rowIndicators.js';
30
32
  import { viewMatchesScope, extractViewState, buildRouteQueryFromViewState, extractViewStateFromRouteQuery, buildViewCreatePayload, savedViewScope } from '../../utils/savedViewHelpers.js';
@@ -902,7 +904,11 @@ var script = {
902
904
  default: () => ({}),
903
905
  },
904
906
 
905
- /** Row action definitions (app-provided, merged with built-in actions) */
907
+ /**
908
+ * Row action definitions, merged with the built-in View / Edit / Copy / Delete.
909
+ * Objects are app actions.
910
+ * A `"builtin:view"`, `"builtin:edit"`, `"builtin:copy"` or `"builtin:delete"` string places that built-in at its position when its `show*Action` toggle is on; enabled built-ins not placed are appended in that order.
911
+ */
906
912
  actions: {
907
913
  type: Array,
908
914
  default: () => [],
@@ -1976,6 +1982,8 @@ var script = {
1976
1982
  folderRowLayouts: {},
1977
1983
  /** The row the keyboard is on, or -1. */
1978
1984
  focusedRowIndex: -1,
1985
+ // The row the context menu shows: set on open, never cleared on close, so a closing menu keeps its entries and a late close cannot null a reopened one.
1986
+ contextMenuShownRow: null,
1979
1987
  /** The row a quick edit is open on, or null. */
1980
1988
  quickEditRow: null,
1981
1989
  /** The row as the server holds it, after a stale save. */
@@ -2688,7 +2696,7 @@ var script = {
2688
2696
  if (this.quickEditFields.length > 0) {
2689
2697
  handlers['row-quick-edit'] = () => this.focusedRow && this.openQuickEdit(this.focusedRow);
2690
2698
  }
2691
- if (this.focusedRow && this.rowActionsFor(this.focusedRow).length > 0) {
2699
+ if (this.focusedRow && this.primaryRowActionFor(this.focusedRow)) {
2692
2700
  handlers['row-primary'] = () => this.runPrimaryRowAction();
2693
2701
  }
2694
2702
  return handlers
@@ -3369,7 +3377,8 @@ var script = {
3369
3377
  },
3370
3378
 
3371
3379
  /**
3372
- * Merged actions: app-provided first, then built-in defaults.
3380
+ * Merged actions: the declared entries in order, each `"builtin:<id>"` placeholder replaced by that built-in when its toggle is on, then the enabled built-ins not placed.
3381
+ * See `resolveRowActions`.
3373
3382
  *
3374
3383
  * REQ-MAD-3 / REQ-MAD-4 / REQ-MAD-5 / REQ-MAD-6 / REQ-MAD-7
3375
3384
  * (manifest-actions-dispatch) — for any action whose `handler`
@@ -3385,58 +3394,41 @@ var script = {
3385
3394
  registry: this.effectiveRegistry,
3386
3395
  customComponents: this.effectiveCustomComponents,
3387
3396
  };
3388
- // Drop anything that is not an action OBJECT. A bare string — the
3389
- // shorthand `"edit"` an author reasonably expects to mean "show the
3390
- // built-in Edit" — has no `label` and no `icon`, so it rendered as a
3391
- // full-height NcActionButton with nothing in it: an invisible,
3392
- // clickable, inert row in the overflow menu. Observed on dossiq,
3393
- // where `config.actions: ["create", "edit", "delete", {…}]` put three
3394
- // blank rows above the real ones on four different index pages.
3395
- //
3396
- // Named, not silently swallowed: a dropped action is a capability the
3397
- // author asked for and did not get, and the manifest schema now
3398
- // rejects the shape at authoring time (`config.actions` is governed by
3399
- // the same `action` definition as `pages[].actions`). Built-ins are
3400
- // turned on with the `show*Action` toggles, not by naming them here.
3401
3397
  // A named source may supply its own row actions, on the same
3402
3398
  // precedence as its columns: what the manifest declares wins, and the
3403
- // source is the DEFAULT for a page that declares none. Without this
3404
- // the source's `rowActions` were declared and never read — the third
3405
- // field of the same adapter to be wired late, after `columns` and
3406
- // `addLabel`.
3407
- //
3408
- // Note what this still cannot do: these are MERGED with the built-ins
3409
- // below, so a source can add an action but cannot say "these and no
3410
- // others". Suppressing a built-in is the `show*Action` toggles' job.
3399
+ // source is the DEFAULT for a page that declares none.
3400
+ // Either list may place built-ins with `"builtin:<id>"`; turning one on or off stays the `show*Action` toggles' job.
3411
3401
  const manifestDeclared = this.actions && this.actions.length > 0;
3412
3402
  const declaredActions = manifestDeclared
3413
3403
  ? this.actions
3414
3404
  : ((this.isNamedSource && this.namedSource && this.namedSource.rowActions) || []);
3415
3405
 
3416
- const declared = [];
3417
- for (const a of declaredActions) {
3418
- if (a && typeof a === 'object' && !Array.isArray(a)) {
3406
+ const { actions, warnings } = resolveRowActions(declaredActions, this.defaultActions, {
3407
+ prepare: (a) => {
3419
3408
  // A SOURCE action may say `action: 'open'`: open this row the
3420
3409
  // way a row click does — the source's own navigation
3421
3410
  // (`openRow`/`detailRoute`), with `edit-open` emitted so a
3422
3411
  // host that configured a row target (`config.rowRoute`) wins.
3423
- // Resolved here because a source is a composable with no
3424
- // router; the flows source declared exactly this action and
3425
- // it rendered as a dead menu entry, because `action` was a
3426
- // key nothing read (dispatch reads `handler` and `type`).
3427
- // Source-declared actions only: the manifest grammar for
3428
- // navigation is `type`/`handler`, and stays so.
3412
+ // Resolved here because a source is a composable with no router.
3413
+ // Source-declared actions only: the manifest grammar for navigation is `type`/`handler`, and stays so.
3429
3414
  if (!manifestDeclared && a.action === 'open' && typeof a.handler !== 'function') {
3430
- declared.push({ ...a, handler: (row) => this.openSourceRow(row) });
3431
- continue
3415
+ return { ...a, handler: (row) => this.openSourceRow(row) }
3432
3416
  }
3433
- declared.push(dispatchAction(a, ctx));
3417
+ return dispatchAction(a, ctx)
3418
+ },
3419
+ });
3420
+ for (const warning of warnings) {
3421
+ // A toggle turned off at runtime (permissions, readOnly) legitimately silences a placeholder; the validator flags a statically-off one.
3422
+ if (warning.code === 'disabled-placeholder') {
3434
3423
  continue
3435
3424
  }
3436
- // eslint-disable-next-line no-console
3437
- console.warn(`[CnIndexPage] Ignoring action ${JSON.stringify(a)}: actions must be objects with an id and a label. To show a built-in action use the showViewAction / showEditAction / showCopyAction / showDeleteAction props.`);
3425
+ // A dropped entry is always named; the placement hints are dev-only.
3426
+ if (warning.code === 'invalid-entry' || process.env.NODE_ENV !== 'production') {
3427
+ // eslint-disable-next-line no-console
3428
+ console.warn(`[CnIndexPage] "${this.title}": ${warning.message}`);
3429
+ }
3438
3430
  }
3439
- return [...declared, ...this.defaultActions]
3431
+ return actions
3440
3432
  },
3441
3433
 
3442
3434
  hasRowActions() {
@@ -4682,9 +4674,20 @@ var script = {
4682
4674
  },
4683
4675
 
4684
4676
  /**
4685
- * Run the first action the focused row offers. "First" is the page's
4686
- * order, narrowed by what the server allows on that record, so the
4687
- * primary action is never one this caller may not run.
4677
+ * The first action a row's menu shows and enables: the page's order, narrowed by what the server allows, by `visible` / `visibleWhen`, and by `disabled`.
4678
+ * The keyboard therefore never runs what the menu hides or greys out.
4679
+ *
4680
+ * @param {object} row The row.
4681
+ * @return {(object|null)} The action, or null.
4682
+ * @spec openspec/changes/row-action-builtin-placement/specs/index-page/spec.md
4683
+ */
4684
+ primaryRowActionFor(row) {
4685
+ return this.rowActionsFor(row).find((action) => isRowActionVisible(action, row)
4686
+ && !(typeof action.disabled === 'function' ? action.disabled(row) : action.disabled)) || null
4687
+ },
4688
+
4689
+ /**
4690
+ * Run the focused row's primary action (see `primaryRowActionFor`).
4688
4691
  *
4689
4692
  * @return {void}
4690
4693
  * @spec openspec/changes/working-list-row-actions/specs/index-page/spec.md
@@ -4694,14 +4697,14 @@ var script = {
4694
4697
  if (!row) {
4695
4698
  return
4696
4699
  }
4697
- const [first] = this.rowActionsFor(row);
4700
+ const first = this.primaryRowActionFor(row);
4698
4701
  if (!first) {
4699
4702
  return
4700
4703
  }
4701
4704
  if (typeof first.handler === 'function') {
4702
4705
  first.handler(row);
4703
4706
  }
4704
- this.$emit('action', { action: first.label, row });
4707
+ this.onRowAction(rowActionPayload(first, row));
4705
4708
  },
4706
4709
 
4707
4710
  /**
@@ -5018,16 +5021,22 @@ var script = {
5018
5021
  },
5019
5022
 
5020
5023
  /**
5021
- * Intercepts CnRowActions' bubbled `@action` so `handler: "none"`
5022
- * actions are dropped before re-emit.
5024
+ * Intercepts CnRowActions' and CnContextMenu's bubbled `@action` so `handler: "none"` actions are dropped before re-emit.
5025
+ * A built-in is matched by its id, an app action by its label.
5023
5026
  *
5024
- * @param {{action: string, row: object}} payload The bubbled action payload.
5027
+ * @param {{action: string, row: object, id?: string, builtin?: boolean}} payload The bubbled action payload.
5025
5028
  */
5026
5029
  onRowAction(payload) {
5027
- const matched = this.mergedActions.find((a) => a.label === payload.action);
5030
+ const matched = payload.builtin === true
5031
+ ? this.mergedActions.find((a) => a.builtin === true && a.id === payload.id)
5032
+ : this.mergedActions.find((a) => a.builtin !== true && a.label === payload.action);
5028
5033
  if (matched && matched._dispatchSuppress) {
5029
5034
  return
5030
5035
  }
5036
+ /**
5037
+ * @event action A row action was chosen from a row's actions menu, its right-click menu or the keyboard primary action. Payload: `action` (the label), the row, the action's `id` when it has one, and `builtin: true` for a built-in View / Edit / Copy / Delete. Its handler has already run.
5038
+ * @type {{ action: string, row: object, id?: string, builtin?: boolean }}
5039
+ */
5031
5040
  this.$emit('action', payload);
5032
5041
  },
5033
5042
 
@@ -5973,6 +5982,7 @@ var script = {
5973
5982
  // --- Context menu handlers ---
5974
5983
 
5975
5984
  onRowContextMenu({ row, event }) {
5985
+ this.contextMenuShownRow = row;
5976
5986
  this.openContextMenu({ item: row, event });
5977
5987
  },
5978
5988