# @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 conversion
```

## Exports 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` + `MenuItem`s                                              |
| `EnumerationRadioComponent`           | `EnumerationRadio`           | `RadioGroup` + `FormControlLabel`s                                  |
| `EnumerationToggleButtonbarComponent` | `EnumerationToggleButtonbar` | `ToggleButtonGroup` + `ToggleButton`s                               |
| `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
- **`@type` discriminator dispatch**: `VisualElementRenderer` and `InputRenderer` switch on `@type` to delegate to the correct renderer
- **Action resolution via `findActionByDefinition`**: Buttons/containers match their inline `actionDefinition` against page `actions` by `xmi: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 `useRef` to prevent duplicate dispatches in StrictMode
- **Context fallback pattern**: Components accept page/dispatch via props but fall back to context
- **Lazy code splitting**: `PageRenderer` uses `React.lazy` for each container type with `Suspense`
- **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 overrides `transferId` via nested `PageProvider` so `useVisualBinding` can find data in the store
- **Runtime dynamic behavior**: Button renderers support `hiddenBy`/`enabledBy` model references via `useElementVisibility()` and `useElementDisabled()` hooks from `@judo/core`. Group-level visibility hides entire button groups; per-button visibility/disabled state is evaluated independently.
