Skip to main content
Version: v0.6.x

Contributing

The repo is a pnpm workspace: the library at the root, an Expo example app in example/ that renders against the library source (edits hot-reload), and this docs site in website/.

Setup​

git clone https://github.com/elik56a/react-native-pickers.git
cd react-native-pickers
pnpm install # also installs the git hooks

Scripts​

CommandWhat it does
pnpm webExample app in the browser
pnpm iosExample app in the iOS Simulator
pnpm androidExample app in the Android emulator
pnpm docsThis site at localhost:3001
pnpm testJest + React Native Testing Library
pnpm lintBiome: lint, format and import order
pnpm formatFix whatever lint can fix
pnpm typecheckTypeScript, including tests
pnpm buildCompile to lib/ (ESM + .d.ts)
pnpm gen:emojiRegenerate the emoji data from emojibase

Project structure​

Each picker has its own folder under src/: wheel, time, calendar, date, datetime, select and emoji. They build on sheet (bottom sheets) and core (theme, shared hooks and utils). Imports only flow one way: feature → sheet → core.

Every folder has the same layout:

src/select/
├─ SelectPicker.tsx components render only
├─ components/ smaller render-only parts
├─ hooks/ state and event handling
├─ select.utils.ts pure logic
├─ select.utils.test.ts unit tests for every util
├─ select.types.ts
├─ select.constants.ts
├─ select.styles.ts
├─ SelectPicker.test.tsx interaction tests
└─ index.ts the folder's public API

Where new code goes:

  • Pure logic (calculations, filtering, date math) goes in <feature>.utils.ts, with a unit test next to it.
  • State and event handling goes in a hook under hooks/.
  • Components only render: they call hooks and utils, with no inline logic.
  • Types, constants and styles go in their own <feature>.*.ts files, never inside components.

Conventions​

  • Tests sit next to the file they test.
  • Use arrow functions: export const fn = () =>, not export function.
  • Returned objects with two or more properties go one property per line. A Biome plugin enforces it, and pnpm format fixes it.
  • Imports come in three blocks separated by a blank line: React and React Native, other packages, then our own code.
  • Commit messages follow Conventional Commits: feat:, fix:, refactor(select):, docs: and so on.

Checks​

The pre-commit hook formats and lints the staged files and runs typecheck, and the commit-msg hook checks the message. On every pull request, CI runs lint, typecheck, tests and the build. Pull requests are squash-merged, so CI also checks that the PR title is a Conventional Commit: it becomes the commit message on master.

Releasing​

Releases are automated with release-please and driven by the commit messages on master:

  • fix: makes a patch release, feat: a minor one, and a ! or a BREAKING CHANGE: footer a major one (a minor one before 1.0).
  • Commits that only touch website/, example/, .github/ or lint/ don't trigger a release.
  • After every merge, release-please updates a chore(release): vX.Y.Z pull request with the version bump and the changelog entry. Nothing ships while it stays open.
  • Merging that PR tags the version, creates the GitHub release, publishes to npm and redeploys these docs.
  • To pick the version yourself, add a Release-As: 1.0.0 footer to a commit.

The docs are versioned from the git tags: /docs always matches the latest release on npm, master is published as Next at /docs/next, and every minor line keeps its own version in the dropdown.