@conduction/nextcloud-vue 2.89.0 → 2.89.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +27 -3
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue.js +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +27 -10
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue2.js +19 -0
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue3.js +4 -4
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue3.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +8 -8
- package/dist/esm/utils/gridStack.js +7 -3
- package/dist/esm/utils/gridStack.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +81 -20
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +8 -8
- package/package.json +1 -1
- package/src/components/CnAppRoot/CnAppRoot.vue +27 -3
- package/src/components/CnDashboardGrid/CnDashboardGrid.vue +27 -10
- package/src/components/CnInteractionFormWidget/CnInteractionFormWidget.vue +20 -0
- package/src/utils/gridStack.js +7 -3
|
@@ -38141,17 +38141,17 @@ button.cn-object-calendar__overflow[data-v-e1c69ee2] {
|
|
|
38141
38141
|
}
|
|
38142
38142
|
|
|
38143
38143
|
|
|
38144
|
-
.cn-dashboard-grid[data-v-
|
|
38144
|
+
.cn-dashboard-grid[data-v-a76b6fc6] {
|
|
38145
38145
|
width: 100%;
|
|
38146
38146
|
min-height: 200px;
|
|
38147
38147
|
}
|
|
38148
|
-
.grid-stack[data-v-
|
|
38148
|
+
.grid-stack[data-v-a76b6fc6] {
|
|
38149
38149
|
background: transparent;
|
|
38150
38150
|
}
|
|
38151
38151
|
|
|
38152
38152
|
/* Screen-reader-only text: the keyboard key map and the live region. Kept in
|
|
38153
38153
|
the layout (not `display: none`) so assistive tech still reads it. */
|
|
38154
|
-
.cn-dashboard-grid__sr-only[data-v-
|
|
38154
|
+
.cn-dashboard-grid__sr-only[data-v-a76b6fc6] {
|
|
38155
38155
|
position: absolute;
|
|
38156
38156
|
width: 1px;
|
|
38157
38157
|
height: 1px;
|
|
@@ -38166,7 +38166,7 @@ button.cn-object-calendar__overflow[data-v-e1c69ee2] {
|
|
|
38166
38166
|
/* Grid items become tab stops in edit mode — give them a visible focus ring
|
|
38167
38167
|
that satisfies WCAG 2.1 SC 2.4.7 without relying on the widget's own
|
|
38168
38168
|
styling. `outline-offset` keeps the ring outside the rounded card. */
|
|
38169
|
-
.grid-stack-item[data-v-
|
|
38169
|
+
.grid-stack-item[data-v-a76b6fc6]:focus-visible {
|
|
38170
38170
|
outline: 2px solid var(--color-primary-element, #0082c9);
|
|
38171
38171
|
outline-offset: 2px;
|
|
38172
38172
|
border-radius: var(--border-radius-container-large, 16px);
|
|
@@ -38178,19 +38178,19 @@ button.cn-object-calendar__overflow[data-v-e1c69ee2] {
|
|
|
38178
38178
|
cell never shrank: "Waiting for me" stayed a tall card around one row. In
|
|
38179
38179
|
such a cell the child takes its own height. A cell without the key keeps
|
|
38180
38180
|
the filling child. */
|
|
38181
|
-
.cn-dashboard-grid__item--fit[data-v-
|
|
38181
|
+
.cn-dashboard-grid__item--fit[data-v-a76b6fc6] > .grid-stack-item-content > * {
|
|
38182
38182
|
height: auto;
|
|
38183
38183
|
}
|
|
38184
|
-
[data-v-
|
|
38184
|
+
[data-v-a76b6fc6] .grid-stack-item-content {
|
|
38185
38185
|
background: var(--color-main-background);
|
|
38186
38186
|
border: none;
|
|
38187
38187
|
box-shadow: none;
|
|
38188
38188
|
overflow: hidden;
|
|
38189
38189
|
}
|
|
38190
|
-
[data-v-
|
|
38190
|
+
[data-v-a76b6fc6] .grid-stack-item-content:has(.cn-widget-wrapper--borderless) {
|
|
38191
38191
|
background: transparent;
|
|
38192
38192
|
}
|
|
38193
|
-
[data-v-
|
|
38193
|
+
[data-v-a76b6fc6] .grid-stack-placeholder > .placeholder-content {
|
|
38194
38194
|
background: var(--color-primary-element-light);
|
|
38195
38195
|
border: 2px dashed var(--color-primary-element);
|
|
38196
38196
|
border-radius: var(--border-radius-large);
|
|
@@ -65,8 +65,11 @@ function readGridGeometry(items) {
|
|
|
65
65
|
* full-width card under the stat tiles landed below the lists.
|
|
66
66
|
*
|
|
67
67
|
* @spec openspec/changes/dashboard-growth-keeps-order/specs/dashboard-grid/spec.md#requirement-a-growing-cell-keeps-the-order-of-the-cards-under-it
|
|
68
|
-
*
|
|
69
|
-
*
|
|
68
|
+
* The growing item is never among the items it moves, also when `nodes`
|
|
69
|
+
* holds another reference to it (a proxy of the same node, matched by `el`).
|
|
70
|
+
*
|
|
71
|
+
* @param {Array<{x: number, y: number, w: number, h: number, el: (HTMLElement|undefined)}>} nodes The grid's items (the growing one among them).
|
|
72
|
+
* @param {{x: number, y: number, w: number, h: number, el: (HTMLElement|undefined)}} node The growing item.
|
|
70
73
|
* @param {number} h Its new height, in grid rows.
|
|
71
74
|
* @return {Array<{node: object, y: number}>} The items to move and their new row, bottom-most first.
|
|
72
75
|
*/
|
|
@@ -81,7 +84,8 @@ function planGrowth(nodes, node, h) {
|
|
|
81
84
|
while (queue.length > 0) {
|
|
82
85
|
const rect = queue.shift();
|
|
83
86
|
for (const other of nodes) {
|
|
84
|
-
|
|
87
|
+
const self = other === node || (node.el && other.el === node.el);
|
|
88
|
+
if (self || moved.has(other) || !overlaps(rect, other)) {
|
|
85
89
|
continue
|
|
86
90
|
}
|
|
87
91
|
const next = { x: other.x, y: other.y + delta, w: other.w, h: other.h };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gridStack.js","sources":["../../../src/utils/gridStack.js"],"sourcesContent":["/**\n * Thin GridStack bootstrap shared by the drag/resize grids (CnDashboardGrid and\n * CnWidgetGrid's editable body slot). Keeps the GridStack option shape in one\n * place so the two engines stay consistent.\n *\n * @module utils/gridStack\n */\n\nimport { GridStack } from 'gridstack'\n// `gridstack` is a peerDependency, not bundled — see the matching comment in\n// CnDashboardGrid.vue. The consumer must install `gridstack` themselves and\n// import its stylesheet (`gridstack/dist/gridstack.min.css`) from that same\n// copy; nc-vue ships no GridStack CSS of its own so the JS driving the grid\n// and the CSS sizing it can never come from two different versions.\n\n/**\n * Initialise a GridStack instance on a `.grid-stack` element.\n *\n * @param {HTMLElement} el The `.grid-stack` container element.\n * @param {object} opts Options.\n * @param {number} opts.columns Column count.\n * @param {boolean} opts.editable Whether drag + resize are enabled.\n * @param {number} [opts.cellHeight] Cell height in px (default 80).\n * @param {number} [opts.margin] Grid margin in px (default 12).\n * @return {import('gridstack').GridStack} The GridStack instance.\n */\nexport function initGridStack(el, opts) {\n\tconst { columns, editable, cellHeight = 80, margin = 12 } = opts\n\treturn GridStack.init({\n\t\tcolumn: columns,\n\t\tcellHeight,\n\t\tmargin,\n\t\tfloat: true,\n\t\tanimate: true,\n\t\tdisableDrag: !editable,\n\t\tdisableResize: !editable,\n\t\tremovable: false,\n\t}, el)\n}\n\n/**\n * Read the geometry GridStack reports for a changed set of items into a plain\n * map keyed by node id.\n *\n * @param {Array<{id: (string|number), x: number, y: number, w: number, h: number}>} items\n * The items GridStack passes to its `change` handler.\n * @return {Map<string, {gridX: number, gridY: number, gridWidth: number, gridHeight: number}>}\n */\nexport function readGridGeometry(items) {\n\tconst map = new Map()\n\tfor (const it of items || []) {\n\t\tmap.set(String(it.id), { gridX: it.x, gridY: it.y, gridWidth: it.w, gridHeight: it.h })\n\t}\n\treturn map\n}\n\n/**\n * Where the items under a growing cell go so they keep their order: every item\n * the growth would overlap moves down by the growth, and so does every item\n * that move would overlap in turn. Items beside the cell stay put.\n *\n * GridStack resolves the same collision itself, but not in order: when\n * pipelinq's size-to-content banner grew from two rows to three, the\n * full-width card under the stat tiles landed below the lists.\n *\n * @spec openspec/changes/dashboard-growth-keeps-order/specs/dashboard-grid/spec.md#requirement-a-growing-cell-keeps-the-order-of-the-cards-under-it\n * @param {Array<{x: number, y: number, w: number, h: number}>} nodes The grid's items (the growing one among them).\n * @param {{x: number, y: number, w: number, h: number}} node The growing item.\n * @param {number} h Its new height, in grid rows.\n * @return {Array<{node: object, y: number}>} The items to move and their new row, bottom-most first.\n */\nexport function planGrowth(nodes, node, h) {\n\tconst delta = h - node.h\n\tif (!(delta > 0)) {\n\t\treturn []\n\t}\n\tconst moved = new Map()\n\tconst overlaps = (a, b) => a.x < b.x + b.w && b.x < a.x + a.w && a.y < b.y + b.h && b.y < a.y + a.h\n\tconst queue = [{ x: node.x, y: node.y, w: node.w, h }]\n\twhile (queue.length > 0) {\n\t\tconst rect = queue.shift()\n\t\tfor (const other of nodes) {\n\t\t\
|
|
1
|
+
{"version":3,"file":"gridStack.js","sources":["../../../src/utils/gridStack.js"],"sourcesContent":["/**\n * Thin GridStack bootstrap shared by the drag/resize grids (CnDashboardGrid and\n * CnWidgetGrid's editable body slot). Keeps the GridStack option shape in one\n * place so the two engines stay consistent.\n *\n * @module utils/gridStack\n */\n\nimport { GridStack } from 'gridstack'\n// `gridstack` is a peerDependency, not bundled — see the matching comment in\n// CnDashboardGrid.vue. The consumer must install `gridstack` themselves and\n// import its stylesheet (`gridstack/dist/gridstack.min.css`) from that same\n// copy; nc-vue ships no GridStack CSS of its own so the JS driving the grid\n// and the CSS sizing it can never come from two different versions.\n\n/**\n * Initialise a GridStack instance on a `.grid-stack` element.\n *\n * @param {HTMLElement} el The `.grid-stack` container element.\n * @param {object} opts Options.\n * @param {number} opts.columns Column count.\n * @param {boolean} opts.editable Whether drag + resize are enabled.\n * @param {number} [opts.cellHeight] Cell height in px (default 80).\n * @param {number} [opts.margin] Grid margin in px (default 12).\n * @return {import('gridstack').GridStack} The GridStack instance.\n */\nexport function initGridStack(el, opts) {\n\tconst { columns, editable, cellHeight = 80, margin = 12 } = opts\n\treturn GridStack.init({\n\t\tcolumn: columns,\n\t\tcellHeight,\n\t\tmargin,\n\t\tfloat: true,\n\t\tanimate: true,\n\t\tdisableDrag: !editable,\n\t\tdisableResize: !editable,\n\t\tremovable: false,\n\t}, el)\n}\n\n/**\n * Read the geometry GridStack reports for a changed set of items into a plain\n * map keyed by node id.\n *\n * @param {Array<{id: (string|number), x: number, y: number, w: number, h: number}>} items\n * The items GridStack passes to its `change` handler.\n * @return {Map<string, {gridX: number, gridY: number, gridWidth: number, gridHeight: number}>}\n */\nexport function readGridGeometry(items) {\n\tconst map = new Map()\n\tfor (const it of items || []) {\n\t\tmap.set(String(it.id), { gridX: it.x, gridY: it.y, gridWidth: it.w, gridHeight: it.h })\n\t}\n\treturn map\n}\n\n/**\n * Where the items under a growing cell go so they keep their order: every item\n * the growth would overlap moves down by the growth, and so does every item\n * that move would overlap in turn. Items beside the cell stay put.\n *\n * GridStack resolves the same collision itself, but not in order: when\n * pipelinq's size-to-content banner grew from two rows to three, the\n * full-width card under the stat tiles landed below the lists.\n *\n * @spec openspec/changes/dashboard-growth-keeps-order/specs/dashboard-grid/spec.md#requirement-a-growing-cell-keeps-the-order-of-the-cards-under-it\n * The growing item is never among the items it moves, also when `nodes`\n * holds another reference to it (a proxy of the same node, matched by `el`).\n *\n * @param {Array<{x: number, y: number, w: number, h: number, el: (HTMLElement|undefined)}>} nodes The grid's items (the growing one among them).\n * @param {{x: number, y: number, w: number, h: number, el: (HTMLElement|undefined)}} node The growing item.\n * @param {number} h Its new height, in grid rows.\n * @return {Array<{node: object, y: number}>} The items to move and their new row, bottom-most first.\n */\nexport function planGrowth(nodes, node, h) {\n\tconst delta = h - node.h\n\tif (!(delta > 0)) {\n\t\treturn []\n\t}\n\tconst moved = new Map()\n\tconst overlaps = (a, b) => a.x < b.x + b.w && b.x < a.x + a.w && a.y < b.y + b.h && b.y < a.y + a.h\n\tconst queue = [{ x: node.x, y: node.y, w: node.w, h }]\n\twhile (queue.length > 0) {\n\t\tconst rect = queue.shift()\n\t\tfor (const other of nodes) {\n\t\t\tconst self = other === node || (node.el && other.el === node.el)\n\t\t\tif (self || moved.has(other) || !overlaps(rect, other)) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst next = { x: other.x, y: other.y + delta, w: other.w, h: other.h }\n\t\t\tmoved.set(other, next.y)\n\t\t\tqueue.push(next)\n\t\t}\n\t}\n\treturn [...moved.entries()]\n\t\t.map(([item, y]) => ({ node: item, y }))\n\t\t.sort((a, b) => b.y - a.y)\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -199632,6 +199632,11 @@ var script$3e = {
|
|
|
199632
199632
|
cnTranslate: { default: () => (key) => key },
|
|
199633
199633
|
},
|
|
199634
199634
|
|
|
199635
|
+
// A dashboard binds the widget's `content` keys as attributes too. Falling
|
|
199636
|
+
// through, `submitLabel` would reach CnFormWidgetBase and win over the
|
|
199637
|
+
// translated label the widget passes, so attributes go through rootAttrs.
|
|
199638
|
+
inheritAttrs: false,
|
|
199639
|
+
|
|
199635
199640
|
props: {
|
|
199636
199641
|
/**
|
|
199637
199642
|
* Persisted configuration blob (see component description for the shape).
|
|
@@ -199667,6 +199672,19 @@ var script$3e = {
|
|
|
199667
199672
|
},
|
|
199668
199673
|
|
|
199669
199674
|
computed: {
|
|
199675
|
+
/**
|
|
199676
|
+
* The attributes for the root form: everything the widget was given,
|
|
199677
|
+
* minus the names CnFormWidgetBase takes as props, which the widget
|
|
199678
|
+
* sets itself.
|
|
199679
|
+
*
|
|
199680
|
+
* @spec openspec/changes/interaction-form-fits-and-reads-dutch/specs/interaction-form-widget/spec.md#requirement-the-interaction-form-fits-its-card-and-reads-in-the-readers-language
|
|
199681
|
+
* @return {object} The attributes to bind.
|
|
199682
|
+
*/
|
|
199683
|
+
rootAttrs() {
|
|
199684
|
+
const own = new Set(Object.keys(__sfc_main$3f.props || {}));
|
|
199685
|
+
return Object.fromEntries(Object.entries(this.$attrs).filter(([key]) => !own.has(vue$1.camelize(key))))
|
|
199686
|
+
},
|
|
199687
|
+
|
|
199670
199688
|
register() {
|
|
199671
199689
|
return this.content.register || 'pipelinq'
|
|
199672
199690
|
},
|
|
@@ -200034,7 +200052,7 @@ function render$3e(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
200034
200052
|
const _component_NcButton = vue$1.resolveComponent("NcButton");
|
|
200035
200053
|
const _component_CnFormWidgetBase = vue$1.resolveComponent("CnFormWidgetBase");
|
|
200036
200054
|
|
|
200037
|
-
return (vue$1.openBlock(), vue$1.createBlock(_component_CnFormWidgetBase, {
|
|
200055
|
+
return (vue$1.openBlock(), vue$1.createBlock(_component_CnFormWidgetBase, vue$1.mergeProps($options.rootAttrs, {
|
|
200038
200056
|
blockClass: "cn-interaction-form-widget",
|
|
200039
200057
|
fields: $options.formFields,
|
|
200040
200058
|
model: $data.form,
|
|
@@ -200046,7 +200064,7 @@ function render$3e(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
200046
200064
|
errorMessage: $data.errorMessage,
|
|
200047
200065
|
"onUpdate:field": $options.onFieldUpdate,
|
|
200048
200066
|
onSubmit: $options.onRegister
|
|
200049
|
-
}, {
|
|
200067
|
+
}), {
|
|
200050
200068
|
"field-client": vue$1.withCtx(() => [
|
|
200051
200069
|
vue$1.createVNode(_component_CnResourceSelect, {
|
|
200052
200070
|
register: $options.register,
|
|
@@ -200079,7 +200097,7 @@ function render$3e(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
200079
200097
|
: vue$1.createCommentVNode("v-if", true)
|
|
200080
200098
|
]),
|
|
200081
200099
|
_: 1 /* STABLE */
|
|
200082
|
-
},
|
|
200100
|
+
}, 16 /* FULL_PROPS */, ["fields", "model", "errors", "canSubmit", "submitting", "submitLabel", "submittingLabel", "errorMessage", "onUpdate:field", "onSubmit"]))
|
|
200083
200101
|
}
|
|
200084
200102
|
|
|
200085
200103
|
script$3e.render = render$3e;
|
|
@@ -306984,8 +307002,11 @@ function readGridGeometry(items) {
|
|
|
306984
307002
|
* full-width card under the stat tiles landed below the lists.
|
|
306985
307003
|
*
|
|
306986
307004
|
* @spec openspec/changes/dashboard-growth-keeps-order/specs/dashboard-grid/spec.md#requirement-a-growing-cell-keeps-the-order-of-the-cards-under-it
|
|
306987
|
-
*
|
|
306988
|
-
*
|
|
307005
|
+
* The growing item is never among the items it moves, also when `nodes`
|
|
307006
|
+
* holds another reference to it (a proxy of the same node, matched by `el`).
|
|
307007
|
+
*
|
|
307008
|
+
* @param {Array<{x: number, y: number, w: number, h: number, el: (HTMLElement|undefined)}>} nodes The grid's items (the growing one among them).
|
|
307009
|
+
* @param {{x: number, y: number, w: number, h: number, el: (HTMLElement|undefined)}} node The growing item.
|
|
306989
307010
|
* @param {number} h Its new height, in grid rows.
|
|
306990
307011
|
* @return {Array<{node: object, y: number}>} The items to move and their new row, bottom-most first.
|
|
306991
307012
|
*/
|
|
@@ -307000,7 +307021,8 @@ function planGrowth(nodes, node, h) {
|
|
|
307000
307021
|
while (queue.length > 0) {
|
|
307001
307022
|
const rect = queue.shift();
|
|
307002
307023
|
for (const other of nodes) {
|
|
307003
|
-
|
|
307024
|
+
const self = other === node || (node.el && other.el === node.el);
|
|
307025
|
+
if (self || moved.has(other) || !overlaps(rect, other)) {
|
|
307004
307026
|
continue
|
|
307005
307027
|
}
|
|
307006
307028
|
const next = { x: other.x, y: other.y + delta, w: other.w, h: other.h };
|
|
@@ -307624,16 +307646,27 @@ var script$1t = {
|
|
|
307624
307646
|
* (`itemsInRowOrder`). A cell that shrinks is left to GridStack as
|
|
307625
307647
|
* before.
|
|
307626
307648
|
*
|
|
307649
|
+
* The grid is read raw: through Vue's proxy `engine.nodes` holds proxies
|
|
307650
|
+
* while `el.gridstackNode` is the plain node, so the growing cell would
|
|
307651
|
+
* not be recognised among the nodes and would be moved down by its own
|
|
307652
|
+
* growth. Moving a cell makes GridStack measure it again, so a cell the
|
|
307653
|
+
* wrapper is already growing goes straight to GridStack.
|
|
307654
|
+
*
|
|
307627
307655
|
* @spec openspec/changes/dashboard-growth-keeps-order/specs/dashboard-grid/spec.md#requirement-a-growing-cell-keeps-the-order-of-the-cards-under-it
|
|
307628
307656
|
* @return {void}
|
|
307629
307657
|
*/
|
|
307630
307658
|
keepOrderOnGrowth() {
|
|
307631
|
-
const grid = this.grid;
|
|
307659
|
+
const grid = vue$1.toRaw(this.grid);
|
|
307632
307660
|
if (!grid || typeof grid.resizeToContent !== 'function' || typeof grid.update !== 'function') {
|
|
307633
307661
|
return
|
|
307634
307662
|
}
|
|
307635
307663
|
const resize = grid.resizeToContent.bind(grid);
|
|
307664
|
+
const growing = new Set();
|
|
307636
307665
|
grid.resizeToContent = (el) => {
|
|
307666
|
+
if (growing.has(el)) {
|
|
307667
|
+
resize(el);
|
|
307668
|
+
return
|
|
307669
|
+
}
|
|
307637
307670
|
const node = el && el.gridstackNode;
|
|
307638
307671
|
const nodes = grid.engine && Array.isArray(grid.engine.nodes) ? grid.engine.nodes : null;
|
|
307639
307672
|
const rows = node && nodes ? this.contentRows(el, node) : null;
|
|
@@ -307644,15 +307677,20 @@ var script$1t = {
|
|
|
307644
307677
|
}
|
|
307645
307678
|
// Inside a batch the moves are not packed until the cell has grown.
|
|
307646
307679
|
const batching = Boolean(grid.engine.batchMode);
|
|
307647
|
-
|
|
307648
|
-
|
|
307649
|
-
|
|
307650
|
-
|
|
307651
|
-
|
|
307652
|
-
|
|
307653
|
-
|
|
307654
|
-
|
|
307655
|
-
|
|
307680
|
+
growing.add(el);
|
|
307681
|
+
try {
|
|
307682
|
+
if (!batching) {
|
|
307683
|
+
grid.batchUpdate();
|
|
307684
|
+
}
|
|
307685
|
+
for (const step of plan) {
|
|
307686
|
+
grid.update(step.node.el, { y: step.y });
|
|
307687
|
+
}
|
|
307688
|
+
resize(el);
|
|
307689
|
+
if (!batching) {
|
|
307690
|
+
grid.batchUpdate(false);
|
|
307691
|
+
}
|
|
307692
|
+
} finally {
|
|
307693
|
+
growing.delete(el);
|
|
307656
307694
|
}
|
|
307657
307695
|
};
|
|
307658
307696
|
},
|
|
@@ -308255,7 +308293,7 @@ function render$1t(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
308255
308293
|
}
|
|
308256
308294
|
|
|
308257
308295
|
script$1t.render = render$1t;
|
|
308258
|
-
script$1t.__scopeId = "data-v-
|
|
308296
|
+
script$1t.__scopeId = "data-v-a76b6fc6";
|
|
308259
308297
|
const __sfc_main$1t = script$1t;
|
|
308260
308298
|
|
|
308261
308299
|
/**
|
|
@@ -358535,6 +358573,7 @@ var script$h = {
|
|
|
358535
358573
|
// write lands; this warns the user while there are unsaved/in-flight
|
|
358536
358574
|
// changes. Registered before the early-return so it always installs.
|
|
358537
358575
|
window.addEventListener('beforeunload', this.onBeforeUnload);
|
|
358576
|
+
window.addEventListener(OBJECTS_CHANGED_EVENT, this.onObjectsChanged);
|
|
358538
358577
|
|
|
358539
358578
|
// Opt-out fast-path: empty `requiresApps` already initialised
|
|
358540
358579
|
// `capabilitiesLoading` to `false` in data(); skip the check.
|
|
@@ -358580,6 +358619,7 @@ var script$h = {
|
|
|
358580
358619
|
this.removeDiagnostics = null;
|
|
358581
358620
|
}
|
|
358582
358621
|
window.removeEventListener('beforeunload', this.onBeforeUnload);
|
|
358622
|
+
window.removeEventListener(OBJECTS_CHANGED_EVENT, this.onObjectsChanged);
|
|
358583
358623
|
this.cnScopedTheme.teardown(this.appId);
|
|
358584
358624
|
// Scope the side effect to the shell's lifetime. Layers already written
|
|
358585
358625
|
// stay on screen (see `uninstallModalStack`), so a dialog outliving the
|
|
@@ -359426,13 +359466,17 @@ var script$h = {
|
|
|
359426
359466
|
* response `total` written to `cnMenuItemCounts[item.id]`. The
|
|
359427
359467
|
* request goes straight through axios rather than the object store,
|
|
359428
359468
|
* so the index page's whole-schema total in the store is left alone.
|
|
359429
|
-
* Failures leave the badge unrendered.
|
|
359469
|
+
* Failures leave the badge unrendered. Given a changed register and
|
|
359470
|
+
* schema, only the entries counting that list are read again.
|
|
359430
359471
|
*
|
|
359431
359472
|
* @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-menu-entry-counts-a-filtered-list
|
|
359473
|
+
* @param {{register?: string|null, schema?: string|null}|null} [changed] The list that changed; null reads every count.
|
|
359432
359474
|
* @return {void}
|
|
359433
359475
|
* @private
|
|
359434
359476
|
*/
|
|
359435
|
-
_hydrateMenuItemCounts() {
|
|
359477
|
+
_hydrateMenuItemCounts(changed = null) {
|
|
359478
|
+
const register = changed?.register ?? null;
|
|
359479
|
+
const schema = changed?.schema ?? null;
|
|
359436
359480
|
const collect = (items) => {
|
|
359437
359481
|
const out = [];
|
|
359438
359482
|
for (const item of items ?? []) {
|
|
@@ -359447,10 +359491,27 @@ var script$h = {
|
|
|
359447
359491
|
return out
|
|
359448
359492
|
};
|
|
359449
359493
|
for (const item of collect(this.manifest?.menu)) {
|
|
359450
|
-
|
|
359494
|
+
if ((register === null || item.count.register === register) && (schema === null || item.count.schema === schema)) {
|
|
359495
|
+
this._fetchMenuItemCount(item);
|
|
359496
|
+
}
|
|
359451
359497
|
}
|
|
359452
359498
|
},
|
|
359453
359499
|
|
|
359500
|
+
/**
|
|
359501
|
+
* Objects changed outside the list showing them (`cn:objects-changed`,
|
|
359502
|
+
* see `dispatchObjectsChanged`): read the filtered menu counts of that
|
|
359503
|
+
* register and schema again, so a badge follows a claim, a close or a
|
|
359504
|
+
* bulk action instead of keeping the number it had at mount. A signal
|
|
359505
|
+
* without a register or schema reads every filtered count again.
|
|
359506
|
+
*
|
|
359507
|
+
* @spec openspec/changes/menu-counts-follow-changed-objects/specs/layout-components/spec.md#requirement-a-filtered-menu-count-follows-changed-objects
|
|
359508
|
+
* @param {CustomEvent} event The signal, with `detail: { register, schema, id }`.
|
|
359509
|
+
* @return {void}
|
|
359510
|
+
*/
|
|
359511
|
+
onObjectsChanged(event) {
|
|
359512
|
+
this._hydrateMenuItemCounts(event?.detail ?? null);
|
|
359513
|
+
},
|
|
359514
|
+
|
|
359454
359515
|
/**
|
|
359455
359516
|
* One filtered-count request for a menu entry; see
|
|
359456
359517
|
* `_hydrateMenuItemCounts`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: package/dist/nextcloud-vue.cjs.js.map
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 40768932 bytes
|
|
4
|
+
sha256: 5eaf232e7473c7af37c95cfc8b0839550069002fa540192d0ea4b88131fbc06d
|
package/dist/nextcloud-vue.css
CHANGED
|
@@ -38141,17 +38141,17 @@ button.cn-object-calendar__overflow[data-v-e1c69ee2] {
|
|
|
38141
38141
|
}
|
|
38142
38142
|
|
|
38143
38143
|
|
|
38144
|
-
.cn-dashboard-grid[data-v-
|
|
38144
|
+
.cn-dashboard-grid[data-v-a76b6fc6] {
|
|
38145
38145
|
width: 100%;
|
|
38146
38146
|
min-height: 200px;
|
|
38147
38147
|
}
|
|
38148
|
-
.grid-stack[data-v-
|
|
38148
|
+
.grid-stack[data-v-a76b6fc6] {
|
|
38149
38149
|
background: transparent;
|
|
38150
38150
|
}
|
|
38151
38151
|
|
|
38152
38152
|
/* Screen-reader-only text: the keyboard key map and the live region. Kept in
|
|
38153
38153
|
the layout (not `display: none`) so assistive tech still reads it. */
|
|
38154
|
-
.cn-dashboard-grid__sr-only[data-v-
|
|
38154
|
+
.cn-dashboard-grid__sr-only[data-v-a76b6fc6] {
|
|
38155
38155
|
position: absolute;
|
|
38156
38156
|
width: 1px;
|
|
38157
38157
|
height: 1px;
|
|
@@ -38166,7 +38166,7 @@ button.cn-object-calendar__overflow[data-v-e1c69ee2] {
|
|
|
38166
38166
|
/* Grid items become tab stops in edit mode — give them a visible focus ring
|
|
38167
38167
|
that satisfies WCAG 2.1 SC 2.4.7 without relying on the widget's own
|
|
38168
38168
|
styling. `outline-offset` keeps the ring outside the rounded card. */
|
|
38169
|
-
.grid-stack-item[data-v-
|
|
38169
|
+
.grid-stack-item[data-v-a76b6fc6]:focus-visible {
|
|
38170
38170
|
outline: 2px solid var(--color-primary-element, #0082c9);
|
|
38171
38171
|
outline-offset: 2px;
|
|
38172
38172
|
border-radius: var(--border-radius-container-large, 16px);
|
|
@@ -38178,19 +38178,19 @@ button.cn-object-calendar__overflow[data-v-e1c69ee2] {
|
|
|
38178
38178
|
cell never shrank: "Waiting for me" stayed a tall card around one row. In
|
|
38179
38179
|
such a cell the child takes its own height. A cell without the key keeps
|
|
38180
38180
|
the filling child. */
|
|
38181
|
-
.cn-dashboard-grid__item--fit[data-v-
|
|
38181
|
+
.cn-dashboard-grid__item--fit[data-v-a76b6fc6] > .grid-stack-item-content > * {
|
|
38182
38182
|
height: auto;
|
|
38183
38183
|
}
|
|
38184
|
-
[data-v-
|
|
38184
|
+
[data-v-a76b6fc6] .grid-stack-item-content {
|
|
38185
38185
|
background: var(--color-main-background);
|
|
38186
38186
|
border: none;
|
|
38187
38187
|
box-shadow: none;
|
|
38188
38188
|
overflow: hidden;
|
|
38189
38189
|
}
|
|
38190
|
-
[data-v-
|
|
38190
|
+
[data-v-a76b6fc6] .grid-stack-item-content:has(.cn-widget-wrapper--borderless) {
|
|
38191
38191
|
background: transparent;
|
|
38192
38192
|
}
|
|
38193
|
-
[data-v-
|
|
38193
|
+
[data-v-a76b6fc6] .grid-stack-placeholder > .placeholder-content {
|
|
38194
38194
|
background: var(--color-primary-element-light);
|
|
38195
38195
|
border: 2px dashed var(--color-primary-element);
|
|
38196
38196
|
border-radius: var(--border-radius-large);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conduction/nextcloud-vue",
|
|
3
|
-
"version": "2.89.
|
|
3
|
+
"version": "2.89.2",
|
|
4
4
|
"description": "Shared Vue component library for Conduction Nextcloud apps — complements @nextcloud/vue with higher-level components, OpenRegister integration, and NL Design System support",
|
|
5
5
|
"homepage": "https://github.com/ConductionNL/nextcloud-vue#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -740,6 +740,7 @@ import { DEFAULT_FORGE, resolveForge } from '../../utils/forge.js'
|
|
|
740
740
|
import { BUILT_IN_KB_PROVIDERS } from '../../utils/kbSearchProviders.js'
|
|
741
741
|
import { createManifestTranslate } from '../../utils/manifestTranslate.js'
|
|
742
742
|
import { installModalStack, uninstallModalStack } from '../../utils/modalStack.js'
|
|
743
|
+
import { OBJECTS_CHANGED_EVENT } from '../../utils/objectSignals.js'
|
|
743
744
|
import { resolveBrand } from '../../utils/resolveBrand.js'
|
|
744
745
|
import { resolveFilterTokens } from '../../utils/resolveFilterTokens.js'
|
|
745
746
|
import { passesContextPredicates } from '../../utils/visibleIfContext.js'
|
|
@@ -3221,6 +3222,7 @@ export default {
|
|
|
3221
3222
|
// write lands; this warns the user while there are unsaved/in-flight
|
|
3222
3223
|
// changes. Registered before the early-return so it always installs.
|
|
3223
3224
|
window.addEventListener('beforeunload', this.onBeforeUnload)
|
|
3225
|
+
window.addEventListener(OBJECTS_CHANGED_EVENT, this.onObjectsChanged)
|
|
3224
3226
|
|
|
3225
3227
|
// Opt-out fast-path: empty `requiresApps` already initialised
|
|
3226
3228
|
// `capabilitiesLoading` to `false` in data(); skip the check.
|
|
@@ -3266,6 +3268,7 @@ export default {
|
|
|
3266
3268
|
this.removeDiagnostics = null
|
|
3267
3269
|
}
|
|
3268
3270
|
window.removeEventListener('beforeunload', this.onBeforeUnload)
|
|
3271
|
+
window.removeEventListener(OBJECTS_CHANGED_EVENT, this.onObjectsChanged)
|
|
3269
3272
|
this.cnScopedTheme.teardown(this.appId)
|
|
3270
3273
|
// Scope the side effect to the shell's lifetime. Layers already written
|
|
3271
3274
|
// stay on screen (see `uninstallModalStack`), so a dialog outliving the
|
|
@@ -4112,13 +4115,17 @@ export default {
|
|
|
4112
4115
|
* response `total` written to `cnMenuItemCounts[item.id]`. The
|
|
4113
4116
|
* request goes straight through axios rather than the object store,
|
|
4114
4117
|
* so the index page's whole-schema total in the store is left alone.
|
|
4115
|
-
* Failures leave the badge unrendered.
|
|
4118
|
+
* Failures leave the badge unrendered. Given a changed register and
|
|
4119
|
+
* schema, only the entries counting that list are read again.
|
|
4116
4120
|
*
|
|
4117
4121
|
* @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-menu-entry-counts-a-filtered-list
|
|
4122
|
+
* @param {{register?: string|null, schema?: string|null}|null} [changed] The list that changed; null reads every count.
|
|
4118
4123
|
* @return {void}
|
|
4119
4124
|
* @private
|
|
4120
4125
|
*/
|
|
4121
|
-
_hydrateMenuItemCounts() {
|
|
4126
|
+
_hydrateMenuItemCounts(changed = null) {
|
|
4127
|
+
const register = changed?.register ?? null
|
|
4128
|
+
const schema = changed?.schema ?? null
|
|
4122
4129
|
const collect = (items) => {
|
|
4123
4130
|
const out = []
|
|
4124
4131
|
for (const item of items ?? []) {
|
|
@@ -4133,10 +4140,27 @@ export default {
|
|
|
4133
4140
|
return out
|
|
4134
4141
|
}
|
|
4135
4142
|
for (const item of collect(this.manifest?.menu)) {
|
|
4136
|
-
|
|
4143
|
+
if ((register === null || item.count.register === register) && (schema === null || item.count.schema === schema)) {
|
|
4144
|
+
this._fetchMenuItemCount(item)
|
|
4145
|
+
}
|
|
4137
4146
|
}
|
|
4138
4147
|
},
|
|
4139
4148
|
|
|
4149
|
+
/**
|
|
4150
|
+
* Objects changed outside the list showing them (`cn:objects-changed`,
|
|
4151
|
+
* see `dispatchObjectsChanged`): read the filtered menu counts of that
|
|
4152
|
+
* register and schema again, so a badge follows a claim, a close or a
|
|
4153
|
+
* bulk action instead of keeping the number it had at mount. A signal
|
|
4154
|
+
* without a register or schema reads every filtered count again.
|
|
4155
|
+
*
|
|
4156
|
+
* @spec openspec/changes/menu-counts-follow-changed-objects/specs/layout-components/spec.md#requirement-a-filtered-menu-count-follows-changed-objects
|
|
4157
|
+
* @param {CustomEvent} event The signal, with `detail: { register, schema, id }`.
|
|
4158
|
+
* @return {void}
|
|
4159
|
+
*/
|
|
4160
|
+
onObjectsChanged(event) {
|
|
4161
|
+
this._hydrateMenuItemCounts(event?.detail ?? null)
|
|
4162
|
+
},
|
|
4163
|
+
|
|
4140
4164
|
/**
|
|
4141
4165
|
* One filtered-count request for a menu entry; see
|
|
4142
4166
|
* `_hydrateMenuItemCounts`.
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
<script>
|
|
72
72
|
import { translate as t } from '@nextcloud/l10n'
|
|
73
73
|
import { GridStack } from 'gridstack'
|
|
74
|
+
import { toRaw } from 'vue'
|
|
74
75
|
import { planGrowth } from '../../utils/gridStack.js'
|
|
75
76
|
// `gridstack` is a peerDependency (see package.json), not bundled — this
|
|
76
77
|
// component's JS and the consumer's GridStack stylesheet MUST come from the
|
|
@@ -683,16 +684,27 @@ export default {
|
|
|
683
684
|
* (`itemsInRowOrder`). A cell that shrinks is left to GridStack as
|
|
684
685
|
* before.
|
|
685
686
|
*
|
|
687
|
+
* The grid is read raw: through Vue's proxy `engine.nodes` holds proxies
|
|
688
|
+
* while `el.gridstackNode` is the plain node, so the growing cell would
|
|
689
|
+
* not be recognised among the nodes and would be moved down by its own
|
|
690
|
+
* growth. Moving a cell makes GridStack measure it again, so a cell the
|
|
691
|
+
* wrapper is already growing goes straight to GridStack.
|
|
692
|
+
*
|
|
686
693
|
* @spec openspec/changes/dashboard-growth-keeps-order/specs/dashboard-grid/spec.md#requirement-a-growing-cell-keeps-the-order-of-the-cards-under-it
|
|
687
694
|
* @return {void}
|
|
688
695
|
*/
|
|
689
696
|
keepOrderOnGrowth() {
|
|
690
|
-
const grid = this.grid
|
|
697
|
+
const grid = toRaw(this.grid)
|
|
691
698
|
if (!grid || typeof grid.resizeToContent !== 'function' || typeof grid.update !== 'function') {
|
|
692
699
|
return
|
|
693
700
|
}
|
|
694
701
|
const resize = grid.resizeToContent.bind(grid)
|
|
702
|
+
const growing = new Set()
|
|
695
703
|
grid.resizeToContent = (el) => {
|
|
704
|
+
if (growing.has(el)) {
|
|
705
|
+
resize(el)
|
|
706
|
+
return
|
|
707
|
+
}
|
|
696
708
|
const node = el && el.gridstackNode
|
|
697
709
|
const nodes = grid.engine && Array.isArray(grid.engine.nodes) ? grid.engine.nodes : null
|
|
698
710
|
const rows = node && nodes ? this.contentRows(el, node) : null
|
|
@@ -703,15 +715,20 @@ export default {
|
|
|
703
715
|
}
|
|
704
716
|
// Inside a batch the moves are not packed until the cell has grown.
|
|
705
717
|
const batching = Boolean(grid.engine.batchMode)
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
718
|
+
growing.add(el)
|
|
719
|
+
try {
|
|
720
|
+
if (!batching) {
|
|
721
|
+
grid.batchUpdate()
|
|
722
|
+
}
|
|
723
|
+
for (const step of plan) {
|
|
724
|
+
grid.update(step.node.el, { y: step.y })
|
|
725
|
+
}
|
|
726
|
+
resize(el)
|
|
727
|
+
if (!batching) {
|
|
728
|
+
grid.batchUpdate(false)
|
|
729
|
+
}
|
|
730
|
+
} finally {
|
|
731
|
+
growing.delete(el)
|
|
715
732
|
}
|
|
716
733
|
}
|
|
717
734
|
},
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
-->
|
|
5
5
|
<template>
|
|
6
6
|
<CnFormWidgetBase
|
|
7
|
+
v-bind="rootAttrs"
|
|
7
8
|
blockClass="cn-interaction-form-widget"
|
|
8
9
|
:fields="formFields"
|
|
9
10
|
:model="form"
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
<script>
|
|
52
53
|
import { translate as t } from '@nextcloud/l10n'
|
|
53
54
|
import { NcButton } from '@nextcloud/vue'
|
|
55
|
+
import { camelize } from 'vue'
|
|
54
56
|
import OpenInNew from 'vue-material-design-icons/OpenInNew.vue'
|
|
55
57
|
import CnFormWidgetBase from '../CnFormWidgetBase/CnFormWidgetBase.vue'
|
|
56
58
|
import CnResourceSelect from '../CnResourceSelect/CnResourceSelect.vue'
|
|
@@ -125,6 +127,11 @@ export default {
|
|
|
125
127
|
cnTranslate: { default: () => (key) => key },
|
|
126
128
|
},
|
|
127
129
|
|
|
130
|
+
// A dashboard binds the widget's `content` keys as attributes too. Falling
|
|
131
|
+
// through, `submitLabel` would reach CnFormWidgetBase and win over the
|
|
132
|
+
// translated label the widget passes, so attributes go through rootAttrs.
|
|
133
|
+
inheritAttrs: false,
|
|
134
|
+
|
|
128
135
|
props: {
|
|
129
136
|
/**
|
|
130
137
|
* Persisted configuration blob (see component description for the shape).
|
|
@@ -160,6 +167,19 @@ export default {
|
|
|
160
167
|
},
|
|
161
168
|
|
|
162
169
|
computed: {
|
|
170
|
+
/**
|
|
171
|
+
* The attributes for the root form: everything the widget was given,
|
|
172
|
+
* minus the names CnFormWidgetBase takes as props, which the widget
|
|
173
|
+
* sets itself.
|
|
174
|
+
*
|
|
175
|
+
* @spec openspec/changes/interaction-form-fits-and-reads-dutch/specs/interaction-form-widget/spec.md#requirement-the-interaction-form-fits-its-card-and-reads-in-the-readers-language
|
|
176
|
+
* @return {object} The attributes to bind.
|
|
177
|
+
*/
|
|
178
|
+
rootAttrs() {
|
|
179
|
+
const own = new Set(Object.keys(CnFormWidgetBase.props || {}))
|
|
180
|
+
return Object.fromEntries(Object.entries(this.$attrs).filter(([key]) => !own.has(camelize(key))))
|
|
181
|
+
},
|
|
182
|
+
|
|
163
183
|
register() {
|
|
164
184
|
return this.content.register || 'pipelinq'
|
|
165
185
|
},
|
package/src/utils/gridStack.js
CHANGED
|
@@ -64,8 +64,11 @@ export function readGridGeometry(items) {
|
|
|
64
64
|
* full-width card under the stat tiles landed below the lists.
|
|
65
65
|
*
|
|
66
66
|
* @spec openspec/changes/dashboard-growth-keeps-order/specs/dashboard-grid/spec.md#requirement-a-growing-cell-keeps-the-order-of-the-cards-under-it
|
|
67
|
-
*
|
|
68
|
-
*
|
|
67
|
+
* The growing item is never among the items it moves, also when `nodes`
|
|
68
|
+
* holds another reference to it (a proxy of the same node, matched by `el`).
|
|
69
|
+
*
|
|
70
|
+
* @param {Array<{x: number, y: number, w: number, h: number, el: (HTMLElement|undefined)}>} nodes The grid's items (the growing one among them).
|
|
71
|
+
* @param {{x: number, y: number, w: number, h: number, el: (HTMLElement|undefined)}} node The growing item.
|
|
69
72
|
* @param {number} h Its new height, in grid rows.
|
|
70
73
|
* @return {Array<{node: object, y: number}>} The items to move and their new row, bottom-most first.
|
|
71
74
|
*/
|
|
@@ -80,7 +83,8 @@ export function planGrowth(nodes, node, h) {
|
|
|
80
83
|
while (queue.length > 0) {
|
|
81
84
|
const rect = queue.shift()
|
|
82
85
|
for (const other of nodes) {
|
|
83
|
-
|
|
86
|
+
const self = other === node || (node.el && other.el === node.el)
|
|
87
|
+
if (self || moved.has(other) || !overlaps(rect, other)) {
|
|
84
88
|
continue
|
|
85
89
|
}
|
|
86
90
|
const next = { x: other.x, y: other.y + delta, w: other.w, h: other.h }
|