@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/dist/index.mjs CHANGED
@@ -4,18 +4,34 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
- // src/services/nfc/service.ts
7
+ // src/nfc/a/index.ts
8
+ var a_exports = {};
9
+ __export(a_exports, {
10
+ operations: () => operations,
11
+ utils: () => utils
12
+ });
13
+
14
+ // src/nfc/a/operations.ts
15
+ import NfcManager2, { NfcTech } from "react-native-nfc-manager";
16
+
17
+ // src/nfc/service.ts
8
18
  import { Platform } from "react-native";
9
19
  import NfcManager, {
10
20
  NfcEvents
11
21
  } from "react-native-nfc-manager";
12
22
  var NfcService = class {
23
+ // needed for iOS restart
13
24
  constructor() {
14
25
  this.state = { mode: "idle", tag: null };
15
26
  this.listeners = /* @__PURE__ */ new Set();
27
+ this.isProcessingTag = false;
28
+ this.currentCooldownMs = 1500;
29
+ this.lastUsedReaderFlags = null;
16
30
  NfcManager.start();
17
31
  }
18
- // --- internal state mgmt ---
32
+ // -----------------------------
33
+ // Internal state management
34
+ // -----------------------------
19
35
  setState(partial) {
20
36
  this.state = { ...this.state, ...partial };
21
37
  for (const listener of this.listeners) listener(this.state);
@@ -30,17 +46,45 @@ var NfcService = class {
30
46
  this.listeners.delete(fn);
31
47
  };
32
48
  }
33
- // --- Reader lifecycle ---
34
- async startReader(readerModeFlags, onTag) {
49
+ // -----------------------------
50
+ // START READER
51
+ // -----------------------------
52
+ async startReader(readerModeFlags, onTag, options) {
53
+ var _a;
35
54
  if (this.state.mode !== "idle") {
36
55
  console.warn(`[NFC] Cannot start reader while ${this.state.mode}`);
37
56
  return;
38
57
  }
39
- this.setState({ mode: "starting" });
40
- NfcManager.setEventListener(NfcEvents.DiscoverTag, (tag) => {
41
- this.setState({ tag });
42
- onTag == null ? void 0 : onTag(tag);
43
- });
58
+ this.currentOnTag = onTag;
59
+ this.currentCooldownMs = (_a = options == null ? void 0 : options.cooldownMs) != null ? _a : 1500;
60
+ this.lastUsedReaderFlags = readerModeFlags;
61
+ this.isProcessingTag = false;
62
+ this.setState({ mode: "starting", tag: null });
63
+ NfcManager.setEventListener(
64
+ NfcEvents.DiscoverTag,
65
+ async (tag) => {
66
+ if (!tag) return;
67
+ if (this.isProcessingTag) return;
68
+ this.isProcessingTag = true;
69
+ this.setState({ tag, mode: "active" });
70
+ try {
71
+ if (this.currentOnTag) {
72
+ await this.currentOnTag(tag);
73
+ }
74
+ } catch (err) {
75
+ console.warn("[NFC] onTag handler error:", err);
76
+ } finally {
77
+ const cooldown = this.currentCooldownMs;
78
+ setTimeout(async () => {
79
+ this.isProcessingTag = false;
80
+ this.setState({ tag: null, mode: "active" });
81
+ if (Platform.OS === "ios") {
82
+ await this._restartIosReader();
83
+ }
84
+ }, cooldown);
85
+ }
86
+ }
87
+ );
44
88
  try {
45
89
  await NfcManager.registerTagEvent({
46
90
  isReaderModeEnabled: true,
@@ -51,23 +95,53 @@ var NfcService = class {
51
95
  }
52
96
  } catch (err) {
53
97
  console.warn("[NFC] startReader error:", err);
54
- this.setState({ mode: "idle" });
98
+ this._resetReaderState();
55
99
  }
56
100
  }
101
+ // -----------------------------
102
+ // STOP READER
103
+ // -----------------------------
57
104
  async stopReader() {
58
105
  if (["idle", "stopping"].includes(this.state.mode)) return;
59
106
  this.setState({ mode: "stopping" });
60
107
  try {
61
108
  await NfcManager.unregisterTagEvent();
62
- } catch {
109
+ } catch (err) {
110
+ console.warn("[NFC] unregisterTagEvent error:", err);
111
+ }
112
+ this._resetReaderState();
113
+ }
114
+ _resetReaderState() {
115
+ this.setState({ mode: "idle", tag: null });
116
+ this.currentOnTag = void 0;
117
+ this.isProcessingTag = false;
118
+ }
119
+ // -----------------------------
120
+ // iOS RESTART
121
+ // -----------------------------
122
+ async _restartIosReader() {
123
+ if (Platform.OS !== "ios") return;
124
+ if (this.lastUsedReaderFlags == null) return;
125
+ try {
126
+ await NfcManager.unregisterTagEvent();
127
+ await NfcManager.registerTagEvent({
128
+ isReaderModeEnabled: true,
129
+ readerModeFlags: this.lastUsedReaderFlags
130
+ });
131
+ this.setState({ mode: "active" });
132
+ } catch (err) {
133
+ console.warn("[NFC] iOS restart error:", err);
134
+ this._resetReaderState();
63
135
  }
64
- this.setState({ mode: "idle" });
65
136
  }
137
+ // -----------------------------
138
+ // Technology sessions (NDEF, NfcV, etc.)
139
+ // -----------------------------
66
140
  async withTechnology(tech, handler) {
67
141
  if (this.state.mode === "technology") {
68
- throw new Error(`[NFC] Technology is already in use!`);
142
+ throw new Error("[NFC] Technology is already in use!");
69
143
  }
70
- if (this.state.mode === "starting" || this.state.mode === "active" || this.state.mode === "stopping") {
144
+ if (["starting", "active", "stopping"].includes(this.state.mode)) {
71
145
  await this.stopReader();
72
146
  }
73
147
  if (this.state.mode !== "idle") {
@@ -75,15 +149,15 @@ var NfcService = class {
75
149
  `[NFC] Cannot start technology session in mode ${this.state.mode}`
76
150
  );
77
151
  }
78
- this.setState({ mode: "technology" });
152
+ this.setState({ mode: "technology", tag: null });
79
153
  try {
80
154
  await NfcManager.requestTechnology(tech, {
81
155
  alertMessage: "Hold near NFC tag"
82
- // iOS
83
156
  });
84
157
  const result = await handler();
85
- if (Platform.OS === "ios")
158
+ if (Platform.OS === "ios") {
86
159
  await NfcManager.setAlertMessageIOS("Success!");
160
+ }
87
161
  return result;
88
162
  } catch (err) {
89
163
  const message = typeof err === "string" ? err : (err == null ? void 0 : err.message) || "Unknown NFC error";
@@ -91,85 +165,44 @@ var NfcService = class {
91
165
  } finally {
92
166
  try {
93
167
  await NfcManager.cancelTechnologyRequest();
94
- } catch (cancelErr) {
95
- console.warn("[NFC] cancelTechnologyRequest failed:", cancelErr);
168
+ } catch {
96
169
  }
97
- this.setState({ mode: "idle" });
170
+ this.setState({ mode: "idle", tag: null });
98
171
  }
99
172
  }
100
173
  };
101
174
  var nfcService = new NfcService();
102
175
 
103
- // src/services/nfc/a/index.ts
104
- var a_exports = {};
105
- __export(a_exports, {
106
- operations: () => operations,
107
- utils: () => utils
108
- });
109
-
110
- // src/services/nfc/a/operations.ts
111
- import NfcManager2, { NfcTech as NfcTech2 } from "react-native-nfc-manager";
176
+ // src/nfc/a/operations.ts
112
177
  var operations = {
113
178
  async transceive(data) {
114
- return nfcService.withTechnology(NfcTech2.NfcA, async () => {
179
+ return nfcService.withTechnology(NfcTech.NfcA, async () => {
115
180
  return await NfcManager2.transceive(data);
116
181
  });
117
182
  }
118
183
  };
119
184
 
120
- // src/services/nfc/a/utils.ts
185
+ // src/nfc/a/utils.ts
121
186
  var utils = {};
122
187
 
123
- // src/services/nfc/ndef/index.ts
124
- var ndef_exports = {};
125
- __export(ndef_exports, {
126
- operations: () => operations2,
127
- utils: () => utils2
128
- });
129
-
130
- // src/services/nfc/ndef/operations.ts
131
- import NfcManager3, {
132
- Ndef,
133
- NfcTech as NfcTech3
134
- } from "react-native-nfc-manager";
135
- var operations2 = {
136
- async writeNdef(records) {
137
- await nfcService.withTechnology([NfcTech3.Ndef, NfcTech3.NfcA], async () => {
138
- const bytes = Ndef.encodeMessage(records);
139
- await NfcManager3.ndefHandler.writeNdefMessage(bytes);
140
- });
141
- },
142
- writeTextNdef(text) {
143
- const record = Ndef.textRecord(text);
144
- return this.writeNdef([record]);
145
- },
146
- writeUriNdef(uri) {
147
- const record = Ndef.uriRecord(uri);
148
- return this.writeNdef([record]);
149
- }
150
- };
151
-
152
- // src/services/nfc/ndef/utils.ts
153
- var utils2 = {};
154
-
155
- // src/services/nfc/v/index.ts
188
+ // src/nfc/v/index.ts
156
189
  var v_exports = {};
157
190
  __export(v_exports, {
158
- operations: () => operations3,
159
- utils: () => utils3
191
+ operations: () => operations2,
192
+ utils: () => utils2
160
193
  });
161
194
 
162
- // src/services/nfc/v/operations.ts
163
- import NfcManager5 from "react-native-nfc-manager";
164
-
165
- // src/services/nfc/v/internal.ts
195
+ // src/nfc/v/operations.ts
166
196
  import NfcManager4 from "react-native-nfc-manager";
167
197
 
168
- // src/services/nfc/v/utils.ts
198
+ // src/nfc/v/internal.ts
199
+ import NfcManager3 from "react-native-nfc-manager";
200
+
201
+ // src/nfc/v/utils.ts
169
202
  import { Platform as Platform2 } from "react-native";
170
- import { NfcTech as NfcTech4 } from "react-native-nfc-manager";
171
- var utils3 = {
172
- tech: Platform2.OS === "ios" ? [NfcTech4.Iso15693IOS] : NfcTech4.NfcV,
203
+ import { NfcTech as NfcTech2 } from "react-native-nfc-manager";
204
+ var utils2 = {
205
+ tech: Platform2.OS === "ios" ? [NfcTech2.Iso15693IOS] : NfcTech2.NfcV,
173
206
  Flags: {
174
207
  HIGH_DATA_RATE: 2,
175
208
  ADDRESSED: 32
@@ -194,7 +227,7 @@ var utils3 = {
194
227
  reverseUid(tagIdHex) {
195
228
  const bytes = [];
196
229
  for (let i = 0; i < tagIdHex.length; i += 2) {
197
- bytes.unshift(parseInt(tagIdHex.substring(i, i + 2), 16));
230
+ bytes.unshift(Number.parseInt(tagIdHex.substring(i, i + 2), 16));
198
231
  }
199
232
  return bytes;
200
233
  },
@@ -241,8 +274,12 @@ var utils3 = {
241
274
  if (!resp || resp.length === 0) {
242
275
  throw new Error("Empty NFC-V response");
243
276
  }
244
- if (resp[0] !== 0) {
245
- throw new Error(`Read failed. Status: 0x${resp[0].toString(16)}`);
277
+ const status = resp[0];
278
+ if (status === void 0) {
279
+ throw new Error("Invalid NFC-V response: missing status byte");
280
+ }
281
+ if (status !== 0) {
282
+ throw new Error(`Read failed. Status: 0x${status.toString(16)}`);
246
283
  }
247
284
  return new Uint8Array(resp.slice(1));
248
285
  },
@@ -254,8 +291,12 @@ var utils3 = {
254
291
  if (!resp || resp.length === 0) {
255
292
  throw new Error("Empty NFC-V response");
256
293
  }
257
- if (resp[0] !== 0) {
258
- throw new Error(`Write failed. Status: 0x${resp[0].toString(16)}`);
294
+ const status = resp[0];
295
+ if (status === void 0) {
296
+ throw new Error("Invalid NFC-V response: missing status byte");
297
+ }
298
+ if (status !== 0) {
299
+ throw new Error(`Write failed. Status: 0x${status.toString(16)}`);
259
300
  }
260
301
  },
261
302
  /**
@@ -264,10 +305,18 @@ var utils3 = {
264
305
  */
265
306
  parseSystemInfo(resp) {
266
307
  var _a;
267
- if (!resp || resp.length < 2 || resp[0] !== 0) {
308
+ if (!resp || resp.length < 2) {
309
+ throw new Error("Invalid System Info response");
310
+ }
311
+ const status = resp[0];
312
+ if (status === void 0 || status !== 0) {
268
313
  throw new Error("Invalid System Info response");
269
314
  }
270
- const infoFlags = resp[1] & 15;
315
+ const flagsByte = resp[1];
316
+ if (flagsByte === void 0) {
317
+ throw new Error("Invalid System Info response: missing flags byte");
318
+ }
319
+ const infoFlags = flagsByte & 15;
271
320
  let offset = 2;
272
321
  const result = {};
273
322
  if (resp.length >= offset + 8) {
@@ -282,8 +331,14 @@ var utils3 = {
282
331
  result.afi = resp[offset++];
283
332
  }
284
333
  if (infoFlags & 4 && resp.length >= offset + 2) {
285
- result.numberOfBlocks = resp[offset++] + 1;
286
- result.blockSize = resp[offset++] + 1;
334
+ const numBlocks = resp[offset++];
335
+ const blkSize = resp[offset++];
336
+ if (numBlocks !== void 0) {
337
+ result.numberOfBlocks = numBlocks + 1;
338
+ }
339
+ if (blkSize !== void 0) {
340
+ result.blockSize = blkSize + 1;
341
+ }
287
342
  }
288
343
  if (infoFlags & 8 && resp.length > offset) {
289
344
  result.icReference = resp[offset++];
@@ -303,31 +358,31 @@ var utils3 = {
303
358
  }
304
359
  };
305
360
 
306
- // src/services/nfc/v/internal.ts
361
+ // src/nfc/v/internal.ts
307
362
  async function readBlockRaw(tag, blockNumber) {
308
- const uid = utils3.reverseUid(tag.id);
309
- const cmd = utils3.buildReadBlock(uid, blockNumber);
310
- const resp = await NfcManager4.transceive(cmd);
311
- return utils3.parseReadResponse(resp);
363
+ const uid = utils2.reverseUid(tag.id);
364
+ const cmd = utils2.buildReadBlock(uid, blockNumber);
365
+ const resp = await NfcManager3.transceive(cmd);
366
+ return utils2.parseReadResponse(resp);
312
367
  }
313
368
  async function writeBlockRaw(tag, blockNumber, data) {
314
- const uid = utils3.reverseUid(tag.id);
315
- const cmd = utils3.buildWriteBlock(uid, blockNumber, data);
316
- const resp = await NfcManager4.transceive(cmd);
317
- return utils3.parseWriteResponse(resp);
369
+ const uid = utils2.reverseUid(tag.id);
370
+ const cmd = utils2.buildWriteBlock(uid, blockNumber, data);
371
+ const resp = await NfcManager3.transceive(cmd);
372
+ return utils2.parseWriteResponse(resp);
318
373
  }
319
374
  async function getSystemInfoRaw(tag) {
320
- const uid = utils3.reverseUid(tag.id);
321
- const cmd = utils3.buildGetSystemInfo(uid);
322
- const resp = await NfcManager4.transceive(cmd);
323
- return utils3.parseSystemInfo(resp);
375
+ const uid = utils2.reverseUid(tag.id);
376
+ const cmd = utils2.buildGetSystemInfo(uid);
377
+ const resp = await NfcManager3.transceive(cmd);
378
+ return utils2.parseSystemInfo(resp);
324
379
  }
325
380
 
326
- // src/services/nfc/v/operations.ts
327
- var operations3 = {
381
+ // src/nfc/v/operations.ts
382
+ var operations2 = {
328
383
  async withVTag(handler) {
329
- return nfcService.withTechnology(utils3.tech, async () => {
330
- const tag = await NfcManager5.getTag();
384
+ return nfcService.withTechnology(utils2.tech, async () => {
385
+ const tag = await NfcManager4.getTag();
331
386
  if (!(tag == null ? void 0 : tag.id)) throw new Error("No NFC-V tag detected");
332
387
  return handler(tag);
333
388
  });
@@ -343,14 +398,46 @@ var operations3 = {
343
398
  }
344
399
  };
345
400
 
346
- // src/services/nfc/namespace.ts
401
+ // src/nfc/ndef/index.ts
402
+ var ndef_exports = {};
403
+ __export(ndef_exports, {
404
+ operations: () => operations3,
405
+ utils: () => utils3
406
+ });
407
+
408
+ // src/nfc/ndef/operations.ts
409
+ import NfcManager5, {
410
+ Ndef,
411
+ NfcTech as NfcTech3
412
+ } from "react-native-nfc-manager";
413
+ var operations3 = {
414
+ async writeNdef(records) {
415
+ await nfcService.withTechnology([NfcTech3.Ndef, NfcTech3.NfcA], async () => {
416
+ const bytes = Ndef.encodeMessage(records);
417
+ await NfcManager5.ndefHandler.writeNdefMessage(bytes);
418
+ });
419
+ },
420
+ writeTextNdef(text) {
421
+ const record = Ndef.textRecord(text);
422
+ return this.writeNdef([record]);
423
+ },
424
+ writeUriNdef(uri) {
425
+ const record = Ndef.uriRecord(uri);
426
+ return this.writeNdef([record]);
427
+ }
428
+ };
429
+
430
+ // src/nfc/ndef/utils.ts
431
+ var utils3 = {};
432
+
433
+ // src/nfc/namespace.ts
347
434
  var nfc = {
348
435
  service: nfcService,
349
436
  /** ISO15693 protocol helpers and high-level operations */
350
437
  v: {
351
- ...operations3,
438
+ ...operations2,
352
439
  // NfcVOperations, nfcV
353
- utils: utils3
440
+ utils: utils2
354
441
  },
355
442
  /** NFC-A / Type 2 helpers and operations */
356
443
  a: {
@@ -359,15 +446,107 @@ var nfc = {
359
446
  },
360
447
  /** NDEF read/write utilities and operations */
361
448
  ndef: {
362
- ...operations2,
363
- utils: utils2
449
+ ...operations3,
450
+ utils: utils3
364
451
  }
365
452
  };
453
+
454
+ // src/react/nfc-provider.tsx
455
+ import {
456
+ createContext,
457
+ useContext,
458
+ useEffect,
459
+ useState
460
+ } from "react";
461
+ import { jsx } from "react/jsx-runtime";
462
+ var NfcContext = createContext(null);
463
+ function NfcProvider({ children }) {
464
+ const [state, setState] = useState(nfcService.getState());
465
+ useEffect(() => {
466
+ const unsubscribe = nfcService.subscribe(setState);
467
+ return unsubscribe;
468
+ }, []);
469
+ return /* @__PURE__ */ jsx(NfcContext.Provider, { value: { state, service: nfcService }, children });
470
+ }
471
+ function useNfcContext() {
472
+ const ctx = useContext(NfcContext);
473
+ if (!ctx) throw new Error("useNfcContext must be inside <NfcProvider>");
474
+ return ctx;
475
+ }
476
+
477
+ // src/react/use-nfc.ts
478
+ import { useEffect as useEffect2 } from "react";
479
+ function useNfc(onTag, options) {
480
+ useEffect2(() => {
481
+ const flags = options.flags;
482
+ nfcService.startReader(
483
+ flags,
484
+ async (tag) => {
485
+ if (!tag.id) return;
486
+ onTag(tag.id);
487
+ },
488
+ { cooldownMs: options == null ? void 0 : options.cooldownMs }
489
+ );
490
+ return () => {
491
+ nfcService.stopReader();
492
+ };
493
+ }, [onTag]);
494
+ }
495
+
496
+ // src/react/use-nfc-reader.ts
497
+ import { useCallback } from "react";
498
+ function useNfcReader() {
499
+ const start = useCallback(
500
+ (flags, onTag, cooldownMs) => {
501
+ nfcService.startReader(flags, onTag, { cooldownMs });
502
+ },
503
+ []
504
+ );
505
+ const stop = useCallback(() => {
506
+ nfcService.stopReader();
507
+ }, []);
508
+ return { start, stop };
509
+ }
510
+
511
+ // src/react/use-nfc-state.ts
512
+ import { useEffect as useEffect3, useState as useState2 } from "react";
513
+ function useNfcState() {
514
+ const [nfcState, setNfcState] = useState2(nfcService.getState());
515
+ useEffect3(() => nfcService.subscribe(setNfcState), []);
516
+ return nfcState;
517
+ }
518
+
519
+ // src/react/use-nfc-technology.ts
520
+ import NfcManager6, {
521
+ Ndef as Ndef2,
522
+ NfcTech as NfcTech4
523
+ } from "react-native-nfc-manager";
524
+ function useNfcTechnology() {
525
+ async function writeNdef(records) {
526
+ return nfcService.withTechnology(NfcTech4.Ndef, async () => {
527
+ const bytes = Ndef2.encodeMessage(records);
528
+ await NfcManager6.ndefHandler.writeNdefMessage(bytes);
529
+ });
530
+ }
531
+ async function runWithTech(tech, fn) {
532
+ return nfcService.withTechnology(tech, fn);
533
+ }
534
+ return {
535
+ writeNdef,
536
+ runWithTech
537
+ };
538
+ }
366
539
  export {
367
- ndef_exports as ndef,
540
+ NfcProvider,
368
541
  nfc,
369
542
  a_exports as nfcA,
543
+ ndef_exports as nfcNdef,
370
544
  nfcService,
371
- v_exports as nfcV
545
+ v_exports as nfcV,
546
+ useNfc,
547
+ useNfcContext,
548
+ useNfcReader,
549
+ useNfcState,
550
+ useNfcTechnology
372
551
  };
373
552
  //# sourceMappingURL=index.mjs.map