@conduction/nextcloud-vue 2.62.0 → 2.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue.js +10 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue.js.map +1 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue2.js +189 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue2.js.map +1 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue3.js +72 -0
- package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue3.js.map +1 -0
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +425 -39
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +119 -42
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +186 -9
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +65 -42
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +61 -16
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js.map +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js.map +1 -1
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js +20 -0
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js +3 -2
- package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +33 -2
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js +53 -37
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +29 -0
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +152 -135
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue.js +10 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue.js.map +1 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js +293 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js.map +1 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js +189 -0
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js.map +1 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +253 -9
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +126 -50
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +66 -14
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +23 -14
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +2 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue2.js +3 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue2.js.map +1 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue3.js +1 -1
- package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue3.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +234 -9
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +96 -57
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js +81 -4
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js +22 -5
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +81 -2
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +7 -3
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/selfModeActions.js +3 -3
- package/dist/esm/components/CnIndexPage/selfModeActions.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +41 -2
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +8 -3
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue2.js +121 -12
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue2.js.map +1 -1
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue3.js +3 -1
- package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +326 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +112 -26
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +63 -2
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js +96 -37
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/stagesModel.js +5 -2
- package/dist/esm/components/CnStagesWidget/stagesModel.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +52 -2
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +6 -6
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +14 -2
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +2 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js +10 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +337 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js +102 -0
- package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnTimelineWidget/dashboardRegistration.js +34 -0
- package/dist/esm/components/CnTimelineWidget/dashboardRegistration.js.map +1 -0
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js +131 -8
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js.map +1 -1
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue3.js +40 -38
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +8 -6
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +73 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js +14 -2
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js +19 -0
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js +1 -1
- package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js.map +1 -1
- package/dist/esm/composables/useDependencyCheck.js +65 -0
- package/dist/esm/composables/useDependencyCheck.js.map +1 -0
- package/dist/esm/composables/useWalkthrough.js +218 -6
- package/dist/esm/composables/useWalkthrough.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +45 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +45 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +780 -81
- package/dist/esm/store/useObjectStore.js +8 -0
- package/dist/esm/store/useObjectStore.js.map +1 -1
- package/dist/esm/utils/columnFilters.js +311 -0
- package/dist/esm/utils/columnFilters.js.map +1 -0
- package/dist/esm/utils/groupAutocomplete.js +123 -0
- package/dist/esm/utils/groupAutocomplete.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +2 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/pickerOptions.js +198 -0
- package/dist/esm/utils/pickerOptions.js.map +1 -0
- package/dist/esm/utils/schema.js +83 -7
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/utils/schemaRefSlug.js +19 -3
- package/dist/esm/utils/schemaRefSlug.js.map +1 -1
- package/dist/esm/utils/timelineEvents.js +174 -0
- package/dist/esm/utils/timelineEvents.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/walkthroughSignals.js +88 -0
- package/dist/esm/utils/walkthroughSignals.js.map +1 -0
- package/dist/nextcloud-vue.cjs.js +13088 -7937
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +780 -81
- package/l10n/en.json +45 -0
- package/l10n/nl.json +45 -0
- package/package.json +1 -1
- package/src/components/CnAdminActionCard/CnAdminActionCard.vue +234 -0
- package/src/components/CnAdminActionCard/index.js +4 -0
- package/src/components/CnAppNav/CnAppNav.vue +568 -43
- package/src/components/CnAppRoot/CnAppRoot.md +4 -0
- package/src/components/CnAppRoot/CnAppRoot.vue +223 -16
- package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +61 -16
- package/src/components/CnAuditTrailWidget/CnAuditTrailWidget.vue +22 -1
- package/src/components/CnCellRenderer/CnCellRenderer.vue +33 -2
- package/src/components/CnChoiceCards/CnChoiceCards.vue +56 -31
- package/src/components/CnDashboardPage/CnDashboardPage.vue +45 -4
- package/src/components/CnDataTable/CnColumnFilterPopover.vue +524 -0
- package/src/components/CnDataTable/CnDataTable.md +3 -0
- package/src/components/CnDataTable/CnDataTable.vue +305 -5
- package/src/components/CnDetailPage/CnDetailPage.md +4 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +60 -1
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +2 -2
- package/src/components/CnFieldHelper/CnFieldHelper.vue +4 -2
- package/src/components/CnFormDialog/CnFormDialog.vue +290 -31
- package/src/components/CnHeaderWidget/CnHeaderWidget.vue +116 -6
- package/src/components/CnIndexPage/CnIndexPage.vue +87 -4
- package/src/components/CnIndexPage/selfModeActions.js +3 -3
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +46 -2
- package/src/components/CnResourceSelect/CnResourceSelect.vue +123 -12
- package/src/components/CnSetupWizard/CnSetupWizard.vue +392 -3
- package/src/components/CnStagesWidget/CnStagesWidget.vue +180 -2
- package/src/components/CnStagesWidget/stagesModel.js +5 -2
- package/src/components/CnStatWidget/CnStatWidget.vue +57 -3
- package/src/components/CnTabsWidget/CnTabsWidget.vue +15 -2
- package/src/components/CnTimelineWidget/CnTimelineWidget.vue +477 -0
- package/src/components/CnTimelineWidget/dashboardRegistration.js +32 -0
- package/src/components/CnTimelineWidget/index.js +4 -0
- package/src/components/CnWalkthrough/CnWalkthrough.vue +143 -10
- package/src/components/CnWidgetGrid/builtInWidgets.js +2 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.md +4 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +107 -1
- package/src/components/CnWizardDialog/CnWizardDialog.vue +20 -1
- package/src/components/index.js +2 -0
- package/src/composables/useDependencyCheck.js +61 -0
- package/src/composables/useWalkthrough.js +217 -5
- package/src/css/dashboard.css +49 -0
- package/src/css/detail-page.css +29 -4
- package/src/css/kpi-card.css +24 -1
- package/src/css/table.css +99 -6
- package/src/index.js +2 -0
- package/src/schemas/app-manifest-v2.schema.json +135 -3
- package/src/store/useObjectStore.js +8 -0
- package/src/utils/columnFilters.js +324 -0
- package/src/utils/groupAutocomplete.js +119 -0
- package/src/utils/libraryWidgetKeys.js +2 -0
- package/src/utils/pickerOptions.js +194 -0
- package/src/utils/schema.js +83 -7
- package/src/utils/schemaRefSlug.js +19 -3
- package/src/utils/timelineEvents.js +171 -0
- package/src/utils/validateManifestV2.compiled.js +2 -2
- package/src/utils/walkthroughSignals.js +94 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sources":["../../../src/utils/schema.js"],"sourcesContent":["/**\n * Schema utility functions for auto-generating table columns, cell formatting,\n * form field definitions, and faceted filter definitions from OpenRegister\n * schema property definitions.\n *\n * @module utils/schema\n */\n\nimport { schemaRefSlug } from './schemaRefSlug.js'\n\n/**\n * Default column widths per property type/format.\n */\nconst DEFAULT_WIDTHS = {\n\tboolean: '80px',\n\tinteger: '100px',\n\tnumber: '100px',\n\t'string:uuid': '140px',\n\t'string:date-time': '180px',\n\t'string:email': '200px',\n}\n\n/**\n * Get default width for a property type + format combination.\n *\n * @param {string} type Property type\n * @param {string} [format] Property format\n * @return {string|undefined} CSS width or undefined\n */\nfunction getDefaultWidth(type, format) {\n\tif (format) {\n\t\treturn DEFAULT_WIDTHS[`${type}:${format}`]\n\t}\n\treturn DEFAULT_WIDTHS[type]\n}\n\n/**\n * Generate CnDataTable column definitions from a schema's properties.\n *\n * Reads `schema.properties` and creates column objects sorted by the `order`\n * hint (if present) then alphabetically. Filters out properties marked\n * `visible: false`. Supports include/exclude lists and per-column overrides.\n *\n * @param {object} schema The schema object with a `properties` field\n * @param {object} [options] Configuration options\n * @param {string[]} [options.exclude] Property keys to exclude\n * @param {string[]} [options.include] Property keys to include (whitelist mode)\n * @param {object} [options.overrides] Per-key column overrides, e.g. `{ status: { width: '200px' } }`\n * @param {(text: string) => string} [options.translate] Optional display-layer translation function applied to each column label. Schema property titles are authored in English as the canonical source; consumers pass their bound `t()` (via the injected `cnTranslate`) so the visible header follows the user's language. When omitted, the label is the English source string unchanged (pure, backward-compatible).\n * @return {Array<{key: string, label: string, sortable: boolean, type: string, format: string, width: string}>}\n */\nexport function columnsFromSchema(schema, options = {}) {\n\tconst { exclude = [], include = null, overrides = {}, translate } = options\n\tconst tr = typeof translate === 'function' ? translate : (text) => text\n\n\tif (!schema || !schema.properties) {\n\t\treturn []\n\t}\n\n\tconst entries = Object.entries(schema.properties)\n\t\t.filter(([key, prop]) => {\n\t\t\t// Skip properties marked as not visible\n\t\t\tif (prop.visible === false) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Apply exclude list\n\t\t\tif (exclude.includes(key)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Apply include whitelist\n\t\t\tif (include && !include.includes(key)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Skip complex object types by default (they don't render well in tables)\n\t\t\tif (prop.type === 'object') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\t.sort(([keyA, propA], [keyB, propB]) => {\n\t\t\t// Sort by order hint first, then alphabetically\n\t\t\tconst orderA = typeof propA.order === 'number' ? propA.order : Infinity\n\t\t\tconst orderB = typeof propB.order === 'number' ? propB.order : Infinity\n\t\t\tif (orderA !== orderB) {\n\t\t\t\treturn orderA - orderB\n\t\t\t}\n\t\t\treturn keyA.localeCompare(keyB)\n\t\t})\n\n\treturn entries.map(([key, prop]) => {\n\t\tconst column = {\n\t\t\tkey,\n\t\t\tlabel: tr(prop.title || key),\n\t\t\t// The schema already explains what the property MEANS; carrying that\n\t\t\t// through as the header tooltip means a column like \"Maturity\" or a\n\t\t\t// computed score explains itself in place, instead of the description\n\t\t\t// living only in the schema editor where no reader of the table looks.\n\t\t\tdescription: prop.description ? tr(prop.description) : '',\n\t\t\tsortable: true,\n\t\t\ttype: prop.type || 'string',\n\t\t\tformat: prop.format || null,\n\t\t}\n\n\t\t// Apply default width\n\t\tconst defaultWidth = getDefaultWidth(column.type, column.format)\n\t\tif (defaultWidth) {\n\t\t\tcolumn.width = defaultWidth\n\t\t}\n\n\t\t// Store enum values for cell renderer\n\t\tif (prop.enum) {\n\t\t\tcolumn.enum = prop.enum\n\t\t}\n\n\t\t// Store items type for arrays\n\t\tif (prop.items) {\n\t\t\tcolumn.items = prop.items\n\t\t}\n\n\t\t// Apply per-column overrides\n\t\tif (overrides[key]) {\n\t\t\tObject.assign(column, overrides[key])\n\t\t}\n\n\t\treturn column\n\t})\n}\n\n/**\n * Format a cell value based on its schema property definition.\n *\n * Handles dates, booleans, arrays, numbers, UUIDs, emails, and markdown.\n * Returns a plain string suitable for display in a table cell.\n *\n * @param {unknown} value The raw value\n * @param {object} [property] The schema property definition `{ type, format, enum, items }`\n * @param {object} [options] Formatting options\n * @param {number} [options.truncate] Maximum string length before truncation\n * @return {string} Formatted display string\n */\nexport function formatValue(value, property = {}, options = {}) {\n\tconst { truncate = 100 } = options\n\n\t// Null/undefined/empty\n\tif (value === null || value === undefined || value === '') {\n\t\treturn '—'\n\t}\n\n\tconst { type = 'string', format } = property\n\n\t// Boolean\n\tif (type === 'boolean' || typeof value === 'boolean') {\n\t\treturn value ? '✓' : '—'\n\t}\n\n\t// Number/Integer\n\tif (type === 'integer' || type === 'number') {\n\t\tconst num = Number(value)\n\t\tif (Number.isNaN(num)) {\n\t\t\treturn String(value)\n\t\t}\n\t\treturn num.toLocaleString()\n\t}\n\n\t// Array\n\tif (type === 'array' || Array.isArray(value)) {\n\t\tif (!Array.isArray(value)) {\n\t\t\treturn String(value)\n\t\t}\n\t\tif (value.length === 0) {\n\t\t\treturn '—'\n\t\t}\n\t\t// Stringify each entry so an array of OBJECTS never collapses to the\n\t\t// useless \"[object Object]\" that `Array.prototype.join` produces — a\n\t\t// nested object renders as compact JSON instead (ADR-062: a value cell\n\t\t// must never show \"[object Object]\"). Rich array rendering (inline\n\t\t// tables / chips) lives in CnObjectDataWidget; this is the flat-string\n\t\t// fallback used by tables and truncated cells.\n\t\tconst parts = value.map((v) => {\n\t\t\tif (v !== null && typeof v === 'object') {\n\t\t\t\ttry {\n\t\t\t\t\treturn JSON.stringify(v)\n\t\t\t\t} catch {\n\t\t\t\t\treturn '[Object]'\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn String(v)\n\t\t})\n\t\t// For short arrays, join values\n\t\tif (parts.length <= 3) {\n\t\t\treturn parts.join(', ')\n\t\t}\n\t\treturn `${parts.slice(0, 3).join(', ')} +${parts.length - 3}`\n\t}\n\n\t// Object — render as JSON; tables truncate, multi-line value cells wrap with `<pre>`.\n\tif (type === 'object' || (typeof value === 'object' && value !== null)) {\n\t\ttry {\n\t\t\treturn truncateString(JSON.stringify(value, null, 2), truncate)\n\t\t} catch {\n\t\t\treturn '[Object]'\n\t\t}\n\t}\n\n\t// String types\n\tconst str = String(value)\n\n\t// Date-time\n\tif (format === 'date-time' || format === 'date') {\n\t\ttry {\n\t\t\tconst date = new Date(str)\n\t\t\tif (Number.isNaN(date.getTime())) {\n\t\t\t\treturn str\n\t\t\t}\n\t\t\tif (format === 'date') {\n\t\t\t\treturn date.toLocaleDateString(undefined, {\n\t\t\t\t\tday: '2-digit',\n\t\t\t\t\tmonth: '2-digit',\n\t\t\t\t\tyear: 'numeric',\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn date.toLocaleDateString(undefined, {\n\t\t\t\tday: '2-digit',\n\t\t\t\tmonth: '2-digit',\n\t\t\t\tyear: 'numeric',\n\t\t\t}) + ', ' + date.toLocaleTimeString(undefined, {\n\t\t\t\thour: '2-digit',\n\t\t\t\tminute: '2-digit',\n\t\t\t\tsecond: '2-digit',\n\t\t\t})\n\t\t} catch {\n\t\t\treturn str\n\t\t}\n\t}\n\n\t// UUID — truncate to first 8 chars\n\tif (format === 'uuid') {\n\t\tif (str.length > 8) {\n\t\t\treturn str.substring(0, 8) + '...'\n\t\t}\n\t\treturn str\n\t}\n\n\t// URI — show truncated\n\tif (format === 'uri' || format === 'url') {\n\t\ttry {\n\t\t\tconst url = new URL(str)\n\t\t\treturn url.hostname + url.pathname.substring(0, 20)\n\t\t} catch {\n\t\t\treturn truncateString(str, truncate)\n\t\t}\n\t}\n\n\t// Markdown — strip formatting\n\tif (format === 'markdown') {\n\t\tconst stripped = str\n\t\t\t.replace(/#{1,6}\\s+/g, '') // headings\n\t\t\t.replace(/[*_]{1,3}([^*_]+)[*_]{1,3}/g, '$1') // bold/italic\n\t\t\t.replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1') // links\n\t\t\t.replace(/`{1,3}[^`]*`{1,3}/g, '') // code\n\t\t\t.replace(/\\n+/g, ' ') // newlines\n\t\t\t.trim()\n\t\treturn truncateString(stripped, truncate)\n\t}\n\n\t// Email — display as-is (no truncation)\n\tif (format === 'email') {\n\t\treturn str\n\t}\n\n\t// Plain string — truncate if needed\n\treturn truncateString(str, truncate)\n}\n\n/**\n * Truncate a string to the given length, adding ellipsis if needed.\n *\n * @param {string} str The string to truncate\n * @param {number} maxLength Maximum length\n * @return {string} Truncated string\n */\nfunction truncateString(str, maxLength) {\n\tif (str.length <= maxLength) {\n\t\treturn str\n\t}\n\treturn str.substring(0, maxLength) + '...'\n}\n\n/**\n * Resolve the form widget type for a JSON Schema property.\n *\n * Resolution priority (first match wins):\n * 1. Explicit `prop.widget` — pass-through custom widget name\n * 2. `prop.enum` → `'select'`\n * 3. OpenRegister object reference: `prop.$ref` (a string schema slug) →\n * `'select'`; `array` + `items.$ref` → `'multiselect'`. The consuming\n * surface (CnFormDialog) resolves the reference to a searchable dropdown\n * of the referenced objects (label = human name, value = UUID).\n * 4. Nextcloud user reference: `referenceType: 'nextcloud-user'` (or\n * `format: 'user'`/`'username'`) → `'user'`; an array of such\n * properties → `'user-multiselect'`. CnFormDialog resolves these to a\n * searchable dropdown of real Nextcloud users (label = display name,\n * value = UID).\n * 5. Type-based: `boolean` → `'checkbox'`, `integer`/`number` → `'number'`,\n * `array` + `items.enum` → `'multiselect'`, `array` → `'tags'`\n * 6. Format-based: `date-time` → `'datetime'`, `date` → `'date'`,\n * `email` → `'email'`, `uri`/`url` → `'url'`,\n * `markdown`/`textarea` → `'textarea'`\n * 7. Long text: `maxLength > 255` → `'textarea'`\n * 8. Fallback → `'text'`\n *\n * @param {object} prop The schema property definition (type, format, enum, widget, items, maxLength)\n * @return {string} Widget identifier: 'text'|'email'|'url'|'number'|'checkbox'|'select'|'multiselect'|'user'|'user-multiselect'|'tags'|'textarea'|'date'|'datetime' or a custom string\n */\n/**\n * Normalise a JSON-Schema `$ref` value into an OpenRegister schema reference\n * identifier. OpenRegister authors a `$ref` as a schema *slug* (string) but\n * persists/serves it as the numeric schema *id* (e.g. `85`). Both forms are\n * valid object-reference targets (the objects API resolves either).\n *\n * The schema editor writes the JSON-Pointer form — `#/components/schemas/<slug>`\n * — so a `$ref` reaching here may be a pointer rather than a bare slug. Passing\n * the whole pointer through as the schema identifier made the object picker query\n * a schema literally named \"#/components/schemas/cow\", which matches nothing: the\n * dropdown rendered but came back empty. Take the tail after the last `/`, which\n * is what the editor itself does when it resolves a $ref back to a schema.\n *\n * A `$ref` is authored as the schema's PascalCase (or spaced) *title*, not\n * its slug (`ReportPeriod`, not `report-period`); the objects API 404s on\n * the title for any multi-word schema (defect 7, learniq round 1). Routing\n * the tail through {@link schemaRefSlug} fixes that once here, for every\n * consumer of `reference.schema` built below.\n *\n * @param {unknown} ref A `$ref` value (`prop.$ref` or `prop.items.$ref`).\n * @return {string|number|null} The reference identifier, or null.\n */\nfunction normalizeRef(ref) {\n\tif (typeof ref === 'string' && ref !== '') {\n\t\tconst tail = ref.includes('/') ? ref.substring(ref.lastIndexOf('/') + 1) : ref\n\t\tif (tail === '') {\n\t\t\treturn null\n\t\t}\n\t\tconst slug = schemaRefSlug(tail)\n\t\treturn slug !== '' ? slug : null\n\t}\n\tif (typeof ref === 'number' && !Number.isNaN(ref)) {\n\t\treturn ref\n\t}\n\treturn null\n}\n\n/**\n * Whether a (single-value) schema property represents a Nextcloud user.\n *\n * A property is a user field when it declares `referenceType: 'nextcloud-user'`\n * (preferred) OR `format: 'user'` / `format: 'username'`. The consuming surface\n * (CnFormDialog) renders such a property as a searchable dropdown of real\n * Nextcloud users (label = display name, value = UID) instead of a free-text box.\n *\n * @param {object} prop A schema property definition (or `items` for an array).\n * @return {boolean} True when the property marks a Nextcloud user.\n */\nfunction isUserProp(prop) {\n\tif (!prop || typeof prop !== 'object') {\n\t\treturn false\n\t}\n\tif (prop.referenceType === 'nextcloud-user') {\n\t\treturn true\n\t}\n\tconst format = prop.format || ''\n\treturn format === 'user' || format === 'username'\n}\n\nfunction resolveWidget(prop) {\n\t// Explicit widget hint takes priority\n\tif (prop.widget) {\n\t\treturn prop.widget\n\t}\n\n\t// Enum → select\n\tif (prop.enum) {\n\t\treturn 'select'\n\t}\n\n\tconst type = prop.type || 'string'\n\tconst format = prop.format || ''\n\n\t// OpenRegister object reference (`$ref` is a schema slug or numeric id) →\n\t// a searchable dropdown of the referenced objects. An array of\n\t// references (`items.$ref`) → a multi-select. Checked before the\n\t// plain type/format fallback so a `{ type: 'string', format: 'uuid',\n\t// $ref: '<slug-or-id>' }` property renders as a dropdown, not a UUID box.\n\tif (normalizeRef(prop.$ref) !== null) {\n\t\treturn 'select'\n\t}\n\tif (type === 'array' && prop.items && normalizeRef(prop.items.$ref) !== null) {\n\t\treturn 'multiselect'\n\t}\n\n\t// Nextcloud user reference (referenceType 'nextcloud-user' or\n\t// format 'user'/'username'): a searchable dropdown of real Nextcloud\n\t// users (label = display name, value = UID). An array of users is a\n\t// multi-select. Checked before the plain type/format fallback so a\n\t// user-marked property renders as a picker, not a free-text box.\n\tif (isUserProp(prop)) {\n\t\treturn 'user'\n\t}\n\tif (type === 'array' && isUserProp(prop.items)) {\n\t\treturn 'user-multiselect'\n\t}\n\n\t// Boolean → switch/checkbox\n\tif (type === 'boolean') {\n\t\treturn 'checkbox'\n\t}\n\n\t// Number types\n\tif (type === 'integer' || type === 'number') {\n\t\treturn 'number'\n\t}\n\n\t// Array types\n\tif (type === 'array') {\n\t\tif (prop.items && prop.items.enum) {\n\t\t\treturn 'multiselect'\n\t\t}\n\t\treturn 'tags'\n\t}\n\n\t// Format-based widgets\n\tif (format === 'date-time') {\n\t\treturn 'datetime'\n\t}\n\tif (format === 'date') {\n\t\treturn 'date'\n\t}\n\tif (format === 'email') {\n\t\treturn 'email'\n\t}\n\tif (format === 'uri' || format === 'url') {\n\t\treturn 'url'\n\t}\n\tif (format === 'markdown' || format === 'textarea') {\n\t\treturn 'textarea'\n\t}\n\n\t// Long text → textarea\n\tif (prop.maxLength && prop.maxLength > 255) {\n\t\treturn 'textarea'\n\t}\n\n\treturn 'text'\n}\n\n/**\n * Longest description rendered inline as helper text. Beyond this a field's\n * description is split — a short lead-in stays under the input, the full text\n * moves behind the info popover — because some schema properties document a\n * whole adapter dispatch table and would otherwise dwarf the field itself.\n */\nconst DESCRIPTION_INLINE_MAX = 120\n\n/** Tokens ending in a period that do not end a sentence. */\nconst NON_TERMINAL_ABBREVIATIONS = ['e.g', 'i.e', 'etc', 'vs', 'cf', 'incl', 'approx', 'resp', 'no']\n\n/**\n * The first sentence of `text`, or '' when it has no sentence boundary.\n *\n * @param {string} text The text to scan.\n * @return {string} The first sentence including its terminator.\n */\nfunction firstSentenceOf(text) {\n\tconst boundary = /[.!?](?=\\s|$)/g\n\tlet match\n\twhile ((match = boundary.exec(text)) !== null) {\n\t\tconst lastWord = text.slice(0, match.index).split(/\\s+/).pop().toLowerCase()\n\t\t// \"e.g.\" and single-letter initials carry a period mid-sentence.\n\t\tif (NON_TERMINAL_ABBREVIATIONS.includes(lastWord) || /^[a-z]$/i.test(lastWord)) {\n\t\t\tcontinue\n\t\t}\n\t\treturn text.slice(0, match.index + 1)\n\t}\n\treturn ''\n}\n\n/**\n * Truncate to `max` characters on a word boundary, with an ellipsis.\n *\n * @param {string} text The text to clamp.\n * @param {number} max The maximum length before the ellipsis.\n * @return {string} The clamped text.\n */\nfunction clampToWord(text, max) {\n\tconst cut = text.slice(0, max)\n\tconst lastSpace = cut.lastIndexOf(' ')\n\t// Only honour the word boundary when it isn't hacking off most of the clamp.\n\treturn `${(lastSpace > max * 0.6 ? cut.slice(0, lastSpace) : cut).trimEnd()}…`\n}\n\n/**\n * Split a description into the part rendered inline and the full text.\n *\n * Short descriptions (the overwhelming majority — \"Human-readable name\") pass\n * through untouched with no long form. Longer ones yield their first sentence\n * as `short` when that alone fits, else a word-clamped prefix, and the whole\n * original as `long` for the caller to put behind an info affordance.\n *\n * @param {string} text The raw description.\n * @param {number} [max] Longest text kept inline.\n * @return {{short: string, long: string}} The inline text and the full text ('' when nothing was split off).\n */\nexport function splitDescription(text, max = DESCRIPTION_INLINE_MAX) {\n\tconst full = typeof text === 'string' ? text.trim() : ''\n\tif (!full || full.length <= max) {\n\t\treturn { short: full, long: '' }\n\t}\n\n\tconst sentence = firstSentenceOf(full)\n\treturn {\n\t\tshort: sentence && sentence.length <= max ? sentence : clampToWord(full, max),\n\t\tlong: full,\n\t}\n}\n\n/**\n * Property names that carry the tenant a record belongs to, compared after\n * lower-casing and dropping `_` / `-`, so `tenant_id`, `tenantId` and\n * `tenant-id` all match.\n *\n * @type {Set<string>}\n */\nconst TENANT_PROPERTY_NAMES = new Set(['tenant', 'tenantid', 'tenantuuid'])\n\n/**\n * Whether a schema property holds the tenant a record belongs to.\n *\n * Tenant is set by the platform, never by the person filling in a form, so\n * a create form must not ask for it. OpenRegister marks no such property\n * itself: learniq's work group ships `tenant_id` as a plain required string\n * with no format, no `readOnly` and no flag, which is why the create dialog\n * showed a required \"Tenant *\" box. So the test reads the property's\n * semantics in this order:\n *\n * 1. An explicit opt-out, `x-openregister-tenant: false`, keeps it a normal field.\n * 2. An explicit marker makes it a tenant field whatever it is called:\n * `x-openregister-tenant: true`, `x-platform-managed: true`,\n * `x-managed-by: 'platform'`, `format: 'tenant'` or `referenceType: 'tenant'`.\n * 3. Otherwise its name decides: `tenant`, `tenant_id` / `tenantId` or `tenant_uuid`.\n *\n * `organisation` is deliberately NOT matched by name: plenty of schemas let a\n * person pick an organisation (a contact's employer, a supplier), and hiding\n * that would take a real question away. A schema whose `organisation`\n * property is the tenant says so with one of the markers above.\n *\n * @param {string} key The property key.\n * @param {object} prop The property definition.\n * @return {boolean} True when the property is platform-managed tenancy.\n */\nexport function isTenantProperty(key, prop) {\n\tconst p = (prop && typeof prop === 'object') ? prop : {}\n\tif (p['x-openregister-tenant'] === false) {\n\t\treturn false\n\t}\n\tif (p['x-openregister-tenant'] === true\n\t\t|| p['x-platform-managed'] === true\n\t\t|| p['x-managed-by'] === 'platform'\n\t\t|| p.format === 'tenant'\n\t\t|| p.referenceType === 'tenant') {\n\t\treturn true\n\t}\n\tconst name = typeof key === 'string' ? key.toLowerCase().replace(/[-_]/g, '') : ''\n\treturn TENANT_PROPERTY_NAMES.has(name)\n}\n\n/**\n * Generate form field definitions from a schema's properties.\n *\n * Reads `schema.properties` and creates field descriptor objects suitable\n * for auto-generating form UIs. Follows the same pattern as\n * `columnsFromSchema()` — filters, sorts, and supports overrides.\n *\n * @param {object} schema The schema object with a `properties` field\n * @param {object} [options] Configuration options\n * @param {string[]} [options.exclude] Property keys to exclude\n * @param {string[]} [options.include] Property keys to include (whitelist mode)\n * @param {object} [options.overrides] Per-key field overrides, e.g. `{ status: { widget: 'select' } }`. Recognised keys: `hidden` (true → drop the field), `order` (number → wins over the schema property's `order` for sorting), `readOnly` (false on a schema-readOnly key un-skips it), plus any field props to merge (`label`, `widget`, `enum`, …). A single overrides map therefore controls visibility, ordering and rendering on every surface that consumes this pipeline (data widget + form dialog).\n * @param {boolean} [options.includeReadOnly] Whether to include readOnly properties\n * @param {boolean} [options.hideTenant] Drop properties that hold the record's tenant (see `isTenantProperty`). Off by default, so a detail page still shows the tenant; CnFormDialog turns it on because nobody should be asked for it. `overrides[key].hidden === false` keeps one visible.\n * @param {(text: string) => string} [options.translate] Optional display-layer translation function applied to each field's `label` and `description`. Schema property titles/descriptions are authored in English as the canonical source; consumers pass their bound `t()` (via the injected `cnTranslate`) so the rendered field label follows the user's language. When omitted, label/description are the English source strings unchanged (pure, backward-compatible).\n * @return {Array<{key: string, label: string, description: string, descriptionLong: string, type: string, format: string|null, widget: string, required: boolean, readOnly: boolean, default: unknown, enum: Array|null, enumLabels: object|null, items: object|null, referenceType: string|null, referenceSemanticType: string|null, referenceSemanticApp: string|null, reference: {schema: string|number, multiple: boolean}|null, userPicker: {multiple: boolean}|null, fillFrom: object|null, validation: object, order: number}>} `description` is the inline helper text (see `splitDescription`); `descriptionLong` carries the full text when it was too long to render inline, else ''. `enumLabels` maps each raw enum value to its English display label (from the property's `x-enum-labels`), or null.\n */\nexport function fieldsFromSchema(schema, options = {}) {\n\tconst { exclude = [], include = null, overrides = {}, includeReadOnly = false, hideTenant = false, translate } = options\n\tconst tr = typeof translate === 'function' ? translate : (text) => text\n\n\tif (!schema || !schema.properties) {\n\t\treturn []\n\t}\n\n\tconst requiredKeys = Array.isArray(schema.required) ? schema.required : []\n\n\tconst entries = Object.entries(schema.properties)\n\t\t.filter(([key, prop]) => {\n\t\t\t// Skip properties marked as not visible\n\t\t\tif (prop.visible === false) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Per-key override visibility: `overrides[key].hidden === true` hides\n\t\t\t// the field on every surface that consumes this pipeline (data widget\n\t\t\t// + form dialog), so a single config map controls both.\n\t\t\tif (overrides[key]?.hidden === true) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Platform-managed tenancy (`tenant_id` and friends): nobody is\n\t\t\t// asked for it on a form. An explicit `hidden: false` override\n\t\t\t// brings it back for the rare surface that does need it.\n\t\t\tif (hideTenant && overrides[key]?.hidden !== false && isTenantProperty(key, prop)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Skip readOnly properties by default — UNLESS a per-key override\n\t\t\t// explicitly re-enables the field (`overrides[key].readOnly === false`).\n\t\t\t// This lets a consumer surface a schema-readOnly field (e.g. a\n\t\t\t// denormalised name that's read-only on edit but must be collected\n\t\t\t// on create) without flipping the whole form to includeReadOnly.\n\t\t\tif (prop.readOnly === true && !includeReadOnly && overrides[key]?.readOnly !== false) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Apply exclude list\n\t\t\tif (exclude.includes(key)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Apply include whitelist\n\t\t\tif (include && !include.includes(key)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Skip complex object types unless the caller opts in with an explicit widget\n\t\t\t// (e.g. `widget: 'json'` or `widget: 'code'` in CnFormDialog) — or unless the\n\t\t\t// property is an OpenRegister object REFERENCE (`$ref`). A reference is a\n\t\t\t// relation to another schema's object, which resolveWidget maps to a\n\t\t\t// searchable 'select'; dropping it here meant a related-object property\n\t\t\t// (e.g. cow.barn → barn) silently never rendered in the form at all.\n\t\t\tif (prop.type === 'object' && !prop.widget && normalizeRef(prop.$ref) === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\t.sort(([keyA, propA], [keyB, propB]) => {\n\t\t\t// Sort by EFFECTIVE order: a per-key `overrides[key].order` wins over\n\t\t\t// the schema property's own `order`, then alphabetically. Honouring the\n\t\t\t// override here means every consumer (data widget + form dialog) gets\n\t\t\t// the same ordering from one map — no per-component re-sort needed.\n\t\t\tconst orderA = typeof overrides[keyA]?.order === 'number'\n\t\t\t\t? overrides[keyA].order\n\t\t\t\t: (typeof propA.order === 'number' ? propA.order : Infinity)\n\t\t\tconst orderB = typeof overrides[keyB]?.order === 'number'\n\t\t\t\t? overrides[keyB].order\n\t\t\t\t: (typeof propB.order === 'number' ? propB.order : Infinity)\n\t\t\tif (orderA !== orderB) {\n\t\t\t\treturn orderA - orderB\n\t\t\t}\n\t\t\treturn keyA.localeCompare(keyB)\n\t\t})\n\n\treturn entries.map(([key, prop]) => {\n\t\tconst description = splitDescription(prop.description ? tr(prop.description) : '')\n\t\tconst field = {\n\t\t\tkey,\n\t\t\tlabel: tr(prop.title || key),\n\t\t\tdescription: description.short,\n\t\t\tdescriptionLong: description.long,\n\t\t\ttype: prop.type || 'string',\n\t\t\tformat: prop.format || null,\n\t\t\twidget: resolveWidget(prop),\n\t\t\t// Icon picker (`widget: 'icon'`) config forwarded to CnIconBrowser via\n\t\t\t// CnFormDialog: which sources to offer (`iconSources`), consumer icon\n\t\t\t// catalogues (JSON entries — FontAwesome/OpenGemeenten data is usually\n\t\t\t// supplied via a fieldOverride instead), and whether custom-SVG is\n\t\t\t// enabled. `searchable` is obsolete — the browser always searches.\n\t\t\t// Omitted keys fall back to CnIconBrowser's own defaults, which include\n\t\t\t// the bundled NL-government sets.\n\t\t\ticonSources: prop.iconSources || undefined,\n\t\t\tcatalogues: prop.catalogues || undefined,\n\t\t\tallowCustomSvg: prop.allowCustomSvg || undefined,\n\t\t\tsearchable: prop.searchable,\n\t\t\trequired: requiredKeys.includes(key),\n\t\t\treadOnly: prop.readOnly || false,\n\t\t\tdefault: prop.default !== undefined ? prop.default : null,\n\t\t\tenum: prop.enum || null,\n\t\t\t// Display labels for the enum CODES, keyed by raw value. An enum\n\t\t\t// value is a stored contract value, not display text — several are\n\t\t\t// non-English by design (`ingediend`) — so a schema declares the\n\t\t\t// English label here and the consumer surface translates THAT.\n\t\t\t// Without it the only thing a form can show is the raw code.\n\t\t\tenumLabels: prop.enumLabels\n\t\t\t\t|| prop['x-enum-labels']\n\t\t\t\t|| (prop.items && (prop.items.enumLabels || prop.items['x-enum-labels']))\n\t\t\t\t|| null,\n\t\t\titems: prop.items || null,\n\t\t\t// Pluggable integration registry marker (AD-18): a property\n\t\t\t// can declare `referenceType: '<integration-id>'` so consumer\n\t\t\t// surfaces (CnFormDialog, CnDetailGrid) render that\n\t\t\t// integration's single-entity widget instead of a plain input.\n\t\t\treferenceType: prop.referenceType || null,\n\t\t\t// Cross-app semantic reference (ADR-048): a property can declare\n\t\t\t// `referenceSemanticType: '<canonical-uri>'` (e.g.\n\t\t\t// 'https://schema.org/Organization') plus an optional\n\t\t\t// `referenceSemanticApp: '<appid>'` naming the app expected to\n\t\t\t// provide it. The consuming surface (CnFormDialog) resolves the\n\t\t\t// URI against OpenRegister's discovery endpoint: when SOME\n\t\t\t// installed schema implements it, the field renders as a\n\t\t\t// searchable object picker over that provider schema's register;\n\t\t\t// when NONE does, the field renders DISABLED with a tooltip. This\n\t\t\t// is the semantic sibling of `referenceType` (integration id).\n\t\t\t// `null` when the keys are absent (no behaviour change). Pure: no\n\t\t\t// resolution happens here.\n\t\t\treferenceSemanticType: prop.referenceSemanticType || null,\n\t\t\treferenceSemanticApp: prop.referenceSemanticApp || null,\n\t\t\t// OpenRegister object reference (`$ref`): when a property points\n\t\t\t// at another schema (`$ref: '<slug>'`, or `items.$ref` for an\n\t\t\t// array), record the referenced schema slug + whether it is a\n\t\t\t// multi-value reference. The consuming surface (CnFormDialog)\n\t\t\t// resolves this to a searchable dropdown of the referenced\n\t\t\t// objects, storing the chosen UUID(s). `null` for non-reference\n\t\t\t// properties. Pure: no fetching happens here.\n\t\t\t//\n\t\t\t// Cross-app object relation (ADR-066): a reference property may\n\t\t\t// carry `x-external-register: '<app>'` naming the register the\n\t\t\t// referenced schema lives in — a link into ANOTHER fleet app\n\t\t\t// (e.g. a procest case referencing a decidesk decision). When\n\t\t\t// present it is recorded as `reference.register` so the picker\n\t\t\t// resolves/scopes/creates against that register instead of the\n\t\t\t// form's own; absent, the reference stays same-register (the form's\n\t\t\t// `register` prop is used). Consolidates the ad-hoc caseReference /\n\t\t\t// approvalDecisionId / x-mirror-of variants onto one convention.\n\t\t\treference: (normalizeRef(prop.$ref) !== null)\n\t\t\t\t? { schema: normalizeRef(prop.$ref), multiple: false, ...(prop['x-external-register'] ? { register: prop['x-external-register'] } : {}) }\n\t\t\t\t: (prop.type === 'array' && prop.items && normalizeRef(prop.items.$ref) !== null)\n\t\t\t\t\t\t? { schema: normalizeRef(prop.items.$ref), multiple: true, ...((prop.items['x-external-register'] || prop['x-external-register']) ? { register: prop.items['x-external-register'] || prop['x-external-register'] } : {}) }\n\t\t\t\t\t\t: null,\n\t\t\t// Nextcloud user reference: when a property marks a NC user\n\t\t\t// (`referenceType: 'nextcloud-user'`, or `format: 'user'`/\n\t\t\t// `'username'`), tag it so CnFormDialog renders a searchable\n\t\t\t// dropdown of real Nextcloud users (label = display name,\n\t\t\t// value = UID) instead of a free-text box. `multiple` is true\n\t\t\t// for an array of users (`items` marks the user). `null` for\n\t\t\t// non-user properties. Pure: no fetching happens here.\n\t\t\tuserPicker: isUserProp(prop)\n\t\t\t\t? { multiple: false }\n\t\t\t\t: (prop.type === 'array' && isUserProp(prop.items))\n\t\t\t\t\t\t? { multiple: true }\n\t\t\t\t\t\t: null,\n\t\t\t// Conditional immutability (AD: x-openregister-readonly-when): a\n\t\t\t// property can declare it becomes read-only when another field on the\n\t\t\t// same object holds a given value — e.g. a hybrid app's identity\n\t\t\t// fields. Consumers (CnObjectDataWidget) evaluate this against the\n\t\t\t// object's current data. Shape: `{ field, equals }` or `{ field, in: [] }`.\n\t\t\treadOnlyWhen: prop['x-openregister-readonly-when'] || prop.readOnlyWhen || null,\n\t\t\tvalidation: {\n\t\t\t\tminLength: prop.minLength,\n\t\t\t\tmaxLength: prop.maxLength,\n\t\t\t\tminimum: prop.minimum,\n\t\t\t\tmaximum: prop.maximum,\n\t\t\t\tpattern: prop.pattern,\n\t\t\t},\n\t\t\torder: typeof prop.order === 'number' ? prop.order : Infinity,\n\t\t}\n\n\t\t// Apply per-field overrides\n\t\tif (overrides[key]) {\n\t\t\tObject.assign(field, overrides[key])\n\t\t}\n\n\t\treturn field\n\t})\n}\n\n/**\n * Generate faceted filter definitions from a schema's facetable properties.\n *\n * Reads `schema.properties` and creates filter definitions for properties\n * marked with `facetable: true`. Maps property types to appropriate filter\n * widget types (select, checkbox, text).\n *\n * A property may say how it wants to be asked for, with `inputControl` —\n * the same word openregister answers under `?_facetable=true`. One of\n * `text`, `select`, `multiselect`, `range`, `date-range`, `boolean` or\n * `reference`. It wins over the type guess; an unknown one falls back to it.\n *\n * @param {object} schema The schema object with a `properties` field\n * @param {object} [options] Configuration options\n * @param {(text: string) => string} [options.translate] Optional display-layer translation function applied to each filter's `label` and `description`. Schema property titles are authored in English as the canonical source; consumers pass their bound `t()` (via the injected `cnTranslate`) so the rendered filter label follows the user's language. When omitted, label/description are the English source strings unchanged (pure, backward-compatible).\n * @return {Array<{key: string, label: string, type: string, propertyType: string, options: Array}>}\n */\nexport function filtersFromSchema(schema, options = {}) {\n\tif (!schema || !schema.properties) {\n\t\treturn []\n\t}\n\n\tconst { translate } = options\n\tconst tr = typeof translate === 'function' ? translate : (text) => text\n\n\treturn Object.entries(schema.properties)\n\t\t.filter(([, prop]) => {\n\t\t\tif (prop.facetable !== true) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\t.sort(([keyA, propA], [keyB, propB]) => {\n\t\t\tconst orderA = typeof propA.order === 'number' ? propA.order : Infinity\n\t\t\tconst orderB = typeof propB.order === 'number' ? propB.order : Infinity\n\t\t\tif (orderA !== orderB) {\n\t\t\t\treturn orderA - orderB\n\t\t\t}\n\t\t\treturn keyA.localeCompare(keyB)\n\t\t})\n\t\t.map(([key, prop]) => {\n\t\t\tconst filter = {\n\t\t\t\tkey,\n\t\t\t\tlabel: tr(prop.title || key),\n\t\t\t\tdescription: prop.description ? tr(prop.description) : '',\n\t\t\t\tpropertyType: prop.type || 'string',\n\t\t\t\toptions: [],\n\t\t\t\tvalue: null,\n\t\t\t}\n\n\t\t\t// Map property type to filter widget type\n\t\t\tif (prop.type === 'boolean') {\n\t\t\t\tfilter.type = 'checkbox'\n\t\t\t} else if (prop.enum) {\n\t\t\t\tfilter.type = 'select'\n\t\t\t\tconst enumLabels = prop.enumLabels || prop['x-enum-labels'] || {}\n\t\t\t\tfilter.options = prop.enum.map((val) => ({\n\t\t\t\t\tid: val,\n\t\t\t\t\t// The filter VALUE stays the raw schema code (it is what the\n\t\t\t\t\t// query sends); only the label follows the user's language.\n\t\t\t\t\tlabel: tr(enumLabels[val] || String(val)),\n\t\t\t\t}))\n\t\t\t} else {\n\t\t\t\t// Default to select — options loaded dynamically from facet API\n\t\t\t\tfilter.type = 'select'\n\t\t\t}\n\n\t\t\t// 🔑 `inputControl` IS THE PROPERTY'S OWN ANSWER TO \"HOW DO I ASK\n\t\t\t// FOR THIS\", and it wins over the type guess above. It is the same\n\t\t\t// word openregister's PropertySearchProfile reads\n\t\t\t// (`searchable_fields[<prop>].inputControl` under `?_facetable=true`),\n\t\t\t// so a property declared once is asked for the same way on the\n\t\t\t// list, the facet, the API and the portal. Before this, a date\n\t\t\t// property rendered as a multi-select of nothing: the sidebar had\n\t\t\t// exactly two widgets and every non-boolean landed on one of them.\n\t\t\t//\n\t\t\t// An unknown control falls through to the type guess rather than\n\t\t\t// rendering nothing, because a widget this version has not learned\n\t\t\t// yet must degrade to a working one, not to an empty box.\n\t\t\tconst control = String(prop.inputControl || '').trim()\n\t\t\tif (control === 'date-range' || control === 'range') {\n\t\t\t\tfilter.type = 'date-range'\n\t\t\t\tif (Array.isArray(prop.presets)) {\n\t\t\t\t\tfilter.presets = prop.presets.map((preset) => ({\n\t\t\t\t\t\t...preset,\n\t\t\t\t\t\tlabel: tr(preset.label || preset.id),\n\t\t\t\t\t}))\n\t\t\t\t}\n\t\t\t} else if (control === 'text') {\n\t\t\t\tfilter.type = 'text'\n\t\t\t} else if (control === 'reference') {\n\t\t\t\t// A picker over another list. `optionsSource` says where the\n\t\t\t\t// rows come from; the VALUE is the referenced object's uuid,\n\t\t\t\t// never its title.\n\t\t\t\tfilter.type = 'reference'\n\t\t\t} else if (control === 'boolean') {\n\t\t\t\tfilter.type = 'checkbox'\n\t\t\t}\n\n\t\t\tif (prop.optionsSource && typeof prop.optionsSource === 'object') {\n\t\t\t\tfilter.optionsSource = prop.optionsSource\n\t\t\t}\n\n\t\t\t// A single-valued filter is one the server answers with ONE\n\t\t\t// argument (`priority`, `objectUuid`). Declared rather than\n\t\t\t// inferred: `multiselect` and `select` differ in nothing a widget\n\t\t\t// can see, and sending two values to an endpoint that reads one\n\t\t\t// silently answers about the last of them.\n\t\t\tfilter.multiple = control !== 'select' && control !== 'reference'\n\n\t\t\treturn filter\n\t\t})\n}\n\n/**\n * URL-like string formats — values must parse as a `URL` to be considered valid.\n */\nconst URL_FORMATS = new Set([\n\t'url',\n\t'uri',\n\t'uri-reference',\n\t'iri',\n\t'iri-reference',\n\t'uri-template',\n\t'accessUrl',\n\t'shareUrl',\n\t'downloadUrl',\n])\n\n/**\n * Regex-based validators for additional standard string formats.\n */\nconst FORMAT_PATTERNS = {\n\temail: /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/i,\n\t'idn-email': /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/i,\n\tuuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n\tipv4: /^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$/,\n\tipv6: /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/i,\n\thostname: /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i,\n\tsemver: /^\\d+\\.\\d+\\.\\d+(?:[-+][0-9A-Za-z.-]+)?$/,\n\t'color-hex': /^#[0-9a-f]{6}$/i,\n\t'color-hex-alpha': /^#[0-9a-f]{8}$/i,\n\t'color-rgb': /^rgb\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*\\)$/i,\n\t'color-rgba': /^rgba\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*[\\d.]+\\s*\\)$/i,\n\t'color-hsl': /^hsl\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}%\\s*,\\s*\\d{1,3}%\\s*\\)$/i,\n\t'color-hsla': /^hsla\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}%\\s*,\\s*\\d{1,3}%\\s*,\\s*[\\d.]+\\s*\\)$/i,\n}\n\n/**\n * Validate a single value against a JSON-Schema-style property definition.\n *\n * Returns null when the value is valid, otherwise a short English error\n * message describing the violation (caller is responsible for translation).\n * An empty value (`null`/`undefined`/`''`) is considered valid here unless\n * `options.required` is set; required-ness is typically enforced separately\n * by the form so an empty input doesn't show a redundant inline error.\n *\n * @param {unknown} value The value to validate.\n * @param {object} [property] The schema property definition.\n * @param {object} [options] Extra checks.\n * @param {boolean} [options.required] When true, an empty value is reported.\n * @return {string|null}\n */\nexport function validateValue(value, property = {}, options = {}) {\n\tconst { required = false } = options\n\tconst empty = value === null || value === undefined || value === ''\n\t\t|| (Array.isArray(value) && value.length === 0)\n\tif (empty) {\n\t\treturn required ? 'This field is required.' : null\n\t}\n\tconst type = property.type || 'string'\n\tif (type === 'integer') {\n\t\tif (typeof value !== 'number' || !Number.isInteger(value)) {\n\t\t\treturn 'Value must be an integer.'\n\t\t}\n\t} else if (type === 'number') {\n\t\tif (typeof value !== 'number' || Number.isNaN(value)) {\n\t\t\treturn 'Value must be a number.'\n\t\t}\n\t}\n\tif (type === 'integer' || type === 'number') {\n\t\tif (typeof property.minimum === 'number' && value < property.minimum) {\n\t\t\treturn `Value must be at least ${property.minimum}.`\n\t\t}\n\t\tif (typeof property.maximum === 'number' && value > property.maximum) {\n\t\t\treturn `Value must be at most ${property.maximum}.`\n\t\t}\n\t}\n\tif (type === 'string') {\n\t\tif (typeof value !== 'string') {\n\t\t\treturn 'Value must be a string.'\n\t\t}\n\t\tif (typeof property.minLength === 'number' && value.length < property.minLength) {\n\t\t\treturn `Must be at least ${property.minLength} characters.`\n\t\t}\n\t\tif (typeof property.maxLength === 'number' && value.length > property.maxLength) {\n\t\t\treturn `Must be at most ${property.maxLength} characters.`\n\t\t}\n\t\tif (property.pattern) {\n\t\t\ttry {\n\t\t\t\tif (!new RegExp(property.pattern).test(value)) {\n\t\t\t\t\treturn 'Value does not match the required pattern.'\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore broken schema patterns.\n\t\t\t}\n\t\t}\n\t\tif (property.const !== undefined && value !== property.const) {\n\t\t\treturn `Value must be '${property.const}'.`\n\t\t}\n\t\tconst fmtErr = validateStringFormat(property.format, value)\n\t\tif (fmtErr) {\n\t\t\treturn fmtErr\n\t\t}\n\t}\n\tif (type === 'array') {\n\t\tif (!Array.isArray(value)) {\n\t\t\treturn 'Value must be a list.'\n\t\t}\n\t\tif (typeof property.minItems === 'number' && value.length < property.minItems) {\n\t\t\treturn `Select at least ${property.minItems} items.`\n\t\t}\n\t\tif (typeof property.maxItems === 'number' && value.length > property.maxItems) {\n\t\t\treturn `Select at most ${property.maxItems} items.`\n\t\t}\n\t\tif (property.items && typeof property.items === 'object') {\n\t\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\t\tconst itemErr = validateValue(value[i], property.items)\n\t\t\t\tif (itemErr) {\n\t\t\t\t\treturn `Item ${i + 1}: ${itemErr}`\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (type === 'boolean' && typeof value !== 'boolean') {\n\t\treturn 'Value must be a boolean.'\n\t}\n\tif (Array.isArray(property.enum) && property.enum.length > 0 && !property.enum.includes(value)) {\n\t\treturn 'Value must be one of the allowed options.'\n\t}\n\treturn null\n}\n\n/**\n * Validate a string value against a JSON-Schema `format`.\n *\n * @param {string} format Schema format identifier.\n * @param {string} value String value to validate.\n * @return {string|null} Error message or null when valid.\n */\nfunction validateStringFormat(format, value) {\n\tif (!format) {\n\t\treturn null\n\t}\n\tif (format === 'time') {\n\t\t// HTML5 `<input type=\"time\">` produces `HH:MM` or `HH:MM:SS[.sss]`.\n\t\t// `new Date()` won't parse a bare time, so check the shape directly.\n\t\treturn /^([01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?$/.test(value)\n\t\t\t? null\n\t\t\t: 'Value must be a valid time.'\n\t}\n\tif (format === 'date' || format === 'date-time') {\n\t\treturn Number.isNaN(new Date(value).getTime()) ? `Value must be a valid ${format}.` : null\n\t}\n\tif (URL_FORMATS.has(format)) {\n\t\t// Accept fully-qualified URLs (`https://example.com`) and protocol-less\n\t\t// shorthand (`example.com/path`) by retrying with an `https://` prefix.\n\t\t// Reject obviously non-URL inputs (whitespace, missing dots / authority).\n\t\tif (/\\s/.test(value)) {\n\t\t\treturn 'Value must be a valid URL.'\n\t\t}\n\t\ttry {\n\t\t\tnew URL(value)\n\t\t\treturn null\n\t\t} catch {\n\t\t\t// Fall through to the prefix retry.\n\t\t}\n\t\ttry {\n\t\t\tconst parsed = new URL('https://' + value)\n\t\t\tif (parsed.hostname && parsed.hostname.includes('.')) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to the rejection below.\n\t\t}\n\t\treturn 'Value must be a valid URL.'\n\t}\n\tconst re = FORMAT_PATTERNS[format]\n\tif (re && !re.test(value)) {\n\t\treturn `Value must be a valid '${format}'.`\n\t}\n\treturn null\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema.js","sources":["../../../src/utils/schema.js"],"sourcesContent":["/**\n * Schema utility functions for auto-generating table columns, cell formatting,\n * form field definitions, and faceted filter definitions from OpenRegister\n * schema property definitions.\n *\n * @module utils/schema\n */\n\nimport { schemaRefSlug } from './schemaRefSlug.js'\n\n/**\n * Default column widths per property type/format.\n */\nconst DEFAULT_WIDTHS = {\n\tboolean: '80px',\n\tinteger: '100px',\n\tnumber: '100px',\n\t'string:uuid': '140px',\n\t'string:date-time': '180px',\n\t'string:email': '200px',\n}\n\n/**\n * Get default width for a property type + format combination.\n *\n * @param {string} type Property type\n * @param {string} [format] Property format\n * @return {string|undefined} CSS width or undefined\n */\nfunction getDefaultWidth(type, format) {\n\tif (format) {\n\t\treturn DEFAULT_WIDTHS[`${type}:${format}`]\n\t}\n\treturn DEFAULT_WIDTHS[type]\n}\n\n/**\n * Generate CnDataTable column definitions from a schema's properties.\n *\n * Reads `schema.properties` and creates column objects sorted by the `order`\n * hint (if present) then alphabetically. Filters out properties marked\n * `visible: false`. Supports include/exclude lists and per-column overrides.\n *\n * @param {object} schema The schema object with a `properties` field\n * @param {object} [options] Configuration options\n * @param {string[]} [options.exclude] Property keys to exclude\n * @param {string[]} [options.include] Property keys to include (whitelist mode)\n * @param {object} [options.overrides] Per-key column overrides, e.g. `{ status: { width: '200px' } }`\n * @param {(text: string) => string} [options.translate] Optional display-layer translation function applied to each column label. Schema property titles are authored in English as the canonical source; consumers pass their bound `t()` (via the injected `cnTranslate`) so the visible header follows the user's language. When omitted, the label is the English source string unchanged (pure, backward-compatible).\n * @return {Array<{key: string, label: string, sortable: boolean, type: string, format: string, width: string}>}\n */\nexport function columnsFromSchema(schema, options = {}) {\n\tconst { exclude = [], include = null, overrides = {}, translate } = options\n\tconst tr = typeof translate === 'function' ? translate : (text) => text\n\n\tif (!schema || !schema.properties) {\n\t\treturn []\n\t}\n\n\tconst entries = Object.entries(schema.properties)\n\t\t.filter(([key, prop]) => {\n\t\t\t// Skip properties marked as not visible\n\t\t\tif (prop.visible === false) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Apply exclude list\n\t\t\tif (exclude.includes(key)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Apply include whitelist\n\t\t\tif (include && !include.includes(key)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Skip complex object types by default (they don't render well in tables)\n\t\t\tif (prop.type === 'object') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\t.sort(([keyA, propA], [keyB, propB]) => {\n\t\t\t// Sort by order hint first, then alphabetically\n\t\t\tconst orderA = typeof propA.order === 'number' ? propA.order : Infinity\n\t\t\tconst orderB = typeof propB.order === 'number' ? propB.order : Infinity\n\t\t\tif (orderA !== orderB) {\n\t\t\t\treturn orderA - orderB\n\t\t\t}\n\t\t\treturn keyA.localeCompare(keyB)\n\t\t})\n\n\treturn entries.map(([key, prop]) => {\n\t\tconst column = {\n\t\t\tkey,\n\t\t\tlabel: tr(prop.title || key),\n\t\t\t// The schema already explains what the property MEANS; carrying that\n\t\t\t// through as the header tooltip means a column like \"Maturity\" or a\n\t\t\t// computed score explains itself in place, instead of the description\n\t\t\t// living only in the schema editor where no reader of the table looks.\n\t\t\tdescription: prop.description ? tr(prop.description) : '',\n\t\t\tsortable: true,\n\t\t\ttype: prop.type || 'string',\n\t\t\tformat: prop.format || null,\n\t\t}\n\n\t\t// Apply default width\n\t\tconst defaultWidth = getDefaultWidth(column.type, column.format)\n\t\tif (defaultWidth) {\n\t\t\tcolumn.width = defaultWidth\n\t\t}\n\n\t\t// Store enum values for cell renderer\n\t\tif (prop.enum) {\n\t\t\tcolumn.enum = prop.enum\n\t\t}\n\n\t\t// Store items type for arrays\n\t\tif (prop.items) {\n\t\t\tcolumn.items = prop.items\n\t\t}\n\n\t\t// Apply per-column overrides\n\t\tif (overrides[key]) {\n\t\t\tObject.assign(column, overrides[key])\n\t\t}\n\n\t\treturn column\n\t})\n}\n\n/**\n * Format a cell value based on its schema property definition.\n *\n * Handles dates, booleans, arrays, numbers, UUIDs, emails, and markdown.\n * Returns a plain string suitable for display in a table cell.\n *\n * @param {unknown} value The raw value\n * @param {object} [property] The schema property definition `{ type, format, enum, items }`\n * @param {object} [options] Formatting options\n * @param {number} [options.truncate] Maximum string length before truncation\n * @return {string} Formatted display string\n */\nexport function formatValue(value, property = {}, options = {}) {\n\tconst { truncate = 100 } = options\n\n\t// Null/undefined/empty\n\tif (value === null || value === undefined || value === '') {\n\t\treturn '—'\n\t}\n\n\tconst { type = 'string', format } = property\n\n\t// Boolean\n\tif (type === 'boolean' || typeof value === 'boolean') {\n\t\treturn value ? '✓' : '—'\n\t}\n\n\t// Number/Integer\n\tif (type === 'integer' || type === 'number') {\n\t\tconst num = Number(value)\n\t\tif (Number.isNaN(num)) {\n\t\t\treturn String(value)\n\t\t}\n\t\treturn num.toLocaleString()\n\t}\n\n\t// Array\n\tif (type === 'array' || Array.isArray(value)) {\n\t\tif (!Array.isArray(value)) {\n\t\t\treturn String(value)\n\t\t}\n\t\tif (value.length === 0) {\n\t\t\treturn '—'\n\t\t}\n\t\t// Stringify each entry so an array of OBJECTS never collapses to the\n\t\t// useless \"[object Object]\" that `Array.prototype.join` produces — a\n\t\t// nested object renders as compact JSON instead (ADR-062: a value cell\n\t\t// must never show \"[object Object]\"). Rich array rendering (inline\n\t\t// tables / chips) lives in CnObjectDataWidget; this is the flat-string\n\t\t// fallback used by tables and truncated cells.\n\t\tconst parts = value.map((v) => {\n\t\t\tif (v !== null && typeof v === 'object') {\n\t\t\t\ttry {\n\t\t\t\t\treturn JSON.stringify(v)\n\t\t\t\t} catch {\n\t\t\t\t\treturn '[Object]'\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn String(v)\n\t\t})\n\t\t// For short arrays, join values\n\t\tif (parts.length <= 3) {\n\t\t\treturn parts.join(', ')\n\t\t}\n\t\treturn `${parts.slice(0, 3).join(', ')} +${parts.length - 3}`\n\t}\n\n\t// Object — render as JSON; tables truncate, multi-line value cells wrap with `<pre>`.\n\tif (type === 'object' || (typeof value === 'object' && value !== null)) {\n\t\ttry {\n\t\t\treturn truncateString(JSON.stringify(value, null, 2), truncate)\n\t\t} catch {\n\t\t\treturn '[Object]'\n\t\t}\n\t}\n\n\t// String types\n\tconst str = String(value)\n\n\t// Date-time\n\tif (format === 'date-time' || format === 'date') {\n\t\ttry {\n\t\t\tconst date = new Date(str)\n\t\t\tif (Number.isNaN(date.getTime())) {\n\t\t\t\treturn str\n\t\t\t}\n\t\t\tif (format === 'date') {\n\t\t\t\treturn date.toLocaleDateString(undefined, {\n\t\t\t\t\tday: '2-digit',\n\t\t\t\t\tmonth: '2-digit',\n\t\t\t\t\tyear: 'numeric',\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn date.toLocaleDateString(undefined, {\n\t\t\t\tday: '2-digit',\n\t\t\t\tmonth: '2-digit',\n\t\t\t\tyear: 'numeric',\n\t\t\t}) + ', ' + date.toLocaleTimeString(undefined, {\n\t\t\t\thour: '2-digit',\n\t\t\t\tminute: '2-digit',\n\t\t\t\tsecond: '2-digit',\n\t\t\t})\n\t\t} catch {\n\t\t\treturn str\n\t\t}\n\t}\n\n\t// UUID — truncate to first 8 chars\n\tif (format === 'uuid') {\n\t\tif (str.length > 8) {\n\t\t\treturn str.substring(0, 8) + '...'\n\t\t}\n\t\treturn str\n\t}\n\n\t// URI — show truncated\n\tif (format === 'uri' || format === 'url') {\n\t\ttry {\n\t\t\tconst url = new URL(str)\n\t\t\treturn url.hostname + url.pathname.substring(0, 20)\n\t\t} catch {\n\t\t\treturn truncateString(str, truncate)\n\t\t}\n\t}\n\n\t// Markdown — strip formatting\n\tif (format === 'markdown') {\n\t\tconst stripped = str\n\t\t\t.replace(/#{1,6}\\s+/g, '') // headings\n\t\t\t.replace(/[*_]{1,3}([^*_]+)[*_]{1,3}/g, '$1') // bold/italic\n\t\t\t.replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, '$1') // links\n\t\t\t.replace(/`{1,3}[^`]*`{1,3}/g, '') // code\n\t\t\t.replace(/\\n+/g, ' ') // newlines\n\t\t\t.trim()\n\t\treturn truncateString(stripped, truncate)\n\t}\n\n\t// Email — display as-is (no truncation)\n\tif (format === 'email') {\n\t\treturn str\n\t}\n\n\t// Plain string — truncate if needed\n\treturn truncateString(str, truncate)\n}\n\n/**\n * Truncate a string to the given length, adding ellipsis if needed.\n *\n * @param {string} str The string to truncate\n * @param {number} maxLength Maximum length\n * @return {string} Truncated string\n */\nfunction truncateString(str, maxLength) {\n\tif (str.length <= maxLength) {\n\t\treturn str\n\t}\n\treturn str.substring(0, maxLength) + '...'\n}\n\n/**\n * Resolve the form widget type for a JSON Schema property.\n *\n * Resolution priority (first match wins):\n * 1. Explicit `prop.widget` — pass-through custom widget name\n * 2. `prop.enum` → `'select'`\n * 3. OpenRegister object reference: `prop.$ref` (a string schema slug) →\n * `'select'`; `array` + `items.$ref` → `'multiselect'`. The consuming\n * surface (CnFormDialog) resolves the reference to a searchable dropdown\n * of the referenced objects (label = human name, value = UUID).\n * 4. Nextcloud user reference: `referenceType: 'nextcloud-user'` (or\n * `format: 'user'`/`'username'`/`'nc-user'`) → `'user'`; an array of such\n * properties → `'user-multiselect'`. CnFormDialog resolves these to a\n * searchable dropdown of real Nextcloud users (label = display name,\n * value = UID). A Nextcloud group (`referenceType: 'nextcloud-group'` or\n * `format: 'nc-group'`) → `'group'`, an array of groups →\n * `'group-multiselect'`. `format: 'language'` → `'language'` and\n * `format: 'timezone'` → `'timezone'` (both searchable code lists).\n * 5. Type-based: `boolean` → `'checkbox'`, `integer`/`number` → `'number'`,\n * `array` + `items.enum` → `'multiselect'`, `array` → `'tags'`\n * 6. Format-based: `date-time` → `'datetime'`, `date` → `'date'`,\n * `email` → `'email'`, `uri`/`url` → `'url'`,\n * `markdown`/`textarea` → `'textarea'`\n * 7. Long text: `maxLength > 255` → `'textarea'`\n * 8. Fallback → `'text'`\n *\n * @param {object} prop The schema property definition (type, format, enum, widget, items, maxLength)\n * @return {string} Widget identifier: 'text'|'email'|'url'|'number'|'checkbox'|'select'|'multiselect'|'user'|'user-multiselect'|'tags'|'textarea'|'date'|'datetime' or a custom string\n */\n/**\n * Normalise a JSON-Schema `$ref` value into an OpenRegister schema reference\n * identifier. OpenRegister authors a `$ref` as a schema *slug* (string) but\n * persists/serves it as the numeric schema *id* (e.g. `85`). Both forms are\n * valid object-reference targets (the objects API resolves either).\n *\n * The schema editor writes the JSON-Pointer form — `#/components/schemas/<slug>`\n * — so a `$ref` reaching here may be a pointer rather than a bare slug. Passing\n * the whole pointer through as the schema identifier made the object picker query\n * a schema literally named \"#/components/schemas/cow\", which matches nothing: the\n * dropdown rendered but came back empty. Take the tail after the last `/`, which\n * is what the editor itself does when it resolves a $ref back to a schema.\n *\n * A `$ref` is authored as the schema's PascalCase (or spaced) *title*, not\n * its slug (`ReportPeriod`, not `report-period`); the objects API 404s on\n * the title for any multi-word schema (defect 7, learniq round 1). Routing\n * the tail through {@link schemaRefSlug} fixes that once here, for every\n * consumer of `reference.schema` built below.\n *\n * @param {unknown} ref A `$ref` value (`prop.$ref` or `prop.items.$ref`).\n * @return {string|number|null} The reference identifier, or null.\n */\nfunction normalizeRef(ref) {\n\tif (typeof ref === 'string' && ref !== '') {\n\t\tconst tail = ref.includes('/') ? ref.substring(ref.lastIndexOf('/') + 1) : ref\n\t\tif (tail === '') {\n\t\t\treturn null\n\t\t}\n\t\tconst slug = schemaRefSlug(tail)\n\t\treturn slug !== '' ? slug : null\n\t}\n\tif (typeof ref === 'number' && !Number.isNaN(ref)) {\n\t\treturn ref\n\t}\n\treturn null\n}\n\n/**\n * Whether a (single-value) schema property represents a Nextcloud user.\n *\n * A property is a user field when it declares `referenceType: 'nextcloud-user'`\n * (preferred) OR `format: 'user'` / `format: 'username'`. The consuming surface\n * (CnFormDialog) renders such a property as a searchable dropdown of real\n * Nextcloud users (label = display name, value = UID) instead of a free-text box.\n *\n * @param {object} prop A schema property definition (or `items` for an array).\n * @return {boolean} True when the property marks a Nextcloud user.\n */\nfunction isUserProp(prop) {\n\tif (!prop || typeof prop !== 'object') {\n\t\treturn false\n\t}\n\tif (prop.referenceType === 'nextcloud-user') {\n\t\treturn true\n\t}\n\tconst format = prop.format || ''\n\treturn format === 'user' || format === 'username' || format === 'nc-user'\n}\n\n/**\n * Whether a (single-value) schema property represents a Nextcloud group.\n *\n * A property is a group field when it declares `referenceType: 'nextcloud-group'`\n * or `format: 'nc-group'`. CnFormDialog renders it as a searchable dropdown of\n * Nextcloud groups (label = display name, value = group id).\n *\n * @spec openspec/changes/form-pickers-from-schema/specs/schema-utilities/spec.md\n * @param {object} prop A schema property definition (or `items` for an array).\n * @return {boolean} True when the property marks a Nextcloud group.\n */\nfunction isGroupProp(prop) {\n\tif (!prop || typeof prop !== 'object') {\n\t\treturn false\n\t}\n\treturn prop.referenceType === 'nextcloud-group' || prop.format === 'nc-group'\n}\n\n/**\n * @spec openspec/changes/form-pickers-from-schema/specs/schema-utilities/spec.md\n * @param {object} prop The schema property definition.\n * @return {string} The widget identifier (see the block above).\n */\nfunction resolveWidget(prop) {\n\t// Explicit widget hint takes priority\n\tif (prop.widget) {\n\t\treturn prop.widget\n\t}\n\n\t// Enum → select\n\tif (prop.enum) {\n\t\treturn 'select'\n\t}\n\n\tconst type = prop.type || 'string'\n\tconst format = prop.format || ''\n\n\t// OpenRegister object reference (`$ref` is a schema slug or numeric id) →\n\t// a searchable dropdown of the referenced objects. An array of\n\t// references (`items.$ref`) → a multi-select. Checked before the\n\t// plain type/format fallback so a `{ type: 'string', format: 'uuid',\n\t// $ref: '<slug-or-id>' }` property renders as a dropdown, not a UUID box.\n\tif (normalizeRef(prop.$ref) !== null) {\n\t\treturn 'select'\n\t}\n\tif (type === 'array' && prop.items && normalizeRef(prop.items.$ref) !== null) {\n\t\treturn 'multiselect'\n\t}\n\n\t// Nextcloud user reference (referenceType 'nextcloud-user' or\n\t// format 'user'/'username'): a searchable dropdown of real Nextcloud\n\t// users (label = display name, value = UID). An array of users is a\n\t// multi-select. Checked before the plain type/format fallback so a\n\t// user-marked property renders as a picker, not a free-text box.\n\tif (isUserProp(prop)) {\n\t\treturn 'user'\n\t}\n\tif (type === 'array' && isUserProp(prop.items)) {\n\t\treturn 'user-multiselect'\n\t}\n\n\t// Nextcloud group (`format: 'nc-group'` / `referenceType: 'nextcloud-group'`):\n\t// a searchable dropdown of groups storing the group id.\n\tif (isGroupProp(prop)) {\n\t\treturn 'group'\n\t}\n\tif (type === 'array' && isGroupProp(prop.items)) {\n\t\treturn 'group-multiselect'\n\t}\n\n\t// Language and time zone codes: a searchable list instead of a free-text\n\t// box, so a person picks \"Dutch\" and the record stores `nl`.\n\tif (type === 'string' && format === 'language') {\n\t\treturn 'language'\n\t}\n\tif (type === 'string' && format === 'timezone') {\n\t\treturn 'timezone'\n\t}\n\n\t// Boolean → switch/checkbox\n\tif (type === 'boolean') {\n\t\treturn 'checkbox'\n\t}\n\n\t// Number types\n\tif (type === 'integer' || type === 'number') {\n\t\treturn 'number'\n\t}\n\n\t// Array types\n\tif (type === 'array') {\n\t\tif (prop.items && prop.items.enum) {\n\t\t\treturn 'multiselect'\n\t\t}\n\t\treturn 'tags'\n\t}\n\n\t// Format-based widgets\n\tif (format === 'date-time') {\n\t\treturn 'datetime'\n\t}\n\tif (format === 'date') {\n\t\treturn 'date'\n\t}\n\tif (format === 'email') {\n\t\treturn 'email'\n\t}\n\tif (format === 'uri' || format === 'url') {\n\t\treturn 'url'\n\t}\n\tif (format === 'markdown' || format === 'textarea') {\n\t\treturn 'textarea'\n\t}\n\n\t// Long text → textarea\n\tif (prop.maxLength && prop.maxLength > 255) {\n\t\treturn 'textarea'\n\t}\n\n\treturn 'text'\n}\n\n/**\n * Longest description rendered inline as helper text. Beyond this a field's\n * description is split — a short lead-in stays under the input, the full text\n * moves behind the info popover — because some schema properties document a\n * whole adapter dispatch table and would otherwise dwarf the field itself.\n */\nconst DESCRIPTION_INLINE_MAX = 120\n\n/** Tokens ending in a period that do not end a sentence. */\nconst NON_TERMINAL_ABBREVIATIONS = ['e.g', 'i.e', 'etc', 'vs', 'cf', 'incl', 'approx', 'resp', 'no']\n\n/**\n * The first sentence of `text`, or '' when it has no sentence boundary.\n *\n * @param {string} text The text to scan.\n * @return {string} The first sentence including its terminator.\n */\nfunction firstSentenceOf(text) {\n\tconst boundary = /[.!?](?=\\s|$)/g\n\tlet match\n\twhile ((match = boundary.exec(text)) !== null) {\n\t\tconst lastWord = text.slice(0, match.index).split(/\\s+/).pop().toLowerCase()\n\t\t// \"e.g.\" and single-letter initials carry a period mid-sentence.\n\t\tif (NON_TERMINAL_ABBREVIATIONS.includes(lastWord) || /^[a-z]$/i.test(lastWord)) {\n\t\t\tcontinue\n\t\t}\n\t\treturn text.slice(0, match.index + 1)\n\t}\n\treturn ''\n}\n\n/**\n * Truncate to `max` characters on a word boundary, with an ellipsis.\n *\n * @param {string} text The text to clamp.\n * @param {number} max The maximum length before the ellipsis.\n * @return {string} The clamped text.\n */\nfunction clampToWord(text, max) {\n\tconst cut = text.slice(0, max)\n\tconst lastSpace = cut.lastIndexOf(' ')\n\t// Only honour the word boundary when it isn't hacking off most of the clamp.\n\treturn `${(lastSpace > max * 0.6 ? cut.slice(0, lastSpace) : cut).trimEnd()}…`\n}\n\n/**\n * Split a description into the part rendered inline and the full text.\n *\n * Short descriptions (the overwhelming majority — \"Human-readable name\") pass\n * through untouched with no long form. Longer ones yield their first sentence\n * as `short` when that alone fits, else a word-clamped prefix, and the whole\n * original as `long` for the caller to put behind an info affordance.\n *\n * @param {string} text The raw description.\n * @param {number} [max] Longest text kept inline.\n * @return {{short: string, long: string}} The inline text and the full text ('' when nothing was split off).\n */\nexport function splitDescription(text, max = DESCRIPTION_INLINE_MAX) {\n\tconst full = typeof text === 'string' ? text.trim() : ''\n\tif (!full || full.length <= max) {\n\t\treturn { short: full, long: '' }\n\t}\n\n\tconst sentence = firstSentenceOf(full)\n\treturn {\n\t\tshort: sentence && sentence.length <= max ? sentence : clampToWord(full, max),\n\t\tlong: full,\n\t}\n}\n\n/**\n * Property names that carry the tenant a record belongs to, compared after\n * lower-casing and dropping `_` / `-`, so `tenant_id`, `tenantId` and\n * `tenant-id` all match.\n *\n * @type {Set<string>}\n */\nconst TENANT_PROPERTY_NAMES = new Set(['tenant', 'tenantid', 'tenantuuid'])\n\n/**\n * Whether a schema property holds the tenant a record belongs to.\n *\n * Tenant is set by the platform, never by the person filling in a form, so\n * a create form must not ask for it. OpenRegister marks no such property\n * itself: learniq's work group ships `tenant_id` as a plain required string\n * with no format, no `readOnly` and no flag, which is why the create dialog\n * showed a required \"Tenant *\" box. So the test reads the property's\n * semantics in this order:\n *\n * 1. An explicit opt-out, `x-openregister-tenant: false`, keeps it a normal field.\n * 2. An explicit marker makes it a tenant field whatever it is called:\n * `x-openregister-tenant: true`, `x-platform-managed: true`,\n * `x-managed-by: 'platform'`, `format: 'tenant'` or `referenceType: 'tenant'`.\n * 3. Otherwise its name decides: `tenant`, `tenant_id` / `tenantId` or `tenant_uuid`.\n *\n * `organisation` is deliberately NOT matched by name: plenty of schemas let a\n * person pick an organisation (a contact's employer, a supplier), and hiding\n * that would take a real question away. A schema whose `organisation`\n * property is the tenant says so with one of the markers above.\n *\n * @param {string} key The property key.\n * @param {object} prop The property definition.\n * @return {boolean} True when the property is platform-managed tenancy.\n */\nexport function isTenantProperty(key, prop) {\n\tconst p = (prop && typeof prop === 'object') ? prop : {}\n\tif (p['x-openregister-tenant'] === false) {\n\t\treturn false\n\t}\n\tif (p['x-openregister-tenant'] === true\n\t\t|| p['x-platform-managed'] === true\n\t\t|| p['x-managed-by'] === 'platform'\n\t\t|| p.format === 'tenant'\n\t\t|| p.referenceType === 'tenant') {\n\t\treturn true\n\t}\n\tconst name = typeof key === 'string' ? key.toLowerCase().replace(/[-_]/g, '') : ''\n\treturn TENANT_PROPERTY_NAMES.has(name)\n}\n\n/**\n * Generate form field definitions from a schema's properties.\n *\n * Reads `schema.properties` and creates field descriptor objects suitable\n * for auto-generating form UIs. Follows the same pattern as\n * `columnsFromSchema()` — filters, sorts, and supports overrides.\n *\n * @param {object} schema The schema object with a `properties` field\n * @param {object} [options] Configuration options\n * @param {string[]} [options.exclude] Property keys to exclude\n * @param {string[]} [options.include] Property keys to include (whitelist mode)\n * @param {object} [options.overrides] Per-key field overrides, e.g. `{ status: { widget: 'select' } }`. Recognised keys: `hidden` (true → drop the field), `order` (number → wins over the schema property's `order` for sorting), `readOnly` (false on a schema-readOnly key un-skips it), plus any field props to merge (`label`, `widget`, `enum`, …). A single overrides map therefore controls visibility, ordering and rendering on every surface that consumes this pipeline (data widget + form dialog).\n * @param {boolean} [options.includeReadOnly] Whether to include readOnly properties\n * @param {boolean} [options.hideTenant] Drop properties that hold the record's tenant (see `isTenantProperty`). Off by default, so a detail page still shows the tenant; CnFormDialog turns it on because nobody should be asked for it. `overrides[key].hidden === false` keeps one visible.\n * @param {(text: string) => string} [options.translate] Optional display-layer translation function applied to each field's `label` and `description`. Schema property titles/descriptions are authored in English as the canonical source; consumers pass their bound `t()` (via the injected `cnTranslate`) so the rendered field label follows the user's language. When omitted, label/description are the English source strings unchanged (pure, backward-compatible).\n * @spec openspec/changes/form-pickers-from-schema/specs/schema-utilities/spec.md\n * @return {Array<{key: string, label: string, description: string, descriptionLong: string, type: string, format: string|null, widget: string, required: boolean, readOnly: boolean, default: unknown, enum: Array|null, enumLabels: object|null, items: object|null, referenceType: string|null, referenceSemanticType: string|null, referenceSemanticApp: string|null, reference: {schema: string|number, multiple: boolean, register?: string, labelField?: string}|null, allowCreate: boolean, userPicker: {multiple: boolean}|null, groupPicker: {multiple: boolean}|null, defaultToken: string|null, fillFrom: object|null, validation: object, order: number}>} `description` is the inline helper text (see `splitDescription`); `descriptionLong` carries the property's `x-help` text when it declares one, else the full description when it was too long to render inline, else ''. `enumLabels` maps each raw enum value to its English display label (from the property's `x-enum-labels`), or null.\n */\nexport function fieldsFromSchema(schema, options = {}) {\n\tconst { exclude = [], include = null, overrides = {}, includeReadOnly = false, hideTenant = false, translate } = options\n\tconst tr = typeof translate === 'function' ? translate : (text) => text\n\n\tif (!schema || !schema.properties) {\n\t\treturn []\n\t}\n\n\tconst requiredKeys = Array.isArray(schema.required) ? schema.required : []\n\n\tconst entries = Object.entries(schema.properties)\n\t\t.filter(([key, prop]) => {\n\t\t\t// Skip properties marked as not visible\n\t\t\tif (prop.visible === false) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Per-key override visibility: `overrides[key].hidden === true` hides\n\t\t\t// the field on every surface that consumes this pipeline (data widget\n\t\t\t// + form dialog), so a single config map controls both.\n\t\t\tif (overrides[key]?.hidden === true) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Platform-managed tenancy (`tenant_id` and friends): nobody is\n\t\t\t// asked for it on a form. An explicit `hidden: false` override\n\t\t\t// brings it back for the rare surface that does need it.\n\t\t\tif (hideTenant && overrides[key]?.hidden !== false && isTenantProperty(key, prop)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Skip readOnly properties by default — UNLESS a per-key override\n\t\t\t// explicitly re-enables the field (`overrides[key].readOnly === false`).\n\t\t\t// This lets a consumer surface a schema-readOnly field (e.g. a\n\t\t\t// denormalised name that's read-only on edit but must be collected\n\t\t\t// on create) without flipping the whole form to includeReadOnly.\n\t\t\tif (prop.readOnly === true && !includeReadOnly && overrides[key]?.readOnly !== false) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Apply exclude list\n\t\t\tif (exclude.includes(key)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Apply include whitelist\n\t\t\tif (include && !include.includes(key)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Skip complex object types unless the caller opts in with an explicit widget\n\t\t\t// (e.g. `widget: 'json'` or `widget: 'code'` in CnFormDialog) — or unless the\n\t\t\t// property is an OpenRegister object REFERENCE (`$ref`). A reference is a\n\t\t\t// relation to another schema's object, which resolveWidget maps to a\n\t\t\t// searchable 'select'; dropping it here meant a related-object property\n\t\t\t// (e.g. cow.barn → barn) silently never rendered in the form at all.\n\t\t\tif (prop.type === 'object' && !prop.widget && normalizeRef(prop.$ref) === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\t.sort(([keyA, propA], [keyB, propB]) => {\n\t\t\t// Sort by EFFECTIVE order: a per-key `overrides[key].order` wins over\n\t\t\t// the schema property's own `order`, then alphabetically. Honouring the\n\t\t\t// override here means every consumer (data widget + form dialog) gets\n\t\t\t// the same ordering from one map — no per-component re-sort needed.\n\t\t\tconst orderA = typeof overrides[keyA]?.order === 'number'\n\t\t\t\t? overrides[keyA].order\n\t\t\t\t: (typeof propA.order === 'number' ? propA.order : Infinity)\n\t\t\tconst orderB = typeof overrides[keyB]?.order === 'number'\n\t\t\t\t? overrides[keyB].order\n\t\t\t\t: (typeof propB.order === 'number' ? propB.order : Infinity)\n\t\t\tif (orderA !== orderB) {\n\t\t\t\treturn orderA - orderB\n\t\t\t}\n\t\t\treturn keyA.localeCompare(keyB)\n\t\t})\n\n\treturn entries.map(([key, prop]) => {\n\t\tconst description = splitDescription(prop.description ? tr(prop.description) : '')\n\t\t// `x-help` is the long explanation behind the (i) popover. It always\n\t\t// shows the popover, while `description` stays the short helper line.\n\t\tconst help = typeof prop['x-help'] === 'string' && prop['x-help'].trim() !== ''\n\t\t\t? tr(prop['x-help'].trim())\n\t\t\t: ''\n\t\tconst labelField = prop['x-label-field']\n\t\t\t|| (prop.items && prop.items['x-label-field'])\n\t\t\t|| null\n\t\tconst field = {\n\t\t\tkey,\n\t\t\tlabel: tr(prop.title || key),\n\t\t\tdescription: description.short,\n\t\t\tdescriptionLong: help || description.long,\n\t\t\ttype: prop.type || 'string',\n\t\t\tformat: prop.format || null,\n\t\t\twidget: resolveWidget(prop),\n\t\t\t// Icon picker (`widget: 'icon'`) config forwarded to CnIconBrowser via\n\t\t\t// CnFormDialog: which sources to offer (`iconSources`), consumer icon\n\t\t\t// catalogues (JSON entries — FontAwesome/OpenGemeenten data is usually\n\t\t\t// supplied via a fieldOverride instead), and whether custom-SVG is\n\t\t\t// enabled. `searchable` is obsolete — the browser always searches.\n\t\t\t// Omitted keys fall back to CnIconBrowser's own defaults, which include\n\t\t\t// the bundled NL-government sets.\n\t\t\ticonSources: prop.iconSources || undefined,\n\t\t\tcatalogues: prop.catalogues || undefined,\n\t\t\tallowCustomSvg: prop.allowCustomSvg || undefined,\n\t\t\tsearchable: prop.searchable,\n\t\t\trequired: requiredKeys.includes(key),\n\t\t\treadOnly: prop.readOnly || false,\n\t\t\tdefault: prop.default !== undefined ? prop.default : null,\n\t\t\t// A default that depends on who opens the form (`x-default:\n\t\t\t// 'current-language'` / `'current-timezone'`). Resolved by the\n\t\t\t// consuming form on a NEW object only; never on edit.\n\t\t\tdefaultToken: typeof prop['x-default'] === 'string' ? prop['x-default'] : null,\n\t\t\tenum: prop.enum || null,\n\t\t\t// Display labels for the enum CODES, keyed by raw value. An enum\n\t\t\t// value is a stored contract value, not display text — several are\n\t\t\t// non-English by design (`ingediend`) — so a schema declares the\n\t\t\t// English label here and the consumer surface translates THAT.\n\t\t\t// Without it the only thing a form can show is the raw code.\n\t\t\tenumLabels: prop.enumLabels\n\t\t\t\t|| prop['x-enum-labels']\n\t\t\t\t|| (prop.items && (prop.items.enumLabels || prop.items['x-enum-labels']))\n\t\t\t\t|| null,\n\t\t\titems: prop.items || null,\n\t\t\t// Pluggable integration registry marker (AD-18): a property\n\t\t\t// can declare `referenceType: '<integration-id>'` so consumer\n\t\t\t// surfaces (CnFormDialog, CnDetailGrid) render that\n\t\t\t// integration's single-entity widget instead of a plain input.\n\t\t\treferenceType: prop.referenceType || null,\n\t\t\t// Cross-app semantic reference (ADR-048): a property can declare\n\t\t\t// `referenceSemanticType: '<canonical-uri>'` (e.g.\n\t\t\t// 'https://schema.org/Organization') plus an optional\n\t\t\t// `referenceSemanticApp: '<appid>'` naming the app expected to\n\t\t\t// provide it. The consuming surface (CnFormDialog) resolves the\n\t\t\t// URI against OpenRegister's discovery endpoint: when SOME\n\t\t\t// installed schema implements it, the field renders as a\n\t\t\t// searchable object picker over that provider schema's register;\n\t\t\t// when NONE does, the field renders DISABLED with a tooltip. This\n\t\t\t// is the semantic sibling of `referenceType` (integration id).\n\t\t\t// `null` when the keys are absent (no behaviour change). Pure: no\n\t\t\t// resolution happens here.\n\t\t\treferenceSemanticType: prop.referenceSemanticType || null,\n\t\t\treferenceSemanticApp: prop.referenceSemanticApp || null,\n\t\t\t// OpenRegister object reference (`$ref`): when a property points\n\t\t\t// at another schema (`$ref: '<slug>'`, or `items.$ref` for an\n\t\t\t// array), record the referenced schema slug + whether it is a\n\t\t\t// multi-value reference. The consuming surface (CnFormDialog)\n\t\t\t// resolves this to a searchable dropdown of the referenced\n\t\t\t// objects, storing the chosen UUID(s). `null` for non-reference\n\t\t\t// properties. Pure: no fetching happens here.\n\t\t\t//\n\t\t\t// Cross-app object relation (ADR-066): a reference property may\n\t\t\t// carry `x-external-register: '<app>'` naming the register the\n\t\t\t// referenced schema lives in — a link into ANOTHER fleet app\n\t\t\t// (e.g. a procest case referencing a decidesk decision). When\n\t\t\t// present it is recorded as `reference.register` so the picker\n\t\t\t// resolves/scopes/creates against that register instead of the\n\t\t\t// form's own; absent, the reference stays same-register (the form's\n\t\t\t// `register` prop is used). Consolidates the ad-hoc caseReference /\n\t\t\t// approvalDecisionId / x-mirror-of variants onto one convention.\n\t\t\t//\n\t\t\t// `x-label-field` names the referenced object's property that labels\n\t\t\t// an option and that an inline create writes the typed term to\n\t\t\t// (`reference.labelField`, default `name` at the consumer).\n\t\t\treference: (normalizeRef(prop.$ref) !== null)\n\t\t\t\t? { schema: normalizeRef(prop.$ref), multiple: false, ...(prop['x-external-register'] ? { register: prop['x-external-register'] } : {}), ...(labelField ? { labelField } : {}) }\n\t\t\t\t: (prop.type === 'array' && prop.items && normalizeRef(prop.items.$ref) !== null)\n\t\t\t\t\t\t? { schema: normalizeRef(prop.items.$ref), multiple: true, ...((prop.items['x-external-register'] || prop['x-external-register']) ? { register: prop.items['x-external-register'] || prop['x-external-register'] } : {}), ...(labelField ? { labelField } : {}) }\n\t\t\t\t\t\t: null,\n\t\t\t// Select OR create (`x-allow-create: true`, on the property or on\n\t\t\t// its `items` for an array): the picker offers \"Create\" next to the\n\t\t\t// existing objects. Only meaningful on a reference.\n\t\t\tallowCreate: prop['x-allow-create'] === true\n\t\t\t\t|| (prop.type === 'array' && !!prop.items && prop.items['x-allow-create'] === true),\n\t\t\t// Template copy (`x-fill-from: { formKey: sourceKey }`): choosing a\n\t\t\t// referenced object copies those of its values into this form.\n\t\t\tfillFrom: (prop['x-fill-from'] && typeof prop['x-fill-from'] === 'object') ? prop['x-fill-from'] : null,\n\t\t\t// Nextcloud user reference: when a property marks a NC user\n\t\t\t// (`referenceType: 'nextcloud-user'`, or `format: 'user'`/\n\t\t\t// `'username'`), tag it so CnFormDialog renders a searchable\n\t\t\t// dropdown of real Nextcloud users (label = display name,\n\t\t\t// value = UID) instead of a free-text box. `multiple` is true\n\t\t\t// for an array of users (`items` marks the user). `null` for\n\t\t\t// non-user properties. Pure: no fetching happens here.\n\t\t\tuserPicker: isUserProp(prop)\n\t\t\t\t? { multiple: false }\n\t\t\t\t: (prop.type === 'array' && isUserProp(prop.items))\n\t\t\t\t\t\t? { multiple: true }\n\t\t\t\t\t\t: null,\n\t\t\t// Nextcloud group reference (`format: 'nc-group'` or\n\t\t\t// `referenceType: 'nextcloud-group'`): the form stores the group id.\n\t\t\tgroupPicker: isGroupProp(prop)\n\t\t\t\t? { multiple: false }\n\t\t\t\t: (prop.type === 'array' && isGroupProp(prop.items))\n\t\t\t\t\t\t? { multiple: true }\n\t\t\t\t\t\t: null,\n\t\t\t// Conditional immutability (AD: x-openregister-readonly-when): a\n\t\t\t// property can declare it becomes read-only when another field on the\n\t\t\t// same object holds a given value — e.g. a hybrid app's identity\n\t\t\t// fields. Consumers (CnObjectDataWidget) evaluate this against the\n\t\t\t// object's current data. Shape: `{ field, equals }` or `{ field, in: [] }`.\n\t\t\treadOnlyWhen: prop['x-openregister-readonly-when'] || prop.readOnlyWhen || null,\n\t\t\tvalidation: {\n\t\t\t\tminLength: prop.minLength,\n\t\t\t\tmaxLength: prop.maxLength,\n\t\t\t\tminimum: prop.minimum,\n\t\t\t\tmaximum: prop.maximum,\n\t\t\t\tpattern: prop.pattern,\n\t\t\t},\n\t\t\torder: typeof prop.order === 'number' ? prop.order : Infinity,\n\t\t}\n\n\t\t// Apply per-field overrides\n\t\tif (overrides[key]) {\n\t\t\tObject.assign(field, overrides[key])\n\t\t}\n\n\t\treturn field\n\t})\n}\n\n/**\n * Generate faceted filter definitions from a schema's facetable properties.\n *\n * Reads `schema.properties` and creates filter definitions for properties\n * marked with `facetable: true`. Maps property types to appropriate filter\n * widget types (select, checkbox, text).\n *\n * A property may say how it wants to be asked for, with `inputControl` —\n * the same word openregister answers under `?_facetable=true`. One of\n * `text`, `select`, `multiselect`, `range`, `date-range`, `boolean` or\n * `reference`. It wins over the type guess; an unknown one falls back to it.\n *\n * @param {object} schema The schema object with a `properties` field\n * @param {object} [options] Configuration options\n * @param {(text: string) => string} [options.translate] Optional display-layer translation function applied to each filter's `label` and `description`. Schema property titles are authored in English as the canonical source; consumers pass their bound `t()` (via the injected `cnTranslate`) so the rendered filter label follows the user's language. When omitted, label/description are the English source strings unchanged (pure, backward-compatible).\n * @return {Array<{key: string, label: string, type: string, propertyType: string, options: Array}>}\n */\nexport function filtersFromSchema(schema, options = {}) {\n\tif (!schema || !schema.properties) {\n\t\treturn []\n\t}\n\n\tconst { translate } = options\n\tconst tr = typeof translate === 'function' ? translate : (text) => text\n\n\treturn Object.entries(schema.properties)\n\t\t.filter(([, prop]) => {\n\t\t\tif (prop.facetable !== true) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\t.sort(([keyA, propA], [keyB, propB]) => {\n\t\t\tconst orderA = typeof propA.order === 'number' ? propA.order : Infinity\n\t\t\tconst orderB = typeof propB.order === 'number' ? propB.order : Infinity\n\t\t\tif (orderA !== orderB) {\n\t\t\t\treturn orderA - orderB\n\t\t\t}\n\t\t\treturn keyA.localeCompare(keyB)\n\t\t})\n\t\t.map(([key, prop]) => {\n\t\t\tconst filter = {\n\t\t\t\tkey,\n\t\t\t\tlabel: tr(prop.title || key),\n\t\t\t\tdescription: prop.description ? tr(prop.description) : '',\n\t\t\t\tpropertyType: prop.type || 'string',\n\t\t\t\toptions: [],\n\t\t\t\tvalue: null,\n\t\t\t}\n\n\t\t\t// Map property type to filter widget type\n\t\t\tif (prop.type === 'boolean') {\n\t\t\t\tfilter.type = 'checkbox'\n\t\t\t} else if (prop.enum) {\n\t\t\t\tfilter.type = 'select'\n\t\t\t\tconst enumLabels = prop.enumLabels || prop['x-enum-labels'] || {}\n\t\t\t\tfilter.options = prop.enum.map((val) => ({\n\t\t\t\t\tid: val,\n\t\t\t\t\t// The filter VALUE stays the raw schema code (it is what the\n\t\t\t\t\t// query sends); only the label follows the user's language.\n\t\t\t\t\tlabel: tr(enumLabels[val] || String(val)),\n\t\t\t\t}))\n\t\t\t} else {\n\t\t\t\t// Default to select — options loaded dynamically from facet API\n\t\t\t\tfilter.type = 'select'\n\t\t\t}\n\n\t\t\t// 🔑 `inputControl` IS THE PROPERTY'S OWN ANSWER TO \"HOW DO I ASK\n\t\t\t// FOR THIS\", and it wins over the type guess above. It is the same\n\t\t\t// word openregister's PropertySearchProfile reads\n\t\t\t// (`searchable_fields[<prop>].inputControl` under `?_facetable=true`),\n\t\t\t// so a property declared once is asked for the same way on the\n\t\t\t// list, the facet, the API and the portal. Before this, a date\n\t\t\t// property rendered as a multi-select of nothing: the sidebar had\n\t\t\t// exactly two widgets and every non-boolean landed on one of them.\n\t\t\t//\n\t\t\t// An unknown control falls through to the type guess rather than\n\t\t\t// rendering nothing, because a widget this version has not learned\n\t\t\t// yet must degrade to a working one, not to an empty box.\n\t\t\tconst control = String(prop.inputControl || '').trim()\n\t\t\tif (control === 'date-range' || control === 'range') {\n\t\t\t\tfilter.type = 'date-range'\n\t\t\t\tif (Array.isArray(prop.presets)) {\n\t\t\t\t\tfilter.presets = prop.presets.map((preset) => ({\n\t\t\t\t\t\t...preset,\n\t\t\t\t\t\tlabel: tr(preset.label || preset.id),\n\t\t\t\t\t}))\n\t\t\t\t}\n\t\t\t} else if (control === 'text') {\n\t\t\t\tfilter.type = 'text'\n\t\t\t} else if (control === 'reference') {\n\t\t\t\t// A picker over another list. `optionsSource` says where the\n\t\t\t\t// rows come from; the VALUE is the referenced object's uuid,\n\t\t\t\t// never its title.\n\t\t\t\tfilter.type = 'reference'\n\t\t\t} else if (control === 'boolean') {\n\t\t\t\tfilter.type = 'checkbox'\n\t\t\t}\n\n\t\t\tif (prop.optionsSource && typeof prop.optionsSource === 'object') {\n\t\t\t\tfilter.optionsSource = prop.optionsSource\n\t\t\t}\n\n\t\t\t// A single-valued filter is one the server answers with ONE\n\t\t\t// argument (`priority`, `objectUuid`). Declared rather than\n\t\t\t// inferred: `multiselect` and `select` differ in nothing a widget\n\t\t\t// can see, and sending two values to an endpoint that reads one\n\t\t\t// silently answers about the last of them.\n\t\t\tfilter.multiple = control !== 'select' && control !== 'reference'\n\n\t\t\treturn filter\n\t\t})\n}\n\n/**\n * URL-like string formats — values must parse as a `URL` to be considered valid.\n */\nconst URL_FORMATS = new Set([\n\t'url',\n\t'uri',\n\t'uri-reference',\n\t'iri',\n\t'iri-reference',\n\t'uri-template',\n\t'accessUrl',\n\t'shareUrl',\n\t'downloadUrl',\n])\n\n/**\n * Regex-based validators for additional standard string formats.\n */\nconst FORMAT_PATTERNS = {\n\temail: /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/i,\n\t'idn-email': /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/i,\n\tuuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n\tipv4: /^((25[0-5]|(2[0-4]|1\\d|[1-9]|)\\d)\\.?\\b){4}$/,\n\tipv6: /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/i,\n\thostname: /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i,\n\tsemver: /^\\d+\\.\\d+\\.\\d+(?:[-+][0-9A-Za-z.-]+)?$/,\n\t'color-hex': /^#[0-9a-f]{6}$/i,\n\t'color-hex-alpha': /^#[0-9a-f]{8}$/i,\n\t'color-rgb': /^rgb\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*\\)$/i,\n\t'color-rgba': /^rgba\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*\\d{1,3}\\s*,\\s*[\\d.]+\\s*\\)$/i,\n\t'color-hsl': /^hsl\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}%\\s*,\\s*\\d{1,3}%\\s*\\)$/i,\n\t'color-hsla': /^hsla\\(\\s*\\d{1,3}\\s*,\\s*\\d{1,3}%\\s*,\\s*\\d{1,3}%\\s*,\\s*[\\d.]+\\s*\\)$/i,\n}\n\n/**\n * Validate a single value against a JSON-Schema-style property definition.\n *\n * Returns null when the value is valid, otherwise a short English error\n * message describing the violation (caller is responsible for translation).\n * An empty value (`null`/`undefined`/`''`) is considered valid here unless\n * `options.required` is set; required-ness is typically enforced separately\n * by the form so an empty input doesn't show a redundant inline error.\n *\n * @param {unknown} value The value to validate.\n * @param {object} [property] The schema property definition.\n * @param {object} [options] Extra checks.\n * @param {boolean} [options.required] When true, an empty value is reported.\n * @return {string|null}\n */\nexport function validateValue(value, property = {}, options = {}) {\n\tconst { required = false } = options\n\tconst empty = value === null || value === undefined || value === ''\n\t\t|| (Array.isArray(value) && value.length === 0)\n\tif (empty) {\n\t\treturn required ? 'This field is required.' : null\n\t}\n\tconst type = property.type || 'string'\n\tif (type === 'integer') {\n\t\tif (typeof value !== 'number' || !Number.isInteger(value)) {\n\t\t\treturn 'Value must be an integer.'\n\t\t}\n\t} else if (type === 'number') {\n\t\tif (typeof value !== 'number' || Number.isNaN(value)) {\n\t\t\treturn 'Value must be a number.'\n\t\t}\n\t}\n\tif (type === 'integer' || type === 'number') {\n\t\tif (typeof property.minimum === 'number' && value < property.minimum) {\n\t\t\treturn `Value must be at least ${property.minimum}.`\n\t\t}\n\t\tif (typeof property.maximum === 'number' && value > property.maximum) {\n\t\t\treturn `Value must be at most ${property.maximum}.`\n\t\t}\n\t}\n\tif (type === 'string') {\n\t\tif (typeof value !== 'string') {\n\t\t\treturn 'Value must be a string.'\n\t\t}\n\t\tif (typeof property.minLength === 'number' && value.length < property.minLength) {\n\t\t\treturn `Must be at least ${property.minLength} characters.`\n\t\t}\n\t\tif (typeof property.maxLength === 'number' && value.length > property.maxLength) {\n\t\t\treturn `Must be at most ${property.maxLength} characters.`\n\t\t}\n\t\tif (property.pattern) {\n\t\t\ttry {\n\t\t\t\tif (!new RegExp(property.pattern).test(value)) {\n\t\t\t\t\treturn 'Value does not match the required pattern.'\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore broken schema patterns.\n\t\t\t}\n\t\t}\n\t\tif (property.const !== undefined && value !== property.const) {\n\t\t\treturn `Value must be '${property.const}'.`\n\t\t}\n\t\tconst fmtErr = validateStringFormat(property.format, value)\n\t\tif (fmtErr) {\n\t\t\treturn fmtErr\n\t\t}\n\t}\n\tif (type === 'array') {\n\t\tif (!Array.isArray(value)) {\n\t\t\treturn 'Value must be a list.'\n\t\t}\n\t\tif (typeof property.minItems === 'number' && value.length < property.minItems) {\n\t\t\treturn `Select at least ${property.minItems} items.`\n\t\t}\n\t\tif (typeof property.maxItems === 'number' && value.length > property.maxItems) {\n\t\t\treturn `Select at most ${property.maxItems} items.`\n\t\t}\n\t\tif (property.items && typeof property.items === 'object') {\n\t\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\t\tconst itemErr = validateValue(value[i], property.items)\n\t\t\t\tif (itemErr) {\n\t\t\t\t\treturn `Item ${i + 1}: ${itemErr}`\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif (type === 'boolean' && typeof value !== 'boolean') {\n\t\treturn 'Value must be a boolean.'\n\t}\n\tif (Array.isArray(property.enum) && property.enum.length > 0 && !property.enum.includes(value)) {\n\t\treturn 'Value must be one of the allowed options.'\n\t}\n\treturn null\n}\n\n/**\n * Validate a string value against a JSON-Schema `format`.\n *\n * @param {string} format Schema format identifier.\n * @param {string} value String value to validate.\n * @return {string|null} Error message or null when valid.\n */\nfunction validateStringFormat(format, value) {\n\tif (!format) {\n\t\treturn null\n\t}\n\tif (format === 'time') {\n\t\t// HTML5 `<input type=\"time\">` produces `HH:MM` or `HH:MM:SS[.sss]`.\n\t\t// `new Date()` won't parse a bare time, so check the shape directly.\n\t\treturn /^([01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?$/.test(value)\n\t\t\t? null\n\t\t\t: 'Value must be a valid time.'\n\t}\n\tif (format === 'date' || format === 'date-time') {\n\t\treturn Number.isNaN(new Date(value).getTime()) ? `Value must be a valid ${format}.` : null\n\t}\n\tif (URL_FORMATS.has(format)) {\n\t\t// Accept fully-qualified URLs (`https://example.com`) and protocol-less\n\t\t// shorthand (`example.com/path`) by retrying with an `https://` prefix.\n\t\t// Reject obviously non-URL inputs (whitespace, missing dots / authority).\n\t\tif (/\\s/.test(value)) {\n\t\t\treturn 'Value must be a valid URL.'\n\t\t}\n\t\ttry {\n\t\t\tnew URL(value)\n\t\t\treturn null\n\t\t} catch {\n\t\t\t// Fall through to the prefix retry.\n\t\t}\n\t\ttry {\n\t\t\tconst parsed = new URL('https://' + value)\n\t\t\tif (parsed.hostname && parsed.hostname.includes('.')) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to the rejection below.\n\t\t}\n\t\treturn 'Value must be a valid URL.'\n\t}\n\tconst re = FORMAT_PATTERNS[format]\n\tif (re && !re.test(value)) {\n\t\treturn `Value must be a valid '${format}'.`\n\t}\n\treturn null\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -35,9 +35,14 @@
|
|
|
35
35
|
* registers author the slug by hand for multi-word titles) folds to one
|
|
36
36
|
* `-`, leading/trailing dashes trimmed.
|
|
37
37
|
*
|
|
38
|
-
* Idempotent: a value that is already a slug (`report-period`, `cohort
|
|
39
|
-
* passes through unchanged, so it is always safe to route an
|
|
40
|
-
* value through this function defensively.
|
|
38
|
+
* Idempotent: a value that is already a slug (`report-period`, `cohort`,
|
|
39
|
+
* `statusType`) passes through unchanged, so it is always safe to route an
|
|
40
|
+
* already-correct value through this function defensively. A slug is any
|
|
41
|
+
* value that starts with a lowercase letter or digit and holds only
|
|
42
|
+
* letters, digits and dashes; only a title (capital initial, or spaces and
|
|
43
|
+
* punctuation) is kebab-cased.
|
|
44
|
+
*
|
|
45
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-plain-schema-slug-is-left-as-written
|
|
41
46
|
*
|
|
42
47
|
* A numeric schema id (OpenRegister accepts either the slug or the numeric
|
|
43
48
|
* id in the objects-API path) is returned unchanged — slugifying a number
|
|
@@ -63,6 +68,17 @@ function schemaRefSlug(ref) {
|
|
|
63
68
|
if (tail === '') {
|
|
64
69
|
return ''
|
|
65
70
|
}
|
|
71
|
+
// A plain slug is left as written. OpenRegister matches a slug
|
|
72
|
+
// case-insensitively (`statusType`, `statustype` and `StatusType` all
|
|
73
|
+
// answer 200) but `status-type` is another slug and 404s, so a
|
|
74
|
+
// camelCase slug authored as a slug must not be kebab-cased. Only a
|
|
75
|
+
// `$ref` TITLE is: it starts with a capital (`ReportPeriod`) or carries
|
|
76
|
+
// spaces or punctuation (`Praktijkovereenkomst (POK)`). 2.62.0 kebab-cased
|
|
77
|
+
// everything and broke every camelCase slug (dossiq: statusType, caseType,
|
|
78
|
+
// caseObject, bezwaarDecision, bacAdviceRequest, wmsLayer, ...).
|
|
79
|
+
if (/^[a-z0-9][A-Za-z0-9-]*$/.test(tail)) {
|
|
80
|
+
return tail
|
|
81
|
+
}
|
|
66
82
|
const kebab = tail
|
|
67
83
|
// PascalCase / camelCase word boundaries: `ReportPeriod` -> `Report-Period`,
|
|
68
84
|
// an acronym run followed by a new capitalised word: `HTTPServer` -> `HTTP-Server`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemaRefSlug.js","sources":["../../../src/utils/schemaRefSlug.js"],"sourcesContent":["/**\n * Slugify an OpenRegister `$ref` schema reference into the objects API's\n * schema path segment.\n *\n * OpenRegister resolves `GET /api/objects/{register}/{schema}/...` by schema\n * **slug**, case-insensitively for a single-word title (`Cohort` and `cohort`\n * both answer 200), but a slug is only single-word-safe by accident: a\n * multi-word schema title such as `ReportPeriod` or `LearnerProfile` is\n * registered under its kebab-case slug (`report-period`, `learner-profile`)\n * and the PascalCase title itself 404s. A schema's `$ref` is authored as\n * that PascalCase (or spaced) title, not the slug, so every consumer that\n * built an objects-API path straight from `$ref` shipped the same defect\n * (learniq round-1 defect 7 — verified 2026-09-25: `ReportPeriod` and\n * `LearnerProfile` 404, `report-period` and `learner-profile` 200; 128\n * properties across 52 schema titles were affected, which is why\n * `ReportCardDetail` rendered with every relation panel blank).\n *\n * This module is the one fleet-wide fix: every resolver that turns a\n * `$ref` into an objects-API path segment routes through {@link schemaRefSlug}\n * instead of using the raw title. It is distinct from (and does not\n * replace) `savedViewHelpers.js`'s `schemaSlug()`, which reads an\n * ALREADY-KNOWN slug off a page's `schema` prop (string or `{ slug }`\n * object) — this module derives a slug from a raw, possibly-PascalCase\n * `$ref` title instead, so the two are kept as separate named exports\n * rather than overloading one name for two different inputs.\n *\n * @module utils/schemaRefSlug\n */\n\n/**\n * Kebab-case a schema `$ref` value into the OpenRegister objects-API schema\n * slug, matching the register convention (`SchemaMapper::generateSlug()`):\n * lowercase, every run of non `[a-z0-9]` characters (including a PascalCase\n * word boundary, which the PHP fallback never has to handle because these\n * registers author the slug by hand for multi-word titles) folds to one\n * `-`, leading/trailing dashes trimmed.\n *\n * Idempotent: a value that is already a slug (`report-period`, `cohort
|
|
1
|
+
{"version":3,"file":"schemaRefSlug.js","sources":["../../../src/utils/schemaRefSlug.js"],"sourcesContent":["/**\n * Slugify an OpenRegister `$ref` schema reference into the objects API's\n * schema path segment.\n *\n * OpenRegister resolves `GET /api/objects/{register}/{schema}/...` by schema\n * **slug**, case-insensitively for a single-word title (`Cohort` and `cohort`\n * both answer 200), but a slug is only single-word-safe by accident: a\n * multi-word schema title such as `ReportPeriod` or `LearnerProfile` is\n * registered under its kebab-case slug (`report-period`, `learner-profile`)\n * and the PascalCase title itself 404s. A schema's `$ref` is authored as\n * that PascalCase (or spaced) title, not the slug, so every consumer that\n * built an objects-API path straight from `$ref` shipped the same defect\n * (learniq round-1 defect 7 — verified 2026-09-25: `ReportPeriod` and\n * `LearnerProfile` 404, `report-period` and `learner-profile` 200; 128\n * properties across 52 schema titles were affected, which is why\n * `ReportCardDetail` rendered with every relation panel blank).\n *\n * This module is the one fleet-wide fix: every resolver that turns a\n * `$ref` into an objects-API path segment routes through {@link schemaRefSlug}\n * instead of using the raw title. It is distinct from (and does not\n * replace) `savedViewHelpers.js`'s `schemaSlug()`, which reads an\n * ALREADY-KNOWN slug off a page's `schema` prop (string or `{ slug }`\n * object) — this module derives a slug from a raw, possibly-PascalCase\n * `$ref` title instead, so the two are kept as separate named exports\n * rather than overloading one name for two different inputs.\n *\n * @module utils/schemaRefSlug\n */\n\n/**\n * Kebab-case a schema `$ref` value into the OpenRegister objects-API schema\n * slug, matching the register convention (`SchemaMapper::generateSlug()`):\n * lowercase, every run of non `[a-z0-9]` characters (including a PascalCase\n * word boundary, which the PHP fallback never has to handle because these\n * registers author the slug by hand for multi-word titles) folds to one\n * `-`, leading/trailing dashes trimmed.\n *\n * Idempotent: a value that is already a slug (`report-period`, `cohort`,\n * `statusType`) passes through unchanged, so it is always safe to route an\n * already-correct value through this function defensively. A slug is any\n * value that starts with a lowercase letter or digit and holds only\n * letters, digits and dashes; only a title (capital initial, or spaces and\n * punctuation) is kebab-cased.\n *\n * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-plain-schema-slug-is-left-as-written\n *\n * A numeric schema id (OpenRegister accepts either the slug or the numeric\n * id in the objects-API path) is returned unchanged — slugifying a number\n * has no meaning and must never turn `85` into `'85'` and then reject it\n * downstream for being the \"wrong\" type.\n *\n * @param {unknown} ref A `$ref` value: a bare title/slug (`'ReportPeriod'`,\n * `'report-period'`), a JSON-Pointer (`'#/components/schemas/ReportPeriod'`),\n * or a numeric schema id.\n * @return {string|number} The kebab-case slug, the original number, or `''`\n * for a `ref` that carries no usable identifier (null/undefined/empty).\n */\nexport function schemaRefSlug(ref) {\n\tif (typeof ref === 'number') {\n\t\treturn Number.isNaN(ref) ? '' : ref\n\t}\n\tif (typeof ref !== 'string') {\n\t\treturn ''\n\t}\n\t// JSON-Pointer form (`#/components/schemas/<title>`) — take the tail,\n\t// the same rule `normalizeRef()` in `schema.js` already applies.\n\tconst tail = ref.includes('/') ? ref.substring(ref.lastIndexOf('/') + 1) : ref\n\tif (tail === '') {\n\t\treturn ''\n\t}\n\t// A plain slug is left as written. OpenRegister matches a slug\n\t// case-insensitively (`statusType`, `statustype` and `StatusType` all\n\t// answer 200) but `status-type` is another slug and 404s, so a\n\t// camelCase slug authored as a slug must not be kebab-cased. Only a\n\t// `$ref` TITLE is: it starts with a capital (`ReportPeriod`) or carries\n\t// spaces or punctuation (`Praktijkovereenkomst (POK)`). 2.62.0 kebab-cased\n\t// everything and broke every camelCase slug (dossiq: statusType, caseType,\n\t// caseObject, bezwaarDecision, bacAdviceRequest, wmsLayer, ...).\n\tif (/^[a-z0-9][A-Za-z0-9-]*$/.test(tail)) {\n\t\treturn tail\n\t}\n\tconst kebab = tail\n\t\t// PascalCase / camelCase word boundaries: `ReportPeriod` -> `Report-Period`,\n\t\t// an acronym run followed by a new capitalised word: `HTTPServer` -> `HTTP-Server`.\n\t\t.replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n\t\t.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')\n\t\t.toLowerCase()\n\t\t// Spaces, punctuation, parentheses (`Praktijkovereenkomst (POK)`) all\n\t\t// fold to a single dash, exactly as the register's own fallback slug\n\t\t// generator treats anything outside `[a-z0-9-]`.\n\t\t.replace(/[^a-z0-9-]+/g, '-')\n\t\t.replace(/-+/g, '-')\n\t\t.replace(/^-+|-+$/g, '')\n\treturn kebab\n}\n"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,aAAa,CAAC,GAAG,EAAE;AACnC,CAAC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AAC9B,EAAE,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG;AACrC,EAAE;AACF,CAAC,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AAC9B,EAAE,OAAO,EAAE;AACX,EAAE;AACF;AACA;AACA,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAG;AAC/E,CAAC,IAAI,IAAI,KAAK,EAAE,EAAE;AAClB,EAAE,OAAO,EAAE;AACX,EAAE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC,IAAI,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AAC3C,EAAE,OAAO,IAAI;AACb,EAAE;AACF,CAAC,MAAM,KAAK,GAAG,IAAI;AACnB;AACA;AACA,GAAG,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;AACzC,GAAG,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC;AAC5C,GAAG,WAAW,EAAE;AAChB;AACA;AACA;AACA,GAAG,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;AAC/B,GAAG,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;AACtB,GAAG,OAAO,CAAC,UAAU,EAAE,EAAE,EAAC;AAC1B,CAAC,OAAO,KAAK;AACb;;;;"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
3
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Turn an object's dated facts into timeline events.
|
|
8
|
+
*
|
|
9
|
+
* Pure helpers behind `CnTimelineWidget`. An event is
|
|
10
|
+
* `{ id, at, dateOnly, label, detail, source, upcoming }`, where `at` is a
|
|
11
|
+
* `Date`, `dateOnly` says the source value carried no time of day, and
|
|
12
|
+
* `upcoming` says the moment lies after `now`.
|
|
13
|
+
*
|
|
14
|
+
* @module utils/timelineEvents
|
|
15
|
+
* @spec openspec/changes/timeline-widget/specs/timeline-widget/spec.md
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Read a dotted path off an object (`@self.created`, `payment.clearedAt`).
|
|
20
|
+
*
|
|
21
|
+
* @param {object} obj The object.
|
|
22
|
+
* @param {string} path The dotted path.
|
|
23
|
+
* @return {unknown} The value, or undefined.
|
|
24
|
+
*/
|
|
25
|
+
function readPath(obj, path) {
|
|
26
|
+
if (!obj || typeof path !== 'string' || path === '') {
|
|
27
|
+
return undefined
|
|
28
|
+
}
|
|
29
|
+
if (Object.hasOwn(obj, path)) {
|
|
30
|
+
return obj[path]
|
|
31
|
+
}
|
|
32
|
+
return path.split('.').reduce((acc, part) => ((acc === null || acc === undefined) ? undefined : acc[part]), obj)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Parse a stored date value. A bare `YYYY-MM-DD` is a calendar day and is
|
|
37
|
+
* read as local midnight, not UTC, so it never shows as the day before.
|
|
38
|
+
*
|
|
39
|
+
* @param {unknown} raw The stored value.
|
|
40
|
+
* @return {{at: Date, dateOnly: boolean}|null} The moment, or null when it is not a date.
|
|
41
|
+
*/
|
|
42
|
+
function parseMoment(raw) {
|
|
43
|
+
if (raw === undefined || raw === null || raw === '') {
|
|
44
|
+
return null
|
|
45
|
+
}
|
|
46
|
+
if (typeof raw === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(raw)) {
|
|
47
|
+
const [y, m, d] = raw.split('-').map(Number);
|
|
48
|
+
return { at: new Date(y, m - 1, d), dateOnly: true }
|
|
49
|
+
}
|
|
50
|
+
const at = new Date(raw);
|
|
51
|
+
return Number.isNaN(at.getTime()) ? null : { at, dateOnly: false }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Build one event, or null when the value is not a date.
|
|
56
|
+
*
|
|
57
|
+
* @param {object} spec `{ id, raw, label, detail, source }`.
|
|
58
|
+
* @param {Date} now The reference moment for `upcoming`.
|
|
59
|
+
* @return {object|null} The event.
|
|
60
|
+
*/
|
|
61
|
+
function makeEvent(spec, now) {
|
|
62
|
+
const moment = parseMoment(spec.raw);
|
|
63
|
+
if (!moment) {
|
|
64
|
+
return null
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
id: spec.id,
|
|
68
|
+
at: moment.at,
|
|
69
|
+
dateOnly: moment.dateOnly,
|
|
70
|
+
label: spec.label || '',
|
|
71
|
+
detail: spec.detail || '',
|
|
72
|
+
source: spec.source,
|
|
73
|
+
upcoming: moment.at.getTime() > now.getTime(),
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Events from the object's own date properties.
|
|
79
|
+
*
|
|
80
|
+
* @param {object} object The object.
|
|
81
|
+
* @param {Array<{field: string, label?: string}>} fields The configured date fields.
|
|
82
|
+
* @param {Date} [now] The reference moment.
|
|
83
|
+
* @return {Array<object>} One event per field that holds a date.
|
|
84
|
+
*/
|
|
85
|
+
function fieldEvents(object, fields, now = new Date()) {
|
|
86
|
+
return (Array.isArray(fields) ? fields : [])
|
|
87
|
+
.filter((f) => f && typeof f.field === 'string')
|
|
88
|
+
.map((f) => makeEvent({ id: `field:${f.field}`, raw: readPath(object, f.field), label: f.label || f.field, source: 'field' }, now))
|
|
89
|
+
.filter(Boolean)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Events from related objects: one per row that holds a date in `dateField`.
|
|
94
|
+
*
|
|
95
|
+
* @param {Array<object>} rows The related objects.
|
|
96
|
+
* @param {{label?: string, dateField?: string, titleField?: string, schema?: string}} config The related-source config.
|
|
97
|
+
* @param {Date} [now] The reference moment.
|
|
98
|
+
* @return {Array<object>} The events.
|
|
99
|
+
*/
|
|
100
|
+
function relatedEvents(rows, config, now = new Date()) {
|
|
101
|
+
const cfg = config || {};
|
|
102
|
+
const dateField = cfg.dateField || '@self.created';
|
|
103
|
+
return (Array.isArray(rows) ? rows : [])
|
|
104
|
+
.map((row, i) => {
|
|
105
|
+
const self = (row && row['@self']) || {};
|
|
106
|
+
const id = String(self.id || row.id || i);
|
|
107
|
+
const title = cfg.titleField ? readPath(row, cfg.titleField) : (row && (row.title || row.name)) || self.name;
|
|
108
|
+
return makeEvent({
|
|
109
|
+
id: `related:${cfg.schema || ''}:${id}`,
|
|
110
|
+
raw: readPath(row, dateField),
|
|
111
|
+
label: cfg.label || '',
|
|
112
|
+
detail: title === undefined || title === null ? '' : String(title),
|
|
113
|
+
source: 'related',
|
|
114
|
+
}, now)
|
|
115
|
+
})
|
|
116
|
+
.filter(Boolean)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Events from audit-trail entries.
|
|
121
|
+
*
|
|
122
|
+
* @param {Array<object>} entries The audit-trail rows.
|
|
123
|
+
* @param {(action: string, actor: string) => string} describe Builds the label from action and actor.
|
|
124
|
+
* @param {Date} [now] The reference moment.
|
|
125
|
+
* @return {Array<object>} The events.
|
|
126
|
+
*/
|
|
127
|
+
function auditEvents(entries, describe, now = new Date()) {
|
|
128
|
+
return (Array.isArray(entries) ? entries : [])
|
|
129
|
+
.map((e, i) => makeEvent({
|
|
130
|
+
id: `audit:${e && (e.id || e.uuid) ? (e.id || e.uuid) : i}`,
|
|
131
|
+
raw: e && (e.created || e.creationDateTime || e.timestamp),
|
|
132
|
+
label: describe(String((e && (e.action || e.event)) || ''), String((e && (e.actorDisplayName || e.userName || e.user || e.actor)) || '')),
|
|
133
|
+
source: 'audit',
|
|
134
|
+
}, now))
|
|
135
|
+
.filter(Boolean)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Events from OpenRegister's timeline (notes, calls, messages).
|
|
140
|
+
*
|
|
141
|
+
* @param {Array<object>} entries The timeline rows.
|
|
142
|
+
* @param {string} noteLabel The label for an entry without a kind.
|
|
143
|
+
* @param {Date} [now] The reference moment.
|
|
144
|
+
* @return {Array<object>} The events.
|
|
145
|
+
*/
|
|
146
|
+
function timelineEntryEvents(entries, noteLabel, now = new Date()) {
|
|
147
|
+
return (Array.isArray(entries) ? entries : [])
|
|
148
|
+
.map((e, i) => makeEvent({
|
|
149
|
+
id: `timeline:${e && e.id ? e.id : i}`,
|
|
150
|
+
raw: e && e.created,
|
|
151
|
+
label: (e && (e.kindTitle || e.kind)) || noteLabel,
|
|
152
|
+
detail: [e && e.author, e && e.message].filter(Boolean).join(': '),
|
|
153
|
+
source: 'timeline',
|
|
154
|
+
}, now))
|
|
155
|
+
.filter(Boolean)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Sort events by time; ties keep their input order.
|
|
160
|
+
*
|
|
161
|
+
* @param {Array<object>} events The events.
|
|
162
|
+
* @param {'asc'|'desc'} [order] Oldest first (default) or newest first.
|
|
163
|
+
* @return {Array<object>} A new, sorted array.
|
|
164
|
+
*/
|
|
165
|
+
function sortEvents(events, order = 'asc') {
|
|
166
|
+
const dir = order === 'desc' ? -1 : 1;
|
|
167
|
+
return (events || [])
|
|
168
|
+
.map((e, i) => ({ e, i }))
|
|
169
|
+
.sort((a, b) => ((a.e.at.getTime() - b.e.at.getTime()) * dir) || (a.i - b.i))
|
|
170
|
+
.map(({ e }) => e)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export { auditEvents, fieldEvents, parseMoment, readPath, relatedEvents, sortEvents, timelineEntryEvents };
|
|
174
|
+
//# sourceMappingURL=timelineEvents.js.map
|