@lax-wp/datasheet-table
v0.1.1
Published
Spreadsheet-style dataset grid: Zustand data engine (undo/redo, hierarchy, formulas, validation, diff) plus the virtualized table UI, extracted from lax-web-portal.
Readme
@lax-wp/datasheet-table
Spreadsheet-style dataset grid extracted from lax-web-portal/src/features/dataset: the Zustand data
engine (undo/redo, 3-level row hierarchy, column formulas, validation, diff, paste/fill, filters,
search) plus the virtualized table UI, the read-only viewer, the filter row and the JSON tab.
Status: extraction in progress. The portal is still the source of truth; this package is being proven in Storybook before the portal switches to consuming it. Nothing was removed from the portal.
Quick start (local)
npm install
npm run storybook # http://localhost:6007
npm test # vitest, jsdom
npm run typecheck
npm run build # dist/ (ES + CJS, one file per module, d.ts)Using it in an app
import { DataSheetContainer, DatasheetProvider, addDatasheetTranslations } from '@lax-wp/datasheet-table';
addDatasheetTranslations(i18n); // once, after the host's i18n init
<DatasheetProvider isDarkMode={isDarkMode} masterData={masterDataAdapter} dynamicData={dynamicDataAdapter}>
<DataSheetContainer ref={handleRef} source={{ headers, current, previous }} isEditMode enableJsonTab />
</DatasheetProvider>;The host must also:
- Tailwind: add
node_modules/@lax-wp/datasheet-table/dist/**/*.jstocontentand use the same theme tokens as@lax-wp/design-system(primary-*,neutral-*,error-*, …).tailwind.config.jshere is the reference. - Design-system shell: render the grid inside
#layout-app-main-content-container(or#full-screen-container); the design-systemModalportals there. Give the grid a flex parent withmin-h-0so it can measure its scroll area. - Monaco (JSON tab): call
monacoManager.configure({ paths: { vs: '/monaco-editor/min/vs' } })once at startup, as the portal does. Storybook falls back to the CDN loader. - Adapters: the
master dataanddynamiccolumn types talk to lax backends. Register anIMasterDataAdapter/IDynamicDataAdapteronDatasheetProvider(seesrc/stories/HostAdapters.stories.tsxfor an in-memory example). Without one those two types are hidden from the data-type selector.
Peer dependencies mirror the design system's: React, antd, Zustand, Immer, TanStack Virtual, dnd-kit, dayjs, zod, i18next/react-i18next, react-toastify, framer-motion, lodash, MUI icons, country-flag-icons.
Layout
src/
├── index.ts public barrel — the only import path for consumers
├── host/ DatasheetProvider, theme + adapter contracts, no-op adapters
├── shared/ constants/helpers copied from the portal (colors, currencies, formats, …)
├── i18n/ en.json (keys = English source strings) + addDatasheetTranslations
├── models/ constants/ store/ validation/ utils/ registry/ hooks/ components/ the grid, verbatim from the portal
├── __fixtures__/ tiny / medium / large datasets for stories and tests
├── stories/ Storybook
└── test-utils/ vitest setup, jsdom stubs, renderWithProvidersSee CLAUDE.md for the extraction rules, the seams that differ from the portal, and how to re-sync.
