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

@innspel/react-native

v0.11.1

Published

Innsendingswidgeten for React Native. Dialog med fokusfelle, kjente feil før feltet, offline-kø gjort synlig.

Readme

@innspel/react-native

Innsendingswidgeten for React Native. Et ark over vertsappen din — aldri en flytende knapp over innholdet.

npm install @innspel/react-native @innspel/core react-native-safe-area-context react-native-svg
cd ios && pod install   # bare i en bar React Native-app

I Expo: npx expo install react-native-safe-area-context react-native-svg, så versjonene passer SDK-et.

react, react-native, react-native-safe-area-context (4.0 eller nyere) og react-native-svg (15.2 eller nyere) er peer-avhengigheter. Widgeten krever ikke Expo, men virker i Expo.

Hvorfor react-native-svg: ikonene er Ionicons, inlinet som SVG i pakken — ikke emoji. En emoji tegnes av operativsystemet i sine egne faste farger, den ser ulik ut på iOS og Android, og en skjermleser leser den opp som navnet sitt («marihøne» for 🐞). Pakken installerer ingen ikonfont og laster ingenting over nett. Mangler avhengigheten, feiler byggetrinnet med navnet på den — widgeten blir aldri stående med usynlige ikoner i drift.

Hvorfor safe-area-context: på edge-to-edge (Android 15+, Expo SDK 53+) tegner React Natives Modal under status- og navigasjonslinja uansett props, og React Native har ingen egen måte å lese de linjenes høyde på Android. Uten insets havner Send-knappen under navigasjonslinja. Har appen en SafeAreaProvider (expo-router har det), leses insetsene derfra; ellers brukes vinduets insets fra oppstart. Du trenger ikke legge til en provider for widgetens skyld. Arket løftes også over tastaturet, siden vinduet ikke lenger krymper for det på edge-to-edge.

Quickstart

import AsyncStorage from '@react-native-async-storage/async-storage';
import { init } from '@innspel/core';
import { createStorage, InnspelProvider, useInnspel } from '@innspel/react-native';

const innspel = init({
  baseUrl: 'https://api.innspel.example',
  tenantKey: 'ik_pub_xxxxxxxx',
  identityProvider: hentFeedbackToken,   // eller null = anonym modus
  storage: createStorage(AsyncStorage),
  context: { platform: 'ios', appVersion: '1.4.2' },
});

export default () => (
  <InnspelProvider client={innspel}>
    <MinApp />
  </InnspelProvider>
);

Vil du at plattformen skal telle tragten (åpnet → spor valgt → sendt), gi init() mottaket fra understien — anonymt, aldri tekst:

import { createIngestTelemetry } from '@innspel/core/telemetri';
// … telemetry: createIngestTelemetry({ baseUrl, tenantKey, platform: 'ios', appVersion: '1.4.2' }),

Åpne widgeten hvor som helst under provideren:

const { open } = useInnspel();
<Button title="Send innspill" onPress={() => open({ screen: 'Dørlista' })} />;

screen er rutens NAVN, aldri data i den. Det styrer hvilke kjente feil innsenderen får se før hun skriver.

Utenfor React — en navigasjonshandler, en krasjlytter — bruker du klienten direkte: innspel.openFeedback({ screen: 'Dørlista' }).

Lukking — X, eller Android-tilbake på første steg — beholder det innsenderen har skrevet til widgeten åpnes igjen; bare en fullført innsending nullstiller. Åpner du med track mens det står et utkast, står hun der hun var. view: 'mine' legges over utkastet, og «Tilbake» i lista lukker.

Legg provideren rundt appen, ikke inni en ScrollView. Arket er en Modal, men React Natives trykkhåndtering går gjennom React-treet: en ScrollView over provideren med keyboardShouldPersistTaps på standardverdien tar første trykk mens tastaturet er oppe, og bruker det til å lukke tastaturet. Send teller det trykket likevel; de andre knappene i arket gjør ikke. Må provideren stå inni en scrollflate, gi den keyboardShouldPersistTaps="handled".

Token-endepunktet

Det eneste du må bygge selv. Se integrasjonsguiden, som viser det med kjørbar ES256-kode. identityProvider: null er anonym modus — et eksplisitt valg, ikke noe du havner i ved å glemme opsjonen.

Tema

Widgeten arver vertsappens flate. Send det du vil overstyre; resten faller tilbake på Innspels eget tema, som er målt mot WCAG AA i begge paletter.

<InnspelProvider
  client={innspel}
  colorScheme="light"
  theme={{ color: { brand: '#E5007D', actionPrimary: '#E5007D' } }}
  tenantName="Følget"
>

tenantName er navnet som står på svaret i «Mine innspill» — ditt, ikke Innspels. Innsenderen skal se hvem som svarte.

fontFamily finnes ikke som token: systemfonten er standard i React Native, og å sette den ville brutt med appen rundt.

Når et innspill er sendt

onSubmitted kalles etter en innsending — også når nettet var borte og innspillet ligger i køen, for innsenderen trykket Send. Du får type, queued, og id når saken finnes hos tjeneren. Ingen identitet: saksnummeret er sakens, og det innsenderen alt ser i kvitteringen. «Ja, jeg også» på en kjent feil gir ikke kallet.

<InnspelProvider
  client={innspel}
  onSubmitted={({ queued }) => {
    hentTellingPaaNytt();                 // «Mine innspill · N» i din egen meny
    if (!queued) spørOmVarslerHvisFørste(); // riktig øyeblikk — ikke ved oppstart
  }}
>

Hva innsenderen møter

| Skjerm | Hva | |---|---| | Første valg | «Noe virker ikke» eller «Jeg ønsker meg noe». Aldri et tredje, aldri spørsmål om kategori eller alvorlighet. | | Kjente feil | I feilsporet før feltet, i ønskesporet etter. Tre svar per kort: «Ja, jeg også» (teller deg uten ny sak), «Ligner, men ikke helt» (ditt eget innspill med lenke), «Nei, det er noe annet». Tom liste hopper skjermen over — treffene er et tilbud, aldri en sperre. | | Feltet | Ett tekstfelt. Send er aktiv fra N tegn, og ingenting annet er obligatorisk. Konteksten som legges ved er synlig og kan fjernes linje for linje. | | Mønstervarsel | Ser teksten ut til å inneholde e-post, telefonnummer, kortnummer, IP eller en tilgangsnøkkel, spør widgeten om det skal fjernes. Den fjerner aldri noe selv. | | Skjermbilde | Valgfritt, én eller to veier: «Legg ved skjermbilde» (skjermen bak arket, tatt ved trykk) og «Velg bilde» (fra galleriet, med din velger). Forhåndsvises og maskeres på enheten — private views automatisk på en fangst, resten med felt, pensel eller «Masker all tekst». Se under. | | Kvittering | Lover noe konkret, per spor, med saksnummer. Ber aldri om en vurdering av appen. Feilet bildet, sier den det — saken er sendt uansett. | | Mine innspill | Status, løftet som hører til, og svaret fra deg under saken. Det som venter på nett står øverst. «Legg til mer» på en åpen sak: ett felt i kortet, maks tre tillegg, aldri et svar på svaret — tilleggene står under innsenderens egen tekst, og i panelet på saken. |

Offline

Faller nettet, køes innspillet lokalt — kun teksten. Køen tømmes når widgeten åpnes eller nettet kommer tilbake, aldri ved oppstart, og innsenderen ser hele tiden at det ligger noe og venter. Taket er 30.

Vil dere at widgeten skal si «Ingen nett» før innsenderen trykker, send inn nettstatus i init({ connectivity }) — for eksempel fra @react-native-community/netinfo. Pakken drar ikke inn den selv. Se docs/sdk/README.md, «Nettstatus».

Tilgjengelighet

Widgeten er en dialog og oppfører seg som en: modal for skjermlesere, lukkes med Android-tilbake og ESC, kvitteringen annonseres, og hver trykkflate er minst 48 punkter. Ikoner er skjult for skjermlesere — etiketten bærer meningen, aldri fargen alene.

WCAG 2.1 AA er grønt-kriterium, ikke en ambisjon. Kontrasten måles i tema-generatoren, som nekter å skrive tokens under kravet.

Skjermbilde

Opt-in per innsending, tatt først når innsenderen trykker, forhåndsvist og maskert på enheten før det lastes opp. Pakken tar ingen avhengighet på fangst — du sender inn captureRef fra react-native-view-shot:

import { captureRef } from 'react-native-view-shot';
import { createScreenshotAdapter, InnspelPrivate } from '@innspel/react-native';

<InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef)}>

Bilde fra galleriet. Et innspill handler sjelden om skjermen widgeten åpnes fra — åpnes den fra en profilside, viser fangsten profilen, ikke feilen. Gi adapteren din egen bildevelger, så får innsenderen «Velg bilde» og kan legge ved et systemskjermbilde tatt der feilen er. Pakken tar ingen avhengighet på velgeren:

import * as ImagePicker from 'expo-image-picker';
import { createScreenshotAdapter, type PickImageFn } from '@innspel/react-native';

const pickImage: PickImageFn = async () => {
  const r = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ['images'], exif: false });
  return r.canceled ? null : { uri: r.assets[0]!.uri, width: r.assets[0]!.width, height: r.assets[0]!.height };
};

// Begge veiene:
<InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef, { pickImage })}>
// Bare «Velg bilde» — skjermen bak arket fanges aldri:
<InnspelProvider client={innspel} screenshot={createScreenshotAdapter(captureRef, { pickImage, captureScreen: false })}>

captureRef trengs fortsatt: forhåndsvisningen med maskene fanges på nytt, og det er komposittet som lastes opp — aldri fila fra galleriet. Systemets bildevelger trenger ingen tillatelse til biblioteket på Android 13+ og iOS. <InnspelPrivate> kan ikke gjelde et bilde fra et annet sted, og forhåndsvisningen sier det til innsenderen.

Din egen setning ved bildesteget. Du kjenner brukerne dine og hva som er greit å legge ved; plattformen eier ikke den setningen. Den står ved knappene og i forhåndsvisningen:

<InnspelProvider
  client={innspel}
  screenshot={adapter}
  imageStepNote={{
    feil: 'Legg ved et skjermbilde av feilen. Ikke send bilder av andre personer.',
    onske: 'Vis gjerne hvor i appen du savner det.',
  }}
>

En streng gjelder begge spor. Et spor uten setning viser ingen.

Uten screenshot finnes ikke steget — ikke som en grå knapp, det finnes ikke. Det samme gjelder når leietakeren har skjermbilde av (screenshotsEnabled: false, tvunget ved mindreårige).

Merk det som aldri skal med på bildet:

<InnspelPrivate><Text>{bruker.navn}</Text></InnspelPrivate>

Det maskeres FØR innsenderen ser forhåndsvisningen, merket «Maskert av appen», og penselen kan ikke oppheve det. Din kode er sannheten, ikke brukerens presisjon.

Innsenderen har tre veier selv, alltid: Masker felt (ett trykk legger en boks), Tegn over (fingerstrøk) og Masker all tekst (hele bildet gjøres uskarpt — JavaScript kan ikke finne tekstnoder i din native app, så det er slik «all tekst» ser ut i React Native). Egne masker angres med ett trykk på dem. «Fjern bildet» finnes alltid.

Det som lastes opp er forhåndsvisningen med maskene, fanget på nytt — det umaskerte bildet forlater aldri enheten. Teksten sendes først; feiler bildet, står saken uten det, og kvitteringen sier «Sendt — skjermbildet kunne ikke legges ved». Uten nett køes teksten og bildet forkastes.

Plattformen re-enkoder bildet i en isolert prosess og fjerner EXIF. PNG, JPEG, WebP; høyst 5 MB og 4096 × 4096.

Betaprogram

import { InnspelProgram } from '@innspel/react-native';

<InnspelProgram invitationToken={tokenFraDyplenke} />

Sett den der invitasjonen hører hjemme — typisk øverst på hjemskjermen. Uten invitasjon og uten deltakelse rendrer den ingenting.

Den viser invitasjonsbanneret, aksepten med tallene (N oppgaver × M minutter, dato til dato, maks K kontakter), oppgavene, kjente feil du slipper å melde, og «Gå ut av programmet» med bekreftelse. Utgangen er umiddelbar.

Tokenet kommer fra deg. Plattformen sender aldri invitasjonen: du får program.invitation_created som webhook med engangs-tokenet og pseudonymet, løser pseudonymet til din egen bruker, og sender lenken i din egen kanal. Fanger appen tokenet fra dyplenken og gir det hit, kan testeren bli med. Uten token vises invitasjonen fortsatt, men «Bli med» er inaktiv.

Oppgavene med utfall og «Hvordan gikk det?» kommer i neste versjon.

Versjoner

Semver fra 0.1.0. Før 1.0.0 kan en minor bryte — pin en eksakt versjon om du trenger ro.

Lisens

MIT. Klientpakkene er permissivt lisensiert fordi koden kjører hos deg og må kunne leses og granskes der. Plattformen bak — API, panel og drift — er det ikke.