@conduction/nextcloud-vue 2.56.0-beta.38 → 2.56.0-beta.39

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 (31) hide show
  1. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +2 -0
  2. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  3. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  4. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
  5. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +36 -0
  6. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  7. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +55 -40
  8. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  9. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue.js +1 -1
  10. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +3 -26
  11. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
  12. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
  13. package/dist/esm/library-style.js +1 -1
  14. package/dist/esm/nextcloud-vue.css +74 -53
  15. package/dist/esm/utils/boardReferenceColumns.js +63 -4
  16. package/dist/esm/utils/boardReferenceColumns.js.map +1 -1
  17. package/dist/esm/utils/contentHeaderLink.js +48 -1
  18. package/dist/esm/utils/contentHeaderLink.js.map +1 -1
  19. package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
  20. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  21. package/dist/nextcloud-vue.cjs.js +255 -121
  22. package/dist/nextcloud-vue.cjs.js.map +2 -2
  23. package/dist/nextcloud-vue.css +74 -53
  24. package/package.json +1 -1
  25. package/src/components/CnIndexPage/CnIndexPage.vue +2 -0
  26. package/src/components/CnTabsWidget/CnTabsWidget.vue +71 -0
  27. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +3 -26
  28. package/src/schemas/app-manifest-v2.schema.json +3 -1
  29. package/src/utils/boardReferenceColumns.js +62 -3
  30. package/src/utils/contentHeaderLink.js +47 -0
  31. package/src/utils/validateManifestV2.compiled.js +2 -2
@@ -127,6 +127,11 @@ export function referenceTargetOf(source, { register = '', property = null } = {
127
127
  * @param {string} [options.narrowValue] The parent the board is narrowed to, '' for all.
128
128
  * @param {string} [options.capacityField] The numeric row field that holds a column's limit.
129
129
  * A column merged from two or more rows shows none: each row has its own limit.
130
+ * @param {string} [options.neutralColor] The colour a row holds when nobody chose one. A merged
131
+ * column then takes its first row colour that is not this one, and this one only when no row
132
+ * has another. Compared as written: "Grey" is not "grey", and a hex value is not a name.
133
+ * @param {object} [options.colorMap] A stored colour to the CSS colour a column is drawn in,
134
+ * applied after the merge. A colour it does not map is kept as stored.
130
135
  * @return {{states: Array<{key: string, label: string, color: string, capacity?: (number|null)}>, keyByValue: Map<string, string>, refsByKey: Map<string, Array<object>>}} The stages.
131
136
  * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-columns-can-be-the-rows-a-field-references
132
137
  */
@@ -139,6 +144,8 @@ export function buildReferenceStages({
139
144
  narrowBy = null,
140
145
  narrowValue = '',
141
146
  capacityField = '',
147
+ neutralColor = '',
148
+ colorMap = null,
142
149
  } = {}) {
143
150
  const list = (Array.isArray(refs) ? refs : []).filter((ref) => ref && typeof ref === 'object' && refIdOf(ref) !== '')
144
151
  const narrowed = narrowBy && narrowBy.field && narrowValue !== ''
@@ -164,8 +171,7 @@ export function buildReferenceStages({
164
171
  keyByValue.set(id, key)
165
172
  if (!refsByKey.has(key)) {
166
173
  refsByKey.set(key, [])
167
- const color = colorField ? readPath(ref, colorField) : ref.color
168
- const state = { key, label, color: typeof color === 'string' ? color : '' }
174
+ const state = { key, label, color: colorOfRef(ref, colorField) }
169
175
  if (capacityField) {
170
176
  state.capacity = capacityOfRef(ref, capacityField)
171
177
  }
@@ -174,13 +180,66 @@ export function buildReferenceStages({
174
180
  refsByKey.get(key).push(ref)
175
181
  }
176
182
  for (const state of states) {
177
- if (capacityField && refsByKey.get(state.key).length > 1) {
183
+ const rows = refsByKey.get(state.key)
184
+ if (capacityField && rows.length > 1) {
178
185
  state.capacity = null
179
186
  }
187
+ if (neutralColor && rows.length > 1) {
188
+ state.color = mergedColumnColor(rows.map((ref) => colorOfRef(ref, colorField)), neutralColor, state.color)
189
+ }
190
+ state.color = mappedColor(state.color, colorMap)
180
191
  }
181
192
  return { states, keyByValue, refsByKey }
182
193
  }
183
194
 
195
+ /**
196
+ * The colour one referenced row carries.
197
+ *
198
+ * @param {object} ref The referenced row.
199
+ * @param {string} colorField The row field that holds the colour, '' for `color`.
200
+ * @return {string} The colour, '' when it has none.
201
+ */
202
+ function colorOfRef(ref, colorField) {
203
+ const color = colorField ? readPath(ref, colorField) : ref.color
204
+ return typeof color === 'string' ? color : ''
205
+ }
206
+
207
+ /**
208
+ * The colour a column merged from several rows takes when a neutral colour
209
+ * is declared: the first chosen colour, so a row stored with the default
210
+ * never outranks one somebody picked, whatever order the rows come in.
211
+ *
212
+ * @param {Array<string>} colors The rows' colours, in column order.
213
+ * @param {string} neutralColor The colour a row holds when nobody chose one.
214
+ * @param {string} fallback The colour when no row has a chosen or neutral one.
215
+ * @return {string} The column's colour.
216
+ * @spec openspec/changes/board-neutral-column-colour/specs/board-view/spec.md#requirement-a-merged-column-prefers-a-chosen-colour
217
+ */
218
+ export function mergedColumnColor(colors, neutralColor, fallback = '') {
219
+ const chosen = colors.find((color) => color !== '' && color !== neutralColor)
220
+ if (chosen !== undefined) {
221
+ return chosen
222
+ }
223
+ return colors.includes(neutralColor) ? neutralColor : fallback
224
+ }
225
+
226
+ /**
227
+ * The CSS colour a stored colour maps to, so a palette name such as
228
+ * "orange" or "grey-light" can draw a theme token.
229
+ *
230
+ * @param {string} color The stored colour.
231
+ * @param {object|null} colorMap A stored colour to a CSS colour.
232
+ * @return {string} The mapped colour, else the stored one.
233
+ * @spec openspec/changes/board-column-colour-map/specs/board-view/spec.md#requirement-a-column-colour-can-be-mapped-to-a-css-colour
234
+ */
235
+ export function mappedColor(color, colorMap) {
236
+ if (!colorMap || typeof colorMap !== 'object' || color === '' || !Object.hasOwn(colorMap, color)) {
237
+ return color
238
+ }
239
+ const mapped = colorMap[color]
240
+ return typeof mapped === 'string' && mapped !== '' ? mapped : color
241
+ }
242
+
184
243
  /**
185
244
  * The limit one referenced row declares.
186
245
  *
@@ -46,3 +46,50 @@ export function contentHeaderLink(content) {
46
46
  }
47
47
  return link
48
48
  }
49
+
50
+ /**
51
+ * The header link a widget DEFINITION declares: `headerLink` on the
52
+ * definition itself, else what its content asks for (see contentHeaderLink).
53
+ *
54
+ * @param {object|null|undefined} widget A widget definition.
55
+ * @return {{label: string, route?: string, params?: object, query?: object, href?: string}|null}
56
+ */
57
+ export function widgetHeaderLink(widget) {
58
+ if (!widget || typeof widget !== 'object') {
59
+ return null
60
+ }
61
+ const declared = widget.headerLink
62
+ if (declared && typeof declared === 'object' && typeof declared.label === 'string' && declared.label !== '') {
63
+ return declared
64
+ }
65
+ return contentHeaderLink(widget.content)
66
+ }
67
+
68
+ /**
69
+ * How to draw a header link: the tag and its attributes. A `route` is a
70
+ * `router-link` (only when a router is mounted), an `href` a plain anchor.
71
+ * An empty tag means there is nothing usable to draw.
72
+ *
73
+ * @param {object|null|undefined} link A link `{ label, route?, params?, query?, href? }`.
74
+ * @param {boolean} hasRouter Whether a router is mounted.
75
+ * @return {{tag: string, attrs: object}}
76
+ */
77
+ export function headerLinkTarget(link, hasRouter) {
78
+ if (!link || typeof link.label !== 'string' || link.label === '') {
79
+ return { tag: '', attrs: {} }
80
+ }
81
+ if (link.route && hasRouter) {
82
+ const to = { name: link.route }
83
+ if (link.params && typeof link.params === 'object') {
84
+ to.params = link.params
85
+ }
86
+ if (link.query && typeof link.query === 'object') {
87
+ to.query = link.query
88
+ }
89
+ return { tag: 'router-link', attrs: { to } }
90
+ }
91
+ if (typeof link.href === 'string' && link.href !== '') {
92
+ return { tag: 'a', attrs: { href: link.href } }
93
+ }
94
+ return { tag: '', attrs: {} }
95
+ }