npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sigx/lynx-keyboard

v0.9.1

Published

Soft-keyboard handling for sigx-lynx — KeyboardStickyView, KeyboardAvoidingView and keyboard hooks

Downloads

2,841

Readme

@sigx/lynx-keyboard

Soft-keyboard handling for SignalX on Lynx, with an API mirroring React Native's (KeyboardAvoidingView, KeyboardStickyView/InputAccessoryView, useKeyboard). Keeps a composer input — and an accessory toolbar above it — pinned to the top edge of the on-screen keyboard.

Keyboard height reaches JS through the safe-area bridge (@sigx/lynx-safe-area): the native publisher reports the IME height as the keyboard inset on every safeAreaChanged event. This package turns that inset into ready-made layout primitives — no extra native module needed. Keyboard handling stays a separate concern from safe-area, mirroring the RN ecosystem split (react-native core / react-native-keyboard-controller vs react-native-safe-area-context).

📚 Documentation

Full guides, API reference and live examples → https://sigx.dev/lynx/modules/keyboard/overview/

Installation

pnpm add @sigx/lynx-keyboard

Requires <SafeAreaProvider> (from @sigx/lynx-safe-area) at the app root — the same provider every safe-area hook already needs.

Quick start

The proven chat-screen shape: the content area shrinks (KeyboardAvoidingView), the composer bar rides the keyboard (KeyboardStickyView). The bar's translate and the area's padding are both max(0, keyboard - bottomInset), so the list bottom always ends exactly where the bar lands.

import { component } from '@sigx/lynx';
import { KeyboardAvoidingView, KeyboardStickyView } from '@sigx/lynx-keyboard';

const ChatScreen = component(() => () => (
  <view style={{ display: 'flex', flexDirection: 'column', flexGrow: 1, flexShrink: 1, flexBasis: 0 }}>
    <KeyboardAvoidingView behavior="padding">
      <scroll-view style={{ flexGrow: 1, flexShrink: 1, flexBasis: 0 }}>
        {/* messages */}
      </scroll-view>
    </KeyboardAvoidingView>
    <KeyboardStickyView>
      {/* toolbar row (formatting buttons, attachments, …) */}
      {/* input row */}
    </KeyboardStickyView>
  </view>
));

Use one primitive per subtree: a bar inside both a padding KeyboardAvoidingView and a KeyboardStickyView lifts twice.

API

<KeyboardStickyView>

Pins its children to the keyboard's top edge with an MT-animated translateY (smooth 60fps, no per-frame thread crossing). When the keyboard is closed the bar rests in its natural flex position. Aliases: KeyboardAccessoryView, KeyboardToolbar.

| Prop | Type | Default | Description | | --- | --- | --- | --- | | offset | number | 0 | Extra gap (dp) above the keyboard. | | animated | boolean | true | false = discrete BG re-render (debug fallback). | | discountBottomInset | boolean | true | Subtract the bottom safe-area inset from the lift. Keep true when an ancestor <SafeAreaView edges={['bottom']}> already pads the home indicator. |

Note: the bar's transform is controlled internally (the MT binding writes translateY via setStyleProperties; the non-animated path writes an inline transform). A transform passed through style will be overridden — wrap children in their own view if you need an additional transform.

<KeyboardAvoidingView>

Wraps content and keeps it above the keyboard. Layout-affecting, so it applies inline BG styles (the same pattern as <SafeAreaView> — MT-driven layout writes don't reflow <scroll-view>).

| Prop | Type | Default | Description | | --- | --- | --- | --- | | behavior | 'padding' \| 'translate' \| 'height' | 'padding' | padding shrinks the column; translate shifts it; height appends a spacer. | | keyboardVerticalOffset | number | 0 | Added to the computed lift (RN parity). | | discountBottomInset | boolean | true | Same as on KeyboardStickyView — set false to lift by the full keyboard height when no ancestor pads the bottom inset. |

Hooks

  • useKeyboard(): Computed<{ height, visible }> — BG-reactive keyboard state.
  • useKeyboardLift(discountBottomInset?, offset?): Computed<number> — the raw lift value.
  • useKeyboardLiftSV(discountBottomInset?, offset?, duration?): SharedValue<number> — smoothly animated MT SharedValue tracking the lift; bind with useAnimatedStyle(ref, sv, 'translateY', { factor: -1 }).

How it works

  • Height sourceuseSafeAreaInsets().value.keyboard. There is no separate keyboard event API in Lynx; the safe-area publisher is canonical.
  • The liftmax(0, keyboard - bottomInset): the keyboard covers the home-indicator region, so a bar that already sits above the bottom inset only needs to rise by the difference. Never add both.
  • BG→MT bridge — the keyboard inset is a BG-only signal (deliberately not a SharedValue in lynx-safe-area). useKeyboardLiftSV watches it from a BG effect and dispatches an MT withTiming (from @sigx/lynx-motion) toward each new target; the tween then runs entirely on the main thread.
  • Transform vs layout — only translateY is MT-animated. Padding/height go through inline BG styles because MT layout writes land after the first layout pass and <scroll-view> won't reflow.

Demo

See the Keyboard lab screen in examples/showcase (Settings tab → Keyboard lab).