import type { Component, InjectionKey } from 'vue' import type { UiGridStatusMap } from '../gridStatus' export type UiSeverity = 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'danger' export type UiButtonType = 'button' | 'submit' | 'reset' export type UiAdapterId = 'primevue-aggrid' | 'native-accessible' export type UiAdapterContractVersion = '4.0' export type UiAdapterCapability = | 'button' | 'text-field' | 'text-area' | 'select' | 'multi-select' | 'checkbox' | 'date-field' | 'number-field' | 'dialog' | 'status-tag' | 'inline-message' | 'paginator' | 'tabs' | 'data-grid' export interface UiSelectOption { label: string value: string | number | boolean | null disabled?: boolean } export interface UiTabItem { id: string label: string disabled?: boolean badge?: string | number } export type UiGridSortDirection = 'asc' | 'desc' export interface UiGridSort { field: string; direction: UiGridSortDirection } export interface UiGridFilter { field: string; operator: string; value: unknown } export interface UiGridQuery { page: number pageSize: number sorts: UiGridSort[] filters: UiGridFilter[] search?: string } export interface UiGridColumn { field: string header: string width?: number minWidth?: number maxWidth?: number flex?: number sortable?: boolean filterable?: boolean sensitive?: boolean editable?: boolean formatter?: (value: unknown, row: unknown) => string statusMap?: UiGridStatusMap } export type UiTextFieldType = 'text' | 'email' | 'password' | 'number' | 'date' export interface UiAdapterDescriptor { readonly id: UiAdapterId readonly version: string readonly contractVersion: UiAdapterContractVersion readonly vendor: string readonly capabilities: ReadonlySet readonly productionEligible: boolean readonly accessibilityBaseline: 'WCAG_2_2_AA_TARGET' } export interface UiAdapter { readonly descriptor: UiAdapterDescriptor readonly components: { Button: Component TextField: Component TextArea: Component Select: Component MultiSelect: Component Checkbox: Component DateField: Component NumberField: Component Dialog: Component StatusTag: Component InlineMessage: Component Paginator: Component Tabs: Component DataGrid: Component } } export const requiredUiAdapterCapabilities: readonly UiAdapterCapability[] = Object.freeze([ 'button', 'text-field', 'text-area', 'select', 'multi-select', 'checkbox', 'date-field', 'number-field', 'dialog', 'status-tag', 'inline-message', 'paginator', 'tabs', 'data-grid' ]) export function assertUiAdapterContract(adapter: UiAdapter): void { if (adapter.descriptor.contractVersion !== '4.0') { throw new Error(`Unsupported UI adapter contract: ${adapter.descriptor.contractVersion}`) } const missing = requiredUiAdapterCapabilities.filter(x => !adapter.descriptor.capabilities.has(x)) if (missing.length > 0) { throw new Error(`UI adapter ${adapter.descriptor.id} is missing capabilities: ${missing.join(', ')}`) } const componentNames = [ 'Button', 'TextField', 'TextArea', 'Select', 'MultiSelect', 'Checkbox', 'DateField', 'NumberField', 'Dialog', 'StatusTag', 'InlineMessage', 'Paginator', 'Tabs', 'DataGrid' ] as const for (const name of componentNames) { if (!adapter.components[name]) throw new Error(`UI adapter ${adapter.descriptor.id} has no component for ${name}`) } } export const uiAdapterKey: InjectionKey = Symbol('KArtSellUiAdapterV4')