@spencerls/react-native-nfc 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/API.md ADDED
@@ -0,0 +1,214 @@
1
+ # @spencerls/react-native-nfc – API Reference
2
+
3
+ This document describes the complete public API surface of the NFC package.
4
+
5
+ All exports come from:
6
+
7
+ ```ts
8
+ import { nfc, nfcService } from "@spencerls/react-native-nfc";
9
+ import {
10
+ useNfc,
11
+ useNfcState,
12
+ useNfcReader,
13
+ useNfcTechnology,
14
+ NfcProvider
15
+ } from "@spencerls/react-native-nfc";
16
+ ```
17
+
18
+ ---
19
+
20
+ # Core Service: `nfcService`
21
+
22
+ ```ts
23
+ import { nfcService } from "@spencerls/react-native-nfc";
24
+ ```
25
+
26
+ ### Methods
27
+
28
+ #### startReader(flags, onTag, options?)
29
+ Starts platform reader mode.
30
+
31
+ ```ts
32
+ nfcService.startReader(
33
+ flags: number,
34
+ onTag: (tag: TagEvent) => void,
35
+ options?: { cooldownMs?: number }
36
+ )
37
+ ```
38
+
39
+ #### stopReader()
40
+ Stops reader mode.
41
+
42
+ ```ts
43
+ await nfcService.stopReader();
44
+ ```
45
+
46
+ #### withTechnology(tech, handler)
47
+ Opens an iOS/Android technology session. Stops reader mode before starting.
48
+
49
+ ```ts
50
+ await nfcService.withTechnology(
51
+ tech: NfcTech | NfcTech[],
52
+ async () => { /* commands */ }
53
+ );
54
+ ```
55
+
56
+ #### getState()
57
+ Returns the current state snapshot.
58
+
59
+ ```ts
60
+ { mode, tag }
61
+ ```
62
+
63
+ #### subscribe(listener)
64
+ Attach a state listener; returns an unsubscribe function.
65
+
66
+ ---
67
+
68
+ # Namespace API: `nfc`
69
+
70
+ ```ts
71
+ import { nfc } from "@spencerls/react-native-nfc";
72
+ ```
73
+
74
+ `nfc` is a namespaced, easy-to-use interface:
75
+
76
+ ```
77
+ nfc.service (NfcService instance)
78
+ nfc.v.* NFC-V operations
79
+ nfc.a.* NFC-A operations
80
+ nfc.ndef.* NDEF operations
81
+ ```
82
+
83
+ ---
84
+
85
+ # NFC-V Namespace: `nfc.v`
86
+
87
+ High-level ISO15693 helpers and raw operations.
88
+
89
+ ```ts
90
+ nfc.v.getSystemInfoNfcV()
91
+ nfc.v.readSingleBlock(uid, blockNumber)
92
+ nfc.v.readMultipleBlocks(uid, start, count)
93
+ nfc.v.writeSingleBlock(uid, blockNumber, data)
94
+ nfc.v.getSecurityStatus(uid, blockNumber)
95
+ ```
96
+
97
+ ---
98
+
99
+ # NFC-A Namespace: `nfc.a`
100
+
101
+ ```ts
102
+ nfc.a.transceive(bytes)
103
+ nfc.a.getAtqa()
104
+ nfc.a.getSak()
105
+ ```
106
+
107
+ ---
108
+
109
+ # NDEF Namespace: `nfc.ndef`
110
+
111
+ ```ts
112
+ nfc.ndef.parse(bytes)
113
+ nfc.ndef.encode(records)
114
+ nfc.ndef.utils.*
115
+ ```
116
+
117
+ ---
118
+
119
+ # React Hooks
120
+
121
+ All hooks live under:
122
+
123
+ ```ts
124
+ import { ... } from "@spencerls/react-native-nfc";
125
+ ```
126
+
127
+ ---
128
+
129
+ ## useNfc(onTag, options)
130
+
131
+ Automatically starts reader mode on mount and stops on unmount.
132
+
133
+ ```ts
134
+ useNfc(
135
+ (tagId: string) => { ... },
136
+ {
137
+ flags?: number,
138
+ cooldownMs?: number
139
+ }
140
+ );
141
+ ```
142
+
143
+ ---
144
+
145
+ ## useNfcState()
146
+
147
+ Access current NFC state:
148
+
149
+ ```tsx
150
+ const { mode, tag } = useNfcState();
151
+ ```
152
+
153
+ ---
154
+
155
+ ## useNfcReader()
156
+
157
+ Manual control over reader mode.
158
+
159
+ ```ts
160
+ const { start, stop } = useNfcReader();
161
+ ```
162
+
163
+ ---
164
+
165
+ ## useNfcTechnology()
166
+
167
+ Runs an NFC technology session (NfcV, Ndef, etc).
168
+
169
+ ```ts
170
+ await runWithTech([NfcTech.NfcV], async () => {
171
+ const info = await nfc.v.getSystemInfoNfcV();
172
+ });
173
+ ```
174
+
175
+ ---
176
+
177
+ # NfcProvider
178
+
179
+ Optional provider that exposes service state to React tree.
180
+
181
+ ```tsx
182
+ <NfcProvider>
183
+ <App />
184
+ </NfcProvider>
185
+ ```
186
+
187
+ ---
188
+
189
+ # Types
190
+
191
+ All types are exported from `@spencerls/react-native-nfc/nfc`.
192
+
193
+ Notable types:
194
+
195
+ ```ts
196
+ NfcState
197
+ NfcMode
198
+ TagEvent
199
+ ```
200
+
201
+ ---
202
+
203
+ # Internal Notes
204
+
205
+ - iOS automatically restarts reader mode after each scan.
206
+ - Android waits for cooldown before accepting next scan.
207
+ - Technology sessions interrupt reader mode safely.
208
+ - `NfcTech` enums must be used. Do not pass raw strings.
209
+
210
+ ---
211
+
212
+ # License
213
+
214
+ MIT © Spencer Smith
package/README.md CHANGED
@@ -1,63 +1,174 @@
1
- # @spencer/nfc
1
+ # @spencerls/react-native-nfc
2
2
 
3
- An easy, clean, React-friendly NFC service built on `react-native-nfc-manager`.
3
+ A clean, React-friendly, cross-platform NFC layer built on top of
4
+ `react-native-nfc-manager`.
5
+
6
+ This package provides:
7
+
8
+ - A unified NFC service (`nfcService`)
9
+ - High-level protocol namespaces (`nfc.v`, `nfc.a`, `nfc.ndef`)
10
+ - Automatic iOS reader restarts
11
+ - Safe Android reader handling
12
+ - Optional React hooks and provider
13
+ - Technology sessions for NDEF/NfcV/NfcA and raw commands
14
+
15
+ The API is designed to be stable, predictable, and easy to use across iOS and Android.
16
+
17
+ ---
4
18
 
5
19
  ## Installation
6
20
 
7
21
  ```bash
8
- npm install @spencer/nfc
9
- # or
10
- yarn add @spencer/nfc
22
+ npm install @spencerls/react-native-nfc
23
+ npm install react-native-nfc-manager
11
24
  ```
12
25
 
13
- ## Requires:
26
+ Works with:
27
+
28
+ - React Native 0.74+
29
+ - Expo (Bare / Prebuild)
30
+ - iOS 13+ (Core NFC)
31
+ - Android API 21+
32
+
33
+ ---
34
+
35
+ ## Basic Usage (Reader Mode)
14
36
 
15
- `react-native-nfc-manager`
37
+ ```tsx
38
+ import { useNfc, useNfcState } from "@spencerls/react-native-nfc";
39
+ import { NfcAdapter } from "react-native-nfc-manager";
40
+
41
+ export default function ScannerScreen() {
42
+ const { mode } = useNfcState();
43
+
44
+ useNfc((tagId) => {
45
+ console.log("Scanned:", tagId);
46
+ }, {
47
+ flags:
48
+ NfcAdapter.FLAG_READER_NFC_V |
49
+ NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS,
50
+ cooldownMs: 800
51
+ });
52
+
53
+ return (
54
+ <View>
55
+ <Text>NFC Mode: {mode}</Text>
56
+ </View>
57
+ );
58
+ }
59
+ ```
16
60
 
17
- React Native 0.74+ or Expo (Bare / Prebuild)
61
+ ---
18
62
 
19
- ## Usage
63
+ ## Manual Reader Control
20
64
 
21
65
  ```tsx
22
- import { nfc } from "@spencer/nfc";
23
- import { Ndef, NfcAdapter } from "react-native-nfc-manager";
24
-
25
- export default function Example() {
26
- const { nfcState } = useNfc();
27
-
28
- useEffect(() => {
29
- nfc.service.startReader(
30
- NfcAdapter.FLAG_READER_NFC_V | NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS,
31
- async (tag) => {
32
- console.log("Tag:", tag);
33
- await nfc.service.stopReader();
34
- await nfc.service.writeNdef([Ndef.textRecord("Hello NFC!")]);
35
- }
66
+ import { useNfcReader } from "@spencerls/react-native-nfc";
67
+ import { NfcAdapter } from "react-native-nfc-manager";
68
+
69
+ export default function Screen() {
70
+ const { start, stop } = useNfcReader();
71
+
72
+ const begin = () => {
73
+ start(
74
+ NfcAdapter.FLAG_READER_NFC_V,
75
+ (tag) => {
76
+ console.log("Tag:", tag.id);
77
+ },
78
+ 1200
36
79
  );
80
+ };
81
+
82
+ return <Button title="Start" onPress={begin} />;
83
+ }
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Technology Sessions (NfcTech.*)
89
+
90
+ Always use `NfcTech` enums.
91
+ Do not pass raw strings.
92
+
93
+ ```tsx
94
+ import { nfc } from "@spencerls/react-native-nfc";
95
+ import { useNfcTechnology } from "@spencerls/react-native-nfc";
96
+ import { NfcTech } from "react-native-nfc-manager";
97
+
98
+ export function ReadSystemInfo() {
99
+ const { runWithTech } = useNfcTechnology();
37
100
 
38
- return () => nfc.service.stopReader();
39
- }, []);
40
-
41
- const start = async () => {
42
- await nfc.v
43
- .getSystemInfoNfcV()
44
- .then((i) => {
45
- console.log("info:", i);
46
- })
47
- .catch((e) => {
48
- console.error("error:", e);
49
- });
101
+ const readInfo = async () => {
102
+ await runWithTech([NfcTech.NfcV], async () => {
103
+ const info = await nfc.v.getSystemInfoNfcV();
104
+ console.log(info);
105
+ });
50
106
  };
51
107
 
108
+ return <Button title="Read NFC-V Info" onPress={readInfo} />;
109
+ }
110
+ ```
111
+
112
+ ---
113
+
114
+ ## NDEF Read/Write
115
+
116
+ ```tsx
117
+ import { useNfcTechnology } from "@spencerls/react-native-nfc";
118
+ import { NfcTech, Ndef, NfcManager } from "react-native-nfc-manager";
119
+
120
+ export default function WriteScreen() {
121
+ const { runWithTech } = useNfcTechnology();
122
+
123
+ const writeHello = async () => {
124
+ await runWithTech([NfcTech.Ndef], async () => {
125
+ const bytes = Ndef.encodeMessage([
126
+ Ndef.textRecord("Hello NFC!")
127
+ ]);
128
+ await NfcManager.ndefHandler.writeNdefMessage(bytes);
129
+ });
130
+ };
131
+
132
+ return <Button title="Write NDEF" onPress={writeHello} />;
133
+ }
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Namespace API
139
+
140
+ ```ts
141
+ import { nfc } from "@spencerls/react-native-nfc";
142
+
143
+ await nfc.v.getSystemInfoNfcV();
144
+ await nfc.v.readSingleBlock(uid, 0);
145
+
146
+ await nfc.a.transceive(rawBytes);
147
+
148
+ await nfc.ndef.parse(ndefBytes);
149
+
150
+ nfc.service.startReader(...);
151
+ nfc.service.withTechnology(...);
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Global Provider (Optional)
157
+
158
+ ```tsx
159
+ import { NfcProvider } from "@spencerls/react-native-nfc";
160
+
161
+ export default function App() {
52
162
  return (
53
- <View style={{ padding: 100 }}>
54
- <Text style={{ color: "#999" }}>NFC Mode: {nfcState.mode}</Text>
55
- <Button title="Scan Tag" onPress={start} />
56
- </View>
163
+ <NfcProvider>
164
+ <RootApp />
165
+ </NfcProvider>
57
166
  );
58
167
  }
59
168
  ```
60
169
 
170
+ ---
171
+
61
172
  ## License
62
173
 
63
174
  MIT © Spencer Smith
package/dist/index.d.mts CHANGED
@@ -1,10 +1,103 @@
1
1
  import * as react_native_nfc_manager from 'react-native-nfc-manager';
2
2
  import { TagEvent, NfcTech, NdefRecord } from 'react-native-nfc-manager';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+ import { PropsWithChildren } from 'react';
5
+
6
+ declare const operations$2: {
7
+ transceive(data: number[]): Promise<number[]>;
8
+ };
9
+
10
+ declare const utils$2: {};
11
+
12
+ declare namespace index$2 {
13
+ export { operations$2 as operations, utils$2 as utils };
14
+ }
3
15
 
4
16
  type StrictTagEvent = TagEvent & {
5
17
  id: string;
6
18
  };
7
19
 
20
+ declare const operations$1: {
21
+ withVTag<T>(handler: (tag: StrictTagEvent) => Promise<T>): Promise<T>;
22
+ writeBlockNfcV(blockNumber: number, data: Uint8Array): Promise<void>;
23
+ readBlockNfcV(blockNumber: number): Promise<Uint8Array<ArrayBufferLike>>;
24
+ getSystemInfoNfcV(): Promise<any>;
25
+ };
26
+
27
+ declare const utils$1: {
28
+ readonly tech: NfcTech.NfcV | NfcTech[];
29
+ readonly Flags: {
30
+ readonly HIGH_DATA_RATE: 2;
31
+ readonly ADDRESSED: 32;
32
+ };
33
+ readonly Commands: {
34
+ readonly READ_SINGLE_BLOCK: 32;
35
+ readonly WRITE_SINGLE_BLOCK: 33;
36
+ readonly GET_SYSTEM_INFO: 43;
37
+ };
38
+ /**
39
+ * Combine multiple flag bits into one byte.
40
+ * Example: Flags.ADDRESSED | Flags.HIGH_DATA_RATE
41
+ */
42
+ readonly flags: (...bits: number[]) => number;
43
+ /**
44
+ * Convert tag.id hex string (MSB->LSB) into reversed byte array (LSB->MSB)
45
+ * ISO15693 requires reversed UID for addressed commands.
46
+ */
47
+ readonly reverseUid: (tagIdHex: string) => number[];
48
+ /**
49
+ * Build READ_SINGLE_BLOCK command.
50
+ * FLAGS: addressed + high data rate by default.
51
+ */
52
+ readonly buildReadBlock: (uidReversed: number[], blockNumber: number) => number[];
53
+ /**
54
+ * Build WRITE_SINGLE_BLOCK command.
55
+ * Note: data must match the block size (usually 4 or 8 bytes).
56
+ */
57
+ readonly buildWriteBlock: (uidReversed: number[], blockNumber: number, data: Uint8Array) => number[];
58
+ /**
59
+ * Build GET_SYSTEM_INFO command.
60
+ */
61
+ readonly buildGetSystemInfo: (uidReversed: number[]) => number[];
62
+ /**
63
+ * Parse a READ_SINGLE_BLOCK response.
64
+ * Response format:
65
+ * - byte[0] = status (0x00 = success)
66
+ * - byte[1..] = block payload bytes
67
+ */
68
+ readonly parseReadResponse: (resp: number[]) => Uint8Array;
69
+ /**
70
+ * Parse WRITE_SINGLE_BLOCK response.
71
+ * Successful write has resp[0] === 0x00.
72
+ */
73
+ readonly parseWriteResponse: (resp: number[]) => void;
74
+ /**
75
+ * Parse GET_SYSTEM_INFO response.
76
+ * Returns: UID, DSFID, AFI, numberOfBlocks, blockSize, manufacturer
77
+ */
78
+ readonly parseSystemInfo: (resp: number[]) => any;
79
+ /** Identify common manufacturers based on UID prefix */
80
+ readonly detectManufacturer: (uid: string) => string;
81
+ };
82
+
83
+ declare namespace index$1 {
84
+ export { operations$1 as operations, utils$1 as utils };
85
+ }
86
+
87
+ declare const operations: {
88
+ writeNdef(records: NdefRecord[]): Promise<void>;
89
+ writeTextNdef(text: string): Promise<void>;
90
+ writeUriNdef(uri: string): Promise<void>;
91
+ };
92
+
93
+ declare const utils: {};
94
+
95
+ declare const index_operations: typeof operations;
96
+ declare const index_utils: typeof utils;
97
+ declare namespace index {
98
+ export { index_operations as operations, index_utils as utils };
99
+ }
100
+
8
101
  type NfcMode = "idle" | "starting" | "active" | "stopping" | "technology";
9
102
 
10
103
  interface NfcState {
@@ -16,12 +109,20 @@ type NfcListener = (state: NfcState) => void;
16
109
  declare class NfcService {
17
110
  private state;
18
111
  private listeners;
112
+ private isProcessingTag;
113
+ private currentOnTag?;
114
+ private currentCooldownMs;
115
+ private lastUsedReaderFlags;
19
116
  constructor();
20
117
  private setState;
21
118
  getState(): NfcState;
22
119
  subscribe(fn: NfcListener): () => void;
23
- startReader(readerModeFlags: number, onTag?: (tag: TagEvent) => void): Promise<void>;
120
+ startReader(readerModeFlags: number, onTag?: (tag: TagEvent) => Promise<void> | void, options?: {
121
+ cooldownMs?: number;
122
+ }): Promise<void>;
24
123
  stopReader(): Promise<void>;
124
+ private _resetReaderState;
125
+ private _restartIosReader;
25
126
  withTechnology<T>(tech: NfcTech | NfcTech[], handler: () => Promise<T>): Promise<T>;
26
127
  }
27
128
  declare const nfcService: NfcService;
@@ -77,95 +178,28 @@ declare const nfc: {
77
178
  };
78
179
  };
79
180
 
80
- declare const operations$2: {
81
- transceive(data: number[]): Promise<number[]>;
82
- };
83
-
84
- declare const utils$2: {};
85
-
86
- declare namespace index$2 {
87
- export { operations$2 as operations, utils$2 as utils };
181
+ interface NfcContextValue {
182
+ state: NfcState;
183
+ service: typeof nfcService;
88
184
  }
185
+ declare function NfcProvider({ children }: PropsWithChildren): react_jsx_runtime.JSX.Element;
186
+ declare function useNfcContext(): NfcContextValue;
89
187
 
90
- declare const operations$1: {
91
- writeNdef(records: NdefRecord[]): Promise<void>;
92
- writeTextNdef(text: string): Promise<void>;
93
- writeUriNdef(uri: string): Promise<void>;
94
- };
95
-
96
- declare const utils$1: {};
188
+ declare function useNfc(onTag: (tagId: string) => void, options: {
189
+ cooldownMs?: number;
190
+ flags: number;
191
+ }): void;
97
192
 
98
- declare namespace index$1 {
99
- export { operations$1 as operations, utils$1 as utils };
100
- }
101
-
102
- declare const operations: {
103
- withVTag<T>(handler: (tag: StrictTagEvent) => Promise<T>): Promise<T>;
104
- writeBlockNfcV(blockNumber: number, data: Uint8Array): Promise<void>;
105
- readBlockNfcV(blockNumber: number): Promise<Uint8Array<ArrayBufferLike>>;
106
- getSystemInfoNfcV(): Promise<any>;
193
+ declare function useNfcReader(): {
194
+ start: (flags: number, onTag: (tag: TagEvent) => void, cooldownMs?: number) => void;
195
+ stop: () => void;
107
196
  };
108
197
 
109
- declare const utils: {
110
- readonly tech: NfcTech.NfcV | NfcTech[];
111
- readonly Flags: {
112
- readonly HIGH_DATA_RATE: 2;
113
- readonly ADDRESSED: 32;
114
- };
115
- readonly Commands: {
116
- readonly READ_SINGLE_BLOCK: 32;
117
- readonly WRITE_SINGLE_BLOCK: 33;
118
- readonly GET_SYSTEM_INFO: 43;
119
- };
120
- /**
121
- * Combine multiple flag bits into one byte.
122
- * Example: Flags.ADDRESSED | Flags.HIGH_DATA_RATE
123
- */
124
- readonly flags: (...bits: number[]) => number;
125
- /**
126
- * Convert tag.id hex string (MSB->LSB) into reversed byte array (LSB->MSB)
127
- * ISO15693 requires reversed UID for addressed commands.
128
- */
129
- readonly reverseUid: (tagIdHex: string) => number[];
130
- /**
131
- * Build READ_SINGLE_BLOCK command.
132
- * FLAGS: addressed + high data rate by default.
133
- */
134
- readonly buildReadBlock: (uidReversed: number[], blockNumber: number) => number[];
135
- /**
136
- * Build WRITE_SINGLE_BLOCK command.
137
- * Note: data must match the block size (usually 4 or 8 bytes).
138
- */
139
- readonly buildWriteBlock: (uidReversed: number[], blockNumber: number, data: Uint8Array) => number[];
140
- /**
141
- * Build GET_SYSTEM_INFO command.
142
- */
143
- readonly buildGetSystemInfo: (uidReversed: number[]) => number[];
144
- /**
145
- * Parse a READ_SINGLE_BLOCK response.
146
- * Response format:
147
- * - byte[0] = status (0x00 = success)
148
- * - byte[1..] = block payload bytes
149
- */
150
- readonly parseReadResponse: (resp: number[]) => Uint8Array;
151
- /**
152
- * Parse WRITE_SINGLE_BLOCK response.
153
- * Successful write has resp[0] === 0x00.
154
- */
155
- readonly parseWriteResponse: (resp: number[]) => void;
156
- /**
157
- * Parse GET_SYSTEM_INFO response.
158
- * Returns: UID, DSFID, AFI, numberOfBlocks, blockSize, manufacturer
159
- */
160
- readonly parseSystemInfo: (resp: number[]) => any;
161
- /** Identify common manufacturers based on UID prefix */
162
- readonly detectManufacturer: (uid: string) => string;
163
- };
198
+ declare function useNfcState(): NfcState;
164
199
 
165
- declare const index_operations: typeof operations;
166
- declare const index_utils: typeof utils;
167
- declare namespace index {
168
- export { index_operations as operations, index_utils as utils };
169
- }
200
+ declare function useNfcTechnology(): {
201
+ writeNdef: (records: NdefRecord[]) => Promise<void>;
202
+ runWithTech: (tech: NfcTech | NfcTech[], fn: () => Promise<void>) => Promise<void>;
203
+ };
170
204
 
171
- export { type NfcMode, type NfcState, index$1 as ndef, nfc, index$2 as nfcA, nfcService, index as nfcV };
205
+ export { type NfcMode, NfcProvider, type NfcState, nfc, index$2 as nfcA, index as nfcNdef, nfcService, index$1 as nfcV, useNfc, useNfcContext, useNfcReader, useNfcState, useNfcTechnology };