Skip to content

1. Custom Columns Prop (w/ Default Renderer & Dot Path Utility) #442

@MitchellShiell

Description

@MitchellShiell

Introduce a customColumns optional prop on DictionaryTableViewer and implement the MetaValueRenderer component. Both are exported from the package public API and form the complete contract that all downstream tickets implement against.

customColumns prop

The prop accepts an array of column configurations. Each entry is either a path-based config (columnHeader + metaPath) or a component-based config (columnHeader + columnComponent). The prop is entirely optional; when omitted, the component behaves identically to the current implementation.

Both modes can be mixed freely within the same array:

<DictionaryTableViewer
	customColumns={[
		{ columnHeader: 'FHIR Mapping', metaPath: 'meta.mappings.FHIR' },
		{ columnHeader: 'All Mappings', columnComponent: AllMappingsCell },
	]}
/>

MetaValueRenderer component

Accepts a single value of any type and renders it appropriately for display in a table cell:

  • String: plain text; strings that are valid URLs render as clickable hyperlinks opening in a new tab
  • Number and boolean: their string representation
  • Array: items as a comma-separated list
  • Object: key-value pairs as readable formatted text
  • Undefined or null: nothing, producing an empty cell

Long values that overflow the cell are truncated and use our already implemented show more design pattern.

Exported so developers can use it inside their own columnComponent implementations when they want standard display behaviour without writing their own type-handling logic:

const FhirMappingCell = ({ field }: { field: SchemaField }) => <MetaValueRenderer value={field.meta?.mappings?.FHIR} />;

The `MetaValueRenderer1 component will be used by default for a custom column if no custom component is specified

getByDotPath utility

Extract getByDotPath from its current private implementation inside DictionaryTableViewer.tsx into a shared, exported location. The utility resolves a dot-notation path string against a SchemaField object and returns the value at that path, or undefined if any key in the chain is absent. It must never throw.

It serves two roles: internally by the framework to resolve metaPath values for path-based columns, and as an export for developers who want safe nested property access inside their own columnComponent implementations:

// Used internally by the framework for path-based columns:
const value = getByDotPath(field, 'meta.mappings.FHIR');

// Also usable by developers in component-based columns:
const FhirMappingCell = ({ field }: { field: SchemaField }) => (
	<MetaValueRenderer value={getByDotPath(field, 'meta.mappings.FHIR')} />
);

Acceptance Criteria

  • customColumns is accepted as an optional prop on DictionaryTableViewer
  • Each entry in the array is either a path-based config (columnHeader + metaPath) or a component-based config (columnHeader + columnComponent)
  • Omitting the prop produces no change to existing behaviour
  • TypeScript rejects entries that provide both metaPath and columnComponent, or neither
  • MetaValueRenderer handles all supported value types without errors
  • URL strings render as anchor elements that open in a new tab
  • Arrays and objects produce readable output that does not cause cell overflow
  • Values exceeding the available cell width are truncated with the full content accessible on hover
  • Undefined and null values produce an empty cell with no placeholder text
  • MetaValueRenderer is exported from the package public API
  • Valid dot-paths resolve to the correct value on a SchemaField object
  • Paths that traverse missing or null intermediate keys return undefined without throwing
  • getByDotPath is exported from the package public API
  • The existing private implementation in DictionaryTableViewer.tsx is replaced with a reference to the extracted utility, with no change in behaviour

Dependencies

None

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions