# Bone Flow #048 - Table Guide

## 1. Getting started

#048 Table is a Display UI for structured rows and columns. Its normal-use HTML Functional Class is `bf-table`.

- UI ID: `UI-048`
- DOC ID: `DOC-0048`
- DOC Version: `1.0.32`
- Runtime: `BoneTable 1.0.16`
- HTML Functional Class: `bf-table`

Table owns tabular display. It does not own spreadsheet-style editing.

## 2. Responsibility

- `#048 Table`: rows, columns, cells, and Cell Renderer placement
- `#049 Grid`: cell editing and grid interaction
- `#073 Pagination`: page navigation
- `#121 Timeline`: time control
- `#002 Bone Joint`: connection evaluation, Joint drawing, abnormal markers, WAIT / FIFO / BLOCKED

## 3. Minimal HTML

```html
<div class="bf-table"
     data-table-columns='[{"key":"name","label":"Name"},{"key":"age","label":"Age","align":"right"}]'
     data-table-rows='[{"name":"Aki","age":31},{"name":"Mika","age":28}]'></div>
```

Column/row attributes are JSON. Plain cells use `textContent`; row data is not interpreted as HTML.

## 4. Table properties

The formal #048 Table property definition is Runtime-owned. Use `BoneTable.getPropertySchema()` / `getPropertyDefaults()` / `getPropertyDefinition(key)` as the source of truth. `inheritParent` is the formal **Parent snap** boolean property and defaults to `true`.

| Property | Type | Default | Meaning |
|---|---|---|---|
| `caption` | string | empty | Table caption |
| `columns` | array | `[]` | Column definitions |
| `rows` | array | `[]` | Row data |
| `showHeader` | boolean | `true` | Show header row |
| `displayRowCount` | integer | `0` | Minimum displayed row count; 0 follows data rows |
| `showEmptyRows` | boolean | `true` | Show empty and padded rows |
| `striped` | boolean | `true` | Alternate row background |
| `hover` | boolean | `true` | Highlight hovered row |
| `bordered` | boolean | `true` | Draw borders |
| `compact` | boolean | `false` | Reduce cell padding |
| `emptyText` | string | `データがありません` | Empty-state text |
| `theme` | select | `dark` | `light / dark / neon` |
| `inheritParent` | boolean | `true` | Snap the Table itself to the available width of its parent |
| `ariaLabel` | string | `Table` | Accessible name |


### Parent snap (`inheritParent`)

`inheritParent` defines the **layout relationship between #048 Table itself and the parent element that hosts the Table**. It is separate from Cell Renderer `snapToCell`.

- Formal property: `inheritParent`
- Property label: **Parent snap (default)**
- Type: `boolean`
- Default: `true`
- Runtime Schema: `BoneTable.getPropertyDefinition("inheritParent")`
- HTML Functional Class: `data-table-inherit-parent="true|false"`

**ON (`true`)**

- Adds `bone-table--inherit-parent` to the Table root.
- Sets `data-inherit-parent="true"`.
- Uses `width:100%; max-width:100%`, so the Table follows the available width of its parent container.

**OFF (`false`)**

- Adds `bone-table--free` to the Table root.
- Sets `data-inherit-parent="false"`.
- Uses `display:inline-block; width:auto; max-width:100%`; the inner table uses `width:auto`, so its own content width becomes the basis while parent overflow is still bounded.

**Difference from `snapToCell`**

- `inheritParent`: **Table itself → parent element**. This is a formal #048 Runtime Property.
- `snapToCell`: **Cell Renderer → Table cell**. This belongs to `columns[].cellElement` / `row.$cells[columnKey]`.
- The two settings are independent. Parent snap does not automatically force every child renderer to fill its cell, and cell snap does not determine whether the Table fills its parent.

The test page's “Formal Property Definition (Runtime Schema)” section renders live values from `BoneTable.getPropertySchema()` / `getPropertyDefaults()` / `getPropertyDefinition(key)` instead of maintaining a handwritten duplicate. The Runtime definition is therefore authoritative for the `inheritParent` type, default, and description.


### Display rows / Show rows with no values

**Display rows** maps to `displayRowCount`. `0` is automatic. When the value is greater than the data-row count, Table pads the shortage with value-less rows. A smaller value never truncates real data. This is intended for ledger/voucher layouts that need a fixed number of ruled rows before values exist.


The Table Property checkbox **Show rows with no values** maps to `showEmptyRows` and defaults to `true`.

- ON: rows whose column values are all empty (`{}`, empty string, `null`, `[]`) remain in the table so row/column rules stay visible.
- OFF: fully empty rows are omitted from the rendered `tbody`.
- `0` and `false` are real values and are not treated as empty.
- `$cells` renderer configuration does not make an otherwise empty row non-empty.

Normal Text / Label / Shape renderers are not mounted for an empty value; the Table cell rules remain.
A Renderer can opt into structural empty-value rendering with `renderEmpty:true`.

#054 Display Timeline uses `renderEmpty:true`, therefore `items=[]` still renders the timeline and vertical grid lines while no Bar or Shape Comment is created.
The built-in #029 NumberBox renderer is registered with `renderEmpty:true`. In voucher mode it keeps the value as `null` and renders only the voucher digit cells/rulings, without inventing a numeric value.

## 5. Columns

A column supports `key / label / align / width / cellElement`.

- `key`: required row-object key; duplicates are rejected
- `label`: header text, defaults to the key
- `align`: `left / center / right`
- `width`: `auto` or a CSS length using `px / % / rem / em / ch`
- `cellElement`: default Cell Renderer configuration for the column

## 6. Rows / $cells override

Rows are plain objects. A property matching the column key is the cell value.

Use `$cells` to override a single cell:

```json
{
  "name": "Aki",
  "status": "Important",
  "$cells": {
    "status": {
      "renderer": "017",
      "props": { "tag": "strong" },
      "snapToCell": true
    }
  }
}
```

`$cells.<columnKey>` overrides the column-level `cellElement` for that cell only.

## 7. Cell Element settings

A Cell Element configuration selects the UI Renderer used for a cell value.

```json
{
  "renderer": "021",
  "props": { "type": "PROCESS", "theme": "dark" },
  "snapToCell": true
}
```

- `renderer`: renderer ID, Component ID, className, or alias
- `props`: properties passed to the selected UI
- `snapToCell`: fit to the cell; default `true`

## 8. Target column + / -

The Target Column selector has `+ / -` controls.

- `+`: insert a new column after the selected column and add blank matching row fields
- `-`: remove the selected column, matching row fields, and `$cells` overrides

## 9. UI Renderer / Cell Renderer Registry

Built-in renderers:

| Renderer | Component | Purpose |
|---|---|---|
| `plain` | Plain Text | Safe text rendering |
| `017` | #017 Text | Text UI |
| `018` | #018 Icon | Icon UI |
| `020` | #020 Label | Label UI |
| `021` | #021 Shape | Shape UI |
| `029` | #029 NumberBox | Number / voucher UI |
| `054` | #054 Display Timeline | Timeline UI |
> #029 NumberBox requires **#022 Hover Border Effect** while rendering. The #048 test page loads the #022 Runtime/CSS before #029.

Registered aliases such as `text / bf-text`, `icon / bf-icon`, `label / bf-label`, `shape / bf-shape`, `numberbox / voucher / bf-numberbox`, and `display-timeline / bf-display-timeline` are also accepted.

Unknown or unavailable renderers fall back to safe text. Raw HTML is never executed.

## 10. Selected UI properties

Selecting a UI Renderer displays **only that renderer's properties** inside Cell Element settings.

- Component Preview is not embedded
- Smoke / Validation / Completion are not embedded
- Values are stored in `cellElement.props`
- Supported editor types: `text / number / boolean / select / textarea / json`
- Nested paths such as `options.theme` are supported

## 11. Runtime-owned Property Schema

A renderer may register `propertySchema` as an array or as a provider function. Provider functions are re-evaluated when the Property Editor reads the schema.

The #054 renderer reads the formal runtime source directly:

```js
BoneDisplayTimeline.getPropertySchema()
```

#048 does not maintain a duplicated #054 property inventory.

## 12. Snap cell element (default)

`cellElement.snapToCell` defaults to `true`.

- `true`: remove Table cell padding and fit the renderer host/child UI to the cell width
- `false`: retain normal Table cell padding

It can be set at both `columns[].cellElement` and `row.$cells[columnKey]`.

For #054 Display Timeline, Table supplies `snapToParent:true` when snap-to-cell is enabled and #054 did not explicitly set it. #048 does not override #054's formal height calculation.

## 13. #017 Text in a cell

Example:

```json
{
  "renderer": "017",
  "props": {
    "tag": "strong",
    "position": "center",
    "whitespace": "normal",
    "overflow": "wrap",
    "selectable": true
  }
}
```

The current #048 Text schema exposes `tag / position / whitespace / overflow / maxLines / selectable / prefix / suffix`. When Text `id` is omitted or empty, #048 assigns a unique DOM id from the Table instance/row/column so repeated rows and multiple Table instances do not create empty or duplicate ids.

## 14. #020 Label in a cell

```json
{
  "renderer": "020",
  "props": {
    "position": "center",
    "hidden": false,
    "disabled": false,
    "title": "Work status"
  }
}
```

The cell value becomes the Label display text.

## 15. #021 Shape in a cell

```json
{
  "renderer": "021",
  "props": {
    "type": "PROCESS",
    "theme": "dark",
    "displayRate": 72,
    "disabled": false
  }
}
```

Use a formal #021 Shape TYPE. #048 does not reimplement Shape.

When multiple #021 Shape instances are placed inside a Table, the formal #021 Runtime emits the same standard Port IDs (`port-left-in` / `port-right-out` / `port-top-in` / `port-bottom-out`). #048 namespaces only those cell DOM IDs with the **Table instance + row + column**, preserves the original ID in `data-bone-table-original-id`, and does not modify #021 Runtime.

## 16. #054 Display Timeline in a cell

#054 properties come from the #054 runtime-owned Property Schema.

The formal time-label property is `timeAxisMode`:

| Value | Meaning |
|---|---|
| `all` | Show time labels on every Timeline |
| `group-first` | Show them only on the first Timeline in the group |
| `none` | Hide time labels |

`showLabels` remains the #054 compatibility-gate property and is not a replacement for `timeAxisMode`.

## 17. #054 group-first / groupIndex

Each #054 cell is a separate Display Timeline instance. For `timeAxisMode="group-first"`, #048 assigns sequential `groupIndex=0,1,2...` values by actual #054-cell order within the same table column.

An explicit `row.$cells.<columnKey>.props.groupIndex` overrides the automatic value for that cell.

## 18. Post-layout renderer hook / afterLayout

Some UI components cannot calculate geometry correctly before their cell is attached to the DOM.

A Cell Renderer may return `afterLayout()` from `mount(ctx)`. #048 executes:

1. renderer mount
2. attach the complete Table to the DOM
3. run `afterLayout()`

The #054 adapter uses this hook to call formal `render()` and establish correct initial Shape Comment coordinates. User clicks are never used as a layout trigger.

## 19. Resize / rerender

#054 cells observe width changes. When a column/Table width changes, #054 rerenders against the new real width.

#048 does not force a fixed #054 height or replace #054's internal layout rules.

## 20. HTML Functional Class

The single normal-use class is `bf-table`.

Main attributes:

| Attribute | Runtime property |
|---|---|
| `data-table-caption` | `caption` |
| `data-table-columns` | `columns` |
| `data-table-rows` | `rows` |
| `data-table-header` | `showHeader` |
| `data-table-striped` | `striped` |
| `data-table-hover` | `hover` |
| `data-table-bordered` | `bordered` |
| `data-table-compact` | `compact` |
| `data-table-empty-text` | `emptyText` |
| `data-table-theme` | `theme` |
| `aria-label` | `ariaLabel` |

## 21. JavaScript / Public API

```js
const host = document.getElementById('table');
BoneTable.create(host, {
  columns: [{ key: 'name', label: 'Name' }],
  rows: [{ name: 'Aki' }]
});
BoneTable.setRows(host, [{ name: 'Mika' }]);
```

Main public APIs:

`defaults / normalizeOptions / normalizeCellElement / create / render / update / setOptions / setRows / setColumns / refreshCells / getRows / getColumns / getOptions / getState / registerCellRenderer / unregisterCellRenderer / getCellRenderer / getCellRendererPropertySchema / getCellRendererPropertyDefaults / listCellRenderers / hasCellRenderer / destroy / isInstance / getCompletionState / complete / reopen`

## 22. Registering future UI components

#048 is designed so new UI components do not require per-component `if` branches in Table.

```js
BoneTable.registerCellRenderer({
  id: "130",
  componentId: "130",
  className: "bf-new-ui",
  aliases: ["new-ui"],
  available: () => Boolean(window.BoneNewUI),
  propertySchema: () => BoneNewUI.getPropertySchema(),
  mount(ctx) {
    const element = BoneNewUI.create(ctx.value, ctx.props);
    ctx.host.appendChild(element);
    return {
      element,
      destroy: () => BoneNewUI.destroy(element)
    };
  }
});
```

If the UI publishes a runtime-owned Property Schema, register that provider directly.


### Structural UI with empty values

When a future UI must draw a frame, scale, or ruling without a value, register it with `renderEmpty:true`. This keeps the contract generic instead of hard-coding component IDs in #048.

```js
BoneTable.registerCellRenderer({
  id: "029",
  componentId: "029",
  renderEmpty: ctx => ctx.props && ctx.props.voucherMode === true,
  mount(ctx) {
    // Draw voucher structure while leaving the numeric value blank.
  }
});
```

## 23. Security / errors

- Plain values use `textContent`
- Unknown renderers fall back to safe text
- Renderer alias collisions are rejected
- Invalid columns, rows, or Property Schema definitions are rejected by Runtime errors

Representative error codes:

- `BONE_TABLE_COLUMN_KEY_DUPLICATE`
- `BONE_TABLE_THEME_INVALID`
- `BONE_TABLE_CELL_RENDERER_REQUIRED`
- `BONE_TABLE_CELL_PROPS_INVALID`
- `BONE_TABLE_CELL_PROPERTY_SCHEMA_INVALID`
- `BONE_TABLE_CELL_PROPERTY_KEY_DUPLICATE`

## 24. Joint / Smoke / Validation / Completion

Connection evaluation, drawing, abnormal markers, WAIT / FIFO / BLOCKED are delegated to #002 Bone Joint.

Smoke / Validation cover Runtime identity, Functional Class, Cell Renderer behavior, Property Schema, safe fallback, #054 Runtime Schema, group-first coordination, and initial post-layout reflow.

Completion is blocked until Smoke / Validation pass and WAIT / BLOCKED visual confirmation is complete. User-localhost confirmation remains a separate release gate before Completed / Specification Frozen.


### #029 empty voucher post-layout
When #029 NumberBox is used in voucher mode, #048 finalizes parent sizing and voucher display in afterLayout after the Table is attached to the DOM. Empty values remain null; only the voucher digit/grid structure is rendered.

### OUT WAIT / BLOCKED manual behavior

Use the formal #017 Text reference structure. The heading is `OUT WAIT / BLOCKED - #002 Joint v1.1.36 Integration`, and there are exactly three operations: `▶ WAIT / FIFO Run`, `⛔ BLOCKED Run`, and `↻ Reset`. Do not add an independent READY/FIFO button, Target READY/BUSY selector, or payload selector. WAIT / FIFO Run holds A and B in the queue while the Target is BUSY / WAITING, then returns the Target to READY after a visible wait and lets the #002 Delivery Channel automatically deliver A → B in FIFO order. WAIT/BLOCKED visual-confirmation checkboxes are not cleared by WAIT/BLOCKED, Smoke, or Validation; only `↻ Reset` explicitly clears them. Smoke/Validation Overall is separate from the visual confirmations, which are required by the Completion gate.


## 25. Theme inheritance

The Table `theme` property accepts `light / dark / neon`. The selected theme is propagated to Cell Renderers as `context.theme`. #021 Shape, #029 NumberBox, and #054 Display Timeline use the parent Table theme. #017 Text, #020 Label, and #018 Icon follow the Table theme presentation as well. #018 Icon is registered as built-in Cell Renderer `018` / `bf-icon`.


**Runtime Schema visibility:** The “Formal Property Definition (Runtime Schema)” section renders the live result of `BoneTable.getPropertySchema()` and does not duplicate the schema in HTML.

## Table display patterns (tableStyle)
Formal presets: `standard`, `striped`, `bordered`, `borderless`, `hover`, `compact`, `striped-hover`, `striped-bordered`, `compact-bordered`. Explicit Stripe / Hover / Border / Compact values override the preset result.


## Automatic Cell Renderer registration / dependency version tracking

#048 does not pin Cell UI runtimes by exact version equality. It validates the registered renderer contract by `componentId` and required APIs, while displaying the runtime version that is actually loaded. A compatible #017 update therefore does not require rewriting an expected version in #048.

Future UI runtimes can expose `getTableCellRendererDefinition()` (or `tableCellRendererDefinition`) or register a provider through `BoneTable.registerCellRendererProvider()`. #048 calls `discoverCellRenderers()` and automatically reflects providers in the Cell Renderer selector and Used Components grid. Registry changes emit `bone-table-cell-renderer-registry-change`, so the page refreshes automatically.

#048 does not guess how to mount an arbitrary UI that does not publish this provider contract. The UI owns its rendering adapter. This removes the need to edit #048 whenever a new conforming UI or compatible runtime version is added.

## #029 Voucher Cell Full-Height Snap (v1.0.31)

When `cellElement: {renderer:"029", snapToCell:true}` is used, #048 aligns voucher vertical rules to row edges. The frozen #029 runtime and `snapToCell:false` are unaffected.


<!-- #048 package 1.0.32; Runtime 1.0.16; #017 Text base preserved. -->
