@judo/components
v0.1.0
Published
> Visual-model-driven MUI components for JUDO UI Runtime
Readme
@judo/components
Visual-model-driven MUI components for JUDO UI Runtime
Purpose
The UI layer (Layer 5) of the JUDO runtime React framework. Interprets ECore XML models at runtime to produce React UI with no code generation. All components receive model objects (PageContainer, Flex, Table, Input, etc.) and render MUI-based UI from their properties.
Architecture Layer
Layer 5 (UI) — the primary visual rendering package, consumed by app-shell and standalone.
Dependencies
| Workspace | External (Peer) |
| ----------------- | ------------------------------------------- |
| @judo/model-api | @mui/material ^7 |
| @judo/core | @mui/x-data-grid ^8 |
| @judo/i18n | @mui/x-data-grid-pro ^8 (optional) |
| @judo/actions | @mui/x-date-pickers ^8 |
| @judo/feedback | @mui/icons-material ^7 |
| @judo/test-ids | @emotion/react ^11, @emotion/styled ^11 |
| | @mdi/font ^7, date-fns ^4, react ^19 |
File Structure
src/
├── index.ts # Barrel export
├── styles.css # Force-full-width CSS for Stack layouts
├── containers/
│ ├── PageRenderer.tsx # Top-level page → container dispatcher
│ ├── TableContainerRenderer.tsx # TABLE container renderer
│ ├── FormContainerRenderer.tsx # FORM container renderer (create dialogs)
│ └── ViewContainerRenderer.tsx # VIEW container renderer
├── dialogs/
│ └── LinkSelectorDialog.tsx # Relation selector dialog (DataGrid + filtering)
├── errors/
│ ├── ContainerErrorBoundary.tsx # Error boundaries per container type
│ └── index.ts # Barrel export
├── hooks/
│ ├── use-file-handling.tsx # File download/upload/export hook
│ ├── use-page-title.ts # Page title resolution hook
│ └── use-table-data.ts # Table data management hook
├── inputs/
│ ├── InputRenderer.tsx # Input type dispatcher
│ ├── TextInputComponent.tsx
│ ├── NumericInputComponent.tsx
│ ├── DateInputComponent.tsx
│ ├── DateTimeInputComponent.tsx
│ ├── TimeInputComponent.tsx
│ ├── TextAreaComponent.tsx
│ ├── CheckboxComponent.tsx
│ ├── SwitchComponent.tsx
│ ├── EnumerationComboComponent.tsx
│ ├── EnumerationRadioComponent.tsx
│ ├── EnumerationToggleButtonbarComponent.tsx
│ ├── BinaryInputComponent.tsx
│ └── PasswordInputComponent.tsx
├── renderers/
│ ├── VisualElementRenderer.tsx # Central type dispatcher
│ ├── FlexRenderer.tsx # Flex layout (Grid + Stack)
│ ├── TableRenderer.tsx # MUI DataGrid wrapper
│ ├── LinkRenderer.tsx # Autocomplete/relation field
│ ├── TabControllerRenderer.tsx # Tab layout
│ ├── ButtonGroupRenderer.tsx # Page-level button groups
│ ├── InlineButtonGroupRenderer.tsx # Inline dropdown button groups
│ ├── StandaloneButtonRenderer.tsx # Standalone navigation buttons
│ ├── RowActionCell.tsx # Per-row action dropdown (internal)
│ ├── SubThemeWrapper.tsx # Theme override wrapper
│ ├── FrameRenderer.tsx # Card/panel frame
│ ├── IconRenderer.tsx # MDI icon renderer
│ ├── PageHeader.tsx # Page title + actions
│ └── TableToolbar.tsx # Custom DataGrid toolbar (internal)
└── utils/
├── alignment-mappers.ts # Enum → CSS alignment mapping
├── build-mask-string.ts # Attribute/relation → _mask string builder
├── build-query-customizer.ts # DataGrid state → REST query (internal)
├── destructive-action-utils.ts # Destructive action detection + confirm options (internal)
├── find-action-by-definition.ts # Action ↔ definition matching (internal)
├── find-on-init-action.ts # OnInit action lookup
├── find-visual-element.ts # Tree search utilities
├── flex-layout.ts # 12-column responsive grid math
├── get-visible-buttons.ts # Button visibility filtering (internal)
├── mdi-alias-map.ts # MDI icon alias resolution (internal)
├── mdi-alias-map.generated.ts # Auto-generated (6,476 aliases)
├── resolve-container-type.ts # Container type resolution
├── singleton-access.ts # Singleton access page detection
├── table-column-utils.ts # Column type mapping (internal)
├── table-filter-utils.ts # DataGrid → REST filter conversion (internal)
└── table-sort-utils.ts # Sort model conversionExports Summary
Container Renderers
| Component | Description |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| PageRenderer | Top-level dispatcher. Lazy-loads container renderers by ContainerType (TABLE/FORM/VIEW) wrapped in error boundaries. Keys on transferId to force remount on navigation. |
| TableContainerRenderer | TABLE container. Finds Table element, resolves Refresh action, dispatches onInit on mount (ref-guarded), renders PageHeader + VisualElementRenderer. |
| FormContainerRenderer | FORM container (create dialogs). Dispatches GetTemplate on mount for default values. Extracts create-dialog context. Sets pageType: "FORM" in dispatcher context. |
| ViewContainerRenderer | VIEW container. Derives edit mode from transfer dirty state. Dispatches Refresh on mount when transfer available. Does NOT force readOnly based on edit mode. Singleton access pages (isAccess=true, isCollection=false): pre-fetches transfer via refreshAccessRelation, wraps children in PageProvider with resolved transferId. |
| resolveContainerType(container) | Returns the container's explicit type or defaults to TABLE. |
Error Boundaries
| Component | Description |
| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| ContainerErrorBoundary | React class error boundary. Displays expandable MUI Alert with error message, element path, model JSON, and component stack. |
| TableErrorBoundary / FormErrorBoundary / ViewErrorBoundary | Typed wrappers with specific labels. |
Visual Element Renderers
| Component | Description |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| VisualElementRenderer | Central @type dispatcher → delegates to appropriate renderer. Checks component overrides and interceptors first. Unknown types log warning and return null. |
| FlexRenderer | Flex layout: Horizontal = MUI Grid (12-column responsive), Vertical = MUI Stack (full-width). Supports size constraints and alignment. |
| TableRenderer | Full-featured MUI DataGrid wrapper. Manages row selection, filter panel, column building, column customizers (useColumnCustomizers), eager/non-eager modes, row actions, forceShowTotalCount. Supports CARD/TAG representationComponent via useItemContainerConfig — renders MUI Card grids or Chip lists instead of DataGrid. |
| LinkRenderer | MUI Autocomplete for relation/link elements with joined ButtonGroup. Supports typeahead, selector dialog, eager/lazy modes, and action buttons (View, Set, Unset, Create, Delete). |
| LinkSelectorDialog | Relation selector dialog with DataGrid table, filtering, and single-row selection for Link Set action. |
| TabControllerRenderer | MUI Tabs with lazy tab panel rendering. Supports vertical/horizontal orientation. |
| ButtonGroupRenderer | Page/dialog-level button groups as horizontal MUI ButtonGroup. Filters visible buttons by edit mode. Supports group-level hiddenBy (via useElementVisibility) and per-button enabledBy/hiddenBy (via useElementDisabled/useElementVisibility). |
| InlineButtonGroupRenderer | Inline dropdown menu with IconButton + Menu + MenuItems. Supports featuredActions for inline buttons. Group-level hiddenBy and per-button enabledBy/hiddenBy dynamic behavior. |
| StandaloneButtonRenderer | Standalone Button elements (e.g., relation navigation buttons). Supports hiddenBy/enabledBy dynamic behavior, button style variants, confirmation dialogs for destructive actions. |
| SubThemeWrapper | Wraps children in a theme override based on model subTheme configuration and transfer data. |
| FrameRenderer | MUI Card with optional header (icon + label). |
| IconRenderer | MDI webfont icon renderer with alias resolution and size support. |
| PageHeader | Page title + page-level ButtonGroup. |
Internal only (not exported): RowActionCell (per-row action dropdown used by TableRenderer), TableToolbar (custom DataGrid toolbar slot).
Input Components (14)
| Component | Model Type | MUI Component |
| ------------------------------------- | ---------------------------- | ------------------------------------------------------------------- |
| InputRenderer | — | Central dispatcher (uses useVisualBinding, useEnumOptionFilter) |
| TextInputComponent | TextInput | TextField |
| NumericInputComponent | NumericInput | TextField (type="number") |
| DateInputComponent | DateInput | DatePicker |
| DateTimeInputComponent | DateTimeInput | TextField (type="datetime-local") |
| TimeInputComponent | TimeInput | TimePicker |
| TextAreaComponent | TextArea | TextField (multiline) |
| CheckboxComponent | Checkbox | MUI Checkbox + FormControlLabel |
| SwitchComponent | Switch | MUI Switch + FormControlLabel |
| EnumerationComboComponent | EnumerationCombo | Select + MenuItems |
| EnumerationRadioComponent | EnumerationRadio | RadioGroup + FormControlLabels |
| EnumerationToggleButtonbarComponent | EnumerationToggleButtonbar | ToggleButtonGroup + ToggleButtons |
| BinaryInputComponent | BinaryInput | File upload button + filename display |
| PasswordInputComponent | PasswordInput | TextField with visibility toggle |
Hooks
| Hook | Description |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| useFileHandling() | File operations: download (attachment/inline preview), upload (two-step flow), JWT filename extraction, and export-to-file from API responses. Uses useApi + useDialog. |
| usePageTitle(options) | Resolves page titles from titleFrom config: static label or dynamic attribute value with label fallback. |
| useTableData(options) | Manages table data for eager (client-side) and non-eager (server-side) modes. Sets DataGrid sort/filter/pagination modes accordingly. |
Exported Utility Functions
| Function | Description |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| mapMainAxisAlignment(alignment) | Enum → CSS justifyContent value. |
| mapCrossAxisAlignment(alignment) | Enum → CSS alignItems value. |
| mapAlignment(alignment) | 2D Alignment enum → both CSS properties. |
| findOnInitAction(page, container) | Finds the onInit action for a container. |
| buildMaskString(params) | Builds _mask string from attribute/relation arrays for REST queries. |
| isSingletonAccessPage(page) | Checks if page is a singleton access page (RelationType with isAccess=true, isCollection=false). |
| getSingletonAccessRelation(page) | Returns the RelationType for a singleton access page, or undefined. |
| resolveContainerType(container) | Returns the container's explicit type or defaults to TABLE. |
| findVisualElementByType(root, type) | DFS search by @type. |
| findVisualElementById(root, id) | DFS search by xmi:id. |
| findVisualElementBySourceId(root, sourceId) | DFS search by sourceId. |
| flattenVisualElements(root) | Pre-order tree flattening. |
| calculateChildGridSize(element) | 12-column proportional sizing for child elements. |
| calculateHorizontalGridSize(element) | Responsive breakpoint configuration for horizontal flex. |
| calculateVerticalGridSize() | Always full-width (12 columns) for vertical flex. |
| calculateScaledSize(element) | Scales element col relative to parent's column span. |
| isVerticalLayout(element) | Checks if a Flex element has VERTICAL direction. |
| buildInitialSortModel(columns) | Builds initial DataGrid sort model from column definitions. |
| buildInitialOrderBy(columns) | Builds REST _orderBy from columns with sort configuration. |
| convertSortModelToOrderBy(sortModel, columns) | MUI sort model → REST format. |
| extractFileNameFromToken(token, fallback) | Standalone JWT filename extraction (also available from useFileHandling). |
Internal utilities (not exported): findActionByDefinition, buildQueryCustomizer, getVisibleButtons, resolveIconName, getColumnType, convertFilterModelToQueryCustomizer, isDestructiveAction, getDestructiveConfirmationOptions.
Key Patterns
- Model-driven rendering: All components receive model objects and render from their properties — no hardcoded layouts
@typediscriminator dispatch:VisualElementRendererandInputRendererswitch on@typeto delegate to the correct renderer- Action resolution via
findActionByDefinition: Buttons/containers match their inlineactionDefinitionagainst pageactionsbyxmi:id - Eager vs non-eager data: Tables support client-side (DataGrid handles everything) and server-side (dispatch on sort/filter/pagination) modes
- Ref-guarded onInit dispatch: All container renderers use
useRefto prevent duplicate dispatches in StrictMode - Context fallback pattern: Components accept page/dispatch via props but fall back to context
- Lazy code splitting:
PageRendererusesReact.lazyfor each container type withSuspense - 12-column responsive grid: Flex layouts scale children proportionally with responsive breakpoints
- MDI icon alias resolution: Build-time generated alias map (6,476 entries) enables runtime icon name resolution
- Singleton access page support: ViewContainerRenderer detects singleton pages (isAccess=true, isCollection=false), pre-fetches transfer via
refreshAccessRelation, and overridestransferIdvia nestedPageProvidersouseVisualBindingcan find data in the store - Runtime dynamic behavior: Button renderers support
hiddenBy/enabledBymodel references viauseElementVisibility()anduseElementDisabled()hooks from@judo/core. Group-level visibility hides entire button groups; per-button visibility/disabled state is evaluated independently.
