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

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 (208) hide show
  1. package/README.md +226 -0
  2. package/css/index.css +5 -0
  3. package/dist/nextcloud-vue.cjs.js +79416 -7715
  4. package/dist/nextcloud-vue.cjs.js.map +1 -1
  5. package/dist/nextcloud-vue.css +3583 -504
  6. package/dist/nextcloud-vue.esm.js +79343 -7692
  7. package/dist/nextcloud-vue.esm.js.map +1 -1
  8. package/l10n/en.json +164 -0
  9. package/l10n/nl.json +164 -0
  10. package/package.json +104 -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 +570 -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 +156 -152
  22. package/src/components/CnCardGrid/index.js +1 -1
  23. package/src/components/CnCellRenderer/CnCellRenderer.vue +132 -132
  24. package/src/components/CnCellRenderer/index.js +1 -1
  25. package/src/components/CnChartWidget/CnChartWidget.vue +346 -0
  26. package/src/components/CnChartWidget/index.js +1 -0
  27. package/src/components/CnConfigurationCard/CnConfigurationCard.vue +77 -77
  28. package/src/components/CnConfigurationCard/index.js +1 -1
  29. package/src/components/CnContextMenu/CnContextMenu.vue +142 -0
  30. package/src/components/CnContextMenu/index.js +1 -0
  31. package/src/components/CnCopyDialog/CnCopyDialog.vue +266 -0
  32. package/src/components/CnCopyDialog/index.js +1 -0
  33. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +229 -0
  34. package/src/components/CnDashboardGrid/index.js +1 -0
  35. package/src/components/CnDashboardPage/CnDashboardPage.vue +397 -0
  36. package/src/components/CnDashboardPage/index.js +1 -0
  37. package/src/components/CnDataTable/CnDataTable.vue +362 -354
  38. package/src/components/CnDataTable/index.js +1 -1
  39. package/src/components/CnDeleteDialog/CnDeleteDialog.vue +177 -0
  40. package/src/components/CnDeleteDialog/index.js +1 -0
  41. package/src/components/CnDetailCard/CnDetailCard.vue +225 -0
  42. package/src/components/CnDetailCard/index.js +1 -0
  43. package/src/components/CnDetailGrid/CnDetailGrid.vue +256 -0
  44. package/src/components/CnDetailGrid/index.js +1 -0
  45. package/src/components/CnDetailPage/CnDetailPage.vue +432 -0
  46. package/src/components/CnDetailPage/index.js +1 -0
  47. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +234 -223
  48. package/src/components/CnFacetSidebar/index.js +1 -1
  49. package/src/components/CnFilterBar/CnFilterBar.vue +153 -152
  50. package/src/components/CnFilterBar/index.js +1 -1
  51. package/src/components/CnFormDialog/CnFormDialog.vue +1047 -0
  52. package/src/components/CnFormDialog/index.js +1 -0
  53. package/src/components/CnIcon/CnIcon.vue +89 -0
  54. package/src/components/CnIcon/index.js +1 -0
  55. package/src/components/CnIndexPage/CnIndexPage.vue +980 -682
  56. package/src/components/CnIndexPage/index.js +1 -1
  57. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +536 -0
  58. package/src/components/CnIndexSidebar/index.js +1 -0
  59. package/src/components/CnInfoWidget/CnInfoWidget.vue +219 -0
  60. package/src/components/CnInfoWidget/index.js +1 -0
  61. package/src/components/CnItemCard/CnItemCard.vue +134 -0
  62. package/src/components/CnItemCard/index.js +1 -0
  63. package/src/components/CnJsonViewer/CnJsonViewer.vue +312 -0
  64. package/src/components/CnJsonViewer/index.js +1 -0
  65. package/src/components/CnKpiGrid/CnKpiGrid.vue +93 -89
  66. package/src/components/CnKpiGrid/index.js +1 -1
  67. package/src/components/CnMassActionBar/CnMassActionBar.vue +161 -160
  68. package/src/components/CnMassActionBar/index.js +1 -1
  69. package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +327 -320
  70. package/src/components/CnMassCopyDialog/index.js +1 -1
  71. package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +245 -238
  72. package/src/components/CnMassDeleteDialog/index.js +1 -1
  73. package/src/components/CnMassExportDialog/CnMassExportDialog.vue +191 -190
  74. package/src/components/CnMassExportDialog/index.js +1 -1
  75. package/src/components/CnMassImportDialog/CnMassImportDialog.vue +494 -491
  76. package/src/components/CnMassImportDialog/index.js +1 -1
  77. package/src/components/CnNoteCard/CnNoteCard.vue +149 -0
  78. package/src/components/CnNoteCard/index.js +1 -0
  79. package/src/components/CnNotesCard/CnNotesCard.vue +416 -0
  80. package/src/components/CnNotesCard/index.js +1 -0
  81. package/src/components/CnObjectCard/CnObjectCard.vue +294 -292
  82. package/src/components/CnObjectCard/index.js +1 -1
  83. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +854 -0
  84. package/src/components/CnObjectDataWidget/index.js +1 -0
  85. package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +289 -0
  86. package/src/components/CnObjectMetadataWidget/index.js +1 -0
  87. package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +369 -0
  88. package/src/components/CnObjectSidebar/CnFilesTab.vue +287 -0
  89. package/src/components/CnObjectSidebar/CnNotesTab.vue +250 -0
  90. package/src/components/CnObjectSidebar/CnObjectSidebar.vue +255 -0
  91. package/src/components/CnObjectSidebar/CnTagsTab.vue +259 -0
  92. package/src/components/CnObjectSidebar/CnTasksTab.vue +483 -0
  93. package/src/components/CnObjectSidebar/index.js +6 -0
  94. package/src/components/CnPageHeader/CnPageHeader.vue +61 -0
  95. package/src/components/CnPageHeader/index.js +1 -0
  96. package/src/components/CnPagination/CnPagination.vue +253 -252
  97. package/src/components/CnPagination/index.js +1 -1
  98. package/src/components/CnProgressBar/CnProgressBar.vue +262 -0
  99. package/src/components/CnProgressBar/index.js +1 -0
  100. package/src/components/CnRegisterMapping/CnRegisterMapping.vue +793 -0
  101. package/src/components/CnRegisterMapping/index.js +1 -0
  102. package/src/components/CnRowActions/CnRowActions.vue +95 -73
  103. package/src/components/CnRowActions/index.js +1 -1
  104. package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +226 -0
  105. package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +788 -0
  106. package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +305 -0
  107. package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +1398 -0
  108. package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +236 -0
  109. package/src/components/CnSchemaFormDialog/index.js +1 -0
  110. package/src/components/CnSettingsCard/CnSettingsCard.vue +92 -92
  111. package/src/components/CnSettingsCard/index.js +1 -1
  112. package/src/components/CnSettingsSection/CnSettingsSection.vue +267 -266
  113. package/src/components/CnSettingsSection/index.js +1 -1
  114. package/src/components/CnStatsBlock/CnStatsBlock.vue +437 -366
  115. package/src/components/CnStatsBlock/index.js +1 -1
  116. package/src/components/CnStatsPanel/CnStatsPanel.vue +321 -0
  117. package/src/components/CnStatsPanel/index.js +1 -0
  118. package/src/components/CnStatusBadge/CnStatusBadge.vue +90 -77
  119. package/src/components/CnStatusBadge/index.js +1 -1
  120. package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +545 -0
  121. package/src/components/CnTabbedFormDialog/index.js +1 -0
  122. package/src/components/CnTableWidget/CnTableWidget.vue +333 -0
  123. package/src/components/CnTableWidget/index.js +1 -0
  124. package/src/components/CnTasksCard/CnTasksCard.vue +374 -0
  125. package/src/components/CnTasksCard/index.js +1 -0
  126. package/src/components/CnTileWidget/CnTileWidget.vue +159 -0
  127. package/src/components/CnTileWidget/index.js +1 -0
  128. package/src/components/CnTimelineStages/CnTimelineStages.vue +294 -0
  129. package/src/components/CnTimelineStages/index.js +1 -0
  130. package/src/components/CnUserActionMenu/CnUserActionMenu.vue +436 -0
  131. package/src/components/CnUserActionMenu/index.js +1 -0
  132. package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +313 -312
  133. package/src/components/CnVersionInfoCard/index.js +1 -1
  134. package/src/components/CnWidgetRenderer/CnWidgetRenderer.vue +180 -0
  135. package/src/components/CnWidgetRenderer/index.js +1 -0
  136. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +248 -0
  137. package/src/components/CnWidgetWrapper/index.js +1 -0
  138. package/src/components/index.js +57 -25
  139. package/src/composables/index.js +5 -3
  140. package/src/composables/useContextMenu.js +126 -0
  141. package/src/composables/useDashboardView.js +286 -0
  142. package/src/composables/useDetailView.js +290 -132
  143. package/src/composables/useListView.js +364 -153
  144. package/src/composables/useSubResource.js +142 -142
  145. package/src/constants/metadata.js +30 -0
  146. package/src/css/CnSchemaFormDialog.css +546 -0
  147. package/src/css/__sample_nextcloud_tokens.css +110 -0
  148. package/src/css/actions-bar.css +54 -0
  149. package/src/css/badge.css +83 -51
  150. package/src/css/card.css +129 -128
  151. package/src/css/context-menu.css +20 -0
  152. package/src/css/dashboard.css +70 -0
  153. package/src/css/detail-page.css +235 -0
  154. package/src/css/detail.css +68 -68
  155. package/src/css/index-page.css +44 -0
  156. package/src/css/index-sidebar.css +193 -0
  157. package/src/css/index.css +17 -8
  158. package/src/css/layout.css +90 -90
  159. package/src/css/page-header.css +35 -0
  160. package/src/css/pagination.css +72 -72
  161. package/src/css/table.css +142 -143
  162. package/src/css/timeline-stages.css +220 -0
  163. package/src/css/utilities.css +46 -46
  164. package/src/index.js +95 -50
  165. package/src/l10n/index.js +12 -0
  166. package/src/mixins/gridLayout.js +118 -0
  167. package/src/store/createCrudStore.d.ts +350 -0
  168. package/src/store/createCrudStore.js +413 -0
  169. package/src/store/createSubResourcePlugin.js +125 -135
  170. package/src/store/index.js +4 -3
  171. package/src/store/pluginMerge.js +55 -0
  172. package/src/store/plugins/auditTrails.js +357 -17
  173. package/src/store/plugins/files.js +250 -186
  174. package/src/store/plugins/index.js +8 -4
  175. package/src/store/plugins/lifecycle.js +180 -180
  176. package/src/store/plugins/logs.d.ts +22 -0
  177. package/src/store/plugins/logs.js +172 -0
  178. package/src/store/plugins/registerMapping.js +195 -0
  179. package/src/store/plugins/relations.js +68 -68
  180. package/src/store/plugins/search.js +385 -0
  181. package/src/store/plugins/selection.js +104 -0
  182. package/src/store/useObjectStore.js +793 -625
  183. package/src/types/auditTrail.d.ts +32 -32
  184. package/src/types/file.d.ts +23 -23
  185. package/src/types/index.d.ts +67 -35
  186. package/src/types/notification.d.ts +36 -36
  187. package/src/types/object.d.ts +40 -40
  188. package/src/types/organisation.d.ts +41 -41
  189. package/src/types/register.d.ts +25 -25
  190. package/src/types/schema.d.ts +39 -39
  191. package/src/types/shared.d.ts +79 -79
  192. package/src/types/source.d.ts +14 -14
  193. package/src/types/task.d.ts +31 -31
  194. package/src/utils/errors.js +96 -96
  195. package/src/utils/getTheme.js +9 -0
  196. package/src/utils/headers.js +80 -44
  197. package/src/utils/id.js +13 -0
  198. package/src/utils/index.js +4 -3
  199. package/src/utils/schema.js +423 -287
  200. package/src/utils/widgetVisibility.js +162 -0
  201. package/src/components/CnDetailViewLayout/CnDetailViewLayout.vue +0 -88
  202. package/src/components/CnDetailViewLayout/index.js +0 -1
  203. package/src/components/CnEmptyState/CnEmptyState.vue +0 -78
  204. package/src/components/CnEmptyState/index.js +0 -1
  205. package/src/components/CnListViewLayout/CnListViewLayout.vue +0 -80
  206. package/src/components/CnListViewLayout/index.js +0 -1
  207. package/src/components/CnViewModeToggle/CnViewModeToggle.vue +0 -77
  208. package/src/components/CnViewModeToggle/index.js +0 -1
@@ -0,0 +1,415 @@
1
+ <template>
2
+ <div
3
+ class="cn-card"
4
+ :class="rootClasses"
5
+ :style="activeStyles"
6
+ @click="onClick">
7
+ <div class="cn-card__header">
8
+ <h2 class="cn-card__title">
9
+ <slot name="icon">
10
+ <component :is="icon" v-if="icon" :size="iconSize" />
11
+ </slot>
12
+ <span ref="titleText" v-tooltip.bottom="computedTooltip" class="cn-card__title-text">{{ title }}</span>
13
+ </h2>
14
+ <div v-if="$slots.actions || $scopedSlots.actions" class="cn-card__actions">
15
+ <slot name="actions" />
16
+ </div>
17
+ <slot name="labels">
18
+ <span v-if="labels.length > 0" class="cn-card__labels">
19
+ <CnStatusBadge
20
+ v-for="(label, i) in labels"
21
+ :key="i"
22
+ :label="label.text"
23
+ :variant="label.variant || 'default'"
24
+ :solid="true" />
25
+ </span>
26
+ </slot>
27
+ </div>
28
+
29
+ <div class="cn-card__body">
30
+ <slot name="description">
31
+ <p v-if="description"
32
+ class="cn-card__description"
33
+ :style="descriptionStyle">
34
+ {{ description }}
35
+ </p>
36
+ </slot>
37
+
38
+ <div v-if="$slots.default || $scopedSlots.default" class="cn-card__content">
39
+ <slot />
40
+ </div>
41
+
42
+ <slot name="stats">
43
+ <div v-if="stats.length > 0" class="cn-card__stats">
44
+ <div v-for="(stat, i) in stats" :key="i" class="cn-card__stat">
45
+ <span class="cn-card__stat-label">{{ stat.label }}:</span>
46
+ <span class="cn-card__stat-value">{{ stat.value }}</span>
47
+ </div>
48
+ </div>
49
+ </slot>
50
+ </div>
51
+
52
+ <!-- Footer -->
53
+ <slot name="footer">
54
+ <div v-if="hasFooterContent" class="cn-card__footer">
55
+ <a
56
+ v-for="(link, i) in footerLinks"
57
+ :key="'link-' + i"
58
+ :href="link.url"
59
+ target="_blank"
60
+ rel="noopener noreferrer"
61
+ class="cn-card__footer-link">
62
+ <slot :name="'footer-link-icon-' + i" />
63
+ {{ link.label || link.url }}
64
+ </a>
65
+ <CnStatusBadge
66
+ v-for="(tag, i) in normalizedTags"
67
+ :key="'tag-' + i"
68
+ :label="tag.text"
69
+ :variant="tag.variant || 'default'"
70
+ size="small" />
71
+ </div>
72
+ </slot>
73
+ </div>
74
+ </template>
75
+
76
+ <script>
77
+ import { CnStatusBadge } from '../CnStatusBadge/index.js'
78
+
79
+ /**
80
+ * CnCard — Generic prop-driven card component.
81
+ *
82
+ * A flexible card for displaying entities with a title, icon, description,
83
+ * labels/badges, stats, and an optional active highlight state. Unlike
84
+ * CnObjectCard (schema-driven), CnCard takes direct props and is ideal
85
+ * for known, fixed-structure entities.
86
+ *
87
+ * @example Basic usage
88
+ * <CnCard
89
+ * title="My Source"
90
+ * description="A PostgreSQL data source"
91
+ * :icon="DatabaseArrowRightOutline"
92
+ * :stats="[{ label: 'Type', value: 'PostgreSQL' }]">
93
+ * <template #actions>
94
+ * <NcActions><NcActionButton @click="edit">Edit</NcActionButton></NcActions>
95
+ * </template>
96
+ * </CnCard>
97
+ *
98
+ * @example With labels and active state
99
+ * <CnCard
100
+ * title="My Organisation"
101
+ * :icon="OfficeBuilding"
102
+ * :active="isActive"
103
+ * active-variant="success"
104
+ * :labels="[
105
+ * { text: 'Default', variant: 'warning' },
106
+ * { text: 'Active', variant: 'success' },
107
+ * ]"
108
+ * :stats="[
109
+ * { label: 'Members', value: 12 },
110
+ * { label: 'Owner', value: 'Admin' },
111
+ * ]" />
112
+ */
113
+ export default {
114
+ name: 'CnCard',
115
+
116
+ components: {
117
+ CnStatusBadge,
118
+ },
119
+
120
+ props: {
121
+ /** Card title text */
122
+ title: {
123
+ type: String,
124
+ default: '',
125
+ },
126
+ /** Description text, displayed with line-clamp truncation */
127
+ description: {
128
+ type: String,
129
+ default: '',
130
+ },
131
+ /** Tooltip text for the title. If not set, falls back to description */
132
+ titleTooltip: {
133
+ type: String,
134
+ default: '',
135
+ },
136
+ /** Icon component (e.g., imported MDI icon). Rendered via <component :is> */
137
+ icon: {
138
+ type: [Object, Function],
139
+ default: null,
140
+ },
141
+ /** Icon size in pixels */
142
+ iconSize: {
143
+ type: Number,
144
+ default: 20,
145
+ },
146
+ /**
147
+ * Array of badge/label objects displayed inline with the title.
148
+ * Each entry: { text: string, variant?: string }
149
+ * Variant maps to CnStatusBadge variants: 'default'|'primary'|'success'|'warning'|'error'|'info'
150
+ * For labels with icons, use the #labels slot override and render CnStatusBadge
151
+ * manually with its #icon slot.
152
+ */
153
+ labels: {
154
+ type: Array,
155
+ default: () => [],
156
+ },
157
+ /**
158
+ * Array of stat rows displayed as label:value pairs.
159
+ * Each entry: { label: string, value: string|number }
160
+ */
161
+ stats: {
162
+ type: Array,
163
+ default: () => [],
164
+ },
165
+ /** Maximum lines for description truncation (CSS line-clamp) */
166
+ descriptionLines: {
167
+ type: Number,
168
+ default: 3,
169
+ },
170
+ /** Whether the card is in an active/highlighted state */
171
+ active: {
172
+ type: Boolean,
173
+ default: false,
174
+ },
175
+ /**
176
+ * Color variant for the active state border and background.
177
+ * Maps to Nextcloud CSS variables.
178
+ */
179
+ activeVariant: {
180
+ type: String,
181
+ default: 'success',
182
+ validator: (v) => ['success', 'primary', 'warning', 'error', 'info'].includes(v),
183
+ },
184
+ /** Whether the card is clickable (adds hover effect and cursor pointer) */
185
+ clickable: {
186
+ type: Boolean,
187
+ default: false,
188
+ },
189
+ /**
190
+ * Array of footer link objects. Each entry: { url: string, label?: string }
191
+ * Links are rendered as clickable anchors. Use the #footer-link-icon-{index} slot
192
+ * to add an icon before a specific link.
193
+ */
194
+ footerLinks: {
195
+ type: Array,
196
+ default: () => [],
197
+ },
198
+ /**
199
+ * Array of tag items for the footer. Accepts either strings or objects.
200
+ * String entries are converted to { text: string, variant: 'default' }.
201
+ * Object entries: { text: string, variant?: string }
202
+ */
203
+ tags: {
204
+ type: Array,
205
+ default: () => [],
206
+ },
207
+ },
208
+
209
+ data() {
210
+ return {
211
+ isTitleEllipsized: false,
212
+ }
213
+ },
214
+
215
+ computed: {
216
+ computedTooltip() {
217
+ if (this.titleTooltip) return this.titleTooltip
218
+ return this.isTitleEllipsized ? this.title : ''
219
+ },
220
+
221
+ rootClasses() {
222
+ return {
223
+ 'cn-card--active': this.active,
224
+ 'cn-card--clickable': this.clickable,
225
+ }
226
+ },
227
+
228
+ descriptionStyle() {
229
+ return {
230
+ '-webkit-line-clamp': this.descriptionLines,
231
+ 'line-clamp': this.descriptionLines,
232
+ }
233
+ },
234
+
235
+ normalizedTags() {
236
+ return this.tags.map(tag =>
237
+ typeof tag === 'string' ? { text: tag, variant: 'default' } : tag,
238
+ )
239
+ },
240
+
241
+ hasFooterContent() {
242
+ return this.footerLinks.length > 0 || this.tags.length > 0
243
+ },
244
+
245
+ activeStyles() {
246
+ if (!this.active) return {}
247
+ const variantMap = {
248
+ success: 'var(--color-success)',
249
+ primary: 'var(--color-primary-element)',
250
+ warning: 'var(--color-warning)',
251
+ error: 'var(--color-error)',
252
+ info: 'var(--color-info)',
253
+ }
254
+ return {
255
+ '--cn-card-active-border': variantMap[this.activeVariant] || variantMap.success,
256
+ }
257
+ },
258
+ },
259
+
260
+ mounted() {
261
+ this.checkTitleEllipsis()
262
+ this._resizeObserver = new ResizeObserver(() => this.checkTitleEllipsis())
263
+ this._resizeObserver.observe(this.$el)
264
+ },
265
+
266
+ beforeDestroy() {
267
+ if (this._resizeObserver) {
268
+ this._resizeObserver.disconnect()
269
+ }
270
+ },
271
+
272
+ methods: {
273
+ onClick(event) {
274
+ if (this.clickable) {
275
+ this.$emit('click', event)
276
+ }
277
+ },
278
+
279
+ checkTitleEllipsis() {
280
+ const el = this.$refs.titleText
281
+ this.isTitleEllipsized = el ? el.scrollWidth > el.clientWidth : false
282
+ },
283
+ },
284
+ }
285
+ </script>
286
+
287
+ <style scoped lang="scss">
288
+ .cn-card {
289
+ padding: 16px;
290
+ border: 1px solid var(--color-border);
291
+ border-radius: var(--border-radius-large);
292
+ background: var(--color-main-background);
293
+ height: 100%;
294
+ display: flex;
295
+ flex-direction: column;
296
+ }
297
+
298
+ .cn-card--active {
299
+ border: 2px solid var(--cn-card-active-border);
300
+ }
301
+
302
+ .cn-card--clickable {
303
+ cursor: pointer;
304
+ transition: box-shadow 0.2s ease, border-color 0.2s ease;
305
+
306
+ &:hover {
307
+ border-color: var(--color-primary-element);
308
+ box-shadow: 0 2px 8px var(--color-box-shadow);
309
+ }
310
+ }
311
+
312
+ .cn-card__header {
313
+ display: grid;
314
+ grid-template-columns: 1fr auto;
315
+ grid-template-rows: auto auto;
316
+ align-items: center;
317
+ border-bottom: 1px solid var(--color-border);
318
+ padding-block-end: 1rem;
319
+ margin-block-end: 0.5rem;
320
+ }
321
+
322
+ .cn-card__title {
323
+ display: flex;
324
+ align-items: center;
325
+ gap: 6px;
326
+ font-size: 16px;
327
+ margin: 0;
328
+ min-width: 0;
329
+ }
330
+
331
+ .cn-card__title-text {
332
+ overflow: hidden;
333
+ text-overflow: ellipsis;
334
+ white-space: nowrap;
335
+ }
336
+
337
+ .cn-card__labels {
338
+ grid-column: 1 / -1;
339
+ display: flex;
340
+ gap: 4px;
341
+ flex-wrap: wrap;
342
+ margin-top: 6px;
343
+ }
344
+
345
+ .cn-card__actions {
346
+ flex-shrink: 0;
347
+ margin-inline-start: 0.25rem;
348
+ }
349
+
350
+ .cn-card__body {
351
+ flex-grow: 1;
352
+ display: flex;
353
+ flex-direction: column;
354
+ justify-content: space-between;
355
+ }
356
+
357
+ .cn-card__description {
358
+ color: var(--color-text-lighter);
359
+ margin-bottom: 12px;
360
+ word-wrap: break-word;
361
+ overflow-wrap: break-word;
362
+ display: -webkit-box;
363
+ -webkit-box-orient: vertical;
364
+ overflow: hidden;
365
+ }
366
+
367
+ .cn-card__content {
368
+ margin-bottom: 12px;
369
+ }
370
+
371
+ .cn-card__stats {
372
+ display: flex;
373
+ flex-direction: column;
374
+ gap: 4px;
375
+ }
376
+
377
+ .cn-card__stat {
378
+ display: flex;
379
+ justify-content: space-between;
380
+ }
381
+
382
+ .cn-card__stat-label {
383
+ color: var(--color-text-lighter);
384
+ font-size: 12px;
385
+ }
386
+
387
+ .cn-card__stat-value {
388
+ font-weight: 600;
389
+ font-size: 12px;
390
+ }
391
+
392
+ .cn-card__footer {
393
+ display: flex;
394
+ flex-wrap: wrap;
395
+ gap: 8px;
396
+ align-items: center;
397
+ padding-top: 8px;
398
+ margin-top: 8px;
399
+ border-top: 1px solid var(--color-border);
400
+ }
401
+
402
+ .cn-card__footer-link {
403
+ display: inline-flex;
404
+ align-items: center;
405
+ gap: 4px;
406
+ font-size: 0.85em;
407
+ color: var(--color-primary-element);
408
+ text-decoration: none;
409
+ transition: color 0.2s;
410
+
411
+ &:hover {
412
+ text-decoration: underline;
413
+ }
414
+ }
415
+ </style>
@@ -0,0 +1 @@
1
+ export { default as CnCard } from './CnCard.vue'