@conduction/nextcloud-vue 2.62.0 → 2.64.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/CnAdminActionCard/CnAdminActionCard.vue.js +10 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue.js.map +1 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue2.js +189 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue2.js.map +1 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue3.js +72 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue3.js.map +1 -0
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +425 -39
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +119 -42
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +186 -9
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +65 -42
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +61 -16
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js.map +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js.map +1 -1
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js +20 -0
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js +3 -2
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +33 -2
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js +53 -37
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +29 -0
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +152 -135
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue.js +10 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue.js.map +1 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js +293 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js.map +1 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js +189 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js.map +1 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +253 -9
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +126 -50
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +66 -14
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +23 -14
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +2 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue2.js +3 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue2.js.map +1 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue3.js +1 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue3.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +234 -9
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +96 -57
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js +81 -4
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js +22 -5
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +81 -2
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +7 -3
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/selfModeActions.js +3 -3
- package/dist/esm/components/CnIndexPage/selfModeActions.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +41 -2
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +8 -3
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue2.js +121 -12
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue2.js.map +1 -1
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue3.js +3 -1
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +326 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +112 -26
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +63 -2
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js +96 -37
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/stagesModel.js +5 -2
- package/dist/esm/components/CnStagesWidget/stagesModel.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +52 -2
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +6 -6
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +14 -2
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +2 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js +10 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +337 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js +102 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/dashboardRegistration.js +34 -0
- package/dist/esm/components/CnTimelineWidget/dashboardRegistration.js.map +1 -0
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js +131 -8
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js.map +1 -1
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue3.js +40 -38
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +8 -6
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +73 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js +14 -2
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js +19 -0
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js.map +1 -1
- package/dist/esm/composables/useDependencyCheck.js +65 -0
- package/dist/esm/composables/useDependencyCheck.js.map +1 -0
- package/dist/esm/composables/useWalkthrough.js +218 -6
- package/dist/esm/composables/useWalkthrough.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +45 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +45 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +780 -81
- package/dist/esm/store/useObjectStore.js +8 -0
- package/dist/esm/store/useObjectStore.js.map +1 -1
- package/dist/esm/utils/columnFilters.js +311 -0
- package/dist/esm/utils/columnFilters.js.map +1 -0
- package/dist/esm/utils/groupAutocomplete.js +123 -0
- package/dist/esm/utils/groupAutocomplete.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +2 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/pickerOptions.js +198 -0
- package/dist/esm/utils/pickerOptions.js.map +1 -0
- package/dist/esm/utils/schema.js +83 -7
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/utils/schemaRefSlug.js +19 -3
- package/dist/esm/utils/schemaRefSlug.js.map +1 -1
- package/dist/esm/utils/timelineEvents.js +174 -0
- package/dist/esm/utils/timelineEvents.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/walkthroughSignals.js +88 -0
- package/dist/esm/utils/walkthroughSignals.js.map +1 -0
- package/dist/nextcloud-vue.cjs.js +13088 -7937
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +780 -81
- package/l10n/en.json +45 -0
- package/l10n/nl.json +45 -0
- package/package.json +1 -1
- package/src/components/CnAdminActionCard/CnAdminActionCard.vue +234 -0
- package/src/components/CnAdminActionCard/index.js +4 -0
- package/src/components/CnAppNav/CnAppNav.vue +568 -43
- package/src/components/CnAppRoot/CnAppRoot.md +4 -0
- package/src/components/CnAppRoot/CnAppRoot.vue +223 -16
- package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +61 -16
- package/src/components/CnAuditTrailWidget/CnAuditTrailWidget.vue +22 -1
- package/src/components/CnCellRenderer/CnCellRenderer.vue +33 -2
- package/src/components/CnChoiceCards/CnChoiceCards.vue +56 -31
- package/src/components/CnDashboardPage/CnDashboardPage.vue +45 -4
- package/src/components/CnDataTable/CnColumnFilterPopover.vue +524 -0
- package/src/components/CnDataTable/CnDataTable.md +3 -0
- package/src/components/CnDataTable/CnDataTable.vue +305 -5
- package/src/components/CnDetailPage/CnDetailPage.md +4 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +60 -1
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +2 -2
- package/src/components/CnFieldHelper/CnFieldHelper.vue +4 -2
- package/src/components/CnFormDialog/CnFormDialog.vue +290 -31
- package/src/components/CnHeaderWidget/CnHeaderWidget.vue +116 -6
- package/src/components/CnIndexPage/CnIndexPage.vue +87 -4
- package/src/components/CnIndexPage/selfModeActions.js +3 -3
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +46 -2
- package/src/components/CnResourceSelect/CnResourceSelect.vue +123 -12
- package/src/components/CnSetupWizard/CnSetupWizard.vue +392 -3
- package/src/components/CnStagesWidget/CnStagesWidget.vue +180 -2
- package/src/components/CnStagesWidget/stagesModel.js +5 -2
- package/src/components/CnStatWidget/CnStatWidget.vue +57 -3
- package/src/components/CnTabsWidget/CnTabsWidget.vue +15 -2
- package/src/components/CnTimelineWidget/CnTimelineWidget.vue +477 -0
- package/src/components/CnTimelineWidget/dashboardRegistration.js +32 -0
- package/src/components/CnTimelineWidget/index.js +4 -0
- package/src/components/CnWalkthrough/CnWalkthrough.vue +143 -10
- package/src/components/CnWidgetGrid/builtInWidgets.js +2 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.md +4 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +107 -1
- package/src/components/CnWizardDialog/CnWizardDialog.vue +20 -1
- package/src/components/index.js +2 -0
- package/src/composables/useDependencyCheck.js +61 -0
- package/src/composables/useWalkthrough.js +217 -5
- package/src/css/dashboard.css +49 -0
- package/src/css/detail-page.css +29 -4
- package/src/css/kpi-card.css +24 -1
- package/src/css/table.css +99 -6
- package/src/index.js +2 -0
- package/src/schemas/app-manifest-v2.schema.json +135 -3
- package/src/store/useObjectStore.js +8 -0
- package/src/utils/columnFilters.js +324 -0
- package/src/utils/groupAutocomplete.js +119 -0
- package/src/utils/libraryWidgetKeys.js +2 -0
- package/src/utils/pickerOptions.js +194 -0
- package/src/utils/schema.js +83 -7
- package/src/utils/schemaRefSlug.js +19 -3
- package/src/utils/timelineEvents.js +171 -0
- package/src/utils/validateManifestV2.compiled.js +2 -2
- package/src/utils/walkthroughSignals.js +94 -0
|
@@ -199,6 +199,162 @@ export function persistWalkthroughSeenVersion(appId, configKey, version, options
|
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
/**
|
|
203
|
+
* localStorage key prefix for the per-browser mirror of tour progress.
|
|
204
|
+
*/
|
|
205
|
+
export const WALKTHROUGH_PROGRESS_STORAGE_PREFIX = 'cn-walkthrough-progress:'
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* The preference key that holds tour progress, next to the completion key.
|
|
209
|
+
*
|
|
210
|
+
* @param {string} configKey `manifest.walkthrough.completionConfigKey` (may be empty).
|
|
211
|
+
* @return {string} `<configKey>-progress`, or '' when no key is declared.
|
|
212
|
+
*/
|
|
213
|
+
export function walkthroughProgressKey(configKey) {
|
|
214
|
+
return configKey ? configKey + '-progress' : ''
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Normalise stored progress (an object, or the JSON string a preference
|
|
219
|
+
* holds) into `{ tourId, stepId, index, version }`, or null.
|
|
220
|
+
*
|
|
221
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
222
|
+
* @param {unknown} value The stored value.
|
|
223
|
+
* @return {{tourId: string, stepId: string, index: number, version: string}|null} The progress.
|
|
224
|
+
*/
|
|
225
|
+
export function normaliseWalkthroughProgress(value) {
|
|
226
|
+
let data = value
|
|
227
|
+
if (typeof data === 'string') {
|
|
228
|
+
if (data === '') {
|
|
229
|
+
return null
|
|
230
|
+
}
|
|
231
|
+
try {
|
|
232
|
+
data = JSON.parse(data)
|
|
233
|
+
} catch {
|
|
234
|
+
return null
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (!isPlainObject(data) || typeof data.tourId !== 'string' || data.tourId === '') {
|
|
238
|
+
return null
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
tourId: data.tourId,
|
|
242
|
+
stepId: typeof data.stepId === 'string' ? data.stepId : '',
|
|
243
|
+
index: Number.isInteger(data.index) && data.index >= 0 ? data.index : 0,
|
|
244
|
+
version: typeof data.version === 'string' ? data.version : '',
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Read the per-browser mirror of the tour progress. Synchronous.
|
|
250
|
+
*
|
|
251
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
252
|
+
* @param {string} appId The Nextcloud app id.
|
|
253
|
+
* @param {Storage} [storage] Injectable storage backend.
|
|
254
|
+
* @return {object|null} The progress, or null.
|
|
255
|
+
*/
|
|
256
|
+
export function readLocalWalkthroughProgress(appId, storage) {
|
|
257
|
+
const s = resolveStorage(storage)
|
|
258
|
+
if (!s) {
|
|
259
|
+
return null
|
|
260
|
+
}
|
|
261
|
+
try {
|
|
262
|
+
return normaliseWalkthroughProgress(s.getItem(WALKTHROUGH_PROGRESS_STORAGE_PREFIX + appId))
|
|
263
|
+
} catch {
|
|
264
|
+
return null
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Load the user's tour progress: the per-user preference
|
|
270
|
+
* `<completionConfigKey>-progress` when declared, else the local mirror.
|
|
271
|
+
*
|
|
272
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
273
|
+
* @param {string} appId The Nextcloud app id.
|
|
274
|
+
* @param {string} configKey `manifest.walkthrough.completionConfigKey` (may be empty).
|
|
275
|
+
* @param {object} [options] `{ http, storage }` injection points for tests.
|
|
276
|
+
* @return {Promise<object|null>} The progress, or null.
|
|
277
|
+
*/
|
|
278
|
+
export async function loadWalkthroughProgress(appId, configKey, options = {}) {
|
|
279
|
+
const local = readLocalWalkthroughProgress(appId, options.storage)
|
|
280
|
+
const key = walkthroughProgressKey(configKey)
|
|
281
|
+
if (!key) {
|
|
282
|
+
return local
|
|
283
|
+
}
|
|
284
|
+
const http = options.http || axios
|
|
285
|
+
try {
|
|
286
|
+
const { data } = await http.get(walkthroughPreferenceUrl(appId, key))
|
|
287
|
+
if (!isPlainObject(data) || !('value' in data)) {
|
|
288
|
+
return local
|
|
289
|
+
}
|
|
290
|
+
return normaliseWalkthroughProgress(data.value) || local
|
|
291
|
+
} catch {
|
|
292
|
+
return local
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Persist the user's tour progress, or clear it with `null`. Writes the
|
|
298
|
+
* local mirror and, with a completion key, the per-user preference. Never
|
|
299
|
+
* throws.
|
|
300
|
+
*
|
|
301
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
302
|
+
* @param {string} appId The Nextcloud app id.
|
|
303
|
+
* @param {string} configKey `manifest.walkthrough.completionConfigKey` (may be empty).
|
|
304
|
+
* @param {object|null} progress `{ tourId, stepId, index, version }`, or null to clear.
|
|
305
|
+
* @param {object} [options] `{ http, storage }` injection points for tests.
|
|
306
|
+
* @return {Promise<boolean>} True when the server preference was written.
|
|
307
|
+
*/
|
|
308
|
+
export function persistWalkthroughProgress(appId, configKey, progress, options = {}) {
|
|
309
|
+
const value = progress ? normaliseWalkthroughProgress(progress) : null
|
|
310
|
+
const raw = value ? JSON.stringify(value) : ''
|
|
311
|
+
const s = resolveStorage(options.storage)
|
|
312
|
+
if (s) {
|
|
313
|
+
try {
|
|
314
|
+
if (raw) {
|
|
315
|
+
s.setItem(WALKTHROUGH_PROGRESS_STORAGE_PREFIX + appId, raw)
|
|
316
|
+
} else {
|
|
317
|
+
s.removeItem(WALKTHROUGH_PROGRESS_STORAGE_PREFIX + appId)
|
|
318
|
+
}
|
|
319
|
+
} catch {
|
|
320
|
+
/* quota / private mode: best-effort */
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const key = walkthroughProgressKey(configKey)
|
|
324
|
+
if (!key) {
|
|
325
|
+
return Promise.resolve(false)
|
|
326
|
+
}
|
|
327
|
+
const http = options.http || axios
|
|
328
|
+
try {
|
|
329
|
+
return Promise.resolve(http.put(walkthroughPreferenceUrl(appId, key), { value: raw }))
|
|
330
|
+
.then(() => true)
|
|
331
|
+
.catch(() => false)
|
|
332
|
+
} catch {
|
|
333
|
+
return Promise.resolve(false)
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Whether an `object-created` signal satisfies a step's `advanceOn`.
|
|
339
|
+
*
|
|
340
|
+
* The signal's own `register` / `schema` (the slugs the creating surface
|
|
341
|
+
* knows) are compared first; an object's `@self` values are numeric ids on
|
|
342
|
+
* OpenRegister and only match a step that also uses ids.
|
|
343
|
+
*
|
|
344
|
+
* @param {object} advanceOn The step's `advanceOn`.
|
|
345
|
+
* @param {object} signal `{ register?, schema?, object? }`.
|
|
346
|
+
* @return {boolean} True when it matches.
|
|
347
|
+
*/
|
|
348
|
+
function objectCreatedMatches(advanceOn, signal) {
|
|
349
|
+
const obj = signal.object || {}
|
|
350
|
+
const self = obj['@self'] || {}
|
|
351
|
+
const same = (want, candidates) => !want || candidates
|
|
352
|
+
.filter((c) => c !== null && c !== undefined && c !== '')
|
|
353
|
+
.some((c) => String(c).toLowerCase() === String(want).toLowerCase())
|
|
354
|
+
return same(advanceOn.register, [signal.register, obj.register, self.register])
|
|
355
|
+
&& same(advanceOn.schema, [signal.schema, obj.schema, self.schema])
|
|
356
|
+
}
|
|
357
|
+
|
|
202
358
|
/**
|
|
203
359
|
* Compare two semver-ish strings. Missing / unparseable parts sort as 0.
|
|
204
360
|
*
|
|
@@ -276,6 +432,9 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
276
432
|
const currentIndex = ref(0)
|
|
277
433
|
const context = ref({})
|
|
278
434
|
const running = ref(false)
|
|
435
|
+
// True while the tour is hidden by ESC or a backdrop click. The tour
|
|
436
|
+
// and its step stay, so it continues where it was.
|
|
437
|
+
const paused = ref(false)
|
|
279
438
|
// True while a user-initiated replay is active (the "Restart tutorial"
|
|
280
439
|
// entry). A replay shows the FULL tour regardless of the persisted
|
|
281
440
|
// seen-version — otherwise a returning user, whose seenVersion already
|
|
@@ -479,6 +638,7 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
479
638
|
*/
|
|
480
639
|
function start(tourId, startIndex = 0) {
|
|
481
640
|
replaying.value = false
|
|
641
|
+
paused.value = false
|
|
482
642
|
activeTourId.value = tourId
|
|
483
643
|
currentIndex.value = startIndex
|
|
484
644
|
context.value = {}
|
|
@@ -503,9 +663,59 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
503
663
|
*/
|
|
504
664
|
function dismiss() {
|
|
505
665
|
running.value = false
|
|
666
|
+
paused.value = false
|
|
506
667
|
activeTourId.value = null
|
|
507
668
|
replaying.value = false
|
|
508
669
|
}
|
|
670
|
+
/**
|
|
671
|
+
* Hide the active tour without ending it (ESC, a click on the dim).
|
|
672
|
+
* The tour and step are kept, so `resumePaused()` continues there.
|
|
673
|
+
*
|
|
674
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
675
|
+
* @return {void}
|
|
676
|
+
*/
|
|
677
|
+
function pause() {
|
|
678
|
+
if (!activeTourId.value) {
|
|
679
|
+
return
|
|
680
|
+
}
|
|
681
|
+
running.value = false
|
|
682
|
+
paused.value = true
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Show a paused tour again at the step it was on.
|
|
686
|
+
*
|
|
687
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
688
|
+
* @return {boolean} True when there was a paused tour to show.
|
|
689
|
+
*/
|
|
690
|
+
function resumePaused() {
|
|
691
|
+
if (!paused.value || !activeTourId.value) {
|
|
692
|
+
return false
|
|
693
|
+
}
|
|
694
|
+
paused.value = false
|
|
695
|
+
running.value = true
|
|
696
|
+
return true
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Start a tour at a remembered step ("continue where you left off").
|
|
700
|
+
* Runs in replay mode so a returning user sees the full tour, and
|
|
701
|
+
* falls back to the first step when the step no longer exists.
|
|
702
|
+
*
|
|
703
|
+
* @spec openspec/changes/walkthrough-advance-pause-resume/specs/cn-walkthrough/spec.md
|
|
704
|
+
* @param {string} tourId The tour id.
|
|
705
|
+
* @param {string} [stepId] The step to continue at.
|
|
706
|
+
* @return {boolean} True when the tour exists and started.
|
|
707
|
+
*/
|
|
708
|
+
function resumeAt(tourId, stepId) {
|
|
709
|
+
const tour = tours.find((t) => t.id === tourId)
|
|
710
|
+
if (!tour) {
|
|
711
|
+
return false
|
|
712
|
+
}
|
|
713
|
+
replaying.value = true
|
|
714
|
+
const idx = composeSteps(tour).findIndex((s) => s.id === stepId)
|
|
715
|
+
start(tourId, Math.max(0, idx))
|
|
716
|
+
replaying.value = true
|
|
717
|
+
return true
|
|
718
|
+
}
|
|
509
719
|
/**
|
|
510
720
|
* Mark the active tour complete: stop running and invoke the
|
|
511
721
|
* `onComplete(appVersion)` persistence callback so the seen version is
|
|
@@ -515,6 +725,7 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
515
725
|
*/
|
|
516
726
|
function complete() {
|
|
517
727
|
running.value = false
|
|
728
|
+
paused.value = false
|
|
518
729
|
activeTourId.value = null
|
|
519
730
|
replaying.value = false
|
|
520
731
|
if (typeof options.onComplete === 'function') {
|
|
@@ -542,12 +753,9 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
542
753
|
runCapture(step, { params: signal.params || {} })
|
|
543
754
|
}
|
|
544
755
|
} else if (signal.kind === 'object-created' && a.type === 'object-created') {
|
|
545
|
-
|
|
546
|
-
const reg = obj.register ?? obj['@self']?.register
|
|
547
|
-
const sch = obj.schema ?? obj['@self']?.schema
|
|
548
|
-
match = (!a.register || reg === a.register) && (!a.schema || sch === a.schema)
|
|
756
|
+
match = objectCreatedMatches(a, signal)
|
|
549
757
|
if (match) {
|
|
550
|
-
runCapture(step, { object:
|
|
758
|
+
runCapture(step, { object: signal.object || {} })
|
|
551
759
|
}
|
|
552
760
|
} else if (signal.kind === 'element' && a.type === 'element-appears') {
|
|
553
761
|
match = true
|
|
@@ -575,9 +783,13 @@ export function useWalkthrough(appId, manifest, options = {}) {
|
|
|
575
783
|
isLast,
|
|
576
784
|
context,
|
|
577
785
|
running,
|
|
786
|
+
paused,
|
|
578
787
|
replaying,
|
|
579
788
|
start,
|
|
580
789
|
restart,
|
|
790
|
+
pause,
|
|
791
|
+
resumePaused,
|
|
792
|
+
resumeAt,
|
|
581
793
|
next,
|
|
582
794
|
back,
|
|
583
795
|
skip,
|
package/src/css/dashboard.css
CHANGED
|
@@ -80,3 +80,52 @@
|
|
|
80
80
|
.cn-dashboard-list__item:hover {
|
|
81
81
|
background: var(--color-background-hover);
|
|
82
82
|
}
|
|
83
|
+
|
|
84
|
+
/* "Install <app>" placeholder in a widget whose app is missing.
|
|
85
|
+
*
|
|
86
|
+
* NcEmptyContent centres its content with `justify-content: center`. In a
|
|
87
|
+
* two-row dashboard tile (about 150px inside an `overflow: hidden` wrapper)
|
|
88
|
+
* the icon, name, description and button are taller than the tile, and plain
|
|
89
|
+
* `center` overflows on BOTH sides, so the top ran out of the widget and the
|
|
90
|
+
* name was cut off. `safe center` falls back to the start edge when the
|
|
91
|
+
* content does not fit, the spacing is compact, and what still does not fit
|
|
92
|
+
* scrolls instead of being clipped. Shared by CnDashboardPage and
|
|
93
|
+
* CnDetailWidgetHost (`cn-requires-app`). The class is doubled to outrank
|
|
94
|
+
* NcEmptyContent's own scoped rules (`.empty-content[data-v-…]`) whatever
|
|
95
|
+
* order the stylesheets load in. */
|
|
96
|
+
.cn-requires-app.cn-requires-app.empty-content,
|
|
97
|
+
.cn-requires-app.cn-requires-app .empty-content {
|
|
98
|
+
justify-content: safe center;
|
|
99
|
+
min-height: 0;
|
|
100
|
+
max-height: 100%;
|
|
101
|
+
overflow: auto;
|
|
102
|
+
margin: 0;
|
|
103
|
+
padding: calc(2 * var(--default-grid-baseline, 4px));
|
|
104
|
+
gap: var(--default-grid-baseline, 4px);
|
|
105
|
+
box-sizing: border-box;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.cn-requires-app.cn-requires-app .empty-content__icon {
|
|
109
|
+
width: auto;
|
|
110
|
+
height: auto;
|
|
111
|
+
min-height: 0;
|
|
112
|
+
margin: 0;
|
|
113
|
+
opacity: 0.7;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.cn-requires-app.cn-requires-app .empty-content__name {
|
|
117
|
+
margin: 0;
|
|
118
|
+
font-size: var(--default-font-size, 15px);
|
|
119
|
+
font-weight: 600;
|
|
120
|
+
text-align: center;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.cn-requires-app.cn-requires-app .empty-content__description {
|
|
124
|
+
margin: 0;
|
|
125
|
+
text-align: center;
|
|
126
|
+
font-size: 0.9em;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.cn-requires-app.cn-requires-app .empty-content__action {
|
|
130
|
+
margin-top: var(--default-grid-baseline, 4px);
|
|
131
|
+
}
|
package/src/css/detail-page.css
CHANGED
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
position: relative;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
/* The breadcrumb line above the header (`config.breadcrumb`). */
|
|
12
|
+
.cn-detail-page__breadcrumbs {
|
|
13
|
+
margin-bottom: calc(2 * var(--default-grid-baseline));
|
|
14
|
+
color: var(--color-text-maxcontrast);
|
|
15
|
+
}
|
|
16
|
+
|
|
11
17
|
/* Header */
|
|
12
18
|
.cn-detail-page__header {
|
|
13
19
|
display: flex;
|
|
@@ -106,6 +112,25 @@
|
|
|
106
112
|
flex-shrink: 0;
|
|
107
113
|
}
|
|
108
114
|
|
|
115
|
+
/* Every control in the header sits on one line at one height. The lifecycle
|
|
116
|
+
bar carries `margin: 0 0 8px` for its place above a page body; in the
|
|
117
|
+
header that margin pushed its buttons up and made the row 8px taller, so
|
|
118
|
+
the Edit button beside it read as the bigger one. A consumer's actions
|
|
119
|
+
component can bring its own margins too, so they are reset here as well. */
|
|
120
|
+
.cn-detail-page .cn-detail-page__header-actions .cn-lifecycle-actions {
|
|
121
|
+
margin: 0;
|
|
122
|
+
flex-wrap: nowrap;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.cn-detail-page .cn-detail-page__header-actions > * {
|
|
126
|
+
margin-block: 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.cn-detail-page .cn-detail-page__header-actions .button-vue {
|
|
130
|
+
min-height: var(--default-clickable-area);
|
|
131
|
+
block-size: var(--default-clickable-area);
|
|
132
|
+
}
|
|
133
|
+
|
|
109
134
|
/* The sentence a refused lock acquire left behind, under the locked banner. */
|
|
110
135
|
.cn-detail-page__lock-refusal {
|
|
111
136
|
margin: 0 0 calc(3 * var(--default-grid-baseline));
|
|
@@ -156,7 +181,7 @@
|
|
|
156
181
|
|
|
157
182
|
.cn-detail-page__stats-table thead th {
|
|
158
183
|
padding: calc(1.5 * var(--default-grid-baseline)) calc(2 * var(--default-grid-baseline));
|
|
159
|
-
text-align:
|
|
184
|
+
text-align: start;
|
|
160
185
|
font-weight: 600;
|
|
161
186
|
font-size: 0.9em;
|
|
162
187
|
color: var(--color-text-maxcontrast);
|
|
@@ -181,7 +206,7 @@
|
|
|
181
206
|
}
|
|
182
207
|
|
|
183
208
|
.cn-detail-page__stats-cell--indented {
|
|
184
|
-
padding-
|
|
209
|
+
padding-inline-start: calc(5 * var(--default-grid-baseline)) !important;
|
|
185
210
|
}
|
|
186
211
|
|
|
187
212
|
.cn-detail-page__stats-cell--center {
|
|
@@ -189,7 +214,7 @@
|
|
|
189
214
|
}
|
|
190
215
|
|
|
191
216
|
.cn-detail-page__stats-cell--right {
|
|
192
|
-
text-align:
|
|
217
|
+
text-align: end;
|
|
193
218
|
}
|
|
194
219
|
|
|
195
220
|
/* Body & content */
|
|
@@ -323,7 +348,7 @@
|
|
|
323
348
|
|
|
324
349
|
.cn-detail-page__sidebar-toggle {
|
|
325
350
|
position: fixed;
|
|
326
|
-
|
|
351
|
+
inset-inline-end: calc(5 * var(--default-grid-baseline));
|
|
327
352
|
top: 80px;
|
|
328
353
|
z-index: 10;
|
|
329
354
|
}
|
package/src/css/kpi-card.css
CHANGED
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
padding: var(--cn-kpi-padding-flat, 8px);
|
|
134
134
|
box-sizing: border-box;
|
|
135
135
|
overflow: hidden;
|
|
136
|
-
text-align:
|
|
136
|
+
text-align: start;
|
|
137
137
|
text-decoration: none;
|
|
138
138
|
color: inherit;
|
|
139
139
|
background: transparent;
|
|
@@ -248,6 +248,29 @@
|
|
|
248
248
|
white-space: nowrap;
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
+
/* A caption coloured by a rule (`captionVariant` / `overrides[].captionVariant`):
|
|
252
|
+
"1 due today" in the error colour. Foreground tokens, which stay readable in
|
|
253
|
+
dark mode. */
|
|
254
|
+
.cn-kpi-card__label--primary {
|
|
255
|
+
color: var(--color-primary-element);
|
|
256
|
+
font-weight: 600;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.cn-kpi-card__label--success {
|
|
260
|
+
color: var(--color-text-success, var(--color-success-text));
|
|
261
|
+
font-weight: 600;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.cn-kpi-card__label--warning {
|
|
265
|
+
color: var(--color-element-warning, var(--color-warning-text));
|
|
266
|
+
font-weight: 600;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.cn-kpi-card__label--error {
|
|
270
|
+
color: var(--color-text-error, var(--color-error-text));
|
|
271
|
+
font-weight: 600;
|
|
272
|
+
}
|
|
273
|
+
|
|
251
274
|
/* Semantic variants. Each re-points the ONE accent token, so the icon tint
|
|
252
275
|
and the number move together by construction — there is no second place to
|
|
253
276
|
forget. The inline KPI below shares the same modifiers for the same reason:
|
package/src/css/table.css
CHANGED
|
@@ -155,7 +155,7 @@
|
|
|
155
155
|
.cn-data-table th,
|
|
156
156
|
.cn-data-table td {
|
|
157
157
|
padding: calc(3 * var(--default-grid-baseline));
|
|
158
|
-
text-align:
|
|
158
|
+
text-align: start;
|
|
159
159
|
border-bottom: 1px solid var(--color-border);
|
|
160
160
|
vertical-align: middle;
|
|
161
161
|
max-width: var(--cn-table-cell-max-width, 22rem);
|
|
@@ -174,6 +174,18 @@
|
|
|
174
174
|
white-space: normal;
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
+
/* The secondary line of a cell (`columns[].secondary`): muted, smaller, on its
|
|
178
|
+
own line under the value. Theme hooks: --cn-table-secondary-size and
|
|
179
|
+
--cn-table-secondary-color. */
|
|
180
|
+
.cn-data-table .cn-table-cell__secondary {
|
|
181
|
+
display: block;
|
|
182
|
+
color: var(--cn-table-secondary-color, var(--color-text-maxcontrast));
|
|
183
|
+
font-size: var(--cn-table-secondary-size, 0.9em);
|
|
184
|
+
line-height: 1.35;
|
|
185
|
+
overflow: hidden;
|
|
186
|
+
text-overflow: ellipsis;
|
|
187
|
+
}
|
|
188
|
+
|
|
177
189
|
/* Back to wrapping, for a column holding prose rather than a label:
|
|
178
190
|
`columns: [{ key: 'description', cellClass: 'cn-cell--wrap' }]`. */
|
|
179
191
|
.cn-data-table th.cn-cell--wrap,
|
|
@@ -235,7 +247,7 @@
|
|
|
235
247
|
}
|
|
236
248
|
|
|
237
249
|
.cn-data-table td.cn-cell--end {
|
|
238
|
-
text-align:
|
|
250
|
+
text-align: end;
|
|
239
251
|
white-space: nowrap;
|
|
240
252
|
}
|
|
241
253
|
|
|
@@ -273,7 +285,7 @@
|
|
|
273
285
|
}
|
|
274
286
|
|
|
275
287
|
.cn-table-sort-indicator {
|
|
276
|
-
margin-
|
|
288
|
+
margin-inline-start: var(--default-grid-baseline);
|
|
277
289
|
opacity: 0.6;
|
|
278
290
|
}
|
|
279
291
|
|
|
@@ -295,6 +307,87 @@
|
|
|
295
307
|
outline-offset: -2px;
|
|
296
308
|
}
|
|
297
309
|
|
|
310
|
+
/* Header filter button (CnDataTable `filterable`). 24px hit area with the
|
|
311
|
+
16px icon; the filled icon plus the primary colour marks an active filter,
|
|
312
|
+
so the state never rests on colour alone. */
|
|
313
|
+
.cn-table-header__filter {
|
|
314
|
+
display: inline-flex;
|
|
315
|
+
align-items: center;
|
|
316
|
+
justify-content: center;
|
|
317
|
+
width: 24px;
|
|
318
|
+
min-width: 24px;
|
|
319
|
+
height: 24px;
|
|
320
|
+
min-height: 24px;
|
|
321
|
+
margin: 0 0 0 4px;
|
|
322
|
+
padding: 0;
|
|
323
|
+
border: none;
|
|
324
|
+
border-radius: var(--border-radius, 4px);
|
|
325
|
+
background: transparent;
|
|
326
|
+
color: var(--color-text-maxcontrast);
|
|
327
|
+
vertical-align: middle;
|
|
328
|
+
cursor: pointer;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.cn-table-header__filter:hover {
|
|
332
|
+
background-color: var(--color-background-hover);
|
|
333
|
+
color: var(--color-main-text);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.cn-table-header__filter:focus-visible {
|
|
337
|
+
outline: 2px solid var(--color-main-text);
|
|
338
|
+
outline-offset: 0;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.cn-table-header__filter--active {
|
|
342
|
+
color: var(--color-primary-element);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/* Active header filters above the table, one removable chip each. */
|
|
346
|
+
.cn-data-table__filter-chips {
|
|
347
|
+
display: flex;
|
|
348
|
+
flex-wrap: wrap;
|
|
349
|
+
gap: 6px;
|
|
350
|
+
margin: 0 0 8px;
|
|
351
|
+
padding: 0;
|
|
352
|
+
list-style: none;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.cn-data-table__filter-chip {
|
|
356
|
+
display: inline-flex;
|
|
357
|
+
align-items: center;
|
|
358
|
+
gap: 4px;
|
|
359
|
+
padding: 2px 4px 2px 10px;
|
|
360
|
+
border: 1px solid var(--color-border-dark);
|
|
361
|
+
border-radius: var(--border-radius-pill, 16px);
|
|
362
|
+
background-color: var(--color-background-dark);
|
|
363
|
+
color: var(--color-main-text);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.cn-data-table__filter-chip-remove {
|
|
367
|
+
display: inline-flex;
|
|
368
|
+
align-items: center;
|
|
369
|
+
justify-content: center;
|
|
370
|
+
width: 24px;
|
|
371
|
+
min-width: 24px;
|
|
372
|
+
height: 24px;
|
|
373
|
+
min-height: 24px;
|
|
374
|
+
margin: 0;
|
|
375
|
+
padding: 0;
|
|
376
|
+
border: none;
|
|
377
|
+
border-radius: 50%;
|
|
378
|
+
background: transparent;
|
|
379
|
+
color: var(--color-main-text);
|
|
380
|
+
cursor: pointer;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.cn-data-table__filter-chip-remove:hover {
|
|
384
|
+
background-color: var(--color-background-hover);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.cn-data-table__filter-chip-remove:focus-visible {
|
|
388
|
+
outline: 2px solid var(--color-main-text);
|
|
389
|
+
}
|
|
390
|
+
|
|
298
391
|
/* Multi-column sort priority badge (1, 2, 3), rendered only when two or more rendered, sortable columns are sorted. */
|
|
299
392
|
.cn-table-sort-badge {
|
|
300
393
|
display: inline-flex;
|
|
@@ -302,7 +395,7 @@
|
|
|
302
395
|
justify-content: center;
|
|
303
396
|
min-width: 14px;
|
|
304
397
|
height: 14px;
|
|
305
|
-
margin-
|
|
398
|
+
margin-inline-start: 2px;
|
|
306
399
|
padding: 0 3px;
|
|
307
400
|
border-radius: 7px;
|
|
308
401
|
background-color: var(--color-primary-element);
|
|
@@ -367,7 +460,7 @@
|
|
|
367
460
|
|
|
368
461
|
.cn-table-col--icon {
|
|
369
462
|
width: 40px;
|
|
370
|
-
padding-
|
|
463
|
+
padding-inline-end: 0;
|
|
371
464
|
text-align: center;
|
|
372
465
|
color: var(--color-text-maxcontrast);
|
|
373
466
|
}
|
|
@@ -430,7 +523,7 @@
|
|
|
430
523
|
|
|
431
524
|
.viewTable { width: 100%; border-collapse: collapse; background-color: var(--color-main-background); }
|
|
432
525
|
|
|
433
|
-
.viewTable th, .viewTable td { padding: calc(3 * var(--default-grid-baseline)); text-align:
|
|
526
|
+
.viewTable th, .viewTable td { padding: calc(3 * var(--default-grid-baseline)); text-align: start; border-bottom: 1px solid var(--color-border); vertical-align: middle; }
|
|
434
527
|
|
|
435
528
|
.viewTable th { background: var(--color-background-hover); font-weight: 500; color: var(--color-text-maxcontrast); background-color: var(--color-background-dark); }
|
|
436
529
|
|
package/src/index.js
CHANGED
|
@@ -35,6 +35,7 @@ export {
|
|
|
35
35
|
CnActionsBar,
|
|
36
36
|
CnActionsMenu,
|
|
37
37
|
CnAddWidgetModal,
|
|
38
|
+
CnAdminActionCard,
|
|
38
39
|
CnAdminSettingsShell,
|
|
39
40
|
CnAdvancedFormDialog,
|
|
40
41
|
CnAppLoading,
|
|
@@ -268,6 +269,7 @@ export {
|
|
|
268
269
|
CnTileWidget,
|
|
269
270
|
CnTimelineStages,
|
|
270
271
|
CnTimelineView,
|
|
272
|
+
CnTimelineWidget,
|
|
271
273
|
CnTranslatedBadge,
|
|
272
274
|
CnTreeView,
|
|
273
275
|
CnUserActionMenu,
|