Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2f2dadf
feat(line-items): add LineItems, useLineItems and BulkItemPicker
itsprade Oct 12, 2026
f6b6715
docs(line-items): add LineItems and BulkItemPicker outlines
itsprade Oct 12, 2026
8770e3c
feat(line-items): add useLineItemsGroup for multi-collection documents
itsprade Oct 12, 2026
ab596d6
test(line-items): cover Enter commit in the last row
itsprade Oct 12, 2026
46b6fc5
docs(examples): add LineItems PO and Journal Entry showcase pages
itsprade Oct 12, 2026
6bf953d
fix(line-items): pin and fill every totals-row cell so scrolled conte…
itsprade Oct 12, 2026
2e8fb7d
fix(line-items): ellipsis truncation and header column dividers
itsprade Oct 12, 2026
c6f3dd5
feat(line-items): bulk selection actions via DataTable's footer bar
itsprade Oct 12, 2026
74d99d4
feat(line-items): taller default grid (min(70vh, 720px))
itsprade Oct 12, 2026
e594cb9
feat(line-items): cap the default grid height at 600px
itsprade Oct 12, 2026
5647765
feat(line-items): totals-row top border and scroll-edge shadows
itsprade Oct 12, 2026
f24491b
fix(line-items): soften the scroll-edge shadows
itsprade Oct 12, 2026
d150b48
fix(line-items): controlled round-trip, Tab trap, and cell draft sync
itsprade Oct 12, 2026
ac6210c
fix(line-items,bulk-item-picker): app-shell rules, i18n, a11y and docs
itsprade Oct 12, 2026
2bd4c22
refactor(line-items): settle the API from review
itsprade Oct 12, 2026
0f82249
fix(line-items): round-2 review fixes
itsprade Oct 12, 2026
83a24d5
refactor(tree-picker): rename BulkItemPicker to TreePicker
itsprade Oct 12, 2026
c7a1559
fix(line-items): pinned cells take the row hover tint
itsprade Oct 12, 2026
fb7b1e4
fix(tree-picker): tighten the gap between a child's checkbox and label
itsprade Oct 12, 2026
ac78f8d
feat(tree-picker): click anywhere on a row to check or uncheck it
itsprade Oct 12, 2026
002512e
feat(tree-picker): ease the dialog's height as groups expand and coll…
itsprade Oct 12, 2026
dd0edb2
feat(tree-picker): rotate the expand chevron instead of swapping icons
itsprade Oct 12, 2026
0fb84ad
feat(tree-picker): clicking a group row opens or closes it
itsprade Oct 12, 2026
1d5c943
fix(tree-picker): export inline so published .d.ts type-checks
itsprade Oct 12, 2026
ea82a50
refactor(line-items,tree-picker): settle the API from review round 2
itsprade Oct 12, 2026
44b8383
Merge branch 'feat/tree-picker' into feat/line-items
itsprade Oct 12, 2026
0142a19
Merge branch 'feat/tree-picker' into claude/pr-238-review-fixes-3a35c6
itsprade Oct 13, 2026
a8db388
Merge branch 'feat/tree-picker' into claude/pr-238-review-fixes-3a35c6
itsprade Oct 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .changeset/wise-lines-gather.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
"@tailor-platform/app-shell": minor
---

Add `LineItems` — a spreadsheet-grade editable table for the lines of a document (purchase orders, invoices, journals, stock transfers), plus the `useLineItems` hook and the `createLineItemHelper` field-schema builder.

State lives in the hook; the compound parts render it. `getChangeSet()` returns a transport-agnostic description of what changed, so only real edits are submitted.

```tsx
import { LineItems, useLineItems, createLineItemHelper } from "@tailor-platform/app-shell";

const f = createLineItemHelper<POLine>();
const fields = [
f.field({
key: "sku",
label: "SKU",
render: (l) => l.sku,
editable: ["edit"],
type: { kind: "text" },
}),
f.field({
key: "quantity",
label: "Qty",
render: (l) => l.quantity ?? 0,
editable: ["edit"],
type: { kind: "number", decimals: 0 },
}),
];

function Lines({ lines }: { lines: POLine[] }) {
const lineItems = useLineItems<POLine>({
fields,
defaultLines: lines,
ordering: "manual",
selection: true,
});

return (
<LineItems.Root value={lineItems}>
<LineItems.Search />
<LineItems.Table />
<LineItems.SaveActions onSave={(changeSet) => submit(changeSet.lineChanges)} />
</LineItems.Root>
);
}
```

For documents with more than one list of lines (journal debits and credits, work-order components and operations), `useLineItemsGroup({ debits, credits })` puts several `useLineItems` collections under one save boundary: a shared `isDirty`, one keyed `getChangeSet()`, and group-wide `reset()` / `revert()`.

Includes view and edit modes, inline cell editors that commit on blur or Enter, range selection with TSV copy/paste, pinned columns, a sticky totals row, row selection with an optional bulk-action bar (`selection: { actions }`, the same bar as DataTable, at the table's foot), row virtualization for long documents, and drag reordering with a keyboard fallback on the grip handle.

Built-in labels are localized (English and Japanese) through the app locale, like DataTable.
53 changes: 49 additions & 4 deletions docs-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,50 @@
"examples": "2a4aa694c4d48324"
}
},
"line-items": {
"slug": "line-items",
"kind": "code-backed",
"outline": "docs-src/components/line-items.docs.outline.md",
"output": "docs/components/line-items.md",
"examples": null,
"sources": ["packages/core/src/components/line-items/**"],
"claims": [],
"symbols": [
"LineItems",
"LineItemsChangeSet",
"LineItemsColumnAlign",
"LineItemsCustomEditorContext",
"LineItemsField",
"LineItemsFieldCommit",
"LineItemsFieldType",
"LineItemsGroupChangeSet",
"LineItemsGroupMembers",
"LineItemsLineChange",
"LineItemsMetadataCommit",
"LineItemsMode",
"LineItemsOrderingMode",
"LineItemsRootProps",
"LineItemsRowData",
"LineItemsRowPatch",
"LineItemsSelectOption",
"LineItemsSortDirection",
"LineItemsSortState",
"LineItemsTableProps",
"UseLineItemsGroupReturn",
"UseLineItemsOptions",
"UseLineItemsReturn",
"createLineItemHelper",
"useLineItems",
"useLineItemsGroup"
],
"hashes": {
"typeSurface": "5490757b7147eb0e",
"outline": "02bd4817ec79d1df",
"snapshot": "0fe7d573725826ba",
"outputMd": "a3f0e85fa5875c54",
"examples": null
}
},
"list-dense-scan": {
"slug": "list-dense-scan",
"kind": "prose",
Expand Down Expand Up @@ -1440,9 +1484,9 @@
"symbols": ["TreePicker", "TreePickerNode", "TreePickerProps"],
"hashes": {
"typeSurface": "d58cf3e3b3559ef4",
"outline": "422bea1a7c11a58d",
"outline": "d7367171b068e96a",
"snapshot": "4255a571e84cf5f5",
"outputMd": "010084030ccb6fb5",
"outputMd": "d56641431b2fac6f",
"examples": null
}
},
Expand Down Expand Up @@ -1722,6 +1766,7 @@
"packages/core/skills/app-shell-patterns/references/components/grid.md": "9051eb53dde4179f",
"packages/core/skills/app-shell-patterns/references/components/input.md": "a3a6c9679af99d37",
"packages/core/skills/app-shell-patterns/references/components/layout.md": "66696139a46fabb0",
"packages/core/skills/app-shell-patterns/references/components/line-items.md": "a3f0e85fa5875c54",
"packages/core/skills/app-shell-patterns/references/components/menu.md": "ceb4a05822538d20",
"packages/core/skills/app-shell-patterns/references/components/metric-card.md": "5a1c557768c6590f",
"packages/core/skills/app-shell-patterns/references/components/select.md": "ae287e2bb5abc1c6",
Expand All @@ -1737,7 +1782,7 @@
"packages/core/skills/app-shell-patterns/references/components/timeline.md": "699249c9452485ab",
"packages/core/skills/app-shell-patterns/references/components/toolbar.md": "91d70b140c7bb747",
"packages/core/skills/app-shell-patterns/references/components/tooltip.md": "113c95b2995917ed",
"packages/core/skills/app-shell-patterns/references/components/tree-picker.md": "010084030ccb6fb5",
"packages/core/skills/app-shell-patterns/references/components/tree-picker.md": "d56641431b2fac6f",
"packages/core/skills/app-shell-patterns/references/components/with-guard.md": "d79aaf40cb97073f",
"packages/core/skills/app-shell-patterns/references/api/create-ai-gateway-client.md": "7eaff97521a14ab0",
"packages/core/skills/app-shell-patterns/references/api/create-typed-paths.md": "4c3a858d3eb02a2a",
Expand Down Expand Up @@ -1775,6 +1820,6 @@
"packages/core/skills/app-shell-patterns/references/patterns/list-dense-scan.md": "916baa3cd2b9cbf1",
"packages/core/skills/app-shell-patterns/references/pages/document-detail.md": "717ef4e7ae835aff",
"packages/core/skills/app-shell-patterns/references/migrations.md": "013c3fef2303b096",
"packages/core/skills/app-shell-patterns/SKILL.md": "59a0b9d40318e6ba"
"packages/core/skills/app-shell-patterns/SKILL.md": "11831fe5f4b8eb7c"
}
}
Loading
Loading