@conduction/nextcloud-vue 0.1.0-beta.1 → 0.1.0-beta.10

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 (197) hide show
  1. package/README.md +226 -0
  2. package/css/index.css +5 -0
  3. package/dist/nextcloud-vue.cjs +67614 -0
  4. package/dist/nextcloud-vue.cjs.js +76311 -5905
  5. package/dist/nextcloud-vue.cjs.js.map +1 -1
  6. package/dist/nextcloud-vue.cjs.map +1 -0
  7. package/dist/nextcloud-vue.css +3279 -203
  8. package/dist/nextcloud-vue.esm.js +76240 -5882
  9. package/dist/nextcloud-vue.esm.js.map +1 -1
  10. package/package.json +89 -63
  11. package/src/components/CnActionsBar/CnActionsBar.vue +254 -0
  12. package/src/components/CnActionsBar/index.js +1 -0
  13. package/src/components/CnAdvancedFormDialog/CnAdvancedFormDialog.vue +569 -0
  14. package/src/components/CnAdvancedFormDialog/CnDataTab.vue +217 -0
  15. package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +121 -0
  16. package/src/components/CnAdvancedFormDialog/CnPropertiesTab.vue +422 -0
  17. package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +247 -0
  18. package/src/components/CnAdvancedFormDialog/index.js +1 -0
  19. package/src/components/CnCard/CnCard.vue +415 -0
  20. package/src/components/CnCard/index.js +1 -0
  21. package/src/components/CnCardGrid/CnCardGrid.vue +23 -20
  22. package/src/components/CnCardGrid/index.js +1 -1
  23. package/src/components/CnCellRenderer/index.js +1 -1
  24. package/src/components/CnChartWidget/CnChartWidget.vue +318 -0
  25. package/src/components/CnChartWidget/index.js +1 -0
  26. package/src/components/CnConfigurationCard/index.js +1 -1
  27. package/src/components/CnContextMenu/CnContextMenu.vue +142 -0
  28. package/src/components/CnContextMenu/index.js +1 -0
  29. package/src/components/CnCopyDialog/CnCopyDialog.vue +257 -0
  30. package/src/components/CnCopyDialog/index.js +1 -0
  31. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +229 -0
  32. package/src/components/CnDashboardGrid/index.js +1 -0
  33. package/src/components/CnDashboardPage/CnDashboardPage.vue +396 -0
  34. package/src/components/CnDashboardPage/index.js +1 -0
  35. package/src/components/CnDataTable/CnDataTable.vue +24 -16
  36. package/src/components/CnDataTable/index.js +1 -1
  37. package/src/components/CnDeleteDialog/CnDeleteDialog.vue +177 -0
  38. package/src/components/CnDeleteDialog/index.js +1 -0
  39. package/src/components/CnDetailCard/CnDetailCard.vue +225 -0
  40. package/src/components/CnDetailCard/index.js +1 -0
  41. package/src/components/CnDetailGrid/CnDetailGrid.vue +254 -0
  42. package/src/components/CnDetailGrid/index.js +1 -0
  43. package/src/components/CnDetailPage/CnDetailPage.vue +431 -0
  44. package/src/components/CnDetailPage/index.js +1 -0
  45. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +12 -2
  46. package/src/components/CnFacetSidebar/index.js +1 -1
  47. package/src/components/CnFilterBar/index.js +1 -1
  48. package/src/components/CnFormDialog/CnFormDialog.vue +934 -0
  49. package/src/components/CnFormDialog/index.js +1 -0
  50. package/src/components/CnIcon/CnIcon.vue +89 -0
  51. package/src/components/CnIcon/index.js +1 -0
  52. package/src/components/CnIndexPage/CnIndexPage.vue +589 -291
  53. package/src/components/CnIndexPage/index.js +1 -1
  54. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +535 -0
  55. package/src/components/CnIndexSidebar/index.js +1 -0
  56. package/src/components/CnInfoWidget/CnInfoWidget.vue +219 -0
  57. package/src/components/CnInfoWidget/index.js +1 -0
  58. package/src/components/CnItemCard/CnItemCard.vue +134 -0
  59. package/src/components/CnItemCard/index.js +1 -0
  60. package/src/components/CnJsonViewer/CnJsonViewer.vue +283 -0
  61. package/src/components/CnJsonViewer/index.js +1 -0
  62. package/src/components/CnKpiGrid/CnKpiGrid.vue +5 -1
  63. package/src/components/CnKpiGrid/index.js +1 -1
  64. package/src/components/CnMassActionBar/CnMassActionBar.vue +6 -5
  65. package/src/components/CnMassActionBar/index.js +1 -1
  66. package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +16 -9
  67. package/src/components/CnMassCopyDialog/index.js +1 -1
  68. package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +16 -9
  69. package/src/components/CnMassDeleteDialog/index.js +1 -1
  70. package/src/components/CnMassExportDialog/CnMassExportDialog.vue +8 -7
  71. package/src/components/CnMassExportDialog/index.js +1 -1
  72. package/src/components/CnMassImportDialog/CnMassImportDialog.vue +20 -17
  73. package/src/components/CnMassImportDialog/index.js +1 -1
  74. package/src/components/CnNoteCard/CnNoteCard.vue +149 -0
  75. package/src/components/CnNoteCard/index.js +1 -0
  76. package/src/components/CnNotesCard/CnNotesCard.vue +415 -0
  77. package/src/components/CnNotesCard/index.js +1 -0
  78. package/src/components/CnObjectCard/CnObjectCard.vue +3 -1
  79. package/src/components/CnObjectCard/index.js +1 -1
  80. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +853 -0
  81. package/src/components/CnObjectDataWidget/index.js +1 -0
  82. package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +288 -0
  83. package/src/components/CnObjectMetadataWidget/index.js +1 -0
  84. package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +368 -0
  85. package/src/components/CnObjectSidebar/CnFilesTab.vue +286 -0
  86. package/src/components/CnObjectSidebar/CnNotesTab.vue +249 -0
  87. package/src/components/CnObjectSidebar/CnObjectSidebar.vue +254 -0
  88. package/src/components/CnObjectSidebar/CnTagsTab.vue +258 -0
  89. package/src/components/CnObjectSidebar/CnTasksTab.vue +482 -0
  90. package/src/components/CnObjectSidebar/index.js +6 -0
  91. package/src/components/CnPageHeader/CnPageHeader.vue +61 -0
  92. package/src/components/CnPageHeader/index.js +1 -0
  93. package/src/components/CnPagination/CnPagination.vue +7 -6
  94. package/src/components/CnPagination/index.js +1 -1
  95. package/src/components/CnProgressBar/CnProgressBar.vue +262 -0
  96. package/src/components/CnProgressBar/index.js +1 -0
  97. package/src/components/CnRegisterMapping/CnRegisterMapping.vue +792 -0
  98. package/src/components/CnRegisterMapping/index.js +1 -0
  99. package/src/components/CnRowActions/CnRowActions.vue +25 -3
  100. package/src/components/CnRowActions/index.js +1 -1
  101. package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +226 -0
  102. package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +787 -0
  103. package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +305 -0
  104. package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +1398 -0
  105. package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +236 -0
  106. package/src/components/CnSchemaFormDialog/index.js +1 -0
  107. package/src/components/CnSettingsCard/index.js +1 -1
  108. package/src/components/CnSettingsSection/index.js +1 -1
  109. package/src/components/CnStatsBlock/CnStatsBlock.vue +89 -19
  110. package/src/components/CnStatsBlock/index.js +1 -1
  111. package/src/components/CnStatsPanel/CnStatsPanel.vue +320 -0
  112. package/src/components/CnStatsPanel/index.js +1 -0
  113. package/src/components/CnStatusBadge/CnStatusBadge.vue +15 -2
  114. package/src/components/CnStatusBadge/index.js +1 -1
  115. package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +544 -0
  116. package/src/components/CnTabbedFormDialog/index.js +1 -0
  117. package/src/components/CnTableWidget/CnTableWidget.vue +332 -0
  118. package/src/components/CnTableWidget/index.js +1 -0
  119. package/src/components/CnTasksCard/CnTasksCard.vue +373 -0
  120. package/src/components/CnTasksCard/index.js +1 -0
  121. package/src/components/CnTileWidget/CnTileWidget.vue +159 -0
  122. package/src/components/CnTileWidget/index.js +1 -0
  123. package/src/components/CnTimelineStages/CnTimelineStages.vue +292 -0
  124. package/src/components/CnTimelineStages/index.js +1 -0
  125. package/src/components/CnUserActionMenu/CnUserActionMenu.vue +435 -0
  126. package/src/components/CnUserActionMenu/index.js +1 -0
  127. package/src/components/CnVersionInfoCard/index.js +1 -1
  128. package/src/components/CnWidgetRenderer/CnWidgetRenderer.vue +180 -0
  129. package/src/components/CnWidgetRenderer/index.js +1 -0
  130. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +246 -0
  131. package/src/components/CnWidgetWrapper/index.js +1 -0
  132. package/src/components/index.js +57 -25
  133. package/src/composables/index.js +5 -3
  134. package/src/composables/useContextMenu.js +126 -0
  135. package/src/composables/useDashboardView.js +286 -0
  136. package/src/composables/useDetailView.js +290 -132
  137. package/src/composables/useListView.js +364 -153
  138. package/src/composables/useSubResource.js +142 -142
  139. package/src/constants/metadata.js +30 -0
  140. package/src/css/CnSchemaFormDialog.css +546 -0
  141. package/src/css/__sample_nextcloud_tokens.css +110 -0
  142. package/src/css/actions-bar.css +54 -0
  143. package/src/css/badge.css +83 -51
  144. package/src/css/card.css +129 -128
  145. package/src/css/context-menu.css +20 -0
  146. package/src/css/dashboard.css +70 -0
  147. package/src/css/detail-page.css +235 -0
  148. package/src/css/detail.css +68 -68
  149. package/src/css/index-page.css +44 -0
  150. package/src/css/index-sidebar.css +193 -0
  151. package/src/css/index.css +17 -8
  152. package/src/css/layout.css +90 -90
  153. package/src/css/page-header.css +35 -0
  154. package/src/css/pagination.css +72 -72
  155. package/src/css/table.css +142 -143
  156. package/src/css/timeline-stages.css +220 -0
  157. package/src/css/utilities.css +46 -46
  158. package/src/index.js +91 -50
  159. package/src/mixins/gridLayout.js +118 -0
  160. package/src/store/createCrudStore.js +360 -0
  161. package/src/store/createSubResourcePlugin.js +125 -135
  162. package/src/store/index.js +4 -3
  163. package/src/store/plugins/auditTrails.js +357 -17
  164. package/src/store/plugins/files.js +250 -186
  165. package/src/store/plugins/index.js +7 -4
  166. package/src/store/plugins/lifecycle.js +180 -180
  167. package/src/store/plugins/registerMapping.js +195 -0
  168. package/src/store/plugins/relations.js +68 -68
  169. package/src/store/plugins/search.js +385 -0
  170. package/src/store/plugins/selection.js +104 -0
  171. package/src/store/useObjectStore.js +823 -625
  172. package/src/types/auditTrail.d.ts +32 -32
  173. package/src/types/file.d.ts +23 -23
  174. package/src/types/index.d.ts +35 -35
  175. package/src/types/notification.d.ts +36 -36
  176. package/src/types/object.d.ts +40 -40
  177. package/src/types/organisation.d.ts +41 -41
  178. package/src/types/register.d.ts +25 -25
  179. package/src/types/schema.d.ts +39 -39
  180. package/src/types/shared.d.ts +79 -79
  181. package/src/types/source.d.ts +14 -14
  182. package/src/types/task.d.ts +31 -31
  183. package/src/utils/errors.js +96 -96
  184. package/src/utils/getTheme.js +9 -0
  185. package/src/utils/headers.js +80 -44
  186. package/src/utils/id.js +13 -0
  187. package/src/utils/index.js +4 -3
  188. package/src/utils/schema.js +422 -287
  189. package/src/utils/widgetVisibility.js +162 -0
  190. package/src/components/CnDetailViewLayout/CnDetailViewLayout.vue +0 -88
  191. package/src/components/CnDetailViewLayout/index.js +0 -1
  192. package/src/components/CnEmptyState/CnEmptyState.vue +0 -78
  193. package/src/components/CnEmptyState/index.js +0 -1
  194. package/src/components/CnListViewLayout/CnListViewLayout.vue +0 -80
  195. package/src/components/CnListViewLayout/index.js +0 -1
  196. package/src/components/CnViewModeToggle/CnViewModeToggle.vue +0 -77
  197. package/src/components/CnViewModeToggle/index.js +0 -1
@@ -0,0 +1,225 @@
1
+ <!--
2
+ CnDetailCard — A card container for detail page sections.
3
+
4
+ Visually matches the dashboard widget card style (rounded border, header, content).
5
+ Used inside CnDetailPage to organize entity detail information into cards.
6
+ -->
7
+ <template>
8
+ <div class="cn-detail-card" :class="{ 'cn-detail-card--collapsed': isCollapsed }">
9
+ <!-- Header -->
10
+ <div
11
+ v-if="title || $slots.icon"
12
+ class="cn-detail-card__header"
13
+ :class="{ 'cn-detail-card__header--clickable': collapsible }"
14
+ @click="collapsible && toggleCollapse()">
15
+ <div class="cn-detail-card__header-left">
16
+ <slot name="icon">
17
+ <component
18
+ :is="icon"
19
+ v-if="icon"
20
+ :size="20"
21
+ class="cn-detail-card__icon" />
22
+ </slot>
23
+ <h3 class="cn-detail-card__title">
24
+ {{ title }}
25
+ </h3>
26
+ </div>
27
+ <div class="cn-detail-card__header-right">
28
+ <slot name="actions" />
29
+ <button
30
+ v-if="collapsible"
31
+ class="cn-detail-card__collapse-btn"
32
+ :aria-label="isCollapsed ? 'Expand' : 'Collapse'">
33
+ <ChevronDown
34
+ :size="20"
35
+ :class="{ 'cn-detail-card__chevron--rotated': isCollapsed }" />
36
+ </button>
37
+ </div>
38
+ </div>
39
+
40
+ <!-- Content -->
41
+ <div v-show="!isCollapsed" class="cn-detail-card__content" :class="{ 'cn-detail-card__content--flush': flush }">
42
+ <slot />
43
+ </div>
44
+
45
+ <!-- Footer -->
46
+ <div v-if="$slots.footer" v-show="!isCollapsed" class="cn-detail-card__footer">
47
+ <slot name="footer" />
48
+ </div>
49
+ </div>
50
+ </template>
51
+
52
+ <script>
53
+ import ChevronDown from 'vue-material-design-icons/ChevronDown.vue'
54
+
55
+ /**
56
+ * CnDetailCard — Card container for detail page sections.
57
+ *
58
+ * @example Basic usage
59
+ * <CnDetailCard title="Core Info">
60
+ * <div class="info-grid">...</div>
61
+ * </CnDetailCard>
62
+ *
63
+ * @example With icon and actions
64
+ * <CnDetailCard title="Pipeline" :icon="ChartIcon">
65
+ * <template #actions>
66
+ * <NcButton>Edit</NcButton>
67
+ * </template>
68
+ * <PipelineProgress :stages="stages" />
69
+ * </CnDetailCard>
70
+ *
71
+ * @example Collapsible
72
+ * <CnDetailCard title="Products" :collapsible="true">
73
+ * <ProductList :items="products" />
74
+ * </CnDetailCard>
75
+ */
76
+ export default {
77
+ name: 'CnDetailCard',
78
+
79
+ components: {
80
+ ChevronDown,
81
+ },
82
+
83
+ props: {
84
+ /** Card header title */
85
+ title: {
86
+ type: String,
87
+ default: '',
88
+ },
89
+ /** Optional MDI icon component for the header */
90
+ icon: {
91
+ type: [Object, Function],
92
+ default: null,
93
+ },
94
+ /** Whether the card can be collapsed */
95
+ collapsible: {
96
+ type: Boolean,
97
+ default: false,
98
+ },
99
+ /** Initial collapsed state (only relevant when collapsible is true) */
100
+ collapsed: {
101
+ type: Boolean,
102
+ default: false,
103
+ },
104
+ /**
105
+ * Remove content padding — allows tables and lists to go edge-to-edge.
106
+ */
107
+ flush: {
108
+ type: Boolean,
109
+ default: false,
110
+ },
111
+ },
112
+
113
+ data() {
114
+ return {
115
+ isCollapsed: this.collapsed,
116
+ }
117
+ },
118
+
119
+ watch: {
120
+ collapsed(val) {
121
+ this.isCollapsed = val
122
+ },
123
+ },
124
+
125
+ methods: {
126
+ toggleCollapse() {
127
+ this.isCollapsed = !this.isCollapsed
128
+ this.$emit('update:collapsed', this.isCollapsed)
129
+ },
130
+ },
131
+ }
132
+ </script>
133
+
134
+ <style scoped>
135
+ .cn-detail-card {
136
+ background: var(--color-main-background);
137
+ border: 1px solid var(--color-border);
138
+ border-radius: var(--border-radius-large, 12px);
139
+ overflow: hidden;
140
+ }
141
+
142
+ .cn-detail-card__header {
143
+ display: flex;
144
+ align-items: center;
145
+ justify-content: space-between;
146
+ padding: 12px 16px;
147
+ border-bottom: 1px solid var(--color-border);
148
+ flex-shrink: 0;
149
+ }
150
+
151
+ .cn-detail-card__header--clickable {
152
+ cursor: pointer;
153
+ user-select: none;
154
+ }
155
+
156
+ .cn-detail-card__header--clickable:hover {
157
+ background: var(--color-background-hover);
158
+ }
159
+
160
+ .cn-detail-card--collapsed .cn-detail-card__header {
161
+ border-bottom: none;
162
+ }
163
+
164
+ .cn-detail-card__header-left {
165
+ display: flex;
166
+ align-items: center;
167
+ gap: 8px;
168
+ min-width: 0;
169
+ }
170
+
171
+ .cn-detail-card__header-right {
172
+ display: flex;
173
+ align-items: center;
174
+ gap: 4px;
175
+ flex-shrink: 0;
176
+ }
177
+
178
+ .cn-detail-card__icon {
179
+ color: var(--color-primary-element);
180
+ flex-shrink: 0;
181
+ }
182
+
183
+ .cn-detail-card__title {
184
+ font-weight: 600;
185
+ font-size: 14px;
186
+ margin: 0;
187
+ white-space: nowrap;
188
+ overflow: hidden;
189
+ text-overflow: ellipsis;
190
+ }
191
+
192
+ .cn-detail-card__collapse-btn {
193
+ display: flex;
194
+ align-items: center;
195
+ justify-content: center;
196
+ background: none;
197
+ border: none;
198
+ padding: 4px;
199
+ cursor: pointer;
200
+ color: var(--color-text-maxcontrast);
201
+ border-radius: var(--border-radius);
202
+ }
203
+
204
+ .cn-detail-card__collapse-btn:hover {
205
+ background: var(--color-background-dark);
206
+ }
207
+
208
+ .cn-detail-card__chevron--rotated {
209
+ transform: rotate(-90deg);
210
+ transition: transform 0.2s ease;
211
+ }
212
+
213
+ .cn-detail-card__content {
214
+ padding: 16px;
215
+ }
216
+
217
+ .cn-detail-card__content--flush {
218
+ padding: 0;
219
+ }
220
+
221
+ .cn-detail-card__footer {
222
+ padding: 8px 16px;
223
+ border-top: 1px solid var(--color-border);
224
+ }
225
+ </style>
@@ -0,0 +1 @@
1
+ export { default as CnDetailCard } from './CnDetailCard.vue'
@@ -0,0 +1,254 @@
1
+ <!--
2
+ CnDetailGrid — Data-driven label-value grid for detail/info sections.
3
+
4
+ Supports two layout modes:
5
+ - grid (default): Responsive card grid with label stacked above value
6
+ - horizontal: Vertical list of rows with label on left, value on right
7
+
8
+ Items can be data-driven via the `items` prop, or customized per-item
9
+ via named scoped slots (#item-{index}, #label-{index}, #item-actions-{index}).
10
+ -->
11
+ <template>
12
+ <div
13
+ class="cn-detail-grid"
14
+ :class="rootClasses"
15
+ :style="rootStyles">
16
+ <!-- Empty state -->
17
+ <div v-if="!items.length && !$scopedSlots.default" class="cn-detail-grid__empty">
18
+ <slot name="empty">
19
+ {{ emptyLabel }}
20
+ </slot>
21
+ </div>
22
+
23
+ <!-- Data-driven items -->
24
+ <div
25
+ v-for="(item, index) in items"
26
+ :key="index"
27
+ class="cn-detail-grid__item"
28
+ :class="itemClasses">
29
+ <!-- Label -->
30
+ <div class="cn-detail-grid__label">
31
+ <slot :name="'label-' + index" :item="item" :index="index">
32
+ {{ item.label }}
33
+ </slot>
34
+ </div>
35
+
36
+ <!-- Value -->
37
+ <div class="cn-detail-grid__value">
38
+ <slot :name="'item-' + index" :item="item" :index="index">
39
+ {{ item.value !== undefined && item.value !== null ? item.value : '-' }}
40
+ </slot>
41
+ </div>
42
+
43
+ <!-- Optional per-item actions -->
44
+ <div v-if="$scopedSlots['item-actions-' + index]" class="cn-detail-grid__actions">
45
+ <slot :name="'item-actions-' + index" :item="item" :index="index" />
46
+ </div>
47
+ </div>
48
+
49
+ <!-- Append slot for manual items -->
50
+ <slot />
51
+ </div>
52
+ </template>
53
+
54
+ <script>
55
+ /**
56
+ * CnDetailGrid — Data-driven label-value grid for detail/info sections.
57
+ *
58
+ * @example Simple data-driven grid
59
+ * <CnDetailGrid :items="[
60
+ * { label: 'ID', value: '12345' },
61
+ * { label: 'Status', value: 'Active' },
62
+ * { label: 'Created', value: '2024-01-15' },
63
+ * ]" />
64
+ *
65
+ * @example Grid with custom slot content
66
+ * <CnDetailGrid :items="[
67
+ * { label: 'ID', value: item.id },
68
+ * { label: 'Action' },
69
+ * ]">
70
+ * <template #item-1>
71
+ * <CnStatusBadge :label="item.action" />
72
+ * </template>
73
+ * </CnDetailGrid>
74
+ *
75
+ * @example Horizontal row layout
76
+ * <CnDetailGrid layout="horizontal" :items="fields" />
77
+ */
78
+ export default {
79
+ name: 'CnDetailGrid',
80
+
81
+ props: {
82
+ /**
83
+ * Array of detail items to render.
84
+ * @type {Array<{ label: string, value?: string|number }>}
85
+ */
86
+ items: {
87
+ type: Array,
88
+ default: () => [],
89
+ },
90
+ /**
91
+ * Layout mode.
92
+ * - 'grid': Responsive card grid, label stacked above value
93
+ * - 'horizontal': Vertical list of rows, label on left, value on right
94
+ */
95
+ layout: {
96
+ type: String,
97
+ default: 'grid',
98
+ validator: (v) => ['grid', 'horizontal'].includes(v),
99
+ },
100
+ /**
101
+ * Number of fixed grid columns. Set to 0 (default) for responsive auto-fit.
102
+ * Only applies to layout="grid".
103
+ */
104
+ columns: {
105
+ type: Number,
106
+ default: 0,
107
+ },
108
+ /**
109
+ * Minimum width (px) for auto-fit grid items.
110
+ * Only applies when columns is 0 and layout is 'grid'.
111
+ */
112
+ minItemWidth: {
113
+ type: Number,
114
+ default: 250,
115
+ },
116
+ /**
117
+ * Minimum width (px) for labels in horizontal mode.
118
+ */
119
+ labelWidth: {
120
+ type: Number,
121
+ default: 150,
122
+ },
123
+ /**
124
+ * Whether to show the left accent border on items.
125
+ */
126
+ accent: {
127
+ type: Boolean,
128
+ default: true,
129
+ },
130
+ /**
131
+ * Text shown when the items array is empty.
132
+ */
133
+ emptyLabel: {
134
+ type: String,
135
+ default: 'No details available',
136
+ },
137
+ },
138
+
139
+ computed: {
140
+ rootClasses() {
141
+ return {
142
+ 'cn-detail-grid--grid': this.layout === 'grid',
143
+ 'cn-detail-grid--horizontal': this.layout === 'horizontal',
144
+ 'cn-detail-grid--accent': this.accent,
145
+ }
146
+ },
147
+ rootStyles() {
148
+ if (this.layout === 'grid') {
149
+ if (this.columns > 0) {
150
+ return { 'grid-template-columns': `repeat(${this.columns}, 1fr)` }
151
+ }
152
+ return { 'grid-template-columns': `repeat(auto-fit, minmax(${this.minItemWidth}px, 1fr))` }
153
+ }
154
+ if (this.layout === 'horizontal') {
155
+ return { '--cn-detail-grid-label-width': this.labelWidth + 'px' }
156
+ }
157
+ return {}
158
+ },
159
+ itemClasses() {
160
+ return {
161
+ 'cn-detail-grid__item--horizontal': this.layout === 'horizontal',
162
+ }
163
+ },
164
+ },
165
+ }
166
+ </script>
167
+
168
+ <style scoped>
169
+ /* ===== Grid layout (default) ===== */
170
+ .cn-detail-grid--grid {
171
+ display: grid;
172
+ gap: calc(4 * var(--default-grid-baseline, 4px));
173
+ }
174
+
175
+ /* ===== Horizontal layout ===== */
176
+ .cn-detail-grid--horizontal {
177
+ display: flex;
178
+ flex-direction: column;
179
+ gap: calc(3 * var(--default-grid-baseline, 4px));
180
+ }
181
+
182
+ /* ===== Item (card style) ===== */
183
+ .cn-detail-grid__item {
184
+ display: flex;
185
+ flex-direction: column;
186
+ gap: var(--default-grid-baseline, 4px);
187
+ padding: calc(2 * var(--default-grid-baseline, 4px)) calc(3 * var(--default-grid-baseline, 4px));
188
+ background: var(--color-background-hover);
189
+ border-radius: 0 var(--border-radius) var(--border-radius) 0;
190
+ }
191
+
192
+ /* Accent border */
193
+ .cn-detail-grid--accent .cn-detail-grid__item {
194
+ border-left: 3px solid var(--color-primary-element);
195
+ }
196
+
197
+ /* Horizontal item: row direction */
198
+ .cn-detail-grid__item--horizontal {
199
+ flex-direction: row;
200
+ align-items: center;
201
+ gap: calc(4 * var(--default-grid-baseline, 4px));
202
+ border-radius: var(--border-radius);
203
+ }
204
+
205
+ /* ===== Label ===== */
206
+ .cn-detail-grid__label {
207
+ font-size: 0.85em;
208
+ color: var(--color-text-maxcontrast);
209
+ font-weight: 500;
210
+ }
211
+
212
+ .cn-detail-grid--horizontal .cn-detail-grid__label {
213
+ min-width: var(--cn-detail-grid-label-width, 150px);
214
+ flex-shrink: 0;
215
+ }
216
+
217
+ /* ===== Value ===== */
218
+ .cn-detail-grid__value {
219
+ font-size: 1em;
220
+ color: var(--color-main-text);
221
+ word-break: break-word;
222
+ margin: 0.5rem;
223
+ }
224
+
225
+ .cn-detail-grid--horizontal .cn-detail-grid__value {
226
+ flex: 1;
227
+ }
228
+
229
+ /* ===== Actions ===== */
230
+ .cn-detail-grid__actions {
231
+ flex-shrink: 0;
232
+ display: flex;
233
+ align-items: center;
234
+ }
235
+
236
+ /* ===== Empty state ===== */
237
+ .cn-detail-grid__empty {
238
+ color: var(--color-text-maxcontrast);
239
+ font-style: italic;
240
+ padding: calc(2 * var(--default-grid-baseline, 4px));
241
+ }
242
+
243
+ /* ===== Responsive ===== */
244
+ @media (max-width: 600px) {
245
+ .cn-detail-grid--grid {
246
+ grid-template-columns: 1fr !important;
247
+ }
248
+
249
+ .cn-detail-grid__item--horizontal {
250
+ flex-direction: column;
251
+ align-items: flex-start;
252
+ }
253
+ }
254
+ </style>
@@ -0,0 +1 @@
1
+ export { default as CnDetailGrid } from './CnDetailGrid.vue'