@conduction/nextcloud-vue 2.69.0 → 2.70.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.
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +25 -0
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +155 -152
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +77 -0
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +8 -8
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
- package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue.js +1 -0
- package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue.js.map +1 -1
- package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue2.js +28 -0
- package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue2.js.map +1 -1
- package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js +4 -2
- package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js.map +1 -1
- package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js +25 -1
- package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue3.js +32 -17
- package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnCapabilityTable/CnCapabilityTable.vue2.js +14 -1
- package/dist/esm/components/CnCapabilityTable/CnCapabilityTable.vue2.js.map +1 -1
- package/dist/esm/components/CnCapabilityTable/CnCapabilityTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +43 -2
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js +3 -3
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +25 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +2 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +35 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +54 -3
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +6 -3
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +28 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +3 -2
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue2.js +12 -0
- package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js +9 -0
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js +54 -7
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js +26 -8
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +143 -0
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +68 -25
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnNextStepCard/CnNextStepCard.vue2.js.map +1 -1
- package/dist/esm/components/CnNextStepCard/CnNextStepCard.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +4 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue2.js +17 -3
- package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue3.js +25 -24
- package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +27 -0
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +7 -0
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js +24 -1
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js.map +1 -1
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js +1 -1
- package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js.map +1 -1
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js +11 -0
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js +4 -2
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue2.js +15 -2
- package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue3.js +31 -32
- package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue3.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +145 -0
- package/dist/esm/utils/capabilityComparison.js +29 -1
- package/dist/esm/utils/capabilityComparison.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +2167 -1399
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +145 -0
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.md +2 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +28 -2
- package/src/components/CnAppNav/CnAppNav.vue +85 -8
- package/src/components/CnBreadcrumbs/CnBreadcrumbs.vue +45 -0
- package/src/components/CnCalendarWidget/CnCalendarWidget.vue +32 -4
- package/src/components/CnCapabilityTable/CnCapabilityTable.vue +14 -0
- package/src/components/CnDashboardGrid/CnDashboardGrid.md +2 -0
- package/src/components/CnDashboardGrid/CnDashboardGrid.vue +54 -2
- package/src/components/CnDashboardPage/CnDashboardPage.vue +26 -1
- package/src/components/CnDataTable/CnDataTable.vue +35 -1
- package/src/components/CnDetailPage/CnDetailPage.md +2 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +57 -3
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +30 -1
- package/src/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue +12 -0
- package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +9 -0
- package/src/components/CnHeaderWidget/CnHeaderWidget.vue +95 -8
- package/src/components/CnIndexPage/CnIndexPage.vue +171 -6
- package/src/components/CnNextStepCard/CnNextStepCard.vue +11 -0
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +4 -1
- package/src/components/CnStackedBarWidget/CnStackedBarWidget.vue +34 -7
- package/src/components/CnStagesWidget/CnStagesWidget.vue +19 -0
- package/src/components/CnStatWidget/CnStatWidget.vue +36 -0
- package/src/components/CnStatsBlock/CnStatsBlock.md +2 -0
- package/src/components/CnStatsBlock/CnStatsBlock.vue +25 -2
- package/src/components/CnStatsBlockWidget/CnStatsBlockWidget.vue +13 -0
- package/src/components/CnWeekStripWidget/CnWeekStripWidget.vue +24 -3
- package/src/css/detail-page.css +10 -0
- package/src/css/index-page.css +12 -0
- package/src/css/kpi-card.css +15 -0
- package/src/schemas/app-manifest-v2.schema.json +46 -5
- package/src/utils/capabilityComparison.js +28 -0
- package/src/utils/validateManifestV2.compiled.js +2 -2
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
v-for="(item, index) in layout"
|
|
32
32
|
:key="resolveItemKey(item)"
|
|
33
33
|
class="grid-stack-item"
|
|
34
|
+
:class="{ 'cn-dashboard-grid__item--fit': sizeToContentAttr(item) !== undefined }"
|
|
34
35
|
role="group"
|
|
35
36
|
:aria-label="resolveItemLabel(item, index)"
|
|
36
37
|
:aria-describedby="itemDescribedBy"
|
|
@@ -255,6 +256,19 @@ export default {
|
|
|
255
256
|
type: Boolean,
|
|
256
257
|
default: true,
|
|
257
258
|
},
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* GridStack's `float`. True (the default) keeps every item on the row
|
|
262
|
+
* it was placed on, with empty rows above it if need be. False packs
|
|
263
|
+
* items upward, so a size-to-content cell that shrinks, or a widget
|
|
264
|
+
* that is not shown, closes its gap instead of leaving a band.
|
|
265
|
+
*
|
|
266
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-dashboard-closes-the-gap-a-shrinking-or-hidden-widget-leaves
|
|
267
|
+
*/
|
|
268
|
+
float: {
|
|
269
|
+
type: Boolean,
|
|
270
|
+
default: true,
|
|
271
|
+
},
|
|
258
272
|
},
|
|
259
273
|
|
|
260
274
|
emits: [
|
|
@@ -278,6 +292,8 @@ export default {
|
|
|
278
292
|
return {
|
|
279
293
|
grid: null,
|
|
280
294
|
contentObserver: null,
|
|
295
|
+
/** True while the grid moves an item to where the layout put it. */
|
|
296
|
+
applyingLayout: false,
|
|
281
297
|
domId: `cn-dashboard-grid-${++domIdCounter}`,
|
|
282
298
|
/** Text currently held in the polite live region. */
|
|
283
299
|
announcement: '',
|
|
@@ -485,7 +501,7 @@ export default {
|
|
|
485
501
|
column: this.columns,
|
|
486
502
|
cellHeight: this.cellHeight,
|
|
487
503
|
margin: this.margin,
|
|
488
|
-
float:
|
|
504
|
+
float: this.float,
|
|
489
505
|
animate: true,
|
|
490
506
|
disableDrag: !this.editable,
|
|
491
507
|
disableResize: !this.editable,
|
|
@@ -558,6 +574,10 @@ export default {
|
|
|
558
574
|
// switched off as the grid narrows, and back on as it widens.
|
|
559
575
|
this.syncInteractivity()
|
|
560
576
|
|
|
577
|
+
if (this.applyingLayout) {
|
|
578
|
+
return
|
|
579
|
+
}
|
|
580
|
+
|
|
561
581
|
// GridStack fires `change` for its own responsive rescale too, and at a
|
|
562
582
|
// 12 → 1 breakpoint every item reads `gridX: 0, gridWidth: 1`. Emitting
|
|
563
583
|
// that has the host persist the reflow AS the authored layout, which
|
|
@@ -957,7 +977,29 @@ export default {
|
|
|
957
977
|
const node = this.grid.engine.nodes.find((n) => String(n.id) === String(item.id))
|
|
958
978
|
if (!node) {
|
|
959
979
|
this.grid.makeWidget(el)
|
|
960
|
-
} else if (node.el
|
|
980
|
+
} else if (node.el === el) {
|
|
981
|
+
// The layout MOVED an item the grid already tracks: the
|
|
982
|
+
// page re-compacts its display layout when a widget's
|
|
983
|
+
// condition hides it, and the item below was given a new
|
|
984
|
+
// gridY that never reached GridStack, so a band stayed
|
|
985
|
+
// where the hidden widget had been. A drag reports the
|
|
986
|
+
// grid's own position back, which matches and does
|
|
987
|
+
// nothing here.
|
|
988
|
+
const x = item.gridX ?? node.x
|
|
989
|
+
const y = item.gridY ?? node.y
|
|
990
|
+
if (x !== node.x || y !== node.y) {
|
|
991
|
+
// The layout said where it goes; GridStack's `change`
|
|
992
|
+
// for it is not a user's arrangement and is not
|
|
993
|
+
// reported back (it would write the display-only
|
|
994
|
+
// compaction into the authored layout).
|
|
995
|
+
this.applyingLayout = true
|
|
996
|
+
try {
|
|
997
|
+
this.grid.update(el, { x, y })
|
|
998
|
+
} finally {
|
|
999
|
+
this.applyingLayout = false
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
} else {
|
|
961
1003
|
// Drop the stale node without touching its detached DOM,
|
|
962
1004
|
// then adopt the new element so GridStack sizes/places it.
|
|
963
1005
|
this.grid.removeWidget(node.el, false, false)
|
|
@@ -1016,6 +1058,16 @@ export default {
|
|
|
1016
1058
|
border-radius: var(--border-radius-container-large, 16px);
|
|
1017
1059
|
}
|
|
1018
1060
|
|
|
1061
|
+
/* A size-to-content cell (`sizeToContent`) is measured by GridStack from the
|
|
1062
|
+
content's first child, and a widget wrapper there filled the cell
|
|
1063
|
+
(`height: 100%`), so the measure returned the cell's own height and the
|
|
1064
|
+
cell never shrank: "Waiting for me" stayed a tall card around one row. In
|
|
1065
|
+
such a cell the child takes its own height. A cell without the key keeps
|
|
1066
|
+
the filling child. */
|
|
1067
|
+
.cn-dashboard-grid__item--fit > :deep(.grid-stack-item-content > *) {
|
|
1068
|
+
height: auto;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1019
1071
|
:deep(.grid-stack-item-content) {
|
|
1020
1072
|
background: var(--color-main-background);
|
|
1021
1073
|
border: none;
|
|
@@ -305,6 +305,7 @@
|
|
|
305
305
|
:columns="columns"
|
|
306
306
|
:cellHeight="cellHeight"
|
|
307
307
|
:margin="gridMargin"
|
|
308
|
+
:float="gridFloat"
|
|
308
309
|
@layoutChange="section.view ? onViewLayoutChange($event) : onLayoutChange($event)">
|
|
309
310
|
<template #widget="{ item }">
|
|
310
311
|
<!-- In-app edit overlay (ADR-041): a single launchpad-style
|
|
@@ -1030,6 +1031,19 @@ export default {
|
|
|
1030
1031
|
default: true,
|
|
1031
1032
|
},
|
|
1032
1033
|
|
|
1034
|
+
/**
|
|
1035
|
+
* GridStack's `float` for this dashboard (manifest
|
|
1036
|
+
* `config.gridFloat`). True (the default) keeps every widget on its
|
|
1037
|
+
* row. False packs widgets upward, so a size-to-content widget that
|
|
1038
|
+
* shrinks closes the gap under it instead of leaving an empty band.
|
|
1039
|
+
*
|
|
1040
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-dashboard-closes-the-gap-a-shrinking-or-hidden-widget-leaves
|
|
1041
|
+
*/
|
|
1042
|
+
gridFloat: {
|
|
1043
|
+
type: Boolean,
|
|
1044
|
+
default: true,
|
|
1045
|
+
},
|
|
1046
|
+
|
|
1033
1047
|
/**
|
|
1034
1048
|
* Widget definitions array. Each widget defines metadata for rendering.
|
|
1035
1049
|
*
|
|
@@ -3602,6 +3616,12 @@ export default {
|
|
|
3602
3616
|
|
|
3603
3617
|
getWidgetButtons(item) {
|
|
3604
3618
|
const def = this.getWidgetDef(item.widgetId)
|
|
3619
|
+
// `showButtons: false` on the placement or the definition drops
|
|
3620
|
+
// the footer links ("More events"), for a placement whose card
|
|
3621
|
+
// says enough without them (zuiddrecht-pixel-gaps-3).
|
|
3622
|
+
if (item?.showButtons === false || def?.showButtons === false) {
|
|
3623
|
+
return []
|
|
3624
|
+
}
|
|
3605
3625
|
return def?.buttons || []
|
|
3606
3626
|
},
|
|
3607
3627
|
|
|
@@ -3905,11 +3925,16 @@ export default {
|
|
|
3905
3925
|
// library's own defaults, so a manifest need not set them — but a
|
|
3906
3926
|
// manifest that DOES set them must reach the component, or the
|
|
3907
3927
|
// declaration is a silent no-op that reads like configuration.
|
|
3908
|
-
for (const key of ['countLabel', 'variant', 'showZeroCount', 'horizontal', 'vertical', 'filled', 'route', 'iconClass', 'format']) {
|
|
3928
|
+
for (const key of ['countLabel', 'variant', 'showZeroCount', 'horizontal', 'vertical', 'filled', 'route', 'iconClass', 'format', 'layout']) {
|
|
3909
3929
|
if (props[key] !== undefined) {
|
|
3910
3930
|
out[key] = props[key]
|
|
3911
3931
|
}
|
|
3912
3932
|
}
|
|
3933
|
+
// `content.layout: "stacked"`, the key a stat tile takes, works on
|
|
3934
|
+
// a stats block too (zuiddrecht-pixel-gaps-3).
|
|
3935
|
+
if (out.layout === undefined && typeof content.layout === 'string') {
|
|
3936
|
+
out.layout = content.layout
|
|
3937
|
+
}
|
|
3913
3938
|
// `countLabel` is the unit beside the number ("0 cases", "0 tasks").
|
|
3914
3939
|
// It is manifest-authored prose and was being forwarded raw, so a
|
|
3915
3940
|
// Dutch account read "0 cases" beside a translated widget title.
|
|
@@ -361,6 +361,40 @@ import { CnLockIndicator } from '../CnLockIndicator/index.js'
|
|
|
361
361
|
// consuming app does not pull in the library's global css/index.css.
|
|
362
362
|
import '../../css/table.css'
|
|
363
363
|
|
|
364
|
+
/**
|
|
365
|
+
* Fill a `secondary` template such as `"{identifier} · {requester}"`.
|
|
366
|
+
*
|
|
367
|
+
* A field without a value takes its separator with it: the text between two
|
|
368
|
+
* fields belongs to the field after it, so an empty requester leaves
|
|
369
|
+
* "2026-0002", not "2026-0002 ·", and an empty first field does not leave a
|
|
370
|
+
* leading separator either. Text before the first field and after the last
|
|
371
|
+
* one is kept as written. A template whose fields all have values fills
|
|
372
|
+
* exactly as before.
|
|
373
|
+
*
|
|
374
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-an-empty-field-takes-its-separator-with-it
|
|
375
|
+
* @param {string} template The template, with `{field}` placeholders.
|
|
376
|
+
* @param {(key: string) => string} valueOf The text of a field ('' when empty).
|
|
377
|
+
* @return {string} The filled template.
|
|
378
|
+
*/
|
|
379
|
+
function fillSecondaryTemplate(template, valueOf) {
|
|
380
|
+
// split() with a capture group alternates literal, field, literal, …
|
|
381
|
+
const parts = template.split(/\{([^}]+)\}/)
|
|
382
|
+
const lead = parts[0]
|
|
383
|
+
const tail = parts[parts.length - 1]
|
|
384
|
+
let body = ''
|
|
385
|
+
for (let i = 1; i < parts.length; i += 2) {
|
|
386
|
+
const value = valueOf(parts[i].trim())
|
|
387
|
+
if (value === '') {
|
|
388
|
+
continue
|
|
389
|
+
}
|
|
390
|
+
// The literal before this field: the separator, unless nothing has
|
|
391
|
+
// been written yet (then there is nothing to separate from).
|
|
392
|
+
const separator = i === 1 ? '' : parts[i - 1]
|
|
393
|
+
body += (body === '' ? '' : separator) + value
|
|
394
|
+
}
|
|
395
|
+
return lead + body + tail
|
|
396
|
+
}
|
|
397
|
+
|
|
364
398
|
/**
|
|
365
399
|
* CnDataTable — Generic sortable data table for list views.
|
|
366
400
|
*
|
|
@@ -1451,7 +1485,7 @@ export default {
|
|
|
1451
1485
|
}
|
|
1452
1486
|
const asText = (v) => (v === null || v === undefined ? '' : String(v))
|
|
1453
1487
|
if (spec.includes('{')) {
|
|
1454
|
-
const filled = spec
|
|
1488
|
+
const filled = fillSecondaryTemplate(spec, (key) => asText(this.getCellValue(row, key)))
|
|
1455
1489
|
// A template whose every field is empty leaves only separators:
|
|
1456
1490
|
// nothing worth a line.
|
|
1457
1491
|
return /[\p{L}\p{N}]/u.test(filled) ? filled.trim() : ''
|
|
@@ -444,3 +444,5 @@ When the schema-driven fetch answers 404 the page shows a not-found state whose
|
|
|
444
444
|
### Header card and header widget
|
|
445
445
|
|
|
446
446
|
`headerCard` (default `false`) draws the header as a bordered card. `headerWidget` (default `''`) names a widget in `widgets` to render inside the header under the title, without a card of its own and out of the body grid: the stages bars of the board's case card.
|
|
447
|
+
|
|
448
|
+
`showWidgetActions` (Boolean, default `true`): `false` (manifest `config.showWidgetActions: false`) drops the overflow Actions menu from the cards of the body grid and the side column, unless a widget definition sets `showActions: true`.
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
class="cn-detail-page__breadcrumbs"
|
|
49
49
|
:crumbs="breadcrumbCrumbs"
|
|
50
50
|
:rootText="breadcrumbCrumbs[0].icon === undefined"
|
|
51
|
+
:separator="breadcrumbSeparator"
|
|
51
52
|
data-testid="cn-detail-page-breadcrumbs" />
|
|
52
53
|
<!-- Header -->
|
|
53
54
|
<div
|
|
@@ -749,6 +750,7 @@
|
|
|
749
750
|
:widget="findWidget(item)"
|
|
750
751
|
chrome="card"
|
|
751
752
|
:showCardTitle="showCardTitle(item)"
|
|
753
|
+
:showActions="showWidgetActions"
|
|
752
754
|
:objectId="objectId"
|
|
753
755
|
:object="currentObject"
|
|
754
756
|
:objectType="resolvedObjectType"
|
|
@@ -959,6 +961,7 @@
|
|
|
959
961
|
:widget="widget"
|
|
960
962
|
chrome="card"
|
|
961
963
|
:showCardTitle="true"
|
|
964
|
+
:showActions="showWidgetActions"
|
|
962
965
|
:objectId="objectId"
|
|
963
966
|
:object="currentObject"
|
|
964
967
|
:objectType="resolvedObjectType"
|
|
@@ -2235,18 +2238,38 @@ export default {
|
|
|
2235
2238
|
* belongs to; the record's display name follows as the current
|
|
2236
2239
|
* crumb. `label` goes through the host translate function and shows
|
|
2237
2240
|
* as text; `icon` (an MDI name, e.g. `Home`) draws that icon instead,
|
|
2238
|
-
* with the label as its accessible name.
|
|
2241
|
+
* with the label as its accessible name. `currentField` names a field
|
|
2242
|
+
* of the record (a dotted path, e.g. `identifier`) whose value is the
|
|
2243
|
+
* current crumb instead of the display name; an empty value falls back
|
|
2244
|
+
* to the display name. `separator` draws that text (e.g. `/`) between
|
|
2245
|
+
* the crumbs instead of the chevron. Null (the default) draws no
|
|
2239
2246
|
* trail.
|
|
2240
2247
|
*
|
|
2241
2248
|
* @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-detail-page-drops-its-eyebrow-and-shows-a-breadcrumb
|
|
2242
2249
|
* @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-a-declared-breadcrumb-label-shows-as-text
|
|
2243
|
-
* @
|
|
2250
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-breadcrumb-can-name-the-record-by-a-field-and-use-a-text-separator
|
|
2251
|
+
* @type {{label: string, route?: string, params?: object, href?: string, icon?: string, currentField?: string, separator?: string}|null}
|
|
2244
2252
|
*/
|
|
2245
2253
|
breadcrumb: {
|
|
2246
2254
|
type: Object,
|
|
2247
2255
|
default: null,
|
|
2248
2256
|
},
|
|
2249
2257
|
|
|
2258
|
+
/**
|
|
2259
|
+
* Whether the record's widget cards (the body grid and the side
|
|
2260
|
+
* column) keep their overflow Actions menu when their definition does
|
|
2261
|
+
* not say (`showActions`). `false` (manifest
|
|
2262
|
+
* `config.showWidgetActions: false`) drops it, as on a dashboard; a
|
|
2263
|
+
* widget with `showActions: true` keeps its menu. A card that offers
|
|
2264
|
+
* an Add action keeps the menu that holds it. True by default.
|
|
2265
|
+
*
|
|
2266
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-detail-page-can-drop-the-widget-actions-menu
|
|
2267
|
+
*/
|
|
2268
|
+
showWidgetActions: {
|
|
2269
|
+
type: Boolean,
|
|
2270
|
+
default: true,
|
|
2271
|
+
},
|
|
2272
|
+
|
|
2250
2273
|
/**
|
|
2251
2274
|
* A column of cards beside the body (manifest `config.sideColumn`),
|
|
2252
2275
|
* for the record's facts: deadline, requester, handler, links. Each
|
|
@@ -3438,7 +3461,38 @@ export default {
|
|
|
3438
3461
|
} else if (crumb.href) {
|
|
3439
3462
|
first.href = crumb.href
|
|
3440
3463
|
}
|
|
3441
|
-
return [first, { label: this.
|
|
3464
|
+
return [first, { label: this.breadcrumbCurrentLabel }]
|
|
3465
|
+
},
|
|
3466
|
+
|
|
3467
|
+
/**
|
|
3468
|
+
* The current crumb: the record's `breadcrumb.currentField` value
|
|
3469
|
+
* (the case number on a case page) when declared and filled, else the
|
|
3470
|
+
* display name.
|
|
3471
|
+
*
|
|
3472
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-breadcrumb-can-name-the-record-by-a-field-and-use-a-text-separator
|
|
3473
|
+
* @return {string}
|
|
3474
|
+
*/
|
|
3475
|
+
breadcrumbCurrentLabel() {
|
|
3476
|
+
const field = this.breadcrumb && this.breadcrumb.currentField
|
|
3477
|
+
if (typeof field === 'string' && field !== '') {
|
|
3478
|
+
const value = stageOf(this.resolvedObject, field)
|
|
3479
|
+
if (value !== '') {
|
|
3480
|
+
return value
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
return this.displayTitle
|
|
3484
|
+
},
|
|
3485
|
+
|
|
3486
|
+
/**
|
|
3487
|
+
* The text drawn between the crumbs (`breadcrumb.separator`), or ''
|
|
3488
|
+
* for the chevron.
|
|
3489
|
+
*
|
|
3490
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-breadcrumb-can-name-the-record-by-a-field-and-use-a-text-separator
|
|
3491
|
+
* @return {string}
|
|
3492
|
+
*/
|
|
3493
|
+
breadcrumbSeparator() {
|
|
3494
|
+
const separator = this.breadcrumb && this.breadcrumb.separator
|
|
3495
|
+
return typeof separator === 'string' ? separator : ''
|
|
3442
3496
|
},
|
|
3443
3497
|
|
|
3444
3498
|
/**
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
v-else-if="isData && schemaObject"
|
|
86
86
|
:title="resolvedTitle"
|
|
87
87
|
:chromeless="isBare"
|
|
88
|
-
:showActions="!isBare"
|
|
88
|
+
:showActions="!isBare && actionsShown"
|
|
89
89
|
:icon="widget.icon || null"
|
|
90
90
|
:schema="schemaObject"
|
|
91
91
|
:objectData="object"
|
|
@@ -165,6 +165,7 @@
|
|
|
165
165
|
v-else-if="renderer && isContentOnly && !isBare"
|
|
166
166
|
:title="widget.title || ''"
|
|
167
167
|
titleIconPosition="left"
|
|
168
|
+
:showActions="actionsShown || catalogAddEnabled"
|
|
168
169
|
:showRefresh="false"
|
|
169
170
|
:showRequestFeature="false"
|
|
170
171
|
class="cn-detail-page__catalog-card">
|
|
@@ -473,6 +474,21 @@ export default {
|
|
|
473
474
|
default: null,
|
|
474
475
|
},
|
|
475
476
|
|
|
477
|
+
/**
|
|
478
|
+
* Whether a widget on a card keeps its overflow Actions menu when its
|
|
479
|
+
* definition does not say (`showActions`). `false` (CnDetailPage
|
|
480
|
+
* `showWidgetActions: false`) drops it from the record's data cards; a
|
|
481
|
+
* definition with `showActions: true` keeps it, one with
|
|
482
|
+
* `showActions: false` drops it whatever this says. True by default,
|
|
483
|
+
* which is the menu every card had.
|
|
484
|
+
*
|
|
485
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-detail-page-can-drop-the-widget-actions-menu
|
|
486
|
+
*/
|
|
487
|
+
showActions: {
|
|
488
|
+
type: Boolean,
|
|
489
|
+
default: true,
|
|
490
|
+
},
|
|
491
|
+
|
|
476
492
|
/**
|
|
477
493
|
* The consumer's component registry, consulted before the built-in
|
|
478
494
|
* catalog so a custom widget type overrides a built-in (REQ-MVR-005).
|
|
@@ -839,6 +855,19 @@ export default {
|
|
|
839
855
|
return this.content.allowCreate !== false
|
|
840
856
|
},
|
|
841
857
|
|
|
858
|
+
/**
|
|
859
|
+
* Whether the widget's overflow Actions menu renders: the definition's
|
|
860
|
+
* own `showActions` when it is a boolean, else the surface's
|
|
861
|
+
* `showActions`.
|
|
862
|
+
*
|
|
863
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-detail-page-can-drop-the-widget-actions-menu
|
|
864
|
+
* @return {boolean} true when the menu renders.
|
|
865
|
+
*/
|
|
866
|
+
actionsShown() {
|
|
867
|
+
const own = this.widget && this.widget.showActions
|
|
868
|
+
return typeof own === 'boolean' ? own : this.showActions
|
|
869
|
+
},
|
|
870
|
+
|
|
842
871
|
/**
|
|
843
872
|
* The card header rule, with the surface's layout-driven answer winning
|
|
844
873
|
* when it supplied one.
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
// unconditionally.
|
|
41
41
|
import { loadState } from '@nextcloud/initial-state'
|
|
42
42
|
import CnFeaturesAndRoadmapView from '../CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue'
|
|
43
|
+
import { warnCapabilityComparisonDeprecated } from '../../utils/capabilityComparison.js'
|
|
43
44
|
import { DEFAULT_FORGE } from '../../utils/forge.js'
|
|
44
45
|
|
|
45
46
|
/**
|
|
@@ -175,6 +176,11 @@ export default {
|
|
|
175
176
|
* Manifest config > initialState (`features_roadmap_capabilities`) >
|
|
176
177
|
* null. When null the view renders its two stops as it always has.
|
|
177
178
|
*
|
|
179
|
+
* Deprecated: publish the comparison on the app's docs site and link to it (as dossiq #3312 and pipelinq #2195 did). Still rendered; removal waits for a major version. The same goes for the `features_roadmap_capabilities` initial
|
|
180
|
+
* state key. A development build warns once when either is set.
|
|
181
|
+
*
|
|
182
|
+
* @deprecated since 2.66.0, publish the comparison on the app's docs site and link to it.
|
|
183
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-the-in-app-capability-comparison-is-deprecated
|
|
178
184
|
* @type {object|null}
|
|
179
185
|
*/
|
|
180
186
|
capabilityComparison: {
|
|
@@ -298,5 +304,11 @@ export default {
|
|
|
298
304
|
return readInitialState(this.effectiveAppId, 'features_roadmap_capabilities', null)
|
|
299
305
|
},
|
|
300
306
|
},
|
|
307
|
+
|
|
308
|
+
mounted() {
|
|
309
|
+
if (this.resolvedCapabilityComparison) {
|
|
310
|
+
warnCapabilityComparisonDeprecated('CnFeaturesAndRoadmapPage `capabilityComparison` / the `features_roadmap_capabilities` initial state')
|
|
311
|
+
}
|
|
312
|
+
},
|
|
301
313
|
}
|
|
302
314
|
</script>
|
|
@@ -114,6 +114,7 @@ import CnFeaturesAndRoadmapSidebar from '../CnFeaturesAndRoadmapSidebar/CnFeatur
|
|
|
114
114
|
import CnFeaturesTab from '../CnFeaturesTab/CnFeaturesTab.vue'
|
|
115
115
|
import CnRoadmapTab from '../CnRoadmapTab/CnRoadmapTab.vue'
|
|
116
116
|
import CnSupportDialog from '../CnSupportDialog/CnSupportDialog.vue'
|
|
117
|
+
import { warnCapabilityComparisonDeprecated } from '../../utils/capabilityComparison.js'
|
|
117
118
|
import { buildFeatureRequestUrl, DEFAULT_FORGE } from '../../utils/forge.js'
|
|
118
119
|
|
|
119
120
|
const DEFAULT_OPENBUILT_PATH = '/apps/openbuilt'
|
|
@@ -214,6 +215,11 @@ export default {
|
|
|
214
215
|
* When null (default) the toggle keeps its two stops and the view
|
|
215
216
|
* renders exactly as it does for every app that passes nothing.
|
|
216
217
|
*
|
|
218
|
+
* Deprecated: publish the comparison on the app's docs site and link to it (as dossiq #3312 and pipelinq #2195 did). Still rendered; removal waits for a major version.
|
|
219
|
+
* A development build warns once when it is set.
|
|
220
|
+
*
|
|
221
|
+
* @deprecated since 2.66.0, publish the comparison on the app's docs site and link to it.
|
|
222
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-the-in-app-capability-comparison-is-deprecated
|
|
217
223
|
* @type {object|null}
|
|
218
224
|
*/
|
|
219
225
|
capabilityComparison: {
|
|
@@ -527,6 +533,9 @@ export default {
|
|
|
527
533
|
|
|
528
534
|
mounted() {
|
|
529
535
|
this.publishHoistedSidebar()
|
|
536
|
+
if (this.capabilityComparison) {
|
|
537
|
+
warnCapabilityComparisonDeprecated('CnFeaturesAndRoadmapView `capabilityComparison`')
|
|
538
|
+
}
|
|
530
539
|
},
|
|
531
540
|
|
|
532
541
|
beforeUnmount() {
|
|
@@ -4,12 +4,25 @@
|
|
|
4
4
|
-->
|
|
5
5
|
|
|
6
6
|
<template>
|
|
7
|
-
<div class="cn-header-widget" :class="{ 'cn-header-widget--plain': isPlain, 'cn-header-widget--ground': isGround, 'cn-header-widget--with-views': viewOptions.length > 0 }" :style="wrapperStyle">
|
|
7
|
+
<div class="cn-header-widget" :class="{ 'cn-header-widget--plain': isPlain, 'cn-header-widget--ground': isGround, 'cn-header-widget--with-views': viewOptions.length > 0, 'cn-header-widget--with-emblem': emblem !== null }" :style="wrapperStyle">
|
|
8
8
|
<div
|
|
9
9
|
v-if="hasOverlay"
|
|
10
10
|
class="cn-header-widget__overlay"
|
|
11
11
|
:style="overlayStyle"
|
|
12
12
|
aria-hidden="true" />
|
|
13
|
+
<!-- The emblem beside the greeting (`content.emblem`): a URL, or
|
|
14
|
+
`true` for the theme's emblem (--nldesign-emblem-url). Decoration. -->
|
|
15
|
+
<img
|
|
16
|
+
v-if="emblem && emblem !== true"
|
|
17
|
+
class="cn-header-widget__emblem"
|
|
18
|
+
:src="emblem"
|
|
19
|
+
alt=""
|
|
20
|
+
data-testid="cn-header-widget-emblem">
|
|
21
|
+
<span
|
|
22
|
+
v-else-if="emblem === true"
|
|
23
|
+
class="cn-header-widget__emblem cn-header-widget__emblem--theme"
|
|
24
|
+
aria-hidden="true"
|
|
25
|
+
data-testid="cn-header-widget-emblem" />
|
|
13
26
|
<div class="cn-header-widget__content" :style="contentStyle">
|
|
14
27
|
<p
|
|
15
28
|
v-if="dateLine"
|
|
@@ -140,7 +153,7 @@ export default {
|
|
|
140
153
|
* Persisted widget content: `{title, subtitle, backgroundImageUrl,
|
|
141
154
|
* backgroundImageFileId, backgroundColor, overlayMode, overlayColor,
|
|
142
155
|
* overlayOpacity, textColor, textAlign, verticalAlign, height, cta,
|
|
143
|
-
* greeting, showDate, plain, ground, views}`. All fields are optional except
|
|
156
|
+
* greeting, showDate, kicker, emblem, plain, ground, views}`. All fields are optional except
|
|
144
157
|
* `title` (or `greeting`); unknown enum values collapse to documented
|
|
145
158
|
* defaults and the renderer never throws. `views` is
|
|
146
159
|
* `{ ariaLabel?, options: [{ label, route, params? } | { label, view }] }`:
|
|
@@ -151,7 +164,12 @@ export default {
|
|
|
151
164
|
* own. `ground: true`
|
|
152
165
|
* draws the greeting on the page ground: the plain look with no
|
|
153
166
|
* padding, a 32px heading and the date line 6px above it (a dashboard
|
|
154
|
-
* also drops the widget's card for it).
|
|
167
|
+
* also drops the widget's card for it). A ground greeting takes its
|
|
168
|
+
* own height rather than its grid cell's, so a view switch sits on
|
|
169
|
+
* the heading's line. `kicker` (an i18n key) prefixes the date line, as
|
|
170
|
+
* "Customer contact · Tuesday 6 October". `emblem` (a URL, or `true`
|
|
171
|
+
* for the theme's `--nldesign-emblem-url`) draws the emblem beside the
|
|
172
|
+
* date line and heading, 52px high (`--cn-header-emblem-size`).
|
|
155
173
|
*
|
|
156
174
|
* @type {object}
|
|
157
175
|
*/
|
|
@@ -396,13 +414,30 @@ export default {
|
|
|
396
414
|
},
|
|
397
415
|
|
|
398
416
|
/**
|
|
399
|
-
*
|
|
400
|
-
*
|
|
417
|
+
* The kicker line above the heading: `content.kicker` (through the
|
|
418
|
+
* host translate function, e.g. "Customer contact") and today's date
|
|
419
|
+
* written out ("Monday 5 October 2026") when `showDate` is on, joined
|
|
420
|
+
* by " · ". '' when neither is set. Without `kicker` this is the date
|
|
421
|
+
* line as before.
|
|
401
422
|
*
|
|
402
423
|
* @return {string}
|
|
403
424
|
* @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-greeting-header
|
|
404
425
|
*/
|
|
405
426
|
dateLine() {
|
|
427
|
+
const kicker = this.content && typeof this.content.kicker === 'string' && this.content.kicker !== ''
|
|
428
|
+
? this.effectiveTranslate(this.content.kicker)
|
|
429
|
+
: ''
|
|
430
|
+
const date = this.dateText
|
|
431
|
+
return [kicker, date].filter((part) => part !== '').join(' · ')
|
|
432
|
+
},
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Today's date written out, or '' when `showDate` is off.
|
|
436
|
+
*
|
|
437
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-greeting-kicker-can-carry-a-prefix
|
|
438
|
+
* @return {string}
|
|
439
|
+
*/
|
|
440
|
+
dateText() {
|
|
406
441
|
if (!this.content || this.content.showDate !== true) {
|
|
407
442
|
return ''
|
|
408
443
|
}
|
|
@@ -434,6 +469,21 @@ export default {
|
|
|
434
469
|
}
|
|
435
470
|
},
|
|
436
471
|
|
|
472
|
+
/**
|
|
473
|
+
* The emblem beside the greeting: the URL `content.emblem` names,
|
|
474
|
+
* `true` for the theme's emblem, or null without the key.
|
|
475
|
+
*
|
|
476
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-greeting-can-carry-the-emblem
|
|
477
|
+
* @return {string|true|null}
|
|
478
|
+
*/
|
|
479
|
+
emblem() {
|
|
480
|
+
const value = this.content && this.content.emblem
|
|
481
|
+
if (value === true) {
|
|
482
|
+
return true
|
|
483
|
+
}
|
|
484
|
+
return typeof value === 'string' && value !== '' ? resolveImageUrl(value) : null
|
|
485
|
+
},
|
|
486
|
+
|
|
437
487
|
/** Whether a non-empty subtitle is set. */
|
|
438
488
|
hasSubtitle() {
|
|
439
489
|
return this.subtitle !== ''
|
|
@@ -574,7 +624,12 @@ export default {
|
|
|
574
624
|
return this.isLightColor(this.backgroundColor) ? '#000000' : '#ffffff'
|
|
575
625
|
},
|
|
576
626
|
|
|
577
|
-
/**
|
|
627
|
+
/**
|
|
628
|
+
* Inline style for the banner wrapper.
|
|
629
|
+
*
|
|
630
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-ground-greeting-lines-its-switch-up-with-the-heading
|
|
631
|
+
* @return {object}
|
|
632
|
+
*/
|
|
578
633
|
wrapperStyle() {
|
|
579
634
|
const style = {
|
|
580
635
|
position: 'relative',
|
|
@@ -583,7 +638,11 @@ export default {
|
|
|
583
638
|
// widget. A fixed pixel height ignored the cell, which made the
|
|
584
639
|
// banner un-resizable and made it overflow/scroll inside a
|
|
585
640
|
// smaller cell. The grid controls the size now.
|
|
586
|
-
|
|
641
|
+
// On the page ground there is no banner to fill the cell with:
|
|
642
|
+
// the greeting takes its own height, so the view switch lines
|
|
643
|
+
// up with the heading instead of the bottom of a taller cell,
|
|
644
|
+
// and a size-to-content cell can shrink to it.
|
|
645
|
+
height: this.isGround ? 'auto' : '100%',
|
|
587
646
|
overflow: 'hidden',
|
|
588
647
|
'background-color': this.backgroundColor,
|
|
589
648
|
}
|
|
@@ -619,6 +678,7 @@ export default {
|
|
|
619
678
|
* Inline style for the content flex container.
|
|
620
679
|
*
|
|
621
680
|
* @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-greeting-header
|
|
681
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-ground-greeting-lines-its-switch-up-with-the-heading
|
|
622
682
|
*/
|
|
623
683
|
contentStyle() {
|
|
624
684
|
return {
|
|
@@ -627,7 +687,7 @@ export default {
|
|
|
627
687
|
// Beside a view switch the content shares the row instead of
|
|
628
688
|
// taking the whole width (see .cn-header-widget--with-views).
|
|
629
689
|
width: this.viewOptions.length > 0 ? 'auto' : '100%',
|
|
630
|
-
height: '100%',
|
|
690
|
+
height: this.isGround ? 'auto' : '100%',
|
|
631
691
|
display: 'flex',
|
|
632
692
|
'flex-direction': 'column',
|
|
633
693
|
'align-items': this.flexAlignFromTextAlign,
|
|
@@ -834,6 +894,33 @@ export default {
|
|
|
834
894
|
width: auto;
|
|
835
895
|
}
|
|
836
896
|
|
|
897
|
+
/* The emblem beside the greeting (`content.emblem`): on one row with the
|
|
898
|
+
date line and heading, centred on them, as LpStart draws it. */
|
|
899
|
+
.cn-header-widget--with-emblem {
|
|
900
|
+
display: flex;
|
|
901
|
+
column-gap: var(--cn-header-emblem-gap, 16px);
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
.cn-header-widget--with-emblem .cn-header-widget__content {
|
|
905
|
+
flex: 1 1 auto;
|
|
906
|
+
width: auto;
|
|
907
|
+
min-width: 0;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
.cn-header-widget__emblem {
|
|
911
|
+
position: relative;
|
|
912
|
+
z-index: 1;
|
|
913
|
+
flex: none;
|
|
914
|
+
align-self: center;
|
|
915
|
+
height: var(--cn-header-emblem-size, 52px);
|
|
916
|
+
width: auto;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
.cn-header-widget__emblem--theme {
|
|
920
|
+
width: var(--cn-header-emblem-size, 52px);
|
|
921
|
+
background: var(--nldesign-emblem-url) center / contain no-repeat;
|
|
922
|
+
}
|
|
923
|
+
|
|
837
924
|
.cn-header-widget__views {
|
|
838
925
|
position: relative;
|
|
839
926
|
z-index: 1;
|