demo D224
A production line in React
A measurement profile transpose, an out-of-tolerance list, spread by line, and Cpk in a tile against the column spec
profile · where · statistics.capability
This is a production-line view built from one measurement source: a profile transpose, an out-of-tolerance list, a spread by line, and a capability figure in a tile checked against the column's own spec. It turns raw readings into the few numbers a shift lead actually acts on.
This is the React version. The grid mounts through the createLatticeGrid adapter, which takes its configuration as ordinary props and hands back the live grid through a ref. The grid below is the same one every other tab runs.
The configuration
<link rel="stylesheet" href="https://cdn.latticegrid.dev/lattice-grid@1.108.0/lattice-grid.min.css">
<div id="app"></div>
<script type="module">
import React from 'https://esm.sh/react@18';
import { createRoot } from 'https://esm.sh/react-dom@18/client';
import { createGrid, createStat } from 'https://cdn.latticegrid.dev/lattice-grid@1.108.0/lattice-grid.esm.min.js';
import createLatticeGrid from 'https://cdn.latticegrid.dev/lattice-grid@1.108.0/modules/react.esm.min.js';
const LatticeGrid = createLatticeGrid({ React, createGrid });
const lineColumns = [
{ field: 'line', title: 'Line', filter: { type: 'set' } },
// The spec is the tolerance; the Cpk tile reads it.
{ field: 'bore', title: 'Bore', type: 'millimetres', spec: { lower: 19.96, upper: 20.04, target: 20 } },
{ field: 'temp', title: 'Coolant', type: 'celsius' },
{ field: 'cycle', title: 'Cycle', type: 'seconds' },
];
const profileColumns = [
{ field: 'column', title: 'Measure' },
{ field: 'rows', title: 'n', type: 'number' },
{ field: 'mean', title: 'Mean', type: 'number', format: { decimals: 3 } },
{ field: 'stddev', title: 'σ', type: 'number', format: { decimals: 4 } },
{ field: 'outliers', title: 'Outliers', type: 'number' },
];
const ootColumns = [
{ field: 'id', title: 'Part' },
{ field: 'line', title: 'Line' },
{ field: 'bore', title: 'Bore', type: 'millimetres' },
];
const rows = [/* measured parts */];
function App() {
const lineRef = React.useRef(null);
const tilesRef = React.useRef(null);
const [profile, setProfile] = React.useState(null);
const [oot, setOot] = React.useState(null);
React.useEffect(() => {
const line = lineRef.current && lineRef.current.grid;
if (!line) return;
// profile transposes: one row per column, with count, mean, sd, min, max
// and outliers as the columns. Every other derived shape emits one row per
// group.
setProfile({ mode: 'derived', from: line, profile: ['bore', 'temp', 'cycle'], refresh: 'live' });
// where with no groupBy passes real rows through: the parts outside tolerance.
setOot({ mode: 'derived', from: line, follow: 'filtered', refresh: 'live', where: (r) => Math.abs(r.bore - 20) > 0.04 });
// Cpk against the column's declared spec, read through a value function.
const tile = tilesRef.current.appendChild(document.createElement('div'));
createStat({ grid: line, container: tile, title: 'Cpk',
value: (g) => g.statistics.capability('bore')?.cpk, goodWhen: 'up', baseline: 1.33, decimals: 2 });
}, []);
return (
<>
<LatticeGrid
ref={lineRef}
rowKey="id"
toolPanel={{ side: 'left', panels: ['filters', 'columns'] }}
columns={lineColumns}
rows={rows}
style={{ height: '320px' }}
/>
<div ref={tilesRef} style={{ margin: '16px 0' }} />
{profile && <LatticeGrid autoHeight source={profile} columns={profileColumns} style={{ marginTop: '16px' }} />}
{oot && <LatticeGrid autoHeight source={oot} columns={ootColumns} style={{ marginTop: '16px' }} />}
</>
);
}
createRoot(document.getElementById('app')).render(<App />);
</script>