@conduction/nextcloud-vue 2.103.0 → 2.105.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 +23 -0
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +94 -72
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +18 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +3 -3
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +93 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +6 -3
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +3 -3
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +39 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +14 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +99 -3
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue.js +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js +1 -1
- 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/CnFeaturesBoard/CnFeaturesBoard.vue.js +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js +2 -0
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js +32 -29
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue.js +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js +73 -4
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js +74 -27
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +213 -4
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +105 -85
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js +10 -4
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js +9 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js.map +1 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js +88 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js +39 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue.js +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js +57 -5
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js +37 -4
- package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +3 -3
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +16 -4
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js +11 -0
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +4 -4
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +16 -14
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +18 -2
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
- package/dist/esm/composables/indexSources.js +7 -7
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +8 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +8 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +680 -328
- package/dist/esm/utils/libraryWidgetKeys.js +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/nextcloudApps.js +45 -0
- package/dist/esm/utils/nextcloudApps.js.map +1 -0
- package/dist/esm/utils/nextcloudDirectory.js +18 -1
- package/dist/esm/utils/nextcloudDirectory.js.map +1 -1
- package/dist/esm/utils/scopeListLayout.js +9 -2
- package/dist/esm/utils/scopeListLayout.js.map +1 -1
- package/dist/esm/utils/sortOrder.js +61 -0
- package/dist/esm/utils/sortOrder.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/visibleWhen.js +12 -4
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +4046 -2999
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +680 -328
- package/l10n/en.json +8 -1
- package/l10n/nl.json +8 -1
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.md +1 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +39 -2
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +1 -1
- package/src/components/CnAppRoot/CnAppRoot.md +1 -1
- package/src/components/CnAppRoot/CnAppRoot.vue +21 -4
- package/src/components/CnChartWidget/CnChartWidget.md +2 -0
- package/src/components/CnChartWidget/CnChartWidget.vue +93 -1
- package/src/components/CnDashboardPage/CnDashboardPage.vue +9 -6
- package/src/components/CnDataTable/CnDataTable.md +1 -0
- package/src/components/CnDataTable/CnDataTable.vue +49 -0
- package/src/components/CnDetailPage/CnDetailPage.md +2 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +99 -3
- package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +1 -1
- package/src/components/CnFeaturesBoard/CnFeaturesBoard.vue +4 -1
- package/src/components/CnFlowsPage/CnFlowBoard.vue +132 -8
- package/src/components/CnIndexPage/CnIndexPage.md +5 -2
- package/src/components/CnIndexPage/CnIndexPage.vue +228 -9
- package/src/components/CnIndexPage/useSelfFetchList.js +9 -3
- package/src/components/CnNoticeWidget/CnNoticeWidget.vue +153 -0
- package/src/components/CnNoticeWidget/index.js +12 -0
- package/src/components/CnObjectRow/CnObjectRow.vue +95 -1
- package/src/components/CnSettingsField/CnSettingsField.vue +4 -1
- package/src/components/CnSetupWizard/CnSetupWizard.vue +9 -1
- package/src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue +7 -2
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +15 -4
- package/src/components/CnWidgetGrid/builtInWidgets.js +2 -0
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +18 -2
- package/src/components/index.js +1 -0
- package/src/composables/indexSources.js +7 -7
- package/src/css/dialog.css +20 -2
- package/src/css/index-page.css +19 -0
- package/src/css/look-board-detail.css +77 -4
- package/src/css/look-board-index.css +84 -2
- package/src/css/look-board.css +97 -12
- package/src/index.js +1 -0
- package/src/schemas/app-manifest-v2.schema.json +58 -3
- package/src/utils/libraryWidgetKeys.js +1 -0
- package/src/utils/nextcloudApps.js +50 -0
- package/src/utils/nextcloudDirectory.js +17 -0
- package/src/utils/scopeListLayout.js +9 -2
- package/src/utils/sortOrder.js +58 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/visibleWhen.js +12 -4
|
@@ -2,6 +2,7 @@ import { ref, computed, watch } from 'vue';
|
|
|
2
2
|
import { useObjectSubscription } from '../../composables/useObjectSubscription.js';
|
|
3
3
|
import { withPersonalLenses } from '../../utils/personalLenses.js';
|
|
4
4
|
import { parseSortKeysFromQuery, resolveQueryFilters, resolveFilterMap } from '../../utils/routeFilters.js';
|
|
5
|
+
import { orderToSortKeys } from '../../utils/sortOrder.js';
|
|
5
6
|
import { useObjectStore } from '../../store/useObjectStore.js';
|
|
6
7
|
import { useListView } from '../../composables/useListView.js';
|
|
7
8
|
|
|
@@ -167,7 +168,8 @@ function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
167
168
|
const objCtx = unwrapCtx(objectCtxRaw);
|
|
168
169
|
const base = (objCtx && typeof objCtx === 'object') ? { ...objCtx } : {};
|
|
169
170
|
base.workspace = unwrapCtx(workspaceCtxRaw) || {};
|
|
170
|
-
|
|
171
|
+
// The page's own `appConfig` prop wins over a config an ancestor provides.
|
|
172
|
+
base.config = { ...(unwrapCtx(appConfigRaw) || {}), ...(props.appConfig || {}) };
|
|
171
173
|
return base
|
|
172
174
|
}
|
|
173
175
|
|
|
@@ -179,7 +181,7 @@ function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
179
181
|
// never again. Stringified (like CnDeltaWidget's `sourceKey`) so the
|
|
180
182
|
// watcher fires on real content changes only, not object identity.
|
|
181
183
|
const workspaceSignature = computed(() => JSON.stringify(unwrapCtx(workspaceCtxRaw) || {}));
|
|
182
|
-
const appConfigSignature = computed(() => JSON.stringify(unwrapCtx(appConfigRaw) || {}));
|
|
184
|
+
const appConfigSignature = computed(() => JSON.stringify({ ...(unwrapCtx(appConfigRaw) || {}), ...(props.appConfig || {}) }));
|
|
183
185
|
|
|
184
186
|
// Pass register/schema in their positional id slots (not as a {register, schema} object as
|
|
185
187
|
// second arg) — that previously made fetch URLs go to `/api/objects/undefined/[object Object]`.
|
|
@@ -216,9 +218,12 @@ function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
216
218
|
// legacy single-key `sortKey`/`sortOrder` props.
|
|
217
219
|
const initialRoute = instance && instance.proxy && instance.proxy.$route;
|
|
218
220
|
// The page's own order, which a lens without a `sort` goes back to.
|
|
221
|
+
// `defaultOrder` (manifest `config.defaultOrder`) is the order of last
|
|
222
|
+
// resort, after `sortKeys` and `sortKey`.
|
|
223
|
+
const defaultOrderKeys = orderToSortKeys(props.defaultOrder);
|
|
219
224
|
const pageSortKeys = (Array.isArray(props.sortKeys) && props.sortKeys.length > 0)
|
|
220
225
|
? props.sortKeys
|
|
221
|
-
: (props.sortKey ? [{ key: props.sortKey, order: props.sortOrder || 'asc' }] :
|
|
226
|
+
: (props.sortKey ? [{ key: props.sortKey, order: props.sortOrder || 'asc' }] : defaultOrderKeys);
|
|
222
227
|
// The lens that is active on mount may set its own order.
|
|
223
228
|
const initialTabs = withPersonalLenses(props.quickFilters, props.personalLenses);
|
|
224
229
|
const initialTabSort = (!isMultiQuickFilter && Array.isArray(initialTabs))
|
|
@@ -226,7 +231,8 @@ function useSelfFetchList(props, instance, inject, extras = {}) {
|
|
|
226
231
|
: null;
|
|
227
232
|
const initialSortKeys = parseSortKeysFromQuery(initialRoute)
|
|
228
233
|
|| initialTabSort
|
|
229
|
-
|| (Array.isArray(props.sortKeys) && props.sortKeys.length > 0 ? props.sortKeys : undefined)
|
|
234
|
+
|| (Array.isArray(props.sortKeys) && props.sortKeys.length > 0 ? props.sortKeys : undefined)
|
|
235
|
+
|| (!props.sortKey && defaultOrderKeys.length > 0 ? defaultOrderKeys : undefined);
|
|
230
236
|
// Same deep-link restore for facet filters and search, so opening a
|
|
231
237
|
// shared/bookmarked URL reproduces the same view (CnIndexPage persists
|
|
232
238
|
// both back to the route on change).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSelfFetchList.js","sources":["../../../../src/components/CnIndexPage/useSelfFetchList.js"],"sourcesContent":["import { computed, ref, watch } from 'vue'\nimport { useListView } from '../../composables/index.js'\nimport { useObjectSubscription } from '../../composables/useObjectSubscription.js'\nimport { useObjectStore } from '../../store/index.js'\n// Both filter resolvers live in `utils/routeFilters.js` so CnLogsPage applies\n// the same two grammars (route-param interpolation + `?key=value` deep links)\n// without pulling in this composable's index-only sidebar/subscription wiring.\nimport { withPersonalLenses } from '../../utils/personalLenses.js'\nimport { parseSortKeysFromQuery, resolveFilterMap, resolveQueryFilters } from '../../utils/routeFilters.js'\n\nfunction resolveInitialQuickFilterIndex(quickFilters) {\n\tconst tabs = Array.isArray(quickFilters) ? quickFilters : null\n\tif (!tabs || tabs.length === 0) {\n\t\treturn null\n\t}\n\tconst di = tabs.findIndex((t) => t && t.default === true)\n\treturn di >= 0 ? di : 0\n}\n\n/**\n * OR-merge several quick-filter maps into one fetch filter. Values for the\n * same key collapse to an array (deduped) when more than one tab contributes\n * it — `buildQueryString` serialises an array as `key[]=a&key[]=b`, which the\n * OpenRegister API interprets as an IN / OR match.\n *\n * @param {Array<object>} filterMaps Already route-resolved filter maps.\n * @return {object} The merged filter (scalar when a key has one value, array when many).\n */\n/**\n * Rows one board fetch asks for. A board shows every matching row at once,\n * so it loads far more than a table page (OpenRegister serves up to 1000);\n * past this the board offers \"Load more\".\n *\n * @type {number}\n */\nexport const BOARD_PAGE_SIZE = 500\n\n/**\n * The sort a quick filter sets while it is active (`sort: { key, order }`, or a\n * list of those for a multi-column order), as sort keys, or null when it sets\n * none.\n *\n * @param {object|undefined} tab A quick filter.\n * @return {Array<{key: string, order: string}>|null} The sort keys.\n * @spec openspec/changes/screens-quick-filter-sort/specs/index-page/spec.md\n */\nexport function quickFilterSortKeys(tab) {\n\tconst sort = tab && tab.sort\n\tif (!sort) {\n\t\treturn null\n\t}\n\tconst keys = (Array.isArray(sort) ? sort : [sort])\n\t\t.filter((entry) => entry && typeof entry.key === 'string' && entry.key !== '')\n\t\t.map((entry) => ({ key: entry.key, order: entry.order === 'desc' ? 'desc' : 'asc' }))\n\treturn keys.length > 0 ? keys : null\n}\n\nfunction unionFilterMaps(filterMaps) {\n\tconst grouped = {}\n\tfor (const map of filterMaps) {\n\t\tif (!map || typeof map !== 'object') {\n\t\t\tcontinue\n\t\t}\n\t\tfor (const [k, v] of Object.entries(map)) {\n\t\t\tif (v === undefined || v === null || v === '') {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!grouped[k]) {\n\t\t\t\tgrouped[k] = []\n\t\t\t}\n\t\t\tfor (const item of (Array.isArray(v) ? v : [v])) {\n\t\t\t\tif (!grouped[k].includes(item)) {\n\t\t\t\t\tgrouped[k].push(item)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tconst out = {}\n\tfor (const [k, arr] of Object.entries(grouped)) {\n\t\tout[k] = arr.length === 1 ? arr[0] : arr\n\t}\n\treturn out\n}\n\n/**\n * Self-fetch mode for CnIndexPage: when register+schema are set but no\n * `objects` prop was passed (manifest-driven pages), drive the list ourselves.\n *\n * @param {object} props CnIndexPage props.\n * @param {import('vue').ComponentInternalInstance|null} instance Pass `getCurrentInstance()`.\n * @param {typeof import('vue').inject} inject Pass Vue's `inject`.\n * @param {{activeFolderSchema?: import('vue').Ref<?{schema: string, register?: string}>}} [extras] `activeFolderSchema`: a ref the page sets to the selected folder's `{ schema, register? }`, switching the loaded object type while it is non-null.\n * @return {object} { isSelfFetch, list, selfObjectStore, selfObjectType, activeQuickFilterIndex }\n */\nexport function useSelfFetchList(props, instance, inject, extras = {}) {\n\tconst objectsProvided = !!(\n\t\tinstance && instance.proxy && instance.proxy.$options && instance.proxy.$options.propsData\n\t\t&& Object.hasOwn(instance.proxy.$options.propsData, 'objects')\n\t)\n\t// A named source wins over register/schema. Without this the page would\n\t// fire an OpenRegister request whose rows it then discards in favour of the\n\t// source's — wasted, but worse than wasted if the manifest names both by\n\t// mistake, because the request succeeds and nothing says the two disagree.\n\tconst isSelfFetch = !!(props.register && props.schema) && !objectsProvided && !props.entitySource\n\n\t// \"Also search inside files\" switch, seeded from `?contentSearch=1` so a\n\t// shared link reproduces the list. Only meaningful when `searchInFiles` is on.\n\tconst routeAtSetup = instance && instance.proxy && instance.proxy.$route\n\tconst contentSearch = ref(props.searchInFiles === true && String(routeAtSetup?.query?.contentSearch) === '1')\n\n\tconst activeQuickFilterIndex = ref(resolveInitialQuickFilterIndex(withPersonalLenses(props.quickFilters, props.personalLenses)))\n\tconst selectedQuickFilterIndices = ref([])\n\tconst isMultiQuickFilter = props.quickFilterMultiple === true\n\n\tif (!isSelfFetch) {\n\t\treturn {\n\t\t\tisSelfFetch: false,\n\t\t\tlist: null,\n\t\t\tselfObjectStore: null,\n\t\t\tselfObjectType: '',\n\t\t\tactiveQuickFilterIndex,\n\t\t\tselectedQuickFilterIndices,\n\t\t\tcontentSearch,\n\t\t\tselfFetchTokenCtx: null,\n\t\t\tinitialQueryFilterKeys: [],\n\t\t}\n\t}\n\n\t// The object type follows the selected folder's own schema when it declares\n\t// one; otherwise the page's register and schema.\n\tconst activeFolderSchema = extras.activeFolderSchema || null\n\tconst resolvedTarget = computed(() => {\n\t\tconst folder = activeFolderSchema && activeFolderSchema.value\n\t\tif (folder && folder.schema) {\n\t\t\tconst register = folder.register || props.register\n\t\t\treturn { register, schema: folder.schema, type: `${register}-${folder.schema}` }\n\t\t}\n\t\t// A collection endpoint gets its own type key, so a plain registration of\n\t\t// the same pair elsewhere never resets it.\n\t\tconst collectionUrl = props.collectionUrl || ''\n\t\tconst type = `${props.register}-${props.schema}` + (collectionUrl ? `@${collectionUrl}` : '')\n\t\treturn { register: props.register, schema: props.schema, type, collectionUrl }\n\t})\n\tconst objectType = computed(() => resolvedTarget.value.type)\n\tconst sidebarState = inject('sidebarState', null) ?? inject('objectSidebarState', null)\n\tconst objectStore = useObjectStore()\n\n\t// Token-resolution context for `@workspace.<key>` / `@config.<key>` /\n\t// `@objectId` / `@object.<field>` inside `props.filter` / quick-filter\n\t// tab filters. Same injects + unwrap shape as CnObjectListWidget's\n\t// `objectCtx`/`workspaceCtx`/`tokenCtx` computeds (and CnDeltaWidget) —\n\t// `cnWorkspaceContext` is the reactive bag a dashboard/workspace-root\n\t// (e.g. hrmq's App.vue for multi-administratie) provides; `cnObjectContext`\n\t// is a detail-page's object context (rare on an index page, but harmless\n\t// to support); `cnAppConfig` is the page-level app config bag. All three\n\t// default to null/absent so an app that never provides them is unaffected.\n\tconst objectCtxRaw = inject('cnObjectContext', null)\n\tconst workspaceCtxRaw = inject('cnWorkspaceContext', null)\n\tconst appConfigRaw = inject('cnAppConfig', null)\n\tconst unwrapCtx = (v) => ((v && typeof v === 'object' && 'value' in v) ? v.value : v)\n\n\t/**\n\t * Build the current token-resolution ctx `{ objectId?, object?, workspace, config }`\n\t * from the injected bags, unwrapping Vue refs. Called fresh on every fetch\n\t * so it always reflects the latest workspace/config state.\n\t *\n\t * @return {object} The token ctx.\n\t */\n\tfunction tokenCtx() {\n\t\tconst objCtx = unwrapCtx(objectCtxRaw)\n\t\tconst base = (objCtx && typeof objCtx === 'object') ? { ...objCtx } : {}\n\t\tbase.workspace = unwrapCtx(workspaceCtxRaw) || {}\n\t\tbase.config = unwrapCtx(appConfigRaw) || {}\n\t\treturn base\n\t}\n\n\t// Reactive signature of the workspace/config bags so a change (e.g. the\n\t// administration switcher writing `activeAdministrationId`) triggers a\n\t// re-fetch below — `fixedFilters` is a plain getter called at fetch time\n\t// (see useListView.resolveFixedFilters), it is NOT auto-tracked by Vue,\n\t// so without this the list would resolve the token once on mount and\n\t// never again. Stringified (like CnDeltaWidget's `sourceKey`) so the\n\t// watcher fires on real content changes only, not object identity.\n\tconst workspaceSignature = computed(() => JSON.stringify(unwrapCtx(workspaceCtxRaw) || {}))\n\tconst appConfigSignature = computed(() => JSON.stringify(unwrapCtx(appConfigRaw) || {}))\n\n\t// Pass register/schema in their positional id slots (not as a {register, schema} object as\n\t// second arg) — that previously made fetch URLs go to `/api/objects/undefined/[object Object]`.\n\t// Runs (sync, ahead of the list's own watcher) again whenever the type switches.\n\tfunction registerTarget() {\n\t\tconst { register, schema, type, collectionUrl } = resolvedTarget.value\n\t\tif (typeof objectStore.registerObjectType === 'function') {\n\t\t\tobjectStore.registerObjectType(type, schema, register, {\n\t\t\t\tregisterSlug: register,\n\t\t\t\tschemaSlug: schema,\n\t\t\t\t...(collectionUrl ? { collectionUrl } : {}),\n\t\t\t})\n\t\t}\n\t\t// A mixed list tells its own rows apart by `@self.register`, an id, so a slug register needs resolving.\n\t\tif (collectionUrl && !/^\\d+$/.test(String(register)) && typeof objectStore.fetchRegister === 'function') {\n\t\t\tobjectStore.fetchRegister(type)\n\t\t}\n\t}\n\tregisterTarget()\n\twatch(objectType, registerTarget, { flush: 'sync' })\n\n\t// Seed the visible-column set from the configured columns so the sidebar's\n\t// Columns tab reflects the curated default; null when none are configured\n\t// (schema-driven table — every column starts visible).\n\t// A column marked `hidden: true` is declared but starts outside the set,\n\t// so it is off until the person turns it on in the Columns tab.\n\tconst configuredColumnKeys = (props.columns || [])\n\t\t.filter((c) => !(c && typeof c === 'object' && c.hidden === true))\n\t\t.map((c) => (typeof c === 'string' ? c : c && c.key))\n\t\t.filter(Boolean)\n\n\t// Restore a persisted multi-column sort from the route query first (deep\n\t// link / reload); fall back to a host-passed `sortKeys` prop, then the\n\t// legacy single-key `sortKey`/`sortOrder` props.\n\tconst initialRoute = instance && instance.proxy && instance.proxy.$route\n\t// The page's own order, which a lens without a `sort` goes back to.\n\tconst pageSortKeys = (Array.isArray(props.sortKeys) && props.sortKeys.length > 0)\n\t\t? props.sortKeys\n\t\t: (props.sortKey ? [{ key: props.sortKey, order: props.sortOrder || 'asc' }] : [])\n\t// The lens that is active on mount may set its own order.\n\tconst initialTabs = withPersonalLenses(props.quickFilters, props.personalLenses)\n\tconst initialTabSort = (!isMultiQuickFilter && Array.isArray(initialTabs))\n\t\t? quickFilterSortKeys(initialTabs[activeQuickFilterIndex.value])\n\t\t: null\n\tconst initialSortKeys = parseSortKeysFromQuery(initialRoute)\n\t\t|| initialTabSort\n\t\t|| (Array.isArray(props.sortKeys) && props.sortKeys.length > 0 ? props.sortKeys : undefined)\n\t// Same deep-link restore for facet filters and search, so opening a\n\t// shared/bookmarked URL reproduces the same view (CnIndexPage persists\n\t// both back to the route on change).\n\tconst initialActiveFilters = resolveQueryFilters(initialRoute && initialRoute.query, tokenCtx())\n\tconst initialSearchTerm = (initialRoute && typeof initialRoute.query?._search === 'string') ? initialRoute.query._search : ''\n\n\t// Set right after useListView returns; the fixed-filters getter reads it lazily.\n\tlet listHandle = null\n\tconst list = useListView(() => objectType.value, {\n\t\tobjectStore,\n\t\tsidebarState,\n\t\tdefaultSort: props.sortKey ? { key: props.sortKey, order: props.sortOrder || 'asc' } : undefined,\n\t\tdefaultSortKeys: initialSortKeys,\n\t\tdefaultActiveFilters: initialActiveFilters,\n\t\tdefaultSearchTerm: initialSearchTerm,\n\t\tdefaultPageSize: props.viewMode === 'board' ? BOARD_PAGE_SIZE : ((props.pagination && props.pagination.limit) || undefined),\n\t\tdefaultVisibleColumns: configuredColumnKeys.length ? configuredColumnKeys : null,\n\t\t// `pages[].config.extend` → OpenRegister's repeated `_extend[]`. A\n\t\t// getter so a reactive change re-scopes the next fetch, matching how\n\t\t// `fixedFilters` is read.\n\t\textend: () => (Array.isArray(props.extend) ? props.extend : []),\n\t\tfixedFilters: () => {\n\t\t\tconst route = instance && instance.proxy && instance.proxy.$route\n\t\t\tconst params = (route && route.params) || {}\n\t\t\tconst ctx = tokenCtx()\n\t\t\tconst queryFilters = resolveQueryFilters(route && route.query, ctx)\n\t\t\tconst base = resolveFilterMap(props.filter, params, ctx)\n\t\t\t// A folder-sidebar scope declaring `searchFields` narrows what the\n\t\t\t// search box searches over while that scope is active. Read off the\n\t\t\t// instance, like `$route` above, because the active scope is the\n\t\t\t// component's own state rather than a prop — and read through the\n\t\t\t// one fixed-filter getter rather than a second search path.\n\t\t\tconst scopeSearchFields = (instance && instance.proxy && instance.proxy.activeScopeSearchFields) || []\n\t\t\tconst scopeBase = scopeSearchFields.length > 0 ? { _searchFields: scopeSearchFields } : {}\n\t\t\t// File-content search widens a text search, so it rides only with a term.\n\t\t\tconst widen = props.searchInFiles === true && contentSearch.value && !!(listHandle && listHandle.searchTerm.value)\n\t\t\t// The visible calendar month, only while the page is in calendar mode.\n\t\t\tconst month = (instance && instance.proxy && instance.proxy.calendarRangeFilter) || {}\n\t\t\tconst scope = { ...(widen ? { ...scopeBase, _content_search: 'true' } : scopeBase), ...month }\n\t\t\tconst lensed = withPersonalLenses(props.quickFilters, props.personalLenses)\n\t\t\tconst tabs = Array.isArray(lensed) ? lensed : null\n\t\t\tif (!tabs) {\n\t\t\t\treturn { ...queryFilters, ...scope, ...base }\n\t\t\t}\n\n\t\t\t// Multiple mode: OR the selected tabs' filters together (union).\n\t\t\tif (isMultiQuickFilter) {\n\t\t\t\tconst maps = selectedQuickFilterIndices.value\n\t\t\t\t\t.map((i) => resolveFilterMap(tabs[i]?.filter, params, ctx))\n\t\t\t\treturn { ...queryFilters, ...scope, ...base, ...unionFilterMaps(maps) }\n\t\t\t}\n\n\t\t\t// Single mode: the active tab's filter spread last so it wins\n\t\t\t// over a colliding props.filter entry.\n\t\t\tconst activeIdx = activeQuickFilterIndex.value\n\t\t\tconst tabFilter = (activeIdx !== null && activeIdx !== undefined) ? tabs[activeIdx]?.filter : null\n\t\t\treturn { ...queryFilters, ...scope, ...base, ...resolveFilterMap(tabFilter, params, ctx) }\n\t\t},\n\t})\n\n\tlistHandle = list\n\n\t// Re-fetch when the quick-filter selection changes (pre-existing), OR\n\t// when the workspace/app-config bag content changes (e.g. the\n\t// administration switcher writes a new `activeAdministrationId`) — a\n\t// `@workspace.<key>`/`@config.<key>` token in `props.filter` must re-scope\n\t// the list without a manual reload. A change to `props.filter` itself (a\n\t// host toggling a filter checkbox) re-fetches the same way.\n\tconst filterSignature = computed(() => JSON.stringify(props.filter ?? null))\n\twatch([activeQuickFilterIndex, selectedQuickFilterIndices, contentSearch, workspaceSignature, appConfigSignature, filterSignature], (now, before) => {\n\t\t// Switching lens: a lens with a `sort` sets that order; leaving one\n\t\t// for a lens without goes back to the page's own order. A column the\n\t\t// person sorts by afterwards still wins until the next switch.\n\t\tif (!isMultiQuickFilter && before && now[0] !== before[0]) {\n\t\t\tconst tabs = withPersonalLenses(props.quickFilters, props.personalLenses) || []\n\t\t\tconst keys = quickFilterSortKeys(tabs[now[0]]) || (quickFilterSortKeys(tabs[before[0]]) ? pageSortKeys : null)\n\t\t\tif (keys && list.sortKeys) {\n\t\t\t\tlist.sortKeys.value = keys\n\t\t\t\tlist.sortKey.value = keys[0]?.key ?? null\n\t\t\t\tlist.sortOrder.value = keys[0]?.order ?? 'asc'\n\t\t\t}\n\t\t}\n\t\tif (list && typeof list.refresh === 'function') {\n\t\t\tlist.refresh(1)\n\t\t}\n\t})\n\n\t// Live collection updates (manifest-live-updates): subscribe to the\n\t// page's `or-collection-{register}-{schema}` scope so another user's\n\t// create/update/delete refreshes this list without a manual reload.\n\t// The subscription lifecycle (mount/unmount, in-flight dedupe, epoch\n\t// guard against stale async resolution) lives in useObjectSubscription;\n\t// the refetch-on-event (with the last fetch params, burst-coalesced)\n\t// lives in liveUpdatesPlugin. The `subscribe` prop (default true; from\n\t// a manifest: `config.subscribe: false`) is the opt-out, read through\n\t// a reactive getter so a runtime flip attaches/detaches accordingly.\n\t// Stores without live-updates support (no `subscribe` action) are a\n\t// silent no-op inside the composable, keeping this fully inert.\n\tuseObjectSubscription(objectStore, () => objectType.value, null, {\n\t\tenabled: () => props.subscribe !== false,\n\t})\n\n\treturn {\n\t\tisSelfFetch: true,\n\t\tlist,\n\t\tselfObjectStore: objectStore,\n\t\tselfObjectType: objectType,\n\t\tactiveQuickFilterIndex,\n\t\tselectedQuickFilterIndices,\n\t\tcontentSearch,\n\t\t// The page persists the view state back into the query, and needs both\n\t\t// to do it without trampling the rest of it: the keys it adopted from\n\t\t// the query on load (the only non-`_` ones it may clear), and the ctx\n\t\t// those keys' `@`-tokens resolve against.\n\t\tselfFetchTokenCtx: tokenCtx,\n\t\tinitialQueryFilterKeys: Object.keys(initialActiveFilters),\n\t}\n}\n"],"names":[],"mappings":";;;;;;;AAUA,SAAS,8BAA8B,CAAC,YAAY,EAAE;AACtD,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,YAAY,GAAG,KAAI;AAC/D,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;AACjC,EAAE,OAAO,IAAI;AACb,EAAE;AACF,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,EAAC;AAC1D,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC;AACxB,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACY,MAAC,eAAe,GAAG,IAAG;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,mBAAmB,CAAC,GAAG,EAAE;AACzC,CAAC,MAAM,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC,KAAI;AAC7B,CAAC,IAAI,CAAC,IAAI,EAAE;AACZ,EAAE,OAAO,IAAI;AACb,EAAE;AACF,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC;AAClD,GAAG,MAAM,CAAC,CAAC,KAAK,KAAK,KAAK,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC;AAChF,GAAG,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,KAAK,MAAM,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC,EAAC;AACvF,CAAC,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI;AACrC,CAAC;AACD;AACA,SAAS,eAAe,CAAC,UAAU,EAAE;AACrC,CAAC,MAAM,OAAO,GAAG,GAAE;AACnB,CAAC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE;AAC/B,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AACvC,GAAG,QAAQ;AACX,GAAG;AACH,EAAE,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AAC5C,GAAG,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE;AAClD,IAAI,QAAQ;AACZ,IAAI;AACJ,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;AACpB,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,GAAE;AACnB,IAAI;AACJ,GAAG,KAAK,MAAM,IAAI,KAAK,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;AACpD,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;AACpC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAC;AAC1B,KAAK;AACL,IAAI;AACJ,GAAG;AACH,EAAE;AACF,CAAC,MAAM,GAAG,GAAG,GAAE;AACf,CAAC,KAAK,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AACjD,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAG;AAC1C,EAAE;AACF,CAAC,OAAO,GAAG;AACX,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE,EAAE;AACvE,CAAC,MAAM,eAAe,GAAG,CAAC;AAC1B,EAAE,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS;AAC5F,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;AAChE,GAAE;AACF;AACA;AACA;AACA;AACA,CAAC,MAAM,WAAW,GAAG,CAAC,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,KAAK,CAAC,aAAY;AAClG;AACA;AACA;AACA,CAAC,MAAM,YAAY,GAAG,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAM;AACzE,CAAC,MAAM,aAAa,GAAG,GAAG,CAAC,KAAK,CAAC,aAAa,KAAK,IAAI,IAAI,MAAM,CAAC,YAAY,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,GAAG,EAAC;AAC9G;AACA,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC,8BAA8B,CAAC,kBAAkB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,EAAC;AACjI,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC,EAAE,EAAC;AAC3C,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC,mBAAmB,KAAK,KAAI;AAC9D;AACA,CAAC,IAAI,CAAC,WAAW,EAAE;AACnB,EAAE,OAAO;AACT,GAAG,WAAW,EAAE,KAAK;AACrB,GAAG,IAAI,EAAE,IAAI;AACb,GAAG,eAAe,EAAE,IAAI;AACxB,GAAG,cAAc,EAAE,EAAE;AACrB,GAAG,sBAAsB;AACzB,GAAG,0BAA0B;AAC7B,GAAG,aAAa;AAChB,GAAG,iBAAiB,EAAE,IAAI;AAC1B,GAAG,sBAAsB,EAAE,EAAE;AAC7B,GAAG;AACH,EAAE;AACF;AACA;AACA;AACA,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,kBAAkB,IAAI,KAAI;AAC7D,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM;AACvC,EAAE,MAAM,MAAM,GAAG,kBAAkB,IAAI,kBAAkB,CAAC,MAAK;AAC/D,EAAE,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE;AAC/B,GAAG,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,KAAK,CAAC,SAAQ;AACrD,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE;AACnF,GAAG;AACH;AACA;AACA,EAAE,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,IAAI,GAAE;AACjD,EAAE,MAAM,IAAI,GAAG,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,aAAa,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,GAAG,EAAE,EAAC;AAC/F,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE;AAChF,EAAE,EAAC;AACH,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,cAAc,CAAC,KAAK,CAAC,IAAI,EAAC;AAC7D,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,oBAAoB,EAAE,IAAI,EAAC;AACxF,CAAC,MAAM,WAAW,GAAG,cAAc,GAAE;AACrC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,iBAAiB,EAAE,IAAI,EAAC;AACrD,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,oBAAoB,EAAE,IAAI,EAAC;AAC3D,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa,EAAE,IAAI,EAAC;AACjD,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,EAAC;AACtF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,SAAS,QAAQ,GAAG;AACrB,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,EAAC;AACxC,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,EAAE,GAAG,MAAM,EAAE,GAAG,GAAE;AAC1E,EAAE,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,eAAe,CAAC,IAAI,GAAE;AACnD,EAAE,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,IAAI,GAAE;AAC7C,EAAE,OAAO,IAAI;AACb,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,EAAC;AAC5F,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,EAAC;AACzF;AACA;AACA;AACA;AACA,CAAC,SAAS,cAAc,GAAG;AAC3B,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC,MAAK;AACxE,EAAE,IAAI,OAAO,WAAW,CAAC,kBAAkB,KAAK,UAAU,EAAE;AAC5D,GAAG,WAAW,CAAC,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE;AAC1D,IAAI,YAAY,EAAE,QAAQ;AAC1B,IAAI,UAAU,EAAE,MAAM;AACtB,IAAI,IAAI,aAAa,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC;AAC/C,IAAI,EAAC;AACL,GAAG;AACH;AACA,EAAE,IAAI,aAAa,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,OAAO,WAAW,CAAC,aAAa,KAAK,UAAU,EAAE;AAC3G,GAAG,WAAW,CAAC,aAAa,CAAC,IAAI,EAAC;AAClC,GAAG;AACH,EAAE;AACF,CAAC,cAAc,GAAE;AACjB,CAAC,KAAK,CAAC,UAAU,EAAE,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAC;AACrD;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE;AAClD,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;AACpE,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,KAAK,QAAQ,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;AACvD,GAAG,MAAM,CAAC,OAAO,EAAC;AAClB;AACA;AACA;AACA;AACA,CAAC,MAAM,YAAY,GAAG,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAM;AACzE;AACA,CAAC,MAAM,YAAY,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;AACjF,IAAI,KAAK,CAAC,QAAQ;AAClB,KAAK,KAAK,CAAC,OAAO,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,IAAI,KAAK,EAAE,CAAC,GAAG,EAAE,EAAC;AACpF;AACA,CAAC,MAAM,WAAW,GAAG,kBAAkB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,cAAc,EAAC;AACjF,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,kBAAkB,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;AAC1E,IAAI,mBAAmB,CAAC,WAAW,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;AAClE,IAAI,KAAI;AACR,CAAC,MAAM,eAAe,GAAG,sBAAsB,CAAC,YAAY,CAAC;AAC7D,KAAK,cAAc;AACnB,MAAM,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,GAAG,SAAS,EAAC;AAC9F;AACA;AACA;AACA,CAAC,MAAM,oBAAoB,GAAG,mBAAmB,CAAC,YAAY,IAAI,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAC;AACjG,CAAC,MAAM,iBAAiB,GAAG,CAAC,YAAY,IAAI,OAAO,YAAY,CAAC,KAAK,EAAE,OAAO,KAAK,QAAQ,IAAI,YAAY,CAAC,KAAK,CAAC,OAAO,GAAG,GAAE;AAC9H;AACA;AACA,CAAC,IAAI,UAAU,GAAG,KAAI;AACtB,CAAC,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,UAAU,CAAC,KAAK,EAAE;AAClD,EAAE,WAAW;AACb,EAAE,YAAY;AACd,EAAE,WAAW,EAAE,KAAK,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,IAAI,KAAK,EAAE,GAAG,SAAS;AAClG,EAAE,eAAe,EAAE,eAAe;AAClC,EAAE,oBAAoB,EAAE,oBAAoB;AAC5C,EAAE,iBAAiB,EAAE,iBAAiB;AACtC,EAAE,eAAe,EAAE,KAAK,CAAC,QAAQ,KAAK,OAAO,GAAG,eAAe,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,KAAK,SAAS,CAAC;AAC7H,EAAE,qBAAqB,EAAE,oBAAoB,CAAC,MAAM,GAAG,oBAAoB,GAAG,IAAI;AAClF;AACA;AACA;AACA,EAAE,MAAM,EAAE,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC;AACjE,EAAE,YAAY,EAAE,MAAM;AACtB,GAAG,MAAM,KAAK,GAAG,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAM;AACpE,GAAG,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,GAAE;AAC/C,GAAG,MAAM,GAAG,GAAG,QAAQ,GAAE;AACzB,GAAG,MAAM,YAAY,GAAG,mBAAmB,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,GAAG,EAAC;AACtE,GAAG,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAC;AAC3D;AACA;AACA;AACA;AACA;AACA,GAAG,MAAM,iBAAiB,GAAG,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,uBAAuB,KAAK,GAAE;AACzG,GAAG,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,GAAG,CAAC,GAAG,EAAE,aAAa,EAAE,iBAAiB,EAAE,GAAG,GAAE;AAC7F;AACA,GAAG,MAAM,KAAK,GAAG,KAAK,CAAC,aAAa,KAAK,IAAI,IAAI,aAAa,CAAC,KAAK,IAAI,CAAC,EAAE,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,KAAK,EAAC;AACrH;AACA,GAAG,MAAM,KAAK,GAAG,CAAC,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,mBAAmB,KAAK,GAAE;AACzF,GAAG,MAAM,KAAK,GAAG,EAAE,IAAI,KAAK,GAAG,EAAE,GAAG,SAAS,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,GAAG,KAAK,GAAE;AACjG,GAAG,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,cAAc,EAAC;AAC9E,GAAG,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,KAAI;AACrD,GAAG,IAAI,CAAC,IAAI,EAAE;AACd,IAAI,OAAO,EAAE,GAAG,YAAY,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE;AACjD,IAAI;AACJ;AACA;AACA,GAAG,IAAI,kBAAkB,EAAE;AAC3B,IAAI,MAAM,IAAI,GAAG,0BAA0B,CAAC,KAAK;AACjD,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAC;AAChE,IAAI,OAAO,EAAE,GAAG,YAAY,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,eAAe,CAAC,IAAI,CAAC,EAAE;AAC3E,IAAI;AACJ;AACA;AACA;AACA,GAAG,MAAM,SAAS,GAAG,sBAAsB,CAAC,MAAK;AACjD,GAAG,MAAM,SAAS,GAAG,CAAC,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,KAAI;AACrG,GAAG,OAAO,EAAE,GAAG,YAAY,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE;AAC7F,GAAG;AACH,EAAE,EAAC;AACH;AACA,CAAC,UAAU,GAAG,KAAI;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,EAAC;AAC7E,CAAC,KAAK,CAAC,CAAC,sBAAsB,EAAE,0BAA0B,EAAE,aAAa,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,eAAe,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK;AACtJ;AACA;AACA;AACA,EAAE,IAAI,CAAC,kBAAkB,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE;AAC7D,GAAG,MAAM,IAAI,GAAG,kBAAkB,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,cAAc,CAAC,IAAI,GAAE;AAClF,GAAG,MAAM,IAAI,GAAG,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,YAAY,GAAG,IAAI,EAAC;AACjH,GAAG,IAAI,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE;AAC9B,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,GAAG,KAAI;AAC9B,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,KAAI;AAC7C,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,MAAK;AAClD,IAAI;AACJ,GAAG;AACH,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,UAAU,EAAE;AAClD,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,EAAC;AAClB,GAAG;AACH,EAAE,EAAC;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,qBAAqB,CAAC,WAAW,EAAE,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE;AAClE,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC,SAAS,KAAK,KAAK;AAC1C,EAAE,EAAC;AACH;AACA,CAAC,OAAO;AACR,EAAE,WAAW,EAAE,IAAI;AACnB,EAAE,IAAI;AACN,EAAE,eAAe,EAAE,WAAW;AAC9B,EAAE,cAAc,EAAE,UAAU;AAC5B,EAAE,sBAAsB;AACxB,EAAE,0BAA0B;AAC5B,EAAE,aAAa;AACf;AACA;AACA;AACA;AACA,EAAE,iBAAiB,EAAE,QAAQ;AAC7B,EAAE,sBAAsB,EAAE,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC;AAC3D,EAAE;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"useSelfFetchList.js","sources":["../../../../src/components/CnIndexPage/useSelfFetchList.js"],"sourcesContent":["import { computed, ref, watch } from 'vue'\nimport { useListView } from '../../composables/index.js'\nimport { useObjectSubscription } from '../../composables/useObjectSubscription.js'\nimport { useObjectStore } from '../../store/index.js'\n// Both filter resolvers live in `utils/routeFilters.js` so CnLogsPage applies\n// the same two grammars (route-param interpolation + `?key=value` deep links)\n// without pulling in this composable's index-only sidebar/subscription wiring.\nimport { withPersonalLenses } from '../../utils/personalLenses.js'\nimport { parseSortKeysFromQuery, resolveFilterMap, resolveQueryFilters } from '../../utils/routeFilters.js'\nimport { orderToSortKeys } from '../../utils/sortOrder.js'\n\nfunction resolveInitialQuickFilterIndex(quickFilters) {\n\tconst tabs = Array.isArray(quickFilters) ? quickFilters : null\n\tif (!tabs || tabs.length === 0) {\n\t\treturn null\n\t}\n\tconst di = tabs.findIndex((t) => t && t.default === true)\n\treturn di >= 0 ? di : 0\n}\n\n/**\n * OR-merge several quick-filter maps into one fetch filter. Values for the\n * same key collapse to an array (deduped) when more than one tab contributes\n * it — `buildQueryString` serialises an array as `key[]=a&key[]=b`, which the\n * OpenRegister API interprets as an IN / OR match.\n *\n * @param {Array<object>} filterMaps Already route-resolved filter maps.\n * @return {object} The merged filter (scalar when a key has one value, array when many).\n */\n/**\n * Rows one board fetch asks for. A board shows every matching row at once,\n * so it loads far more than a table page (OpenRegister serves up to 1000);\n * past this the board offers \"Load more\".\n *\n * @type {number}\n */\nexport const BOARD_PAGE_SIZE = 500\n\n/**\n * The sort a quick filter sets while it is active (`sort: { key, order }`, or a\n * list of those for a multi-column order), as sort keys, or null when it sets\n * none.\n *\n * @param {object|undefined} tab A quick filter.\n * @return {Array<{key: string, order: string}>|null} The sort keys.\n * @spec openspec/changes/screens-quick-filter-sort/specs/index-page/spec.md\n */\nexport function quickFilterSortKeys(tab) {\n\tconst sort = tab && tab.sort\n\tif (!sort) {\n\t\treturn null\n\t}\n\tconst keys = (Array.isArray(sort) ? sort : [sort])\n\t\t.filter((entry) => entry && typeof entry.key === 'string' && entry.key !== '')\n\t\t.map((entry) => ({ key: entry.key, order: entry.order === 'desc' ? 'desc' : 'asc' }))\n\treturn keys.length > 0 ? keys : null\n}\n\nfunction unionFilterMaps(filterMaps) {\n\tconst grouped = {}\n\tfor (const map of filterMaps) {\n\t\tif (!map || typeof map !== 'object') {\n\t\t\tcontinue\n\t\t}\n\t\tfor (const [k, v] of Object.entries(map)) {\n\t\t\tif (v === undefined || v === null || v === '') {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif (!grouped[k]) {\n\t\t\t\tgrouped[k] = []\n\t\t\t}\n\t\t\tfor (const item of (Array.isArray(v) ? v : [v])) {\n\t\t\t\tif (!grouped[k].includes(item)) {\n\t\t\t\t\tgrouped[k].push(item)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tconst out = {}\n\tfor (const [k, arr] of Object.entries(grouped)) {\n\t\tout[k] = arr.length === 1 ? arr[0] : arr\n\t}\n\treturn out\n}\n\n/**\n * Self-fetch mode for CnIndexPage: when register+schema are set but no\n * `objects` prop was passed (manifest-driven pages), drive the list ourselves.\n *\n * @param {object} props CnIndexPage props.\n * @param {import('vue').ComponentInternalInstance|null} instance Pass `getCurrentInstance()`.\n * @param {typeof import('vue').inject} inject Pass Vue's `inject`.\n * @param {{activeFolderSchema?: import('vue').Ref<?{schema: string, register?: string}>}} [extras] `activeFolderSchema`: a ref the page sets to the selected folder's `{ schema, register? }`, switching the loaded object type while it is non-null.\n * @return {object} { isSelfFetch, list, selfObjectStore, selfObjectType, activeQuickFilterIndex }\n */\nexport function useSelfFetchList(props, instance, inject, extras = {}) {\n\tconst objectsProvided = !!(\n\t\tinstance && instance.proxy && instance.proxy.$options && instance.proxy.$options.propsData\n\t\t&& Object.hasOwn(instance.proxy.$options.propsData, 'objects')\n\t)\n\t// A named source wins over register/schema. Without this the page would\n\t// fire an OpenRegister request whose rows it then discards in favour of the\n\t// source's — wasted, but worse than wasted if the manifest names both by\n\t// mistake, because the request succeeds and nothing says the two disagree.\n\tconst isSelfFetch = !!(props.register && props.schema) && !objectsProvided && !props.entitySource\n\n\t// \"Also search inside files\" switch, seeded from `?contentSearch=1` so a\n\t// shared link reproduces the list. Only meaningful when `searchInFiles` is on.\n\tconst routeAtSetup = instance && instance.proxy && instance.proxy.$route\n\tconst contentSearch = ref(props.searchInFiles === true && String(routeAtSetup?.query?.contentSearch) === '1')\n\n\tconst activeQuickFilterIndex = ref(resolveInitialQuickFilterIndex(withPersonalLenses(props.quickFilters, props.personalLenses)))\n\tconst selectedQuickFilterIndices = ref([])\n\tconst isMultiQuickFilter = props.quickFilterMultiple === true\n\n\tif (!isSelfFetch) {\n\t\treturn {\n\t\t\tisSelfFetch: false,\n\t\t\tlist: null,\n\t\t\tselfObjectStore: null,\n\t\t\tselfObjectType: '',\n\t\t\tactiveQuickFilterIndex,\n\t\t\tselectedQuickFilterIndices,\n\t\t\tcontentSearch,\n\t\t\tselfFetchTokenCtx: null,\n\t\t\tinitialQueryFilterKeys: [],\n\t\t}\n\t}\n\n\t// The object type follows the selected folder's own schema when it declares\n\t// one; otherwise the page's register and schema.\n\tconst activeFolderSchema = extras.activeFolderSchema || null\n\tconst resolvedTarget = computed(() => {\n\t\tconst folder = activeFolderSchema && activeFolderSchema.value\n\t\tif (folder && folder.schema) {\n\t\t\tconst register = folder.register || props.register\n\t\t\treturn { register, schema: folder.schema, type: `${register}-${folder.schema}` }\n\t\t}\n\t\t// A collection endpoint gets its own type key, so a plain registration of\n\t\t// the same pair elsewhere never resets it.\n\t\tconst collectionUrl = props.collectionUrl || ''\n\t\tconst type = `${props.register}-${props.schema}` + (collectionUrl ? `@${collectionUrl}` : '')\n\t\treturn { register: props.register, schema: props.schema, type, collectionUrl }\n\t})\n\tconst objectType = computed(() => resolvedTarget.value.type)\n\tconst sidebarState = inject('sidebarState', null) ?? inject('objectSidebarState', null)\n\tconst objectStore = useObjectStore()\n\n\t// Token-resolution context for `@workspace.<key>` / `@config.<key>` /\n\t// `@objectId` / `@object.<field>` inside `props.filter` / quick-filter\n\t// tab filters. Same injects + unwrap shape as CnObjectListWidget's\n\t// `objectCtx`/`workspaceCtx`/`tokenCtx` computeds (and CnDeltaWidget) —\n\t// `cnWorkspaceContext` is the reactive bag a dashboard/workspace-root\n\t// (e.g. hrmq's App.vue for multi-administratie) provides; `cnObjectContext`\n\t// is a detail-page's object context (rare on an index page, but harmless\n\t// to support); `cnAppConfig` is the page-level app config bag. All three\n\t// default to null/absent so an app that never provides them is unaffected.\n\tconst objectCtxRaw = inject('cnObjectContext', null)\n\tconst workspaceCtxRaw = inject('cnWorkspaceContext', null)\n\tconst appConfigRaw = inject('cnAppConfig', null)\n\tconst unwrapCtx = (v) => ((v && typeof v === 'object' && 'value' in v) ? v.value : v)\n\n\t/**\n\t * Build the current token-resolution ctx `{ objectId?, object?, workspace, config }`\n\t * from the injected bags, unwrapping Vue refs. Called fresh on every fetch\n\t * so it always reflects the latest workspace/config state.\n\t *\n\t * @return {object} The token ctx.\n\t */\n\tfunction tokenCtx() {\n\t\tconst objCtx = unwrapCtx(objectCtxRaw)\n\t\tconst base = (objCtx && typeof objCtx === 'object') ? { ...objCtx } : {}\n\t\tbase.workspace = unwrapCtx(workspaceCtxRaw) || {}\n\t\t// The page's own `appConfig` prop wins over a config an ancestor provides.\n\t\tbase.config = { ...(unwrapCtx(appConfigRaw) || {}), ...(props.appConfig || {}) }\n\t\treturn base\n\t}\n\n\t// Reactive signature of the workspace/config bags so a change (e.g. the\n\t// administration switcher writing `activeAdministrationId`) triggers a\n\t// re-fetch below — `fixedFilters` is a plain getter called at fetch time\n\t// (see useListView.resolveFixedFilters), it is NOT auto-tracked by Vue,\n\t// so without this the list would resolve the token once on mount and\n\t// never again. Stringified (like CnDeltaWidget's `sourceKey`) so the\n\t// watcher fires on real content changes only, not object identity.\n\tconst workspaceSignature = computed(() => JSON.stringify(unwrapCtx(workspaceCtxRaw) || {}))\n\tconst appConfigSignature = computed(() => JSON.stringify({ ...(unwrapCtx(appConfigRaw) || {}), ...(props.appConfig || {}) }))\n\n\t// Pass register/schema in their positional id slots (not as a {register, schema} object as\n\t// second arg) — that previously made fetch URLs go to `/api/objects/undefined/[object Object]`.\n\t// Runs (sync, ahead of the list's own watcher) again whenever the type switches.\n\tfunction registerTarget() {\n\t\tconst { register, schema, type, collectionUrl } = resolvedTarget.value\n\t\tif (typeof objectStore.registerObjectType === 'function') {\n\t\t\tobjectStore.registerObjectType(type, schema, register, {\n\t\t\t\tregisterSlug: register,\n\t\t\t\tschemaSlug: schema,\n\t\t\t\t...(collectionUrl ? { collectionUrl } : {}),\n\t\t\t})\n\t\t}\n\t\t// A mixed list tells its own rows apart by `@self.register`, an id, so a slug register needs resolving.\n\t\tif (collectionUrl && !/^\\d+$/.test(String(register)) && typeof objectStore.fetchRegister === 'function') {\n\t\t\tobjectStore.fetchRegister(type)\n\t\t}\n\t}\n\tregisterTarget()\n\twatch(objectType, registerTarget, { flush: 'sync' })\n\n\t// Seed the visible-column set from the configured columns so the sidebar's\n\t// Columns tab reflects the curated default; null when none are configured\n\t// (schema-driven table — every column starts visible).\n\t// A column marked `hidden: true` is declared but starts outside the set,\n\t// so it is off until the person turns it on in the Columns tab.\n\tconst configuredColumnKeys = (props.columns || [])\n\t\t.filter((c) => !(c && typeof c === 'object' && c.hidden === true))\n\t\t.map((c) => (typeof c === 'string' ? c : c && c.key))\n\t\t.filter(Boolean)\n\n\t// Restore a persisted multi-column sort from the route query first (deep\n\t// link / reload); fall back to a host-passed `sortKeys` prop, then the\n\t// legacy single-key `sortKey`/`sortOrder` props.\n\tconst initialRoute = instance && instance.proxy && instance.proxy.$route\n\t// The page's own order, which a lens without a `sort` goes back to.\n\t// `defaultOrder` (manifest `config.defaultOrder`) is the order of last\n\t// resort, after `sortKeys` and `sortKey`.\n\tconst defaultOrderKeys = orderToSortKeys(props.defaultOrder)\n\tconst pageSortKeys = (Array.isArray(props.sortKeys) && props.sortKeys.length > 0)\n\t\t? props.sortKeys\n\t\t: (props.sortKey ? [{ key: props.sortKey, order: props.sortOrder || 'asc' }] : defaultOrderKeys)\n\t// The lens that is active on mount may set its own order.\n\tconst initialTabs = withPersonalLenses(props.quickFilters, props.personalLenses)\n\tconst initialTabSort = (!isMultiQuickFilter && Array.isArray(initialTabs))\n\t\t? quickFilterSortKeys(initialTabs[activeQuickFilterIndex.value])\n\t\t: null\n\tconst initialSortKeys = parseSortKeysFromQuery(initialRoute)\n\t\t|| initialTabSort\n\t\t|| (Array.isArray(props.sortKeys) && props.sortKeys.length > 0 ? props.sortKeys : undefined)\n\t\t|| (!props.sortKey && defaultOrderKeys.length > 0 ? defaultOrderKeys : undefined)\n\t// Same deep-link restore for facet filters and search, so opening a\n\t// shared/bookmarked URL reproduces the same view (CnIndexPage persists\n\t// both back to the route on change).\n\tconst initialActiveFilters = resolveQueryFilters(initialRoute && initialRoute.query, tokenCtx())\n\tconst initialSearchTerm = (initialRoute && typeof initialRoute.query?._search === 'string') ? initialRoute.query._search : ''\n\n\t// Set right after useListView returns; the fixed-filters getter reads it lazily.\n\tlet listHandle = null\n\tconst list = useListView(() => objectType.value, {\n\t\tobjectStore,\n\t\tsidebarState,\n\t\tdefaultSort: props.sortKey ? { key: props.sortKey, order: props.sortOrder || 'asc' } : undefined,\n\t\tdefaultSortKeys: initialSortKeys,\n\t\tdefaultActiveFilters: initialActiveFilters,\n\t\tdefaultSearchTerm: initialSearchTerm,\n\t\tdefaultPageSize: props.viewMode === 'board' ? BOARD_PAGE_SIZE : ((props.pagination && props.pagination.limit) || undefined),\n\t\tdefaultVisibleColumns: configuredColumnKeys.length ? configuredColumnKeys : null,\n\t\t// `pages[].config.extend` → OpenRegister's repeated `_extend[]`. A\n\t\t// getter so a reactive change re-scopes the next fetch, matching how\n\t\t// `fixedFilters` is read.\n\t\textend: () => (Array.isArray(props.extend) ? props.extend : []),\n\t\tfixedFilters: () => {\n\t\t\tconst route = instance && instance.proxy && instance.proxy.$route\n\t\t\tconst params = (route && route.params) || {}\n\t\t\tconst ctx = tokenCtx()\n\t\t\tconst queryFilters = resolveQueryFilters(route && route.query, ctx)\n\t\t\tconst base = resolveFilterMap(props.filter, params, ctx)\n\t\t\t// A folder-sidebar scope declaring `searchFields` narrows what the\n\t\t\t// search box searches over while that scope is active. Read off the\n\t\t\t// instance, like `$route` above, because the active scope is the\n\t\t\t// component's own state rather than a prop — and read through the\n\t\t\t// one fixed-filter getter rather than a second search path.\n\t\t\tconst scopeSearchFields = (instance && instance.proxy && instance.proxy.activeScopeSearchFields) || []\n\t\t\tconst scopeBase = scopeSearchFields.length > 0 ? { _searchFields: scopeSearchFields } : {}\n\t\t\t// File-content search widens a text search, so it rides only with a term.\n\t\t\tconst widen = props.searchInFiles === true && contentSearch.value && !!(listHandle && listHandle.searchTerm.value)\n\t\t\t// The visible calendar month, only while the page is in calendar mode.\n\t\t\tconst month = (instance && instance.proxy && instance.proxy.calendarRangeFilter) || {}\n\t\t\tconst scope = { ...(widen ? { ...scopeBase, _content_search: 'true' } : scopeBase), ...month }\n\t\t\tconst lensed = withPersonalLenses(props.quickFilters, props.personalLenses)\n\t\t\tconst tabs = Array.isArray(lensed) ? lensed : null\n\t\t\tif (!tabs) {\n\t\t\t\treturn { ...queryFilters, ...scope, ...base }\n\t\t\t}\n\n\t\t\t// Multiple mode: OR the selected tabs' filters together (union).\n\t\t\tif (isMultiQuickFilter) {\n\t\t\t\tconst maps = selectedQuickFilterIndices.value\n\t\t\t\t\t.map((i) => resolveFilterMap(tabs[i]?.filter, params, ctx))\n\t\t\t\treturn { ...queryFilters, ...scope, ...base, ...unionFilterMaps(maps) }\n\t\t\t}\n\n\t\t\t// Single mode: the active tab's filter spread last so it wins\n\t\t\t// over a colliding props.filter entry.\n\t\t\tconst activeIdx = activeQuickFilterIndex.value\n\t\t\tconst tabFilter = (activeIdx !== null && activeIdx !== undefined) ? tabs[activeIdx]?.filter : null\n\t\t\treturn { ...queryFilters, ...scope, ...base, ...resolveFilterMap(tabFilter, params, ctx) }\n\t\t},\n\t})\n\n\tlistHandle = list\n\n\t// Re-fetch when the quick-filter selection changes (pre-existing), OR\n\t// when the workspace/app-config bag content changes (e.g. the\n\t// administration switcher writes a new `activeAdministrationId`) — a\n\t// `@workspace.<key>`/`@config.<key>` token in `props.filter` must re-scope\n\t// the list without a manual reload. A change to `props.filter` itself (a\n\t// host toggling a filter checkbox) re-fetches the same way.\n\tconst filterSignature = computed(() => JSON.stringify(props.filter ?? null))\n\twatch([activeQuickFilterIndex, selectedQuickFilterIndices, contentSearch, workspaceSignature, appConfigSignature, filterSignature], (now, before) => {\n\t\t// Switching lens: a lens with a `sort` sets that order; leaving one\n\t\t// for a lens without goes back to the page's own order. A column the\n\t\t// person sorts by afterwards still wins until the next switch.\n\t\tif (!isMultiQuickFilter && before && now[0] !== before[0]) {\n\t\t\tconst tabs = withPersonalLenses(props.quickFilters, props.personalLenses) || []\n\t\t\tconst keys = quickFilterSortKeys(tabs[now[0]]) || (quickFilterSortKeys(tabs[before[0]]) ? pageSortKeys : null)\n\t\t\tif (keys && list.sortKeys) {\n\t\t\t\tlist.sortKeys.value = keys\n\t\t\t\tlist.sortKey.value = keys[0]?.key ?? null\n\t\t\t\tlist.sortOrder.value = keys[0]?.order ?? 'asc'\n\t\t\t}\n\t\t}\n\t\tif (list && typeof list.refresh === 'function') {\n\t\t\tlist.refresh(1)\n\t\t}\n\t})\n\n\t// Live collection updates (manifest-live-updates): subscribe to the\n\t// page's `or-collection-{register}-{schema}` scope so another user's\n\t// create/update/delete refreshes this list without a manual reload.\n\t// The subscription lifecycle (mount/unmount, in-flight dedupe, epoch\n\t// guard against stale async resolution) lives in useObjectSubscription;\n\t// the refetch-on-event (with the last fetch params, burst-coalesced)\n\t// lives in liveUpdatesPlugin. The `subscribe` prop (default true; from\n\t// a manifest: `config.subscribe: false`) is the opt-out, read through\n\t// a reactive getter so a runtime flip attaches/detaches accordingly.\n\t// Stores without live-updates support (no `subscribe` action) are a\n\t// silent no-op inside the composable, keeping this fully inert.\n\tuseObjectSubscription(objectStore, () => objectType.value, null, {\n\t\tenabled: () => props.subscribe !== false,\n\t})\n\n\treturn {\n\t\tisSelfFetch: true,\n\t\tlist,\n\t\tselfObjectStore: objectStore,\n\t\tselfObjectType: objectType,\n\t\tactiveQuickFilterIndex,\n\t\tselectedQuickFilterIndices,\n\t\tcontentSearch,\n\t\t// The page persists the view state back into the query, and needs both\n\t\t// to do it without trampling the rest of it: the keys it adopted from\n\t\t// the query on load (the only non-`_` ones it may clear), and the ctx\n\t\t// those keys' `@`-tokens resolve against.\n\t\tselfFetchTokenCtx: tokenCtx,\n\t\tinitialQueryFilterKeys: Object.keys(initialActiveFilters),\n\t}\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import script from './CnNoticeWidget.vue2.js';
|
|
2
|
+
import { render } from './CnNoticeWidget.vue3.js';
|
|
3
|
+
|
|
4
|
+
script.render = render;
|
|
5
|
+
script.__scopeId = "data-v-74287902";
|
|
6
|
+
const __sfc_main = script;
|
|
7
|
+
|
|
8
|
+
export { __sfc_main as default };
|
|
9
|
+
//# sourceMappingURL=CnNoticeWidget.vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnNoticeWidget.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import __sfc_main from '../CnIcon/CnIcon.vue.js';
|
|
2
|
+
|
|
3
|
+
/** The tones a notice takes, and the icon each shows by default. */
|
|
4
|
+
const VARIANT_ICONS = Object.freeze({
|
|
5
|
+
info: 'InformationOutline',
|
|
6
|
+
warning: 'AlertOutline',
|
|
7
|
+
error: 'AlertCircleOutline',
|
|
8
|
+
success: 'CheckCircleOutline',
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* CnNoticeWidget — a toned notice box: an icon, a bold title and a line of
|
|
13
|
+
* text in one rounded box, as the boards draw a warning beside a record
|
|
14
|
+
* (DqSociaalDomein "Bijzondere persoonsgegevens: gezondheid. Elke inzage
|
|
15
|
+
* wordt gelogd met het doel."). Usable in a detail page's side column, its
|
|
16
|
+
* body grid and on a dashboard as widget type `notice`; the surface applies
|
|
17
|
+
* the widget's `visibleWhen`.
|
|
18
|
+
*
|
|
19
|
+
* `content`: `{ variant?, title?, text, icon? }`. `variant` is `info`
|
|
20
|
+
* (default), `warning`, `error` or `success`; `title` and `text` go through
|
|
21
|
+
* the host's translate; `icon` names a CnIcon instead of the variant's own.
|
|
22
|
+
*
|
|
23
|
+
* ```vue
|
|
24
|
+
* <CnNoticeWidget :content="{ variant: 'warning', title: 'Special category data: health.', text: 'Every view is logged with its purpose.' }" />
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
var script = {
|
|
28
|
+
name: 'CnNoticeWidget',
|
|
29
|
+
|
|
30
|
+
components: { CnIcon: __sfc_main },
|
|
31
|
+
|
|
32
|
+
inject: {
|
|
33
|
+
/** The host app's translate function (CnAppRoot `cnTranslate`). */
|
|
34
|
+
cnTranslate: { default: () => (key) => key },
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
props: {
|
|
38
|
+
/**
|
|
39
|
+
* The notice: `{ variant?, title?, text, icon? }`.
|
|
40
|
+
*
|
|
41
|
+
* @type {{variant?: string, title?: string, text?: string, icon?: string}}
|
|
42
|
+
*/
|
|
43
|
+
content: {
|
|
44
|
+
type: Object,
|
|
45
|
+
default: () => ({}),
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
computed: {
|
|
50
|
+
/** @return {string} `info`, `warning`, `error` or `success`. */
|
|
51
|
+
resolvedVariant() {
|
|
52
|
+
const variant = this.content && this.content.variant === 'danger' ? 'error' : this.content && this.content.variant;
|
|
53
|
+
return Object.hasOwn(VARIANT_ICONS, variant) ? variant : 'info'
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
/** @return {string} The icon name. */
|
|
57
|
+
resolvedIcon() {
|
|
58
|
+
const icon = this.content && this.content.icon;
|
|
59
|
+
return typeof icon === 'string' && icon !== '' ? icon : VARIANT_ICONS[this.resolvedVariant]
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
/** @return {string} The title through the host translate. */
|
|
63
|
+
resolvedTitle() {
|
|
64
|
+
return this.translate(this.content && this.content.title)
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
/** @return {string} The text through the host translate. */
|
|
68
|
+
resolvedText() {
|
|
69
|
+
return this.translate(this.content && this.content.text)
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
methods: {
|
|
74
|
+
/**
|
|
75
|
+
* @param {unknown} text A manifest string.
|
|
76
|
+
* @return {string} Its translation, '' for anything but a non-empty string.
|
|
77
|
+
*/
|
|
78
|
+
translate(text) {
|
|
79
|
+
if (typeof text !== 'string' || text === '') {
|
|
80
|
+
return ''
|
|
81
|
+
}
|
|
82
|
+
return typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export { script as default };
|
|
88
|
+
//# sourceMappingURL=CnNoticeWidget.vue2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnNoticeWidget.vue2.js","sources":["../../../../src/components/CnNoticeWidget/CnNoticeWidget.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<section\n\t\tv-if=\"resolvedText || resolvedTitle\"\n\t\tclass=\"cn-notice-widget\"\n\t\t:class=\"`cn-notice-widget--${resolvedVariant}`\"\n\t\t:aria-label=\"resolvedTitle || null\"\n\t\trole=\"note\"\n\t\tdata-testid=\"cn-notice-widget\">\n\t\t<CnIcon\n\t\t\tclass=\"cn-notice-widget__icon\"\n\t\t\t:name=\"resolvedIcon\"\n\t\t\t:size=\"18\"\n\t\t\taria-hidden=\"true\" />\n\t\t<p class=\"cn-notice-widget__text\">\n\t\t\t<strong v-if=\"resolvedTitle\" class=\"cn-notice-widget__title\" data-testid=\"cn-notice-widget-title\">{{ resolvedTitle }}</strong>{{ resolvedTitle && resolvedText ? ' ' : '' }}{{ resolvedText }}\n\t\t</p>\n\t</section>\n</template>\n\n<script>\nimport { CnIcon } from '../CnIcon/index.js'\n\n/** The tones a notice takes, and the icon each shows by default. */\nconst VARIANT_ICONS = Object.freeze({\n\tinfo: 'InformationOutline',\n\twarning: 'AlertOutline',\n\terror: 'AlertCircleOutline',\n\tsuccess: 'CheckCircleOutline',\n})\n\n/**\n * CnNoticeWidget — a toned notice box: an icon, a bold title and a line of\n * text in one rounded box, as the boards draw a warning beside a record\n * (DqSociaalDomein \"Bijzondere persoonsgegevens: gezondheid. Elke inzage\n * wordt gelogd met het doel.\"). Usable in a detail page's side column, its\n * body grid and on a dashboard as widget type `notice`; the surface applies\n * the widget's `visibleWhen`.\n *\n * `content`: `{ variant?, title?, text, icon? }`. `variant` is `info`\n * (default), `warning`, `error` or `success`; `title` and `text` go through\n * the host's translate; `icon` names a CnIcon instead of the variant's own.\n *\n * ```vue\n * <CnNoticeWidget :content=\"{ variant: 'warning', title: 'Special category data: health.', text: 'Every view is logged with its purpose.' }\" />\n * ```\n */\nexport default {\n\tname: 'CnNoticeWidget',\n\n\tcomponents: { CnIcon },\n\n\tinject: {\n\t\t/** The host app's translate function (CnAppRoot `cnTranslate`). */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The notice: `{ variant?, title?, text, icon? }`.\n\t\t *\n\t\t * @type {{variant?: string, title?: string, text?: string, icon?: string}}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} `info`, `warning`, `error` or `success`. */\n\t\tresolvedVariant() {\n\t\t\tconst variant = this.content && this.content.variant === 'danger' ? 'error' : this.content && this.content.variant\n\t\t\treturn Object.hasOwn(VARIANT_ICONS, variant) ? variant : 'info'\n\t\t},\n\n\t\t/** @return {string} The icon name. */\n\t\tresolvedIcon() {\n\t\t\tconst icon = this.content && this.content.icon\n\t\t\treturn typeof icon === 'string' && icon !== '' ? icon : VARIANT_ICONS[this.resolvedVariant]\n\t\t},\n\n\t\t/** @return {string} The title through the host translate. */\n\t\tresolvedTitle() {\n\t\t\treturn this.translate(this.content && this.content.title)\n\t\t},\n\n\t\t/** @return {string} The text through the host translate. */\n\t\tresolvedText() {\n\t\t\treturn this.translate(this.content && this.content.text)\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * @param {unknown} text A manifest string.\n\t\t * @return {string} Its translation, '' for anything but a non-empty string.\n\t\t */\n\t\ttranslate(text) {\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-notice-widget {\n\tdisplay: flex;\n\talign-items: flex-start;\n\tgap: 10px;\n\tpadding: 14px 16px;\n\tborder-radius: var(--cn-board-card-radius, 12px);\n\tfont-size: 14px;\n\tline-height: 1.5;\n\tbackground: color-mix(in srgb, var(--color-info, #0071ad) 10%, var(--color-main-background));\n\tcolor: var(--color-main-text);\n}\n\n.cn-notice-widget--warning {\n\tbackground: var(--color-warning-light, #fff4de);\n\tcolor: var(--color-warning-text, #7a4f00);\n}\n\n.cn-notice-widget--error {\n\tbackground: color-mix(in srgb, var(--color-error, #db0606) 10%, var(--color-main-background));\n\tcolor: var(--color-error-text, var(--color-main-text));\n}\n\n.cn-notice-widget--success {\n\tbackground: color-mix(in srgb, var(--color-success, #2d7b41) 10%, var(--color-main-background));\n\tcolor: var(--color-success-text, var(--color-main-text));\n}\n\n.cn-notice-widget__icon {\n\tflex: 0 0 auto;\n\tmargin-top: 2px;\n}\n\n.cn-notice-widget__text {\n\tmargin: 0;\n\toverflow-wrap: anywhere;\n}\n\n.cn-notice-widget__title {\n\tfont-weight: 700;\n}\n</style>\n"],"names":["CnIcon"],"mappings":";;AA0BA;AACA,MAAM,aAAY,GAAI,MAAM,CAAC,MAAM,CAAC;CACnC,IAAI,EAAE,oBAAoB;CAC1B,OAAO,EAAE,cAAc;CACvB,KAAK,EAAE,oBAAoB;CAC3B,OAAO,EAAE,oBAAoB;AAC9B,CAAC,EAAA;;AAED;;;AAGC;;;;AAIA;;AAEA;AACA;AACA;AACA;;AAEA;;AAED,aAAe;AACd,CAAA,IAAI,EAAE,gBAAgB;;AAEtB,CAAA,UAAU,EAAE,UAAEA,YAAQ;;AAEtB,CAAA,MAAM,EAAE;;AAEP,EAAA,WAAW,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,KAAK,KAAK;EAC5C;;AAED,CAAA,KAAK,EAAE;AACN;AACC;AACA;AACA;;AAED,EAAA,OAAO,EAAE;GACR,IAAI,EAAE,MAAM;AACZ,GAAA,OAAO,EAAE,OAAO,EAAE,CAAC;GACnB;EACD;;AAED,CAAA,QAAQ,EAAE;;AAET,EAAA,eAAe,GAAG;GACjB,MAAM,UAAU,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,OAAQ,KAAI,QAAS,GAAE,UAAU,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,QAAM;GACjH,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,OAAO,CAAA,GAAI,OAAQ,GAAE,MAAK;GAC9D;;AAED;AACA,EAAA,YAAY,GAAG;AACd,GAAA,MAAM,IAAG,GAAI,IAAI,CAAC,OAAM,IAAK,IAAI,CAAC,OAAO,CAAC,KAAG;AAC7C,GAAA,OAAO,OAAO,IAAG,KAAM,YAAY,IAAK,KAAI,EAAG,GAAE,IAAK,GAAE,aAAa,CAAC,IAAI,CAAC,eAAe,CAAA;GAC1F;;;AAGD,EAAA,aAAa,GAAG;GACf,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAM,IAAK,IAAI,CAAC,OAAO,CAAC,KAAK,CAAA;GACxD;;;AAGD,EAAA,YAAY,GAAG;GACd,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,CAAC,IAAI,CAAA;GACvD;EACD;;AAED,CAAA,OAAO,EAAE;AACR;AACC;AACA;;AAED,EAAA,SAAS,CAAC,IAAI,EAAE;AACf,GAAA,IAAI,OAAO,IAAG,KAAM,QAAO,IAAK,SAAS,EAAE,EAAE;AAC5C,IAAA,OAAO,EAAC;AACT,IAAA;AACA,GAAA,OAAO,OAAO,IAAI,CAAC,WAAY,KAAI,UAAW,GAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAA,GAAI,IAAG;GAC5E;EACD;AACF;;;;"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { resolveComponent, openBlock, createElementBlock, normalizeClass, createVNode, createElementVNode, toDisplayString, createCommentVNode, createTextVNode } from 'vue';
|
|
2
|
+
|
|
3
|
+
const _hoisted_1 = ["aria-label"];
|
|
4
|
+
const _hoisted_2 = { class: "cn-notice-widget__text" };
|
|
5
|
+
const _hoisted_3 = {
|
|
6
|
+
key: 0,
|
|
7
|
+
class: "cn-notice-widget__title",
|
|
8
|
+
"data-testid": "cn-notice-widget-title"
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
12
|
+
const _component_CnIcon = resolveComponent("CnIcon");
|
|
13
|
+
|
|
14
|
+
return ($options.resolvedText || $options.resolvedTitle)
|
|
15
|
+
? (openBlock(), createElementBlock("section", {
|
|
16
|
+
key: 0,
|
|
17
|
+
class: normalizeClass(["cn-notice-widget", `cn-notice-widget--${$options.resolvedVariant}`]),
|
|
18
|
+
"aria-label": $options.resolvedTitle || null,
|
|
19
|
+
role: "note",
|
|
20
|
+
"data-testid": "cn-notice-widget"
|
|
21
|
+
}, [
|
|
22
|
+
createVNode(_component_CnIcon, {
|
|
23
|
+
class: "cn-notice-widget__icon",
|
|
24
|
+
name: $options.resolvedIcon,
|
|
25
|
+
size: 18,
|
|
26
|
+
"aria-hidden": "true"
|
|
27
|
+
}, null, 8 /* PROPS */, ["name"]),
|
|
28
|
+
createElementVNode("p", _hoisted_2, [
|
|
29
|
+
($options.resolvedTitle)
|
|
30
|
+
? (openBlock(), createElementBlock("strong", _hoisted_3, toDisplayString($options.resolvedTitle), 1 /* TEXT */))
|
|
31
|
+
: createCommentVNode("v-if", true),
|
|
32
|
+
createTextVNode(toDisplayString($options.resolvedTitle && $options.resolvedText ? ' ' : '') + toDisplayString($options.resolvedText), 1 /* TEXT */)
|
|
33
|
+
])
|
|
34
|
+
], 10 /* CLASS, PROPS */, _hoisted_1))
|
|
35
|
+
: createCommentVNode("v-if", true)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { render };
|
|
39
|
+
//# sourceMappingURL=CnNoticeWidget.vue3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnNoticeWidget.vue3.js","sources":["../../../../src/components/CnNoticeWidget/CnNoticeWidget.vue?vue&type=template&id=74287902&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<section\n\t\tv-if=\"resolvedText || resolvedTitle\"\n\t\tclass=\"cn-notice-widget\"\n\t\t:class=\"`cn-notice-widget--${resolvedVariant}`\"\n\t\t:aria-label=\"resolvedTitle || null\"\n\t\trole=\"note\"\n\t\tdata-testid=\"cn-notice-widget\">\n\t\t<CnIcon\n\t\t\tclass=\"cn-notice-widget__icon\"\n\t\t\t:name=\"resolvedIcon\"\n\t\t\t:size=\"18\"\n\t\t\taria-hidden=\"true\" />\n\t\t<p class=\"cn-notice-widget__text\">\n\t\t\t<strong v-if=\"resolvedTitle\" class=\"cn-notice-widget__title\" data-testid=\"cn-notice-widget-title\">{{ resolvedTitle }}</strong>{{ resolvedTitle && resolvedText ? ' ' : '' }}{{ resolvedText }}\n\t\t</p>\n\t</section>\n</template>\n\n<script>\nimport { CnIcon } from '../CnIcon/index.js'\n\n/** The tones a notice takes, and the icon each shows by default. */\nconst VARIANT_ICONS = Object.freeze({\n\tinfo: 'InformationOutline',\n\twarning: 'AlertOutline',\n\terror: 'AlertCircleOutline',\n\tsuccess: 'CheckCircleOutline',\n})\n\n/**\n * CnNoticeWidget — a toned notice box: an icon, a bold title and a line of\n * text in one rounded box, as the boards draw a warning beside a record\n * (DqSociaalDomein \"Bijzondere persoonsgegevens: gezondheid. Elke inzage\n * wordt gelogd met het doel.\"). Usable in a detail page's side column, its\n * body grid and on a dashboard as widget type `notice`; the surface applies\n * the widget's `visibleWhen`.\n *\n * `content`: `{ variant?, title?, text, icon? }`. `variant` is `info`\n * (default), `warning`, `error` or `success`; `title` and `text` go through\n * the host's translate; `icon` names a CnIcon instead of the variant's own.\n *\n * ```vue\n * <CnNoticeWidget :content=\"{ variant: 'warning', title: 'Special category data: health.', text: 'Every view is logged with its purpose.' }\" />\n * ```\n */\nexport default {\n\tname: 'CnNoticeWidget',\n\n\tcomponents: { CnIcon },\n\n\tinject: {\n\t\t/** The host app's translate function (CnAppRoot `cnTranslate`). */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The notice: `{ variant?, title?, text, icon? }`.\n\t\t *\n\t\t * @type {{variant?: string, title?: string, text?: string, icon?: string}}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} `info`, `warning`, `error` or `success`. */\n\t\tresolvedVariant() {\n\t\t\tconst variant = this.content && this.content.variant === 'danger' ? 'error' : this.content && this.content.variant\n\t\t\treturn Object.hasOwn(VARIANT_ICONS, variant) ? variant : 'info'\n\t\t},\n\n\t\t/** @return {string} The icon name. */\n\t\tresolvedIcon() {\n\t\t\tconst icon = this.content && this.content.icon\n\t\t\treturn typeof icon === 'string' && icon !== '' ? icon : VARIANT_ICONS[this.resolvedVariant]\n\t\t},\n\n\t\t/** @return {string} The title through the host translate. */\n\t\tresolvedTitle() {\n\t\t\treturn this.translate(this.content && this.content.title)\n\t\t},\n\n\t\t/** @return {string} The text through the host translate. */\n\t\tresolvedText() {\n\t\t\treturn this.translate(this.content && this.content.text)\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * @param {unknown} text A manifest string.\n\t\t * @return {string} Its translation, '' for anything but a non-empty string.\n\t\t */\n\t\ttranslate(text) {\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-notice-widget {\n\tdisplay: flex;\n\talign-items: flex-start;\n\tgap: 10px;\n\tpadding: 14px 16px;\n\tborder-radius: var(--cn-board-card-radius, 12px);\n\tfont-size: 14px;\n\tline-height: 1.5;\n\tbackground: color-mix(in srgb, var(--color-info, #0071ad) 10%, var(--color-main-background));\n\tcolor: var(--color-main-text);\n}\n\n.cn-notice-widget--warning {\n\tbackground: var(--color-warning-light, #fff4de);\n\tcolor: var(--color-warning-text, #7a4f00);\n}\n\n.cn-notice-widget--error {\n\tbackground: color-mix(in srgb, var(--color-error, #db0606) 10%, var(--color-main-background));\n\tcolor: var(--color-error-text, var(--color-main-text));\n}\n\n.cn-notice-widget--success {\n\tbackground: color-mix(in srgb, var(--color-success, #2d7b41) 10%, var(--color-main-background));\n\tcolor: var(--color-success-text, var(--color-main-text));\n}\n\n.cn-notice-widget__icon {\n\tflex: 0 0 auto;\n\tmargin-top: 2px;\n}\n\n.cn-notice-widget__text {\n\tmargin: 0;\n\toverflow-wrap: anywhere;\n}\n\n.cn-notice-widget__title {\n\tfont-weight: 700;\n}\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_createVNode"],"mappings":";;;;;;;;;;;;;AAUQ,EAAA,OAAA,CAAA,QAAA,CAAA,YAAI,IAAA,QAAA,CAAA,aAAA;oBADVA;;QAEA,KAAK,EAAAC,cAAA,CAAA,CAAC,kBAAkB,EAAA,CAAA,kBAAA,EAClB,QAAA,CAAA,eAAA,CAAA,CAAA,CAAA,CAAA;AACL,QAAA,YAAU,EAAE,QAAa,CAAA,aAAA,IAAA,IAAA;AACzB,QAAA,IAAG,EAAC,MAAM;AACV,QAAA,aAAS,EAAA,kBAAA;;QACTC,WAIO,CAAA,iBAAA,EAAA;AAHP,UAAA,KAAK,EAAC,wBAAwB;AAC7B,UAAA,IAAI,UAAc,CAAA,YAAA;AAClB,UAAA,IAAC,EAAA,EAAA;AACF,UAAA,aAAO,EAAA,MAAA;;;;;;;;;;;;;;"}
|
|
@@ -2,7 +2,7 @@ import script from './CnObjectRow.vue2.js';
|
|
|
2
2
|
import { render } from './CnObjectRow.vue3.js';
|
|
3
3
|
|
|
4
4
|
script.render = render;
|
|
5
|
-
script.__scopeId = "data-v-
|
|
5
|
+
script.__scopeId = "data-v-6e2b35c2";
|
|
6
6
|
const __sfc_main = script;
|
|
7
7
|
|
|
8
8
|
export { __sfc_main as default };
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { NcCheckboxRadioSwitch } from '@nextcloud/vue';
|
|
2
2
|
import { useClickDragGuard } from '../../composables/useClickDragGuard.js';
|
|
3
|
+
import { joinTemplateParts } from '../../utils/fillTemplate.js';
|
|
4
|
+
import { readPath } from '../../utils/readPath.js';
|
|
3
5
|
import { resolveImageUrl } from '../../utils/resolveImageUrl.js';
|
|
4
6
|
import { preventMiddleClickAutoscroll, isRowMiddleClick } from '../../utils/rowAuxClick.js';
|
|
5
|
-
import __sfc_main from '../
|
|
6
|
-
import __sfc_main$1 from '../
|
|
7
|
+
import __sfc_main from '../CnCellRenderer/CnCellRenderer.vue.js';
|
|
8
|
+
import __sfc_main$1 from '../CnIcon/CnIcon.vue.js';
|
|
9
|
+
import __sfc_main$2 from '../CnStatusBadge/CnStatusBadge.vue.js';
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* CnObjectRow — Compact single-line list row for object display.
|
|
@@ -31,8 +34,9 @@ var script = {
|
|
|
31
34
|
|
|
32
35
|
components: {
|
|
33
36
|
NcCheckboxRadioSwitch,
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
CnCellRenderer: __sfc_main,
|
|
38
|
+
CnIcon: __sfc_main$1,
|
|
39
|
+
CnStatusBadge: __sfc_main$2,
|
|
36
40
|
},
|
|
37
41
|
|
|
38
42
|
props: {
|
|
@@ -52,7 +56,15 @@ var script = {
|
|
|
52
56
|
* Explicit field mapping. Every key is optional and overrides the
|
|
53
57
|
* schema-configuration default.
|
|
54
58
|
*
|
|
55
|
-
*
|
|
59
|
+
* `subtitleTemplate` fills `{field}` tokens from the row (empty parts and
|
|
60
|
+
* their separators drop). `leading` (one cell) and `trailing` (a cell or
|
|
61
|
+
* a list) draw cells as a table column does, `{ key, widget?,
|
|
62
|
+
* widgetProps?, formatter? }`: `{ key: "createdAt", widget: "age" }`
|
|
63
|
+
* reads "6 dagen", `{ key: "deadline", widget: "date", widgetProps: {
|
|
64
|
+
* due: {} } }` the due text. A cell's `width` (CSS) lines the column
|
|
65
|
+
* up across rows.
|
|
66
|
+
*
|
|
67
|
+
* @type {{ titleField?: string, subtitleField?: string, subtitleTemplate?: string, imageField?: string, iconField?: string, iconName?: string, badgeField?: string, badgeVariantField?: string, badgeVariant?: string, badgeColorMap?: object, leading?: object, trailing?: (object|Array<object>) }}
|
|
56
68
|
*/
|
|
57
69
|
config: {
|
|
58
70
|
type: Object,
|
|
@@ -101,6 +113,13 @@ var script = {
|
|
|
101
113
|
},
|
|
102
114
|
|
|
103
115
|
subtitle() {
|
|
116
|
+
if (typeof this.config.subtitleTemplate === 'string' && this.config.subtitleTemplate !== '') {
|
|
117
|
+
const text = joinTemplateParts(this.config.subtitleTemplate, (key) => {
|
|
118
|
+
const value = readPath(this.object, key);
|
|
119
|
+
return value === null || value === undefined ? '' : String(value)
|
|
120
|
+
});
|
|
121
|
+
return text.trim() || null
|
|
122
|
+
}
|
|
104
123
|
const field = this.config.subtitleField || this.schemaConfig.objectDescriptionField;
|
|
105
124
|
if (field && this.object[field] !== null && this.object[field] !== undefined && this.object[field] !== '') {
|
|
106
125
|
return String(this.object[field])
|
|
@@ -148,9 +167,42 @@ var script = {
|
|
|
148
167
|
badgeColorMap() {
|
|
149
168
|
return this.config.badgeColorMap || null
|
|
150
169
|
},
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* The `config.leading` cell, or null.
|
|
173
|
+
*
|
|
174
|
+
* @spec openspec/changes/index-row-list-cells/specs/object-row/spec.md#requirement-a-list-row-can-carry-leading-and-trailing-cells
|
|
175
|
+
* @return {object|null}
|
|
176
|
+
*/
|
|
177
|
+
leadingCell() {
|
|
178
|
+
const cell = this.config.leading;
|
|
179
|
+
return cell && typeof cell === 'object' && typeof cell.key === 'string' && cell.key !== '' ? cell : null
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* The `config.trailing` cells (one object or a list), those with a key.
|
|
184
|
+
*
|
|
185
|
+
* @spec openspec/changes/index-row-list-cells/specs/object-row/spec.md#requirement-a-list-row-can-carry-leading-and-trailing-cells
|
|
186
|
+
* @return {Array<object>}
|
|
187
|
+
*/
|
|
188
|
+
trailingCells() {
|
|
189
|
+
const cells = this.config.trailing;
|
|
190
|
+
const list = Array.isArray(cells) ? cells : (cells && typeof cells === 'object' ? [cells] : []);
|
|
191
|
+
return list.filter((cell) => cell && typeof cell === 'object' && typeof cell.key === 'string' && cell.key !== '')
|
|
192
|
+
},
|
|
151
193
|
},
|
|
152
194
|
|
|
153
195
|
methods: {
|
|
196
|
+
/**
|
|
197
|
+
* A cell's value: the dot-path `key` read off the row.
|
|
198
|
+
*
|
|
199
|
+
* @param {{key: string}} cell The cell.
|
|
200
|
+
* @return {unknown} The value.
|
|
201
|
+
*/
|
|
202
|
+
cellValue(cell) {
|
|
203
|
+
return readPath(this.object, cell.key)
|
|
204
|
+
},
|
|
205
|
+
|
|
154
206
|
/**
|
|
155
207
|
* Row-body click: emits `select` when `selectable` (ignoring drags),
|
|
156
208
|
* otherwise emits `click` for navigation.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnObjectRow.vue2.js","sources":["../../../../src/components/CnObjectRow/CnObjectRow.vue"],"sourcesContent":["<template>\n\t<div\n\t\tclass=\"cn-object-row\"\n\t\t:class=\"{ 'cn-object-row--selected': selected }\"\n\t\t@mousedown=\"onRowMouseDown\"\n\t\t@click=\"onRowClick($event)\"\n\t\t@auxclick=\"onRowAuxClick($event)\">\n\t\t<!-- Selection checkbox -->\n\t\t<div v-if=\"selectable\"\n\t\t\tclass=\"cn-object-row__checkbox\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t:modelValue=\"selected\"\n\t\t\t\t@update:modelValue=\"$emit('select', object)\" />\n\t\t</div>\n\n\t\t<!-- Leading icon / image — omitted entirely when nothing is configured\n\t\t (no image, no icon name, no slot). -->\n\t\t<span v-if=\"hasLeadingIcon\" class=\"cn-object-row__icon\">\n\t\t\t<!-- @slot icon Replace the leading icon/image. -->\n\t\t\t<!-- @binding {object} object The row's object. -->\n\t\t\t<slot name=\"icon\" :object=\"object\">\n\t\t\t\t<img\n\t\t\t\t\tv-if=\"imageUrl\"\n\t\t\t\t\t:src=\"imageUrl\"\n\t\t\t\t\talt=\"\"\n\t\t\t\t\twidth=\"24\"\n\t\t\t\t\theight=\"24\"\n\t\t\t\t\tclass=\"cn-object-row__image\">\n\t\t\t\t<CnIcon v-else-if=\"iconName\" :name=\"iconName\" :size=\"24\" />\n\t\t\t</slot>\n\t\t</span>\n\n\t\t<!-- Main: title + subtitle -->\n\t\t<span class=\"cn-object-row__main\">\n\t\t\t<span class=\"cn-object-row__title\">{{ title }}</span>\n\t\t\t<span v-if=\"subtitle\" class=\"cn-object-row__subtitle\">{{ subtitle }}</span>\n\t\t</span>\n\n\t\t<!-- Badges (default: config-driven status badge) -->\n\t\t<span v-if=\"$slots.badges || badgeLabel\" class=\"cn-object-row__badges\">\n\t\t\t<!-- @slot badges Replace the badge area (overrides the config-driven badge). -->\n\t\t\t<!-- @binding {object} object The row's object. -->\n\t\t\t<slot name=\"badges\" :object=\"object\">\n\t\t\t\t<CnStatusBadge\n\t\t\t\t\tv-if=\"badgeLabel\"\n\t\t\t\t\t:label=\"badgeLabel\"\n\t\t\t\t\t:variant=\"badgeVariant\"\n\t\t\t\t\t:colorMap=\"badgeColorMap\"\n\t\t\t\t\tsize=\"small\" />\n\t\t\t</slot>\n\t\t</span>\n\n\t\t<!-- Trailing actions -->\n\t\t<span v-if=\"$slots.actions\"\n\t\t\tclass=\"cn-object-row__actions\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<!-- @slot actions Trailing actions (copy button, menu, …). -->\n\t\t\t<!-- @binding {object} object The row's object. -->\n\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t</span>\n\t</div>\n</template>\n\n<script>\nimport { NcCheckboxRadioSwitch } from '@nextcloud/vue'\nimport { useClickDragGuard } from '../../composables/useClickDragGuard.js'\nimport { resolveImageUrl } from '../../utils/resolveImageUrl.js'\nimport { isRowMiddleClick, preventMiddleClickAutoscroll } from '../../utils/rowAuxClick.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnStatusBadge } from '../CnStatusBadge/index.js'\n\n/**\n * CnObjectRow — Compact single-line list row for object display.\n *\n * The list-mode counterpart to `CnObjectCard`: a leading icon (or image), a\n * name with an optional subtitle, an optional status badge, and a trailing\n * actions area. Which object fields map to each slot is resolved from the\n * `config` prop first, then from `schema.configuration` (so a schema that\n * already declares `objectNameField` / `objectDescriptionField` / `objectImageField`\n * works with zero extra config).\n *\n * ```vue\n * <CnObjectRow\n * :object=\"secret\"\n * :schema=\"secretSchema\"\n * :config=\"{ subtitleField: 'url', iconName: 'Key' }\">\n * <template #actions=\"{ object }\">\n * <NcButton @click=\"copy(object)\">Copy</NcButton>\n * </template>\n * </CnObjectRow>\n * ```\n */\nexport default {\n\tname: 'CnObjectRow',\n\n\tcomponents: {\n\t\tNcCheckboxRadioSwitch,\n\t\tCnIcon,\n\t\tCnStatusBadge,\n\t},\n\n\tprops: {\n\t\t/** The object data */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Schema definition; `schema.configuration` supplies field defaults */\n\t\tschema: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Explicit field mapping. Every key is optional and overrides the\n\t\t * schema-configuration default.\n\t\t *\n\t\t * @type {{ titleField?: string, subtitleField?: string, imageField?: string, iconField?: string, iconName?: string, badgeField?: string, badgeVariantField?: string, badgeVariant?: string, badgeColorMap?: object }}\n\t\t */\n\t\tconfig: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** Whether this row is selected */\n\t\tselected: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether to show the selection checkbox */\n\t\tselectable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\n\t// Vue 2 had a separate listener channel, so a consumer's `@click` only ever\n\t// saw `$emit('click')`. In Vue 3 an UNDECLARED event name stays a\n\t// fallthrough attribute: `onClick` lands on the root `<div>` as a native\n\t// handler, so the consumer's handler fires once from the DOM click and\n\t// again from `$emit('click', object)` — twice per click, with different\n\t// payloads. Declaring the names here removes them from `$attrs`, which is\n\t// also what stops VTU v2 recording the native DOM event into `emitted()`.\n\temits: ['select', 'click', 'aux-click'],\n\n\tsetup() {\n\t\t// Tell a deliberate row click apart from a text-selection drag.\n\t\treturn useClickDragGuard()\n\t},\n\n\tcomputed: {\n\t\t/** Schema-level configuration block (empty when no schema). */\n\t\tschemaConfig() {\n\t\t\treturn this.schema?.configuration || {}\n\t\t},\n\n\t\ttitle() {\n\t\t\tconst field = this.config.titleField || this.schemaConfig.objectNameField\n\t\t\tif (field && this.object[field] !== null && this.object[field] !== undefined) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn this.object.title || this.object.name || this.object.id || '—'\n\t\t},\n\n\t\tsubtitle() {\n\t\t\tconst field = this.config.subtitleField || this.schemaConfig.objectDescriptionField\n\t\t\tif (field && this.object[field] !== null && this.object[field] !== undefined && this.object[field] !== '') {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\timageUrl() {\n\t\t\tconst field = this.config.imageField || this.schemaConfig.objectImageField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn resolveImageUrl(String(this.object[field]))\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\ticonName() {\n\t\t\tconst field = this.config.iconField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn this.config.iconName || ''\n\t\t},\n\n\t\t/** Whether to render the leading icon column at all. */\n\t\thasLeadingIcon() {\n\t\t\treturn Boolean(this.imageUrl || this.iconName || this.$slots.icon)\n\t\t},\n\n\t\tbadgeLabel() {\n\t\t\tconst field = this.config.badgeField\n\t\t\tif (field && this.object[field] !== null && this.object[field] !== undefined && this.object[field] !== '') {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\tbadgeVariant() {\n\t\t\tconst field = this.config.badgeVariantField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn this.config.badgeVariant || 'default'\n\t\t},\n\n\t\tbadgeColorMap() {\n\t\t\treturn this.config.badgeColorMap || null\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Row-body click: emits `select` when `selectable` (ignoring drags),\n\t\t * otherwise emits `click` for navigation.\n\t\t *\n\t\t * @param {MouseEvent} [event] The originating click event.\n\t\t */\n\t\tonRowClick(event) {\n\t\t\tif (this.selectable) {\n\t\t\t\tif (this.wasDrag(event)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * @event select Emitted when a selectable row toggles selection (body or checkbox click).\n\t\t\t\t * @type {object} The row's object.\n\t\t\t\t */\n\t\t\t\tthis.$emit('select', this.object)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event click Emitted when a non-selectable row is clicked (navigation). Payload: `(object, event)` — the row's object and the native click event, for opening it in a new tab on a ctrl/cmd/shift click. A middle click emits `aux-click` instead.\n\t\t\t * @type {object} The row's object.\n\t\t\t */\n\t\t\tthis.$emit('click', this.object, event)\n\t\t},\n\n\t\t/**\n\t\t * Row mousedown: record the press for the drag guard, and on a\n\t\t * non-selectable row keep a middle press from starting autoscroll.\n\t\t *\n\t\t * @param {MouseEvent} event The mousedown event.\n\t\t */\n\t\tonRowMouseDown(event) {\n\t\t\tthis.onPointerDown(event)\n\t\t\tif (!this.selectable) {\n\t\t\t\tpreventMiddleClickAutoscroll(event)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Row-body middle click on a non-selectable row: emits `aux-click`, not\n\t\t * `click`, so an existing `click` listener that navigates never moves\n\t\t * the current tab away.\n\t\t *\n\t\t * @param {MouseEvent} event The auxclick event.\n\t\t */\n\t\tonRowAuxClick(event) {\n\t\t\tif (this.selectable || !isRowMiddleClick(event)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event aux-click Emitted when a non-selectable row is middle-clicked, for opening it in a new tab (see `openRowTarget`). Payload: `(object, event)` — the row's object and the native auxclick event.\n\t\t\t * @type {object} The row's object.\n\t\t\t */\n\t\t\tthis.$emit('aux-click', this.object, event)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-object-row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 12px;\n\tpadding: 8px 12px;\n\tborder-bottom: 1px solid var(--color-border);\n\tcursor: pointer;\n}\n\n.cn-object-row:hover {\n\tbackground-color: var(--color-background-hover);\n}\n\n.cn-object-row--selected {\n\t/* Inset accent — never border-left (would shift cell content). */\n\tbox-shadow: inset 3px 0 0 0 var(--color-primary-element);\n\tbackground-color: var(--color-primary-element-light);\n}\n\n.cn-object-row__checkbox {\n\tflex-shrink: 0;\n}\n\n.cn-object-row__icon {\n\tflex-shrink: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 24px;\n\theight: 24px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-object-row__image {\n\twidth: 24px;\n\theight: 24px;\n\tobject-fit: contain;\n\tborder-radius: var(--border-radius);\n}\n\n.cn-object-row__main {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 0;\n\tflex: 1;\n}\n\n.cn-object-row__title {\n\tfont-weight: 600;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-object-row__subtitle {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-object-row__badges {\n\tflex-shrink: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n}\n\n.cn-object-row__actions {\n\tflex-shrink: 0;\n\tdisplay: flex;\n\talign-items: center;\n}\n</style>\n"],"names":["CnIcon","CnStatusBadge"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnObjectRow.vue2.js","sources":["../../../../src/components/CnObjectRow/CnObjectRow.vue"],"sourcesContent":["<template>\n\t<div\n\t\tclass=\"cn-object-row\"\n\t\t:class=\"{ 'cn-object-row--selected': selected }\"\n\t\t@mousedown=\"onRowMouseDown\"\n\t\t@click=\"onRowClick($event)\"\n\t\t@auxclick=\"onRowAuxClick($event)\">\n\t\t<!-- Selection checkbox -->\n\t\t<div v-if=\"selectable\"\n\t\t\tclass=\"cn-object-row__checkbox\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t:modelValue=\"selected\"\n\t\t\t\t@update:modelValue=\"$emit('select', object)\" />\n\t\t</div>\n\n\t\t<!-- `config.leading`: one cell before the title, as a table cell renders\n\t\t it (`{ key, widget?, widgetProps?, formatter? }`), e.g. the age\n\t\t \"6 dagen\" in the team queue. -->\n\t\t<span\n\t\t\tv-if=\"leadingCell\"\n\t\t\tclass=\"cn-object-row__lead\"\n\t\t\t:style=\"leadingCell.width ? { width: leadingCell.width } : null\"\n\t\t\tdata-testid=\"cn-object-row-lead\">\n\t\t\t<CnCellRenderer\n\t\t\t\t:value=\"cellValue(leadingCell)\"\n\t\t\t\t:formatter=\"leadingCell.formatter || null\"\n\t\t\t\t:widget=\"leadingCell.widget || null\"\n\t\t\t\t:widgetProps=\"leadingCell.widgetProps || undefined\"\n\t\t\t\t:row=\"object\" />\n\t\t</span>\n\n\t\t<!-- Leading icon / image — omitted entirely when nothing is configured\n\t\t (no image, no icon name, no slot). -->\n\t\t<span v-if=\"hasLeadingIcon\" class=\"cn-object-row__icon\">\n\t\t\t<!-- @slot icon Replace the leading icon/image. -->\n\t\t\t<!-- @binding {object} object The row's object. -->\n\t\t\t<slot name=\"icon\" :object=\"object\">\n\t\t\t\t<img\n\t\t\t\t\tv-if=\"imageUrl\"\n\t\t\t\t\t:src=\"imageUrl\"\n\t\t\t\t\talt=\"\"\n\t\t\t\t\twidth=\"24\"\n\t\t\t\t\theight=\"24\"\n\t\t\t\t\tclass=\"cn-object-row__image\">\n\t\t\t\t<CnIcon v-else-if=\"iconName\" :name=\"iconName\" :size=\"24\" />\n\t\t\t</slot>\n\t\t</span>\n\n\t\t<!-- Main: title + subtitle -->\n\t\t<span class=\"cn-object-row__main\">\n\t\t\t<span class=\"cn-object-row__title\">{{ title }}</span>\n\t\t\t<span v-if=\"subtitle\" class=\"cn-object-row__subtitle\">{{ subtitle }}</span>\n\t\t</span>\n\n\t\t<!-- Badges (default: config-driven status badge) -->\n\t\t<span v-if=\"$slots.badges || badgeLabel\" class=\"cn-object-row__badges\">\n\t\t\t<!-- @slot badges Replace the badge area (overrides the config-driven badge). -->\n\t\t\t<!-- @binding {object} object The row's object. -->\n\t\t\t<slot name=\"badges\" :object=\"object\">\n\t\t\t\t<CnStatusBadge\n\t\t\t\t\tv-if=\"badgeLabel\"\n\t\t\t\t\t:label=\"badgeLabel\"\n\t\t\t\t\t:variant=\"badgeVariant\"\n\t\t\t\t\t:colorMap=\"badgeColorMap\"\n\t\t\t\t\tsize=\"small\" />\n\t\t\t</slot>\n\t\t</span>\n\n\t\t<!-- `config.trailing`: cells after the badges, each in its own column\n\t\t (the case type badge, the due text). -->\n\t\t<span\n\t\t\tv-for=\"(cell, index) in trailingCells\"\n\t\t\t:key=\"cell.key + '-' + index\"\n\t\t\tclass=\"cn-object-row__trail\"\n\t\t\t:style=\"cell.width ? { width: cell.width } : null\"\n\t\t\tdata-testid=\"cn-object-row-trail\">\n\t\t\t<CnCellRenderer\n\t\t\t\t:value=\"cellValue(cell)\"\n\t\t\t\t:formatter=\"cell.formatter || null\"\n\t\t\t\t:widget=\"cell.widget || null\"\n\t\t\t\t:widgetProps=\"cell.widgetProps || undefined\"\n\t\t\t\t:row=\"object\" />\n\t\t</span>\n\n\t\t<!-- Trailing actions -->\n\t\t<span v-if=\"$slots.actions\"\n\t\t\tclass=\"cn-object-row__actions\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<!-- @slot actions Trailing actions (copy button, menu, …). -->\n\t\t\t<!-- @binding {object} object The row's object. -->\n\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t</span>\n\t</div>\n</template>\n\n<script>\nimport { NcCheckboxRadioSwitch } from '@nextcloud/vue'\nimport { useClickDragGuard } from '../../composables/useClickDragGuard.js'\nimport { joinTemplateParts } from '../../utils/fillTemplate.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { resolveImageUrl } from '../../utils/resolveImageUrl.js'\nimport { isRowMiddleClick, preventMiddleClickAutoscroll } from '../../utils/rowAuxClick.js'\nimport { CnCellRenderer } from '../CnCellRenderer/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnStatusBadge } from '../CnStatusBadge/index.js'\n\n/**\n * CnObjectRow — Compact single-line list row for object display.\n *\n * The list-mode counterpart to `CnObjectCard`: a leading icon (or image), a\n * name with an optional subtitle, an optional status badge, and a trailing\n * actions area. Which object fields map to each slot is resolved from the\n * `config` prop first, then from `schema.configuration` (so a schema that\n * already declares `objectNameField` / `objectDescriptionField` / `objectImageField`\n * works with zero extra config).\n *\n * ```vue\n * <CnObjectRow\n * :object=\"secret\"\n * :schema=\"secretSchema\"\n * :config=\"{ subtitleField: 'url', iconName: 'Key' }\">\n * <template #actions=\"{ object }\">\n * <NcButton @click=\"copy(object)\">Copy</NcButton>\n * </template>\n * </CnObjectRow>\n * ```\n */\nexport default {\n\tname: 'CnObjectRow',\n\n\tcomponents: {\n\t\tNcCheckboxRadioSwitch,\n\t\tCnCellRenderer,\n\t\tCnIcon,\n\t\tCnStatusBadge,\n\t},\n\n\tprops: {\n\t\t/** The object data */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Schema definition; `schema.configuration` supplies field defaults */\n\t\tschema: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Explicit field mapping. Every key is optional and overrides the\n\t\t * schema-configuration default.\n\t\t *\n\t\t * `subtitleTemplate` fills `{field}` tokens from the row (empty parts and\n\t\t * their separators drop). `leading` (one cell) and `trailing` (a cell or\n\t\t * a list) draw cells as a table column does, `{ key, widget?,\n\t\t * widgetProps?, formatter? }`: `{ key: \"createdAt\", widget: \"age\" }`\n\t\t * reads \"6 dagen\", `{ key: \"deadline\", widget: \"date\", widgetProps: {\n\t\t * due: {} } }` the due text. A cell's `width` (CSS) lines the column\n\t\t * up across rows.\n\t\t *\n\t\t * @type {{ titleField?: string, subtitleField?: string, subtitleTemplate?: string, imageField?: string, iconField?: string, iconName?: string, badgeField?: string, badgeVariantField?: string, badgeVariant?: string, badgeColorMap?: object, leading?: object, trailing?: (object|Array<object>) }}\n\t\t */\n\t\tconfig: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** Whether this row is selected */\n\t\tselected: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether to show the selection checkbox */\n\t\tselectable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\n\t// Vue 2 had a separate listener channel, so a consumer's `@click` only ever\n\t// saw `$emit('click')`. In Vue 3 an UNDECLARED event name stays a\n\t// fallthrough attribute: `onClick` lands on the root `<div>` as a native\n\t// handler, so the consumer's handler fires once from the DOM click and\n\t// again from `$emit('click', object)` — twice per click, with different\n\t// payloads. Declaring the names here removes them from `$attrs`, which is\n\t// also what stops VTU v2 recording the native DOM event into `emitted()`.\n\temits: ['select', 'click', 'aux-click'],\n\n\tsetup() {\n\t\t// Tell a deliberate row click apart from a text-selection drag.\n\t\treturn useClickDragGuard()\n\t},\n\n\tcomputed: {\n\t\t/** Schema-level configuration block (empty when no schema). */\n\t\tschemaConfig() {\n\t\t\treturn this.schema?.configuration || {}\n\t\t},\n\n\t\ttitle() {\n\t\t\tconst field = this.config.titleField || this.schemaConfig.objectNameField\n\t\t\tif (field && this.object[field] !== null && this.object[field] !== undefined) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn this.object.title || this.object.name || this.object.id || '—'\n\t\t},\n\n\t\tsubtitle() {\n\t\t\tif (typeof this.config.subtitleTemplate === 'string' && this.config.subtitleTemplate !== '') {\n\t\t\t\tconst text = joinTemplateParts(this.config.subtitleTemplate, (key) => {\n\t\t\t\t\tconst value = readPath(this.object, key)\n\t\t\t\t\treturn value === null || value === undefined ? '' : String(value)\n\t\t\t\t})\n\t\t\t\treturn text.trim() || null\n\t\t\t}\n\t\t\tconst field = this.config.subtitleField || this.schemaConfig.objectDescriptionField\n\t\t\tif (field && this.object[field] !== null && this.object[field] !== undefined && this.object[field] !== '') {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\timageUrl() {\n\t\t\tconst field = this.config.imageField || this.schemaConfig.objectImageField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn resolveImageUrl(String(this.object[field]))\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\ticonName() {\n\t\t\tconst field = this.config.iconField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn this.config.iconName || ''\n\t\t},\n\n\t\t/** Whether to render the leading icon column at all. */\n\t\thasLeadingIcon() {\n\t\t\treturn Boolean(this.imageUrl || this.iconName || this.$slots.icon)\n\t\t},\n\n\t\tbadgeLabel() {\n\t\t\tconst field = this.config.badgeField\n\t\t\tif (field && this.object[field] !== null && this.object[field] !== undefined && this.object[field] !== '') {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\tbadgeVariant() {\n\t\t\tconst field = this.config.badgeVariantField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn this.config.badgeVariant || 'default'\n\t\t},\n\n\t\tbadgeColorMap() {\n\t\t\treturn this.config.badgeColorMap || null\n\t\t},\n\n\t\t/**\n\t\t * The `config.leading` cell, or null.\n\t\t *\n\t\t * @spec openspec/changes/index-row-list-cells/specs/object-row/spec.md#requirement-a-list-row-can-carry-leading-and-trailing-cells\n\t\t * @return {object|null}\n\t\t */\n\t\tleadingCell() {\n\t\t\tconst cell = this.config.leading\n\t\t\treturn cell && typeof cell === 'object' && typeof cell.key === 'string' && cell.key !== '' ? cell : null\n\t\t},\n\n\t\t/**\n\t\t * The `config.trailing` cells (one object or a list), those with a key.\n\t\t *\n\t\t * @spec openspec/changes/index-row-list-cells/specs/object-row/spec.md#requirement-a-list-row-can-carry-leading-and-trailing-cells\n\t\t * @return {Array<object>}\n\t\t */\n\t\ttrailingCells() {\n\t\t\tconst cells = this.config.trailing\n\t\t\tconst list = Array.isArray(cells) ? cells : (cells && typeof cells === 'object' ? [cells] : [])\n\t\t\treturn list.filter((cell) => cell && typeof cell === 'object' && typeof cell.key === 'string' && cell.key !== '')\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * A cell's value: the dot-path `key` read off the row.\n\t\t *\n\t\t * @param {{key: string}} cell The cell.\n\t\t * @return {unknown} The value.\n\t\t */\n\t\tcellValue(cell) {\n\t\t\treturn readPath(this.object, cell.key)\n\t\t},\n\n\t\t/**\n\t\t * Row-body click: emits `select` when `selectable` (ignoring drags),\n\t\t * otherwise emits `click` for navigation.\n\t\t *\n\t\t * @param {MouseEvent} [event] The originating click event.\n\t\t */\n\t\tonRowClick(event) {\n\t\t\tif (this.selectable) {\n\t\t\t\tif (this.wasDrag(event)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * @event select Emitted when a selectable row toggles selection (body or checkbox click).\n\t\t\t\t * @type {object} The row's object.\n\t\t\t\t */\n\t\t\t\tthis.$emit('select', this.object)\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event click Emitted when a non-selectable row is clicked (navigation). Payload: `(object, event)` — the row's object and the native click event, for opening it in a new tab on a ctrl/cmd/shift click. A middle click emits `aux-click` instead.\n\t\t\t * @type {object} The row's object.\n\t\t\t */\n\t\t\tthis.$emit('click', this.object, event)\n\t\t},\n\n\t\t/**\n\t\t * Row mousedown: record the press for the drag guard, and on a\n\t\t * non-selectable row keep a middle press from starting autoscroll.\n\t\t *\n\t\t * @param {MouseEvent} event The mousedown event.\n\t\t */\n\t\tonRowMouseDown(event) {\n\t\t\tthis.onPointerDown(event)\n\t\t\tif (!this.selectable) {\n\t\t\t\tpreventMiddleClickAutoscroll(event)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Row-body middle click on a non-selectable row: emits `aux-click`, not\n\t\t * `click`, so an existing `click` listener that navigates never moves\n\t\t * the current tab away.\n\t\t *\n\t\t * @param {MouseEvent} event The auxclick event.\n\t\t */\n\t\tonRowAuxClick(event) {\n\t\t\tif (this.selectable || !isRowMiddleClick(event)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event aux-click Emitted when a non-selectable row is middle-clicked, for opening it in a new tab (see `openRowTarget`). Payload: `(object, event)` — the row's object and the native auxclick event.\n\t\t\t * @type {object} The row's object.\n\t\t\t */\n\t\t\tthis.$emit('aux-click', this.object, event)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-object-row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 12px;\n\tpadding: 8px 12px;\n\tborder-bottom: 1px solid var(--color-border);\n\tcursor: pointer;\n}\n\n.cn-object-row:hover {\n\tbackground-color: var(--color-background-hover);\n}\n\n.cn-object-row--selected {\n\t/* Inset accent — never border-left (would shift cell content). */\n\tbox-shadow: inset 3px 0 0 0 var(--color-primary-element);\n\tbackground-color: var(--color-primary-element-light);\n}\n\n.cn-object-row__lead,\n.cn-object-row__trail {\n\tflex: 0 0 auto;\n\tmin-width: 0;\n}\n\n.cn-object-row__lead {\n\tfont-weight: 600;\n}\n\n.cn-object-row__checkbox {\n\tflex-shrink: 0;\n}\n\n.cn-object-row__icon {\n\tflex-shrink: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 24px;\n\theight: 24px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-object-row__image {\n\twidth: 24px;\n\theight: 24px;\n\tobject-fit: contain;\n\tborder-radius: var(--border-radius);\n}\n\n.cn-object-row__main {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 0;\n\tflex: 1;\n}\n\n.cn-object-row__title {\n\tfont-weight: 600;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-object-row__subtitle {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-object-row__badges {\n\tflex-shrink: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n}\n\n.cn-object-row__actions {\n\tflex-shrink: 0;\n\tdisplay: flex;\n\talign-items: center;\n}\n</style>\n"],"names":["CnCellRenderer","CnIcon","CnStatusBadge"],"mappings":";;;;;;;;;;AA6GA;;AAEC;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;;;;;;AAMA;AACA;;AAED,aAAe;AACd,CAAA,IAAI,EAAE,aAAa;;CAEnB,UAAU,EAAE;AACX,EAAA,qBAAqB;AACrB,kBAAAA,UAAc;AACd,UAAAC,YAAM;iBACNC,YAAa;EACb;;AAED,CAAA,KAAK,EAAE;AACN;AACA,EAAA,MAAM,EAAE;GACP,IAAI,EAAE,MAAM;GACZ,QAAQ,EAAE,IAAI;GACd;;AAED;AACA,EAAA,MAAM,EAAE;GACP,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,IAAI;GACb;;AAED;;;AAGC;AACA;;;;;;;AAOA;AACA;;AAED,EAAA,MAAM,EAAE;GACP,IAAI,EAAE,MAAM;AACZ,GAAA,OAAO,EAAE,OAAO,EAAE,CAAC;GACnB;;;AAGD,EAAA,QAAQ,EAAE;GACT,IAAI,EAAE,OAAO;GACb,OAAO,EAAE,KAAK;GACd;;AAED;EACA,UAAU,EAAE;GACX,IAAI,EAAE,OAAO;GACb,OAAO,EAAE,KAAK;GACd;EACD;;AAED;;;;;AAKA;;AAEA,CAAA,KAAK,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,CAAC;;AAEvC,CAAA,KAAK,GAAG;;EAEP,OAAO,iBAAiB,EAAC;EACzB;;AAED,CAAA,QAAQ,EAAE;;AAET,EAAA,YAAY,GAAG;AACd,GAAA,OAAO,IAAI,CAAC,MAAM,EAAE,aAAc,IAAG,EAAC;GACtC;;AAED,EAAA,KAAK,GAAG;AACP,GAAA,MAAM,KAAM,GAAE,IAAI,CAAC,MAAM,CAAC,UAAS,IAAK,IAAI,CAAC,YAAY,CAAC,gBAAc;AACxE,GAAA,IAAI,KAAM,IAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAE,KAAI,IAAK,IAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAA,KAAM,SAAS,EAAE;AAC7E,IAAA,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACjC,IAAA;GACA,OAAO,IAAI,CAAC,MAAM,CAAC,KAAM,IAAG,IAAI,CAAC,MAAM,CAAC,IAAK,IAAG,IAAI,CAAC,MAAM,CAAC,EAAG,IAAG,GAAE;GACpE;;EAED,QAAQ,GAAG;AACV,GAAA,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,qBAAqB,QAAS,IAAG,IAAI,CAAC,MAAM,CAAC,gBAAiB,KAAI,EAAE,EAAE;AAC5F,IAAA,MAAM,IAAG,GAAI,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,GAAG,KAAK;AACrE,KAAA,MAAM,KAAI,GAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAA;KACvC,OAAO,KAAM,KAAI,IAAK,IAAG,KAAM,KAAI,SAAU,GAAE,EAAC,GAAI,MAAM,CAAC,KAAK,CAAA;KAChE,EAAA;IACD,OAAO,IAAI,CAAC,IAAI,EAAC,IAAK,IAAG;AAC1B,IAAA;AACA,GAAA,MAAM,KAAI,GAAI,IAAI,CAAC,MAAM,CAAC,iBAAiB,IAAI,CAAC,YAAY,CAAC,uBAAqB;AAClF,GAAA,IAAI,SAAS,IAAI,CAAC,MAAM,CAAC,KAAK,CAAA,KAAM,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,CAAA,KAAM,SAAQ,IAAK,IAAI,CAAC,MAAM,CAAC,KAAK,CAAE,KAAI,EAAE,EAAE;AAC1G,IAAA,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACjC,IAAA;AACA,GAAA,OAAO,IAAG;GACV;;EAED,QAAQ,GAAG;AACV,GAAA,MAAM,KAAM,GAAE,IAAI,CAAC,MAAM,CAAC,UAAW,IAAG,IAAI,CAAC,YAAY,CAAC,iBAAe;GACzE,IAAI,KAAI,IAAK,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;IAChC,OAAO,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;AAClD,IAAA;AACA,GAAA,OAAO,IAAG;GACV;;EAED,QAAQ,GAAG;AACV,GAAA,MAAM,KAAM,GAAE,IAAI,CAAC,MAAM,CAAC,UAAQ;GAClC,IAAI,KAAI,IAAK,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;AAChC,IAAA,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACjC,IAAA;GACA,OAAO,IAAI,CAAC,MAAM,CAAC,QAAO,IAAK,EAAC;GAChC;;AAED;AACA,EAAA,cAAc,GAAG;GAChB,OAAO,OAAO,CAAC,IAAI,CAAC,QAAS,IAAG,IAAI,CAAC,QAAS,IAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAA;GACjE;;EAED,UAAU,GAAG;AACZ,GAAA,MAAM,KAAM,GAAE,IAAI,CAAC,MAAM,CAAC,WAAS;AACnC,GAAA,IAAI,SAAS,IAAI,CAAC,MAAM,CAAC,KAAK,CAAA,KAAM,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,CAAA,KAAM,SAAQ,IAAK,IAAI,CAAC,MAAM,CAAC,KAAK,CAAE,KAAI,EAAE,EAAE;AAC1G,IAAA,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACjC,IAAA;AACA,GAAA,OAAO,IAAG;GACV;;AAED,EAAA,YAAY,GAAG;AACd,GAAA,MAAM,KAAM,GAAE,IAAI,CAAC,MAAM,CAAC,kBAAgB;GAC1C,IAAI,KAAI,IAAK,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;AAChC,IAAA,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACjC,IAAA;AACA,GAAA,OAAO,IAAI,CAAC,MAAM,CAAC,YAAW,IAAK,SAAQ;GAC3C;;AAED,EAAA,aAAa,GAAG;AACf,GAAA,OAAO,IAAI,CAAC,MAAM,CAAC,aAAc,IAAG,IAAG;GACvC;;AAED;AACC;AACA;AACA;AACA;;EAED,WAAW,GAAG;GACb,MAAM,IAAK,GAAE,IAAI,CAAC,MAAM,CAAC,QAAM;AAC/B,GAAA,OAAO,IAAK,IAAG,OAAO,IAAG,KAAM,QAAO,IAAK,OAAO,IAAI,CAAC,GAAE,KAAM,QAAO,IAAK,IAAI,CAAC,GAAI,KAAI,EAAG,GAAE,OAAO,IAAG;GACvG;;AAED;;AAEC;AACA;;;AAGD,EAAA,aAAa,GAAG;AACf,GAAA,MAAM,KAAM,GAAE,IAAI,CAAC,MAAM,CAAC,SAAO;AACjC,GAAA,MAAM,IAAG,GAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAE,GAAE,KAAI,IAAK,KAAM,IAAG,OAAO,KAAI,KAAM,WAAW,CAAC,KAAK,CAAE,GAAE,EAAE,EAAA;GAC9F,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,QAAQ,OAAO,SAAS,QAAO,IAAK,OAAO,IAAI,CAAC,QAAQ,QAAO,IAAK,IAAI,CAAC,QAAQ,EAAE,CAAA;GAChH;EACD;;AAED,CAAA,OAAO,EAAE;AACR;AACC;AACA;AACA;;;AAGD,EAAA,SAAS,CAAC,IAAI,EAAE;AACf,GAAA,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAA;GACrC;;AAED;;AAEC;AACA;;;AAGD,EAAA,UAAU,CAAC,KAAK,EAAE;AACjB,GAAA,IAAI,IAAI,CAAC,UAAU,EAAE;IACpB,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;KACxB,MAAK;AACN,KAAA;AACA;AACC;;;AAGD,IAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAA;IAChC,MAAK;AACN,IAAA;AACA;;;;AAIA,GAAA,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAA;GACtC;;AAED;;;AAGC;AACA;;AAED,EAAA,cAAc,CAAC,KAAK,EAAE;GACrB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAA;AACxB,GAAA,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;AACrB,IAAA,4BAA4B,CAAC,KAAK,EAAA;AACnC,IAAA;GACA;;AAED;;;AAGC;AACA;AACA;;AAED,EAAA,aAAa,CAAC,KAAK,EAAE;AACpB,GAAA,IAAI,IAAI,CAAC,UAAW,IAAG,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE;IAChD,MAAK;AACN,IAAA;AACA;AACC;;;AAGD,GAAA,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAA;GAC1C;EACD;AACF;;;;"}
|