Skip to content

V4#108

Merged
mCodex merged 14 commits intomasterfrom
v4
Apr 27, 2026
Merged

V4#108
mCodex merged 14 commits intomasterfrom
v4

Conversation

@mCodex
Copy link
Copy Markdown
Owner

@mCodex mCodex commented Apr 27, 2026

This pull request introduces a major version update (v4.0.0) for the react-native-rooster toast notification library, focusing on a new providerless architecture, improved performance, and a simplified, more flexible API. The example app and core library have been refactored to use the new imperative API, and the toast container logic has been modernized for better separation of concerns and efficiency. Additionally, dependencies and development tooling have been updated, and obsolete test suites and provider-based patterns have been removed.

Core Library Refactor and API Changes:

  • Migrated from a provider-based model (ToastProvider) to a providerless, imperative API using Toaster and toast, simplifying integration and usage. (example/src/App.tsx, package.json, src/components/ToastContainer.tsx, [1] [2] [3]
  • Refactored ToastContainer to accept only a list of toast IDs, with each toast subscribing to its own message slice, improving performance and reducing unnecessary re-renders. (src/components/ToastContainer.tsx, [1] [2] [3]
  • Removed all references to the old provider-based API and associated test suites, fully embracing the new architecture. (src/__tests__/index.test.tsx, src/__tests__/fontSizeConfig.test.tsx, [1] [2]

Example App Updates:

  • Updated the example app to use the new imperative API (Toaster, toast) and demonstrate new features such as stress testing, global configuration, and swipe-to-dismiss. (example/src/App.tsx, [1] [2] [3] [4]
  • Upgraded dependencies in the example app for compatibility with the latest Expo and React Native versions. (example/package.json, example/package.jsonL12-R23)

Dependency and Tooling Updates:

  • Updated core and dev dependencies to the latest major versions, including React Native, React, TypeScript, Jest, and Biome. (package.json, biome.json, [1] [2] [3]
  • Updated Jest preset to use @react-native/jest-preset for improved test compatibility. (package.json, package.jsonL101-R94)

Project Maintenance:

  • Added a .github/FUNDING.yml file to support open source funding via multiple platforms. (.github/FUNDING.yml, .github/FUNDING.ymlR1-R15)

References:
[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15]

mCodex added 9 commits April 27, 2026 13:59
Introduce a providerless, store-backed toast system: add toast store, selectors, and top-level Toaster component; refactor Toast -> ToastItem and ToastContainer to render by id and subscribe per-message (improves rendering isolation). Add swipe-to-dismiss, animation hook (useToastAnimation), reduced-motion hook, and other hooks/helpers. Remove legacy ToastProvider and related tests; update integration tests to exercise the new API. Update dev and example dependencies for tooling and RN preset versions, and add FUNDING.yml.
Bump to v4 and migrate from a Context provider to a providerless API: add Toaster component, a singleton `toast` API, and `useToast()` that no longer causes sibling re-renders. Update README and example to document the new usage (Toaster + toast.show) and add an 8x stress-test example.

Key code changes:
- package.json: version → 4.0.0 and added subpath exports (/accessibility, /haptics, /sizing).
- src/index.tsx: export only the core runtime symbols (Toaster, useToast, toast, configureToast) to improve tree-shaking.
- src/types.ts: introduce HapticFeedback type, unify hapticFeedback usage, remove deprecated provider types.
- src/store/toastStore.ts: fix updateMessage to guard against missing current message and merge patch correctly.
- src/components/Toast.tsx: map extended haptic vocabulary to existing haptic patterns before triggering.
- src/utils/accessibility.ts: add getReducedMotionAnimationConfig and validateWcag22 helpers for WCAG 2.2 compliance and reduced-motion handling.
- Tests: update integration/unit tests to use async act flows and remove fake timers where appropriate to reflect microtask-batched dispatch.
- example/src/App.tsx: switch from ToastProvider to Toaster + toast API, add stressTest button and example config (swipeToDismiss, maxVisible, overflow).
- tsconfig.build.json: exclude test files from build artifacts.

Why: reduce render churn by removing a Context boundary and using per-toast external-store subscriptions, improve accessibility to WCAG 2.2, provide a smaller main bundle via subpath exports, and introduce safer haptic/type handling and test harness adjustments for the new microtask-batched behavior.
Remove subpath exports and streamline public surface (README + package.json + index) so only core runtime symbols are exposed. Simplify accessibility utilities (smaller API, trimmed docs and constants) and update types comments for clarity. Replace complex haptic mapping in Toast with direct normalize/trigger call and add platform/TS lint ignores. Update and tighten tests (remove advanced sizing/haptics suites, adjust haptics tests, type some test inputs, and simplify accessibility tests) and small styling test/type fixes. Overall cleanup reduces bundle surface and aligns tests with the refactored utilities.
Update tsconfig.json to enable additional compiler checks:

- erasableSyntaxOnly: true — restricts code to syntax that can be erased safely during emit
- libReplacement: false — disable automatic library replacement
- noUncheckedSideEffectImports: true — error on imports with potential side effects that aren't explicitly checked

These options tighten type- and module-related checks to catch unsafe patterns and unexpected import side effects earlier.
Set the TypeScript compiler option "isolatedModules" to true in tsconfig.json so each file can be transpiled independently. This is required for single-file transpilers (Babel/ESBuild/ts-jest/ts-node) and helps catch patterns that break isolated compilation and supports faster incremental builds.
Introduce an O(1) byId index to the toast store and use it throughout (getMessage, updateMessage, remove, clear) to avoid repeated linear scans. Batch and optimize operations: rebuild index on setMessages, batch promotions from the queue, reduce allocations, and use for-of loops for listeners/timers. Also expand and improve public docs and API surface: richer README and JSDoc for Toaster, useToast, toast, configureToast alias, index exports, and types; clarify hook/imperative usage and examples. Overall this improves performance, reduces re-renders/allocations, and clarifies public API surface.
Delete an unused require('react') from the ToastContainer mock in useToast.test.tsx to remove a stray variable. Add "types": ["jest"] to tsconfig.json so TypeScript picks up Jest typings (fixes test type/import issues).
@mCodex mCodex self-assigned this Apr 27, 2026
Copilot AI review requested due to automatic review settings April 27, 2026 18:34
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades react-native-rooster to v4 with a providerless architecture centered around a module-level external store, introducing an imperative toast facade and a new <Toaster /> mount point while modernizing container/toast rendering for fewer re-renders.

Changes:

  • Replaces the Context/Provider architecture with an external store + useSyncExternalStore, adding <Toaster /> and toast / configureToast.
  • Refactors toast layout/rendering to be id-driven (ToastContainer receives ids; each toast subscribes to its own message slice).
  • Updates tooling/docs/tests and removes legacy utilities/tests/provider code.

Reviewed changes

Copilot reviewed 42 out of 44 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tsconfig.json Tightens TypeScript compiler settings and adds Jest types.
tsconfig.build.json Excludes tests from build compilation.
src/utils/styling.ts Simplifies style utilities and constants; keeps backwards-compat keys.
src/utils/sizing.ts Removes sizing utilities module (v3-era).
src/utils/positioning.ts Simplifies positioning utilities and introduces constants.
src/utils/haptics.ts Reworks haptics to normalize a broader vocabulary and simplify patterns.
src/utils/accessibility.ts Simplifies accessibility helpers and removes several exported utilities.
src/utils/tests/styling.test.ts Updates styling tests for new exports/typing.
src/utils/tests/sizing.test.ts Removes sizing tests (module removed).
src/utils/tests/positioning.advanced.test.ts Tightens types in positioning tests.
src/utils/tests/mergeToastConfig.test.ts Improves typing in merge tests and updates haptics typing.
src/utils/tests/haptics.test.ts Updates haptics tests for new normalize/trigger APIs.
src/utils/tests/haptics.advanced.test.ts Removes redundant advanced haptics tests.
src/utils/tests/accessibility.test.ts Updates tests to match the simplified accessibility surface.
src/types.ts Adds HapticFeedback, introduces ToastApi/ToasterProps, and expands config options.
src/toast.ts Adds imperative toast facade and configureToast alias.
src/store/useToastSelector.ts Adds useSyncExternalStore selectors for ids/config/messages.
src/store/toastStore.ts Adds module-level external store with ids/config/message subscriptions and overflow logic.
src/store/tests/toastStore.test.ts Adds unit tests for store behavior (add/remove/timers/overflow/subscriptions).
src/providers/tests/ToastProvider.test.tsx Removes provider-based test suite.
src/providers/ToastProvider.tsx Removes the v3 provider implementation.
src/index.tsx Updates public entrypoint exports to Toaster/useToast/toast surface and new types.
src/hooks/useToastAnimation.ts Adds per-toast animation lifecycle hook (enter/exit + pause/resume + reduced motion).
src/hooks/useToast.ts Changes hook to return the singleton toast API (no provider required).
src/hooks/useReducedMotion.ts Adds reduced-motion subscription hook.
src/hooks/tests/useToast.test.tsx Updates hook tests for providerless behavior + Toaster integration.
src/constants/defaultConfig.ts Adds new default config values (maxVisible/overflow/stagger/etc).
src/components/tests/Toaster.test.tsx Adds tests for new <Toaster /> behavior.
src/components/tests/ToastContainer.test.tsx Updates container tests for id-driven rendering and ordering.
src/components/tests/Toast.test.tsx Updates toast tests to store-subscribed id-based ToastItem.
src/components/Toaster.tsx Adds <Toaster /> component mounting store-backed container (lazy render + config merge + multi-mount warning).
src/components/ToastContainer.tsx Refactors container to accept ids and render ToastItem per id.
src/components/Toast.tsx Refactors toast component into id-subscribed ToastItem with swipe-to-dismiss + new animation hook.
src/tests/integration.test.tsx Updates integration tests for providerless v4 API and imperative facade.
src/tests/index.test.tsx Removes provider-era integration tests.
src/tests/fontSizeConfig.test.tsx Removes provider-era font-size config tests.
src/contexts/ToastContext.ts Removes legacy context (no longer used).
package.json Bumps to v4 and updates dev tooling/dependency setup (incl. Jest preset switch).
example/src/App.tsx Updates example app to <Toaster /> + toast stress test and new config props.
example/package.json Updates example dependencies for latest Expo/RN versions.
biome.json Updates Biome schema version reference.
README.md Rewrites docs for v4 providerless architecture and new API surface.
.github/FUNDING.yml Adds funding configuration file.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread package.json Outdated
Comment on lines +66 to +67
"@react-native/babel-preset": "0.x",
"@react-native/jest-preset": "0.x",
Comment thread src/store/toastStore.ts Outdated
if (duration <= 0 || !Number.isFinite(duration)) return;
const handle = setTimeout(() => {
timers.delete(id);
remove(id);
Comment thread src/store/toastStore.ts
Comment on lines +235 to +250
if (state.messages.length >= max) {
if ((state.config.overflow ?? 'evict') === 'queue') {
state.queue = state.queue.concat(message);
return message.id;
}
// 'evict' — drop the oldest with a fast exit
const evicted = state.messages[0];
if (evicted) {
// Re-arm timer to fire (almost) immediately so the UI plays exit anim
clearTimer(evicted.id);
startTimer(evicted.id, FAST_EVICT_DURATION);
}
}

setMessages(state.messages.concat(message));
startTimer(message.id, effectiveDurationFor(message));
Comment thread src/hooks/useToastAnimation.ts Outdated
Comment on lines +136 to +164
(duration: number) => {
clearDismissTimer();
if (duration <= 0) return;
remainingRef.current = duration;
startedAtRef.current = Date.now();
pausedRef.current = false;
dismissTimerRef.current = setTimeout(() => {
dismissTimerRef.current = null;
dismiss();
}, duration);
},
[clearDismissTimer, dismiss],
);

const pauseAutoDismiss = useCallback(() => {
if (pausedRef.current || !dismissTimerRef.current) return;
pausedRef.current = true;
const elapsed = Date.now() - startedAtRef.current;
remainingRef.current = Math.max(0, remainingRef.current - elapsed);
clearDismissTimer();
}, [clearDismissTimer]);

const resumeAutoDismiss = useCallback(() => {
if (!pausedRef.current) return;
pausedRef.current = false;
if (remainingRef.current > 0) {
startAutoDismiss(remainingRef.current);
}
}, [startAutoDismiss]);
Comment thread src/components/Toast.tsx
Comment on lines 157 to 161
const type = message.type ?? 'info';
const isInteractive = !!message.onPress;

// Use custom label if provided, otherwise generate from title/message
const label =
message.accessibilityLabel ?? generateAccessibilityLabel(message);

// Use custom hint if provided, otherwise generate from type and interaction
const hint =
mCodex and others added 5 commits April 27, 2026 15:46
Introduce dismissHandlers to allow animation-aware dismiss callbacks when auto-dismiss timers expire (so the animation layer can play exit animations before removal). Add _registerDismissHandler (exported as registerDismissHandler) which registers/unregisters handlers per toast id. Update timer logic to invoke a handler if present, falling back to remove(id) for test ergonomics. Improve eviction logic to drop multiple oldest toasts in one batched update and schedule fast-evict timers so mounted items can animate out. Ensure dismissHandlers are cleared on remove/clear/__resetForTests. Also bump @react-native/babel-preset and @react-native/jest-preset to ~0.83.6 in package.json.
Centralize auto-dismiss timing in toastStore and remove timer logic from the animation hook. useToastAnimation now imports toastStore, forwards pauseAutoDismiss/resumeAutoDismiss to toastStore, registers a dismiss handler so the store can trigger the exit animation, and drops internal timeout/state bookkeeping. Also simplify unmount cleanup to only stop animations. In Toast, always mark items as interactive (tap-dismissible) so accessibility hints consistently advertise tap-to-dismiss.
Removed the leading underscore from the dismiss handler registration function in src/store/toastStore.ts to make the name consistent and non-private. No behavior changes; the function signature and return remain the same.
Co-authored-by: Copilot <copilot@github.com>
@mCodex mCodex merged commit f5970d3 into master Apr 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants