Development Guide
This guide covers the development workflow, tools, and best practices for contributing to GridSheet.
Development Setup
Section titled “Development Setup”Prerequisites
Section titled “Prerequisites”- Node.js: Version 22.x or later
- pnpm: For package management
- Git: For version control
Installation
Section titled “Installation”# Clone the repositorygit clone https://github.com/your-org/gridsheet.gitcd gridsheet
# Install dependenciespnpm installDevelopment Scripts
Section titled “Development Scripts”# Start Storybook development serverpnpm dev
# Start documentation development serverpnpm doc
# Run unit testspnpm test
# Run e2e tests (uses server)pnpm e2e
# Run linting and apply prettierpnpm lint:fixTesting Strategy
Section titled “Testing Strategy”Testing Policy
Section titled “Testing Policy”GridSheet follows this testing strategy:
- E2E tests (Playwright): The default for all features — component behavior, user interactions, and integration between components.
- Unit tests (Jest): Used only for
packages/functions. Every formula function in that package must have a corresponding Jest unit test.
E2E Test Example
Section titled “E2E Test Example”import { test, expect } from '@playwright/test';import { ctrl, drag, paste } from './utils';
test('time + delta, time + number(days)', async ({ page }) => { await page.goto('http://localhost:5233/iframe.html?id=basic-simple--sheet&viewMode=story'); const a4 = page.locator("[data-address='A4']"); const b4 = page.locator("[data-address='B4']"); const c4 = page.locator("[data-address='C4']"); const a5 = page.locator("[data-address='A5']");
expect(await a4.locator('.gs-cell-rendered').textContent()).toBe('2022-03-05 12:34:56'); expect(await b4.locator('.gs-cell-rendered').textContent()).toBe('11:11:11'); expect(await c4.locator('.gs-cell-rendered').textContent()).toBe('2022-03-05 23:46:07'); expect(await a5.locator('.gs-cell-rendered').textContent()).toBe('2022-03-04 23:34:56');});Available Utilities:
The E2E test suite provides utility functions for common operations:
ctrl: Helper for Ctrl key combinationsdrag: Helper for drag and drop operationspaste: Helper for paste operations
These utilities are available in e2e/utils.ts and can be imported to simplify test writing.
Formula Functions
Section titled “Formula Functions”Creating Custom Formula Functions
Section titled “Creating Custom Formula Functions”When adding new formula functions to GridSheet, follow these guidelines:
Package Location Strategy
Section titled “Package Location Strategy”To keep the distribution size of @gridsheet/react-core as compact as possible, it only includes essential, minimum functions. All future function additions must be made to the @gridsheet/functions package (packages/functions).
Google Spreadsheet Compatibility
Section titled “Google Spreadsheet Compatibility”When adding new functions, prioritize those that are also supported by Google Spreadsheet:
- Target Functions: Focus on functions that exist in Google Sheets
- Specification Matching: Follow Google Sheets’ function specifications and behavior
- Parameter Compatibility: Match argument types, order, and validation rules
- Return Value Consistency: Ensure return values match Google Sheets’ behavior
- Error Handling: Implement the same error conditions and messages
BaseFunction Inheritance
Section titled “BaseFunction Inheritance”All custom formula functions must extend the BaseFunction class:
import { BaseFunction, ensureString } from '@gridsheet/react-core';import type { FunctionArgumentDefinition } from '@gridsheet/react-core';
class CustomFunction extends BaseFunction { // Required properties for documentation and the function guide UI example = 'CUSTOM_FUNCTION("value", 123)'; description = 'Performs a custom operation on the input values'; category = 'text' as const; // math | statistics | text | time | lookup | information | logical | other defs: FunctionArgumentDefinition[] = [ { name: 'value', description: 'The input value to process', acceptedTypes: ['string'] }, { name: 'number', description: 'A numeric parameter', acceptedTypes: ['number'] }, ];
// Required main implementation protected main(value: string, number: number) { // Your custom logic here return `Processed: ${value} with ${number}`; }}Note: The built-in
validate()method automatically checks argument count and types based ondefs. Override it only when you need custom coercion logic beyond whatdefsprovides.
Documentation Properties
Section titled “Documentation Properties”Every formula function must include these properties:
example: Shows how to use the function in a formuladescription: A string describing what the function does (used in the FunctionGuide UI)category: Classification (math,statistics,text,time,lookup,information,logical,other)defs: Array ofFunctionArgumentDefinitionobjects with name, description, and optional type constraints
Function Registration
Section titled “Function Registration”Register custom functions via the additionalFunctions option in useBook (or createBook):
import { useBook } from '@gridsheet/react-core';
const book = useBook({ additionalFunctions: { CUSTOM_FUNCTION: CustomFunction, },});For apps that want all extended functions from the @gridsheet/functions package:
import { useSpellbook } from '@gridsheet/react-core/spellbook';
// useSpellbook pre-loads all extended functions and accepts extra onesconst book = useSpellbook({ additionalFunctions: { CUSTOM_FUNCTION: CustomFunction },});Documentation
Section titled “Documentation”API Documentation
Section titled “API Documentation”# Start documentation development serverpnpm doc
# Build documentationpnpm build:docsStorybook
Section titled “Storybook”# Start Storybook development serverpnpm dev
# Build Storybookpnpm build:storybookContributing
Section titled “Contributing”Pull Request Process
Section titled “Pull Request Process”- Create Feature Branch:
git checkout -b feature/new-feature - Make Changes: Implement your feature
- Run Tests: Ensure all tests pass (
pnpm test) - Update Documentation: Update relevant docs
- Submit PR: Create pull request with description
Code Review Checklist
Section titled “Code Review Checklist”- Code follows style guidelines
- Tests are included and passing
- Documentation is updated
- No breaking changes (or documented)
- Performance impact considered
Release Process
Section titled “Release Process”- Version Bump:
pnpm set-version <version>(updates all packages, commits, and tags) - Push to master:
git push origin master --tags - GitHub Actions (
release.yaml) will automatically build and publish all packages to npm
Recommended: Release via GitHub Actions rather than manually. The CI pipeline handles build order and dependency resolution correctly.
If you must publish manually, always use
pnpm publish(notnpm publish).pnpm publishautomatically convertsworkspace:*references to actual version numbers.npm publishwill leaveworkspace:*as-is, causing installation failures for users.