Conversation
Modernize tooling, packaging, and source quality without changing any public
prop name, runtime default, or the imperative ref API.
Packaging & deps:
- Remove accidental self-dependency on react-native-bouncy-checkbox.
- Drop unused runtime dep @freakycoder/react-native-bounceable -> the package
is now truly zero-runtime-dependency.
- Add peerDependencies (react >=16.8.0, react-native >=0.63.0).
- Add exports map, module/react-native/source/types fields, and a files
allowlist; repoint repo/homepage/bugs/funding URLs to kuraydev.
- Remove dead devDeps (@types/react-native, react-native-typescript-transformer,
prettier-format, npm-post-install, cpx, unused @react-native/* configs).
Build:
- Migrate from hand-rolled tsc+cpx to react-native-builder-bob (CommonJS + ESM +
TypeScript targets). Published output moves from build/dist/* to
build/{commonjs,module,typescript}/*. The default export and bare package
import are unchanged.
Source:
- Add defaultChecked prop (#815) for uncontrolled initial state.
- Default accessibilityRole="checkbox" + accessibilityState (overridable) (#103).
- Fix invalid Callback<any> generic in useStateWithCallback (now fully generic).
- Convert fake StyleSheet function entries to static styles + typed helpers;
hold Animated.Value in useRef; memoize render callbacks.
Tests & CI:
- Add Jest + @testing-library/react-native suite (11 tests).
- Add GitHub Actions CI (typecheck/lint/test/build on Node 18/20/22) and a
semantic-release workflow.
Docs & hygiene:
- Rewrite README: fix unFillColor casing, useBuiltInState=true and
fillColor=#ffc484 defaults, add iconImageStyle/defaultChecked rows, drop dead
disableBuiltInState references, package-name imports, a11y + New Arch/Expo/Web
notes, CI/TS badges.
- Add CHANGELOG, CONTRIBUTING, issue forms and PR template.
BREAKING CHANGE: published module output paths changed (build/dist -> build/
commonjs|module|typescript) and the build now uses react-native-builder-bob with
an exports map. Deep imports into build/dist/* will break; the documented
`import BouncyCheckbox from "react-native-bouncy-checkbox"` entry is unchanged.
The unused @freakycoder/react-native-bounceable runtime dependency was removed;
projects that relied on it being installed transitively must add it directly.
The bundled default check icon (lib/local-assets/check.png, loaded via require) rendered blank on react-native-web because RNW can size a required PNG at 0x0 and applies an inconsistent resize mode. Guarantee explicit dimensions and resizeMode: "contain" on web only (Platform.OS === "web"); native iOS/Android passes no resizeMode and keeps the same style array, so its rendering is byte-for-byte unchanged. No public prop or default value changes. Adds Platform.OS='web' Jest coverage for the icon dimensions/resizeMode and a native byte-for-byte guard test. Closes #103
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A full modernization of
react-native-bouncy-checkboxthat fixes packaging correctness, stands up tooling/CI/tests from scratch, and cleans up the source — without changing any public prop name, runtime default value, or the imperativerefAPI. The package now genuinely ships with zero runtime dependencies and modern dual-format (CJS + ESM) output with proper types.All local checks pass: typecheck, lint, 11 tests, and a clean build.
Non-breaking improvements
Packaging & metadata
react-native-bouncy-checkboxindependencies.peerDependencies:react >=16.8.0,react-native >=0.63.0.exportsmap plusmodule/react-native/source/typesfields and afilesallowlist (tarball is now 20kB and ships onlylib/source +build/+ README/LICENSE).repository/homepage/bugs/FUNDINGto kuraydev. npm package name is unchanged.@types/react-native(deprecated stub),react-native-typescript-transformer,prettier-format,npm-post-install,cpx, and unused@react-native/*config/metro packages.Source & a11y
defaultCheckedprop for uncontrolled initial state (closes add defaultChecked prop #815) — does not affect the existingisChecked/useBuiltInStatemodel.accessibilityRole="checkbox"+accessibilityState={{ checked }}on the touchable (overridable via props) — improves screen-reader andreact-native-websemantics (check icon not rendering on react native web #103).Callback<any>generic inuseStateWithCallback(latent TS error); the helper is now fully generic.StyleSheetfunction "entries" into real static styles + typed dynamic helpers (removes per-render reallocation), moved theAnimated.Valueinto auseRef, and memoized the render callbacks.ImageComponent/TouchableComponentprops asReact.ComponentType<any>(documented) so third-party touchables/images likeFastImagestill type-check.Tests & CI
defaultChecked, controlled prop change,onPress/onLongPresspayloads, imperativeref.onCheckboxPress()/onCheckboxLongPress(),disableText, customtextComponent/iconComponent, and a11y state.typecheck/lint/test/buildon Node 18/20/22) and asemantic-releaseworkflow (replacing the never-run release wiring; no Travis existed).Docs & hygiene
unFillColor(capital F),useBuiltInStatedefaulttrue,fillColordefault#ffc484, addediconImageStyleanddefaultCheckedrows, removed deaddisableBuiltInStatereferences, switched examples to package-name imports, added Accessibility + New Architecture/Expo/Web sections, CI/TypeScript badges, and Contributing/Changelog links. The "Zero Dependency" claim is now true (bounceable removed).CHANGELOG.md(Keep a Changelog),CONTRIBUTING.md, issue forms, and a PR template.Breaking changes (recommend v5.0.0 major)
build/dist/*tobuild/{commonjs,module,typescript}/*via react-native-builder-bob (CommonJS + ESM + TypeScript targets). The documentedimport BouncyCheckbox from "react-native-bouncy-checkbox"entry and the default export shape are unchanged; only deep imports intobuild/dist/*break.exportsmap introduced — module resolution is now condition-based (require→ CJS,import→ ESM,typesper condition,react-native/source→lib/index.ts). Verified bothrequire()and ESMimportresolve.@freakycoder/react-native-bounceableruntime dependency — projects that relied on it being installed transitively must add it directly.peerDependenciesintroduced — may surface peer-range warnings; ranges were chosen wide to minimize friction.No public prop names, runtime defaults, or the
BouncyCheckboxHandleref API changed.Deliberately not changed
Animatedimplementation rather than migrating to Reanimated v3 (React Native Reanimated v3 Version #90) to preserve the install-and-go story; documented the New Architecture compatibility instead.onPress) is not addressed — device-specific, no repro hardware.Verification
npm install --ignore-scripts(1269 pkgs, lockfile regenerated)tsc --noEmiteslint .(0 errors; 2 intentionalno-explicit-anywarnings on open component props)jest11/11bob build, dual CJS/ESM + d.ts,check.pngcopied into both outputsrequire()→build/commonjs/index.js; ESMimport→build/module/index.jsboth resolvenpm pack --dry-run→ 20.2kB, lib source + build only (no examples/tests/gifs)Closes
Partially addresses #103 (accessibility/web semantics); responds to #90 (keep Animated by default).
react-native-web support (Closes #103)
The bundled default check icon (
lib/local-assets/check.png, loaded viarequire()) rendered blank on react-native-web (a few users also reported it on Android). On RNW a required PNG can be sized at0x0and the default resize mode is inconsistent, so the default tick was invisible — the community workaround was to passcheckIconImageSource(or aniconImageStylewith a fixedwidth/height) explicitly.Fix (in
lib/BouncyCheckbox.tsx): the inner checkImageis now made robust on web only:width/height(falling back to the existing10default viaStyleSheet.flattenif a consumer'siconImageStyleomits them).resizeMode: "contain".Both behaviors are gated behind
Platform.OS === "web". On native (iOS/Android) the component returns the exact same[styles.iconImageStyle, iconImageStyle]style array and passes noresizeModeprop, so native rendering is byte-for-byte unchanged. (The icon asset is square — 64×64 into a square 10×10 box — socontainand the native defaultcoveryield identical pixels regardless.)No public prop or export was renamed and no default value or visual changed.
lib/BouncyCheckbox.style.tsextracts the literal10into an exportedDEFAULT_ICON_IMAGE_SIZEconstant (same value).Tests: added a
react-native-webdescribe block that, under a mockedPlatform.OS === "web", asserts the default check icon renders with explicitwidth/height(10) andresizeMode: "contain", plus a native guard test asserting noresizeModeprop is set whenPlatform.OS === "ios". All 13 tests pass.Verification:
tsc --noEmit(clean),eslint .(0 errors),jest(13/13),bob build(commonjs + module + typescript targets succeed). README "New Architecture / Expo / Web" section andCHANGELOG.md([Unreleased]→ Fixed) updated.