Package Structure
This document describes the structure and organization of GridSheet packages.
Monorepo Overview
GridSheet is organized as a monorepo using pnpm workspaces:
gridsheet/
├── packages/
│ ├── core/ # Framework-agnostic core (Sheet, Registry, formula engine, etc.)
│ ├── react-core/ # React implementation (components, hooks, store)
│ ├── preact-core/ # Preact implementation (same codebase, different build target)
│ ├── react-dev/ # Development utilities for React
│ ├── functions/ # Extended formula functions (@gridsheet/functions)
│ ├── vue-core/ # Vue.js implementation (wrapper around preact-core)
│ ├── docs/ # Documentation site
│ └── storybook/ # Component examples and testing
├── e2e/ # Playwright end-to-end tests
├── package.json # Root package configuration
├── tsconfig.json # Root TypeScript configuration
└── README.md # Project overviewDependency Graph
@gridsheet/core ← Framework-agnostic (no React/Preact imports)
├── @gridsheet/react-core ← React components, hooks, store (dep: core)
│ └── @gridsheet/react-dev (peerDep: core)
├── @gridsheet/preact-core ← Preact build via alias (dep: core)
│ └── @gridsheet/vue-core (dep: preact-core)
└── @gridsheet/functions ← Formula definitions (peerDep: core)Why @gridsheet/core exists
@gridsheet/functions uses classes like Sheet, Registry, and BaseFunction from the core. Previously, functions depended on @gridsheet/react-core, which forced Preact users to install react-core as well. This resulted in two separate copies of these classes in the bundle, causing instanceof checks to fail (e.g. SUM returning 0).
By extracting framework-agnostic code into @gridsheet/core, all packages share the same class instances regardless of the framework.
External and peerDependencies
When a package marks a dependency as external in its Vite config, the import statement (e.g. from "@gridsheet/core") is preserved in the built output rather than bundled. This means the dependency must exist in the user's node_modules at runtime.
peerDependencies declares this requirement to the package manager. Without it, npm/pnpm would not warn users when the external dependency is missing or has an incompatible version. Therefore, external and peerDependencies are always paired together.
| Package | external (Vite) | peerDependencies |
|---|---|---|
@gridsheet/core | dayjs | dayjs |
@gridsheet/react-core | react, react-dom, @gridsheet/core, dayjs | react, react-dom, dayjs (core is in dependencies) |
@gridsheet/preact-core | preact, @gridsheet/core, dayjs | preact, dayjs (core is in dependencies) |
@gridsheet/functions | @gridsheet/core, dayjs | @gridsheet/core, dayjs |
@gridsheet/react-dev | react, react-dom, @gridsheet/core | react, react-dom, @gridsheet/core |
Note:
@gridsheet/coreis listed in dependencies (not peerDependencies) forreact-coreandpreact-corebecause they always require it. Forfunctionsandreact-dev, it is a peerDependency because core is expected to be provided by the framework package (react-coreorpreact-core) that the user already has installed.
Versioning Strategy
Core Packages
- @gridsheet/core: Framework-agnostic core (Sheet, Registry, formula engine, policy, coords, spatial, etc.)
- @gridsheet/react-core: React components, hooks, and store
- @gridsheet/preact-core: Preact build (same codebase via react→preact/compat alias)
These core packages always maintain identical versions following semantic versioning: MAJOR.MINOR.PATCH[-PRERELEASE]
Extended Packages
- @gridsheet/functions: Extended formula functions library. Provides
allFunctionsandcreateSpellbook. UseuseSpellbookfrom@gridsheet/react-core/spellbookfor the React hook version. - @gridsheet/react-dev: Development utilities for React.
Wrapper Packages
The Vue implementation is a wrapper around the preact-core:
- @gridsheet/vue-core: Vue.js wrapper around preact-core
When only the wrapper layer is updated, this package uses the format: MAJOR.MINOR.PATCH-X where X starts from 0 and increments as integers.
Version Examples
{
"name": "@gridsheet/react-core",
"version": "2.0.0-rc.2"
}
{
"name": "@gridsheet/preact-core",
"version": "2.0.0-rc.2"
}
{
"name": "@gridsheet/vue-core",
"version": "2.0.0-rc.2-0"
}Git Tagging Strategy
All packages in the monorepo use the following git tag format upon release:
{package-name}/{version}For example:
@gridsheet/react-core/2.0.0-rc.2@gridsheet/vue-core/2.0.0-rc.2-0
Version Bumping Rules
- Core Updates: Both
react-coreandpreact-corebump together - Wrapper Updates: Only
vue-coreincrement the suffix (0, 1, 2, ...) - Breaking Changes: All packages bump major version
- New Features: All packages bump minor version
- Bug Fixes: All packages bump patch version