@conduction/nextcloud-vue 2.89.1 → 2.90.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 (29) hide show
  1. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
  2. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +13 -0
  3. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
  4. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +3 -1
  5. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
  6. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue.js +1 -1
  7. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +27 -10
  8. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
  9. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.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 +18 -0
  12. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  13. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +2 -2
  14. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  15. package/dist/esm/library-style.js +1 -1
  16. package/dist/esm/nextcloud-vue.css +71 -71
  17. package/dist/esm/utils/declaredProps.js +106 -0
  18. package/dist/esm/utils/declaredProps.js.map +1 -0
  19. package/dist/esm/utils/gridStack.js +7 -3
  20. package/dist/esm/utils/gridStack.js.map +1 -1
  21. package/dist/nextcloud-vue.cjs.js +184 -30
  22. package/dist/nextcloud-vue.cjs.js.map +2 -2
  23. package/dist/nextcloud-vue.css +71 -71
  24. package/package.json +1 -1
  25. package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +14 -1
  26. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +27 -10
  27. package/src/components/CnDashboardPage/CnDashboardPage.vue +20 -2
  28. package/src/utils/declaredProps.js +115 -0
  29. package/src/utils/gridStack.js +7 -3
@@ -51261,7 +51261,7 @@ function matchPlainBrackets(state, pos, dir, tree, tokenType, maxScanDistance, b
51261
51261
  }
51262
51262
  const noTokens = /*@__PURE__*/Object.create(null);
51263
51263
  const typeArray = [NodeType.none];
51264
- const warned$2 = [];
51264
+ const warned$3 = [];
51265
51265
  // Cache of node types by name and tags
51266
51266
  const byTag = /*@__PURE__*/Object.create(null);
51267
51267
  const defaultTable = /*@__PURE__*/Object.create(null);
@@ -51281,9 +51281,9 @@ for (let [legacyName, name] of [
51281
51281
  ])
51282
51282
  defaultTable[legacyName] = /*@__PURE__*/createTokenType(noTokens, name);
51283
51283
  function warnForPart(part, msg) {
51284
- if (warned$2.indexOf(part) > -1)
51284
+ if (warned$3.indexOf(part) > -1)
51285
51285
  return;
51286
- warned$2.push(part);
51286
+ warned$3.push(part);
51287
51287
  console.warn(msg);
51288
51288
  }
51289
51289
  function createTokenType(extra, tagStr) {
@@ -158624,7 +158624,7 @@ const DEFAULT_COMPONENT_MAP = Object.freeze({
158624
158624
 
158625
158625
  const KNOWN_TYPES = ['boolean', 'number', 'password', 'string', 'enum', 'json', 'file'];
158626
158626
 
158627
- const warned$1 = new Set();
158627
+ const warned$2 = new Set();
158628
158628
 
158629
158629
  /**
158630
158630
  * Coerce an enum field's options into the `{ label, value }` shape
@@ -158783,8 +158783,8 @@ function cnRenderFormField({ field, value, onInput, t, error, componentMap } = {
158783
158783
  // per process. It used to be taken unconditionally and silently,
158784
158784
  // because the CommonJS lookup that fed `NcTextArea` could never
158785
158785
  // resolve from an ESM build.
158786
- if (!map['string-textarea'] && !warned$1.has('__no-nc-textarea')) {
158787
- warned$1.add('__no-nc-textarea');
158786
+ if (!map['string-textarea'] && !warned$2.has('__no-nc-textarea')) {
158787
+ warned$2.add('__no-nc-textarea');
158788
158788
  // eslint-disable-next-line no-console
158789
158789
  console.warn('[cnRenderFormField] NcTextArea is unavailable from @nextcloud/vue; '
158790
158790
  + 'falling back to a bare <textarea> for `widget: "textarea"` fields. '
@@ -158824,8 +158824,8 @@ function cnRenderFormField({ field, value, onInput, t, error, componentMap } = {
158824
158824
  }
158825
158825
  } else if (!KNOWN_TYPES.includes(field.type)) {
158826
158826
  // Unknown type — warn ONCE per type and fall back to NcTextField.
158827
- if (!warned$1.has(field.type)) {
158828
- warned$1.add(field.type);
158827
+ if (!warned$2.has(field.type)) {
158828
+ warned$2.add(field.type);
158829
158829
  // eslint-disable-next-line no-console
158830
158830
  console.warn(`[cnRenderFormField] Unknown field.type "${field.type}" for field "${field.key}". Falling back to NcTextField. Known types: ${KNOWN_TYPES.join(', ')}.`);
158831
158831
  }
@@ -257068,7 +257068,7 @@ const __sfc_main$2l = script$2l;
257068
257068
  * @spec openspec/changes/environment-banner/tasks.md#task-2
257069
257069
  */
257070
257070
 
257071
- let warned = false;
257071
+ let warned$1 = false;
257072
257072
 
257073
257073
  /**
257074
257074
  * @param {object} options Options.
@@ -257094,8 +257094,8 @@ function useEnvironment({ environment, tenant, apiBase = '/apps/openregister/api
257094
257094
  const value = response && response.data && (response.data.environment ?? (response.data.results && response.data.results.environment));
257095
257095
  fetched.value = { ...fetched.value, [uuid]: typeof value === 'string' ? value : '' };
257096
257096
  } catch (error) {
257097
- if (!warned) {
257098
- warned = true;
257097
+ if (!warned$1) {
257098
+ warned$1 = true;
257099
257099
  // eslint-disable-next-line no-console
257100
257100
  console.warn('[useEnvironment] The organisation could not be read, so no environment is shown.', error);
257101
257101
  }
@@ -257390,6 +257390,19 @@ var script$2k = {
257390
257390
  default: '',
257391
257391
  },
257392
257392
 
257393
+ /**
257394
+ * Mount a tab's `tab-<id>` slot only while that tab is open, and
257395
+ * unmount it when another tab opens, so each visit mounts it afresh
257396
+ * and the page does not load every tab at once. Off (the default),
257397
+ * every panel stays mounted and only the open one shows.
257398
+ *
257399
+ * @spec openspec/changes/admin-settings-lazy-tabs/specs/settings-board-look/spec.md#requirement-the-admin-shell-can-mount-only-the-open-tab
257400
+ */
257401
+ lazyTabs: {
257402
+ type: Boolean,
257403
+ default: false,
257404
+ },
257405
+
257393
257406
  /**
257394
257407
  * How the `tabs` strip is drawn, as CnTabs' `variant`: `line`, the
257395
257408
  * folder tabs (the default), or `underline`, plain labels on a rule
@@ -257950,7 +257963,9 @@ function render$2k(_ctx, _cache, $props, $setup, $data, $options) {
257950
257963
  class: "cn-admin-settings-shell__panel",
257951
257964
  "data-tab": tab.id
257952
257965
  }, [
257953
- vue$1.renderSlot(_ctx.$slots, `tab-${tab.id}`)
257966
+ (!$props.lazyTabs || tab.id === $options.activeTabId)
257967
+ ? vue$1.renderSlot(_ctx.$slots, `tab-${tab.id}`, {}, undefined, undefined, 0)
257968
+ : vue$1.createCommentVNode("v-if", true)
257954
257969
  ], 8 /* PROPS */, _hoisted_11$N)
257955
257970
  ]),
257956
257971
  _: 2 /* DYNAMIC */
@@ -258089,7 +258104,7 @@ function render$2k(_ctx, _cache, $props, $setup, $data, $options) {
258089
258104
  }
258090
258105
 
258091
258106
  script$2k.render = render$2k;
258092
- script$2k.__scopeId = "data-v-c3ceda64";
258107
+ script$2k.__scopeId = "data-v-038f200a";
258093
258108
  const __sfc_main$2k = script$2k;
258094
258109
 
258095
258110
  /**
@@ -307002,8 +307017,11 @@ function readGridGeometry(items) {
307002
307017
  * full-width card under the stat tiles landed below the lists.
307003
307018
  *
307004
307019
  * @spec openspec/changes/dashboard-growth-keeps-order/specs/dashboard-grid/spec.md#requirement-a-growing-cell-keeps-the-order-of-the-cards-under-it
307005
- * @param {Array<{x: number, y: number, w: number, h: number}>} nodes The grid's items (the growing one among them).
307006
- * @param {{x: number, y: number, w: number, h: number}} node The growing item.
307020
+ * The growing item is never among the items it moves, also when `nodes`
307021
+ * holds another reference to it (a proxy of the same node, matched by `el`).
307022
+ *
307023
+ * @param {Array<{x: number, y: number, w: number, h: number, el: (HTMLElement|undefined)}>} nodes The grid's items (the growing one among them).
307024
+ * @param {{x: number, y: number, w: number, h: number, el: (HTMLElement|undefined)}} node The growing item.
307007
307025
  * @param {number} h Its new height, in grid rows.
307008
307026
  * @return {Array<{node: object, y: number}>} The items to move and their new row, bottom-most first.
307009
307027
  */
@@ -307018,7 +307036,8 @@ function planGrowth(nodes, node, h) {
307018
307036
  while (queue.length > 0) {
307019
307037
  const rect = queue.shift();
307020
307038
  for (const other of nodes) {
307021
- if (other === node || moved.has(other) || !overlaps(rect, other)) {
307039
+ const self = other === node || (node.el && other.el === node.el);
307040
+ if (self || moved.has(other) || !overlaps(rect, other)) {
307022
307041
  continue
307023
307042
  }
307024
307043
  const next = { x: other.x, y: other.y + delta, w: other.w, h: other.h };
@@ -307642,16 +307661,27 @@ var script$1t = {
307642
307661
  * (`itemsInRowOrder`). A cell that shrinks is left to GridStack as
307643
307662
  * before.
307644
307663
  *
307664
+ * The grid is read raw: through Vue's proxy `engine.nodes` holds proxies
307665
+ * while `el.gridstackNode` is the plain node, so the growing cell would
307666
+ * not be recognised among the nodes and would be moved down by its own
307667
+ * growth. Moving a cell makes GridStack measure it again, so a cell the
307668
+ * wrapper is already growing goes straight to GridStack.
307669
+ *
307645
307670
  * @spec openspec/changes/dashboard-growth-keeps-order/specs/dashboard-grid/spec.md#requirement-a-growing-cell-keeps-the-order-of-the-cards-under-it
307646
307671
  * @return {void}
307647
307672
  */
307648
307673
  keepOrderOnGrowth() {
307649
- const grid = this.grid;
307674
+ const grid = vue$1.toRaw(this.grid);
307650
307675
  if (!grid || typeof grid.resizeToContent !== 'function' || typeof grid.update !== 'function') {
307651
307676
  return
307652
307677
  }
307653
307678
  const resize = grid.resizeToContent.bind(grid);
307679
+ const growing = new Set();
307654
307680
  grid.resizeToContent = (el) => {
307681
+ if (growing.has(el)) {
307682
+ resize(el);
307683
+ return
307684
+ }
307655
307685
  const node = el && el.gridstackNode;
307656
307686
  const nodes = grid.engine && Array.isArray(grid.engine.nodes) ? grid.engine.nodes : null;
307657
307687
  const rows = node && nodes ? this.contentRows(el, node) : null;
@@ -307662,15 +307692,20 @@ var script$1t = {
307662
307692
  }
307663
307693
  // Inside a batch the moves are not packed until the cell has grown.
307664
307694
  const batching = Boolean(grid.engine.batchMode);
307665
- if (!batching) {
307666
- grid.batchUpdate();
307667
- }
307668
- for (const step of plan) {
307669
- grid.update(step.node.el, { y: step.y });
307670
- }
307671
- resize(el);
307672
- if (!batching) {
307673
- grid.batchUpdate(false);
307695
+ growing.add(el);
307696
+ try {
307697
+ if (!batching) {
307698
+ grid.batchUpdate();
307699
+ }
307700
+ for (const step of plan) {
307701
+ grid.update(step.node.el, { y: step.y });
307702
+ }
307703
+ resize(el);
307704
+ if (!batching) {
307705
+ grid.batchUpdate(false);
307706
+ }
307707
+ } finally {
307708
+ growing.delete(el);
307674
307709
  }
307675
307710
  };
307676
307711
  },
@@ -308273,7 +308308,7 @@ function render$1t(_ctx, _cache, $props, $setup, $data, $options) {
308273
308308
  }
308274
308309
 
308275
308310
  script$1t.render = render$1t;
308276
- script$1t.__scopeId = "data-v-a91998fc";
308311
+ script$1t.__scopeId = "data-v-a76b6fc6";
308277
308312
  const __sfc_main$1t = script$1t;
308278
308313
 
308279
308314
  /**
@@ -318376,6 +318411,108 @@ script$1j.render = render$1j;
318376
318411
  script$1j.__scopeId = "data-v-a78d1ec4";
318377
318412
  const __sfc_main$1j = script$1j;
318378
318413
 
318414
+ /**
318415
+ * SPDX-FileCopyrightText: 2026 Conduction B.V.
318416
+ * SPDX-License-Identifier: EUPL-1.2
318417
+ */
318418
+
318419
+
318420
+ const warned = new Set();
318421
+
318422
+ /**
318423
+ * Add the prop names one component options object declares, following its
318424
+ * `extends` and `mixins`.
318425
+ *
318426
+ * @param {object} options A component options object.
318427
+ * @param {Set<string>} names The set to add camelCase prop names to.
318428
+ * @param {number} depth Recursion guard.
318429
+ */
318430
+ function collect(options, names, depth) {
318431
+ if (!options || typeof options !== 'object' || depth > 8) {
318432
+ return
318433
+ }
318434
+ const props = options.props;
318435
+ if (Array.isArray(props)) {
318436
+ props.forEach((name) => names.add(vue$1.camelize(String(name))));
318437
+ } else if (props && typeof props === 'object') {
318438
+ Object.keys(props).forEach((name) => names.add(vue$1.camelize(name)));
318439
+ }
318440
+ collect(options.extends, names, depth + 1);
318441
+ if (Array.isArray(options.mixins)) {
318442
+ options.mixins.forEach((mixin) => collect(mixin, names, depth + 1));
318443
+ }
318444
+ }
318445
+
318446
+ /**
318447
+ * The prop names a component declares, or `null` when it takes every
318448
+ * attribute itself and so must keep receiving all of them:
318449
+ * - `inheritAttrs: false`: the component forwards `$attrs` on purpose;
318450
+ * - a functional component without `props`: its attrs are its props;
318451
+ * - an async component that has not resolved yet.
318452
+ *
318453
+ * @spec openspec/changes/dashboard-declared-widget-props/specs/dashboard-page/spec.md#requirement-a-dashboard-widget-receives-only-the-content-keys-it-declares
318454
+ * @param {object|((...args: unknown[]) => unknown)|null} component A component definition.
318455
+ * @return {Set<string>|null} camelCase prop names, or null for "all".
318456
+ */
318457
+ function declaredPropNames(component) {
318458
+ if (!component) {
318459
+ return null
318460
+ }
318461
+ if (typeof component === 'function') {
318462
+ if (!component.props) {
318463
+ return null
318464
+ }
318465
+ const names = new Set();
318466
+ collect({ props: component.props }, names, 0);
318467
+ return names
318468
+ }
318469
+ if (typeof component !== 'object') {
318470
+ return null
318471
+ }
318472
+ if (component.__asyncLoader) {
318473
+ return component.__asyncResolved ? declaredPropNames(component.__asyncResolved) : null
318474
+ }
318475
+ const chain = [component, component.extends, ...(component.mixins || [])];
318476
+ if (chain.some((options) => options && options.inheritAttrs === false)) {
318477
+ return null
318478
+ }
318479
+ const names = new Set();
318480
+ collect(component, names, 0);
318481
+ return names
318482
+ }
318483
+
318484
+ /**
318485
+ * Keep the entries of `bindings` whose key `component` declares as a prop.
318486
+ * A component for which {@link declaredPropNames} returns null gets every
318487
+ * entry. A dropped key is warned about once outside production when the
318488
+ * component has no `content` prop either, so the key reaches nothing.
318489
+ *
318490
+ * @spec openspec/changes/dashboard-declared-widget-props/specs/dashboard-page/spec.md#requirement-a-dashboard-widget-receives-only-the-content-keys-it-declares
318491
+ * @param {object|((...args: unknown[]) => unknown)|null} component The component that will receive the bindings.
318492
+ * @param {object} bindings The candidate bindings.
318493
+ * @param {string} label Names the component in the warning (for example the widget type).
318494
+ * @return {object} The bindings the component declares.
318495
+ */
318496
+ function pickDeclaredProps(component, bindings, label) {
318497
+ const declared = declaredPropNames(component);
318498
+ if (!declared || !bindings || typeof bindings !== 'object') {
318499
+ return bindings
318500
+ }
318501
+ const out = {};
318502
+ for (const [key, value] of Object.entries(bindings)) {
318503
+ if (declared.has(vue$1.camelize(key))) {
318504
+ out[key] = value;
318505
+ continue
318506
+ }
318507
+ if (process.env.NODE_ENV !== 'production' && !declared.has('content') && !warned.has(`${label}\u0000${key}`)) {
318508
+ warned.add(`${label}\u0000${key}`);
318509
+ // eslint-disable-next-line no-console
318510
+ console.warn(`[nextcloud-vue] content key "${key}" is not passed to widget "${label}": it declares neither that prop nor \`content\`.`);
318511
+ }
318512
+ }
318513
+ return out
318514
+ }
318515
+
318379
318516
  /** Surfaces understood by the pluggable integration registry (AD-19). */
318380
318517
  const INTEGRATION_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity'];
318381
318518
 
@@ -321021,6 +321158,23 @@ var script$1i = {
321021
321158
  return outcome ? { ...content, conditionOutcome: outcome } : content
321022
321159
  },
321023
321160
 
321161
+ /**
321162
+ * The content keys a registry widget receives as props: only the ones
321163
+ * its renderer declares. An undeclared key would otherwise fall through
321164
+ * as an attribute onto the renderer's root component and could override
321165
+ * a value the widget computes for it. The whole content still arrives
321166
+ * as `content`. A renderer that forwards its own attributes
321167
+ * (`inheritAttrs: false`) keeps receiving every key.
321168
+ *
321169
+ * @param {object} item Layout item.
321170
+ * @return {object} The bindings the renderer declares.
321171
+ * @spec openspec/changes/dashboard-declared-widget-props/specs/dashboard-page/spec.md#requirement-a-dashboard-widget-receives-only-the-content-keys-it-declares
321172
+ */
321173
+ registryWidgetProps(item) {
321174
+ const def = this.getWidgetDef(item.widgetId);
321175
+ return pickDeclaredProps(this.registryRenderer(item), this.registryWidgetBindings(item), def?.type || item.widgetId)
321176
+ },
321177
+
321024
321178
  /**
321025
321179
  * What a container widget (registry `container`, such as `tabs`) needs
321026
321180
  * beside its content: the page's widget definitions, so its tabs find
@@ -322661,7 +322815,7 @@ function render$1i(_ctx, _cache, $props, $setup, $data, $options) {
322661
322815
  (vue$1.openBlock(), vue$1.createBlock(vue$1.resolveDynamicComponent($options.registryRenderer(item)), vue$1.mergeProps({
322662
322816
  widgetId: item.widgetId,
322663
322817
  content: $options.registryWidgetBindings(item)
322664
- }, { ref_for: true }, { ...$options.registryWidgetBindings(item), ...$options.containerBindings(item) }, {
322818
+ }, { ref_for: true }, { ...$options.registryWidgetProps(item), ...$options.containerBindings(item) }, {
322665
322819
  onHeader: $event => ($options.onWidgetHeader(item, $event))
322666
322820
  }), null, 16 /* FULL_PROPS */, ["widgetId", "content", "onHeader"]))
322667
322821
  ]),
@@ -323130,7 +323284,7 @@ function render$1i(_ctx, _cache, $props, $setup, $data, $options) {
323130
323284
  (vue$1.openBlock(), vue$1.createBlock(vue$1.resolveDynamicComponent($options.registryRenderer(item)), vue$1.mergeProps({
323131
323285
  widgetId: item.widgetId,
323132
323286
  content: $options.registryWidgetBindings(item)
323133
- }, { ref_for: true }, { ...$options.registryWidgetBindings(item), ...$options.containerBindings(item), ...$options.cellChromeBindings(item) }, {
323287
+ }, { ref_for: true }, { ...$options.registryWidgetProps(item), ...$options.containerBindings(item), ...$options.cellChromeBindings(item) }, {
323134
323288
  onHeader: $event => ($options.onWidgetHeader(item, $event))
323135
323289
  }), null, 16 /* FULL_PROPS */, ["widgetId", "content", "onHeader"]))
323136
323290
  ]),
@@ -323290,7 +323444,7 @@ function render$1i(_ctx, _cache, $props, $setup, $data, $options) {
323290
323444
  }
323291
323445
 
323292
323446
  script$1i.render = render$1i;
323293
- script$1i.__scopeId = "data-v-20ca81f3";
323447
+ script$1i.__scopeId = "data-v-42bc14a4";
323294
323448
  const __sfc_main$1i = script$1i;
323295
323449
 
323296
323450
  var CnDashboardPage = /*#__PURE__*/Object.freeze({
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/dist/nextcloud-vue.cjs.js.map
3
- size: 40766945 bytes
4
- sha256: 4d5c39c1fefeba7aa7f2181f991b71ad3354d5678ea63646f53060e929223d66
3
+ size: 40779638 bytes
4
+ sha256: b171c6d90fa9da1ac7b3e057618c0102feb5c4a930845adf71bda7617ccd3073