@thelacanians/vue-native-runtime 0.1.2 → 0.3.0

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.js CHANGED
@@ -43,7 +43,7 @@ function createTextNode(text) {
43
43
  };
44
44
  return markRaw(node);
45
45
  }
46
- function createCommentNode(text) {
46
+ function createCommentNode(_text) {
47
47
  const node = {
48
48
  id: getNextNodeId(),
49
49
  type: "__COMMENT__",
@@ -56,7 +56,7 @@ function createCommentNode(text) {
56
56
  }
57
57
 
58
58
  // src/bridge.ts
59
- var NativeBridgeImpl = class {
59
+ var _NativeBridgeImpl = class _NativeBridgeImpl {
60
60
  constructor() {
61
61
  /** Pending operations waiting to be flushed to native */
62
62
  this.pendingOps = [];
@@ -66,7 +66,8 @@ var NativeBridgeImpl = class {
66
66
  this.eventHandlers = /* @__PURE__ */ new Map();
67
67
  /** Pending async callbacks from native module invocations */
68
68
  this.pendingCallbacks = /* @__PURE__ */ new Map();
69
- /** Auto-incrementing callback ID for async native module calls */
69
+ /** Auto-incrementing callback ID for async native module calls.
70
+ * Wraps around at MAX_SAFE_CALLBACK_ID to prevent overflow. */
70
71
  this.nextCallbackId = 1;
71
72
  /** Global event listeners: eventName -> Set of callbacks */
72
73
  this.globalEventHandlers = /* @__PURE__ */ new Map();
@@ -98,10 +99,14 @@ var NativeBridgeImpl = class {
98
99
  const json = JSON.stringify(ops);
99
100
  const flushFn = globalThis.__VN_flushOperations;
100
101
  if (typeof flushFn === "function") {
101
- flushFn(json);
102
- } else if (__DEV__) {
102
+ try {
103
+ flushFn(json);
104
+ } catch (err) {
105
+ console.error("[VueNative] Error in __VN_flushOperations:", err);
106
+ }
107
+ } else {
103
108
  console.warn(
104
- "[VueNative] __VN_flushOperations is not registered. Make sure the Swift runtime has been initialized."
109
+ "[VueNative] __VN_flushOperations is not registered. Make sure the native runtime has been initialized."
105
110
  );
106
111
  }
107
112
  }
@@ -261,7 +266,12 @@ var NativeBridgeImpl = class {
261
266
  */
262
267
  invokeNativeModule(moduleName, methodName, args = [], timeoutMs = 3e4) {
263
268
  return new Promise((resolve, reject) => {
264
- const callbackId = this.nextCallbackId++;
269
+ const callbackId = this.nextCallbackId;
270
+ if (this.nextCallbackId >= _NativeBridgeImpl.MAX_CALLBACK_ID) {
271
+ this.nextCallbackId = 1;
272
+ } else {
273
+ this.nextCallbackId++;
274
+ }
265
275
  const timeoutId = setTimeout(() => {
266
276
  if (this.pendingCallbacks.has(callbackId)) {
267
277
  this.pendingCallbacks.delete(callbackId);
@@ -332,9 +342,9 @@ var NativeBridgeImpl = class {
332
342
  }
333
343
  const handlers = this.globalEventHandlers.get(eventName);
334
344
  if (handlers) {
335
- handlers.forEach((h21) => {
345
+ handlers.forEach((h28) => {
336
346
  try {
337
- h21(payload);
347
+ h28(payload);
338
348
  } catch (err) {
339
349
  console.error(`[VueNative] Error in global event handler "${eventName}":`, err);
340
350
  }
@@ -356,6 +366,9 @@ var NativeBridgeImpl = class {
356
366
  this.globalEventHandlers.clear();
357
367
  }
358
368
  };
369
+ /** Maximum callback ID before wraparound (safe for 32-bit signed int) */
370
+ _NativeBridgeImpl.MAX_CALLBACK_ID = 2147483647;
371
+ var NativeBridgeImpl = _NativeBridgeImpl;
359
372
  if (typeof globalThis.__DEV__ === "undefined") {
360
373
  ;
361
374
  globalThis.__DEV__ = true;
@@ -374,17 +387,21 @@ function toEventName(key) {
374
387
  return key.slice(2).toLowerCase();
375
388
  }
376
389
  function patchStyle(nodeId, prevStyle, nextStyle) {
377
- const prev = prevStyle || {};
378
- const next = nextStyle || {};
379
- for (const key in next) {
380
- if (next[key] !== prev[key]) {
381
- NativeBridge.updateStyle(nodeId, key, next[key]);
390
+ try {
391
+ const prev = prevStyle || {};
392
+ const next = nextStyle || {};
393
+ for (const key in next) {
394
+ if (next[key] !== prev[key]) {
395
+ NativeBridge.updateStyle(nodeId, key, next[key]);
396
+ }
382
397
  }
383
- }
384
- for (const key in prev) {
385
- if (!(key in next)) {
386
- NativeBridge.updateStyle(nodeId, key, null);
398
+ for (const key in prev) {
399
+ if (!(key in next)) {
400
+ NativeBridge.updateStyle(nodeId, key, null);
401
+ }
387
402
  }
403
+ } catch (err) {
404
+ console.error(`[VueNative] Error patching style on node ${nodeId}:`, err);
388
405
  }
389
406
  }
390
407
  var nodeOps = {
@@ -437,22 +454,26 @@ var nodeOps = {
437
454
  * - all else -> updateProp
438
455
  */
439
456
  patchProp(el, key, prevValue, nextValue) {
440
- if (key.startsWith("on") && key.length > 2 && key[2] === key[2].toUpperCase()) {
441
- const eventName = toEventName(key);
442
- if (prevValue) {
443
- NativeBridge.removeEventListener(el.id, eventName);
457
+ try {
458
+ if (key.startsWith("on") && key.length > 2 && key[2] === key[2].toUpperCase()) {
459
+ const eventName = toEventName(key);
460
+ if (prevValue) {
461
+ NativeBridge.removeEventListener(el.id, eventName);
462
+ }
463
+ if (nextValue) {
464
+ NativeBridge.addEventListener(el.id, eventName, nextValue);
465
+ }
466
+ return;
444
467
  }
445
- if (nextValue) {
446
- NativeBridge.addEventListener(el.id, eventName, nextValue);
468
+ if (key === "style") {
469
+ patchStyle(el.id, prevValue, nextValue);
470
+ return;
447
471
  }
448
- return;
449
- }
450
- if (key === "style") {
451
- patchStyle(el.id, prevValue, nextValue);
452
- return;
472
+ el.props[key] = nextValue;
473
+ NativeBridge.updateProp(el.id, key, nextValue);
474
+ } catch (err) {
475
+ console.error(`[VueNative] Error patching prop "${key}" on node ${el.id}:`, err);
453
476
  }
454
- el.props[key] = nextValue;
455
- NativeBridge.updateProp(el.id, key, nextValue);
456
477
  },
457
478
  /**
458
479
  * Insert a child node into a parent, optionally before an anchor node.
@@ -467,30 +488,34 @@ var nodeOps = {
467
488
  }
468
489
  }
469
490
  child.parent = parent;
470
- if (anchor) {
471
- const anchorIdx = parent.children.indexOf(anchor);
472
- if (anchorIdx !== -1) {
473
- parent.children.splice(anchorIdx, 0, child);
474
- } else {
475
- parent.children.push(child);
476
- }
477
- if (child.type !== "__COMMENT__") {
478
- if (anchor.type !== "__COMMENT__") {
479
- NativeBridge.insertBefore(parent.id, child.id, anchor.id);
491
+ try {
492
+ if (anchor) {
493
+ const anchorIdx = parent.children.indexOf(anchor);
494
+ if (anchorIdx !== -1) {
495
+ parent.children.splice(anchorIdx, 0, child);
480
496
  } else {
481
- const realAnchor = findNextNonComment(parent, anchor);
482
- if (realAnchor) {
483
- NativeBridge.insertBefore(parent.id, child.id, realAnchor.id);
497
+ parent.children.push(child);
498
+ }
499
+ if (child.type !== "__COMMENT__") {
500
+ if (anchor.type !== "__COMMENT__") {
501
+ NativeBridge.insertBefore(parent.id, child.id, anchor.id);
484
502
  } else {
485
- NativeBridge.appendChild(parent.id, child.id);
503
+ const realAnchor = findNextNonComment(parent, anchor);
504
+ if (realAnchor) {
505
+ NativeBridge.insertBefore(parent.id, child.id, realAnchor.id);
506
+ } else {
507
+ NativeBridge.appendChild(parent.id, child.id);
508
+ }
486
509
  }
487
510
  }
511
+ } else {
512
+ parent.children.push(child);
513
+ if (child.type !== "__COMMENT__") {
514
+ NativeBridge.appendChild(parent.id, child.id);
515
+ }
488
516
  }
489
- } else {
490
- parent.children.push(child);
491
- if (child.type !== "__COMMENT__") {
492
- NativeBridge.appendChild(parent.id, child.id);
493
- }
517
+ } catch (err) {
518
+ console.error(`[VueNative] Error inserting node ${child.id} into ${parent.id}:`, err);
494
519
  }
495
520
  },
496
521
  /**
@@ -504,8 +529,12 @@ var nodeOps = {
504
529
  parent.children.splice(idx, 1);
505
530
  }
506
531
  child.parent = null;
507
- if (child.type !== "__COMMENT__") {
508
- NativeBridge.removeChild(parent.id, child.id);
532
+ try {
533
+ if (child.type !== "__COMMENT__") {
534
+ NativeBridge.removeChild(parent.id, child.id);
535
+ }
536
+ } catch (err) {
537
+ console.error(`[VueNative] Error removing node ${child.id}:`, err);
509
538
  }
510
539
  }
511
540
  },
@@ -545,7 +574,10 @@ var VView = defineComponent({
545
574
  props: {
546
575
  style: Object,
547
576
  testID: String,
548
- accessibilityLabel: String
577
+ accessibilityLabel: String,
578
+ accessibilityRole: String,
579
+ accessibilityHint: String,
580
+ accessibilityState: Object
549
581
  },
550
582
  setup(props, { slots }) {
551
583
  return () => h("VView", { ...props }, slots.default?.());
@@ -563,7 +595,10 @@ var VText = defineComponent2({
563
595
  type: Boolean,
564
596
  default: false
565
597
  },
566
- accessibilityRole: String
598
+ accessibilityLabel: String,
599
+ accessibilityRole: String,
600
+ accessibilityHint: String,
601
+ accessibilityState: Object
567
602
  },
568
603
  setup(props, { slots }) {
569
604
  return () => h2("VText", { ...props }, slots.default?.());
@@ -585,7 +620,11 @@ var VButton = defineComponent3({
585
620
  default: 0.7
586
621
  },
587
622
  onPress: Function,
588
- onLongPress: Function
623
+ onLongPress: Function,
624
+ accessibilityLabel: String,
625
+ accessibilityRole: String,
626
+ accessibilityHint: String,
627
+ accessibilityState: Object
589
628
  },
590
629
  setup(props, { slots }) {
591
630
  return () => h3(
@@ -635,7 +674,11 @@ var VInput = defineComponent4({
635
674
  type: Boolean,
636
675
  default: false
637
676
  },
638
- style: Object
677
+ style: Object,
678
+ accessibilityLabel: String,
679
+ accessibilityRole: String,
680
+ accessibilityHint: String,
681
+ accessibilityState: Object
639
682
  },
640
683
  emits: ["update:modelValue", "focus", "blur", "submit"],
641
684
  setup(props, { emit }) {
@@ -663,6 +706,10 @@ var VInput = defineComponent4({
663
706
  maxLength: props.maxLength,
664
707
  multiline: props.multiline,
665
708
  style: props.style,
709
+ accessibilityLabel: props.accessibilityLabel,
710
+ accessibilityRole: props.accessibilityRole,
711
+ accessibilityHint: props.accessibilityHint,
712
+ accessibilityState: props.accessibilityState,
666
713
  onChangetext,
667
714
  onFocus,
668
715
  onBlur,
@@ -686,7 +733,11 @@ var VSwitch = defineComponent5({
686
733
  },
687
734
  onTintColor: String,
688
735
  thumbTintColor: String,
689
- style: Object
736
+ style: Object,
737
+ accessibilityLabel: String,
738
+ accessibilityRole: String,
739
+ accessibilityHint: String,
740
+ accessibilityState: Object
690
741
  },
691
742
  emits: ["update:modelValue", "change"],
692
743
  setup(props, { emit }) {
@@ -701,6 +752,10 @@ var VSwitch = defineComponent5({
701
752
  onTintColor: props.onTintColor,
702
753
  thumbTintColor: props.thumbTintColor,
703
754
  style: props.style,
755
+ accessibilityLabel: props.accessibilityLabel,
756
+ accessibilityRole: props.accessibilityRole,
757
+ accessibilityHint: props.accessibilityHint,
758
+ accessibilityState: props.accessibilityState,
704
759
  onChange
705
760
  });
706
761
  }
@@ -773,7 +828,11 @@ var VScrollView = defineComponent7({
773
828
  type: Boolean,
774
829
  default: false
775
830
  },
776
- style: Object
831
+ style: Object,
832
+ accessibilityLabel: String,
833
+ accessibilityRole: String,
834
+ accessibilityHint: String,
835
+ accessibilityState: Object
777
836
  },
778
837
  emits: ["scroll", "refresh"],
779
838
  setup(props, { slots, emit }) {
@@ -795,6 +854,10 @@ var VScrollView = defineComponent7({
795
854
  contentContainerStyle: props.contentContainerStyle,
796
855
  refreshing: props.refreshing,
797
856
  style: props.style,
857
+ accessibilityLabel: props.accessibilityLabel,
858
+ accessibilityRole: props.accessibilityRole,
859
+ accessibilityHint: props.accessibilityHint,
860
+ accessibilityState: props.accessibilityState,
798
861
  onScroll,
799
862
  onRefresh
800
863
  },
@@ -815,7 +878,10 @@ var VImage = defineComponent8({
815
878
  },
816
879
  style: Object,
817
880
  testID: String,
818
- accessibilityLabel: String
881
+ accessibilityLabel: String,
882
+ accessibilityRole: String,
883
+ accessibilityHint: String,
884
+ accessibilityState: Object
819
885
  },
820
886
  emits: ["load", "error"],
821
887
  setup(props, { emit }) {
@@ -863,7 +929,11 @@ var VSlider = defineComponent11({
863
929
  modelValue: { type: Number, default: 0 },
864
930
  min: { type: Number, default: 0 },
865
931
  max: { type: Number, default: 1 },
866
- style: { type: Object, default: () => ({}) }
932
+ style: { type: Object, default: () => ({}) },
933
+ accessibilityLabel: String,
934
+ accessibilityRole: String,
935
+ accessibilityHint: String,
936
+ accessibilityState: Object
867
937
  },
868
938
  emits: ["update:modelValue", "change"],
869
939
  setup(props, { emit }) {
@@ -872,6 +942,10 @@ var VSlider = defineComponent11({
872
942
  value: props.modelValue,
873
943
  minimumValue: props.min,
874
944
  maximumValue: props.max,
945
+ accessibilityLabel: props.accessibilityLabel,
946
+ accessibilityRole: props.accessibilityRole,
947
+ accessibilityHint: props.accessibilityHint,
948
+ accessibilityState: props.accessibilityState,
875
949
  onChange: (val) => {
876
950
  emit("update:modelValue", val);
877
951
  emit("change", val);
@@ -1158,6 +1232,352 @@ var VActionSheet = defineComponent20({
1158
1232
  }
1159
1233
  });
1160
1234
 
1235
+ // src/components/VRefreshControl.ts
1236
+ import { defineComponent as defineComponent21, h as h21 } from "@vue/runtime-core";
1237
+ var VRefreshControl = defineComponent21({
1238
+ name: "VRefreshControl",
1239
+ props: {
1240
+ refreshing: {
1241
+ type: Boolean,
1242
+ default: false
1243
+ },
1244
+ onRefresh: Function,
1245
+ tintColor: String,
1246
+ title: String,
1247
+ style: Object
1248
+ },
1249
+ setup(props) {
1250
+ return () => h21("VRefreshControl", {
1251
+ refreshing: props.refreshing,
1252
+ onRefresh: props.onRefresh,
1253
+ tintColor: props.tintColor,
1254
+ title: props.title
1255
+ });
1256
+ }
1257
+ });
1258
+
1259
+ // src/components/VPressable.ts
1260
+ import { defineComponent as defineComponent22, h as h22 } from "@vue/runtime-core";
1261
+ var VPressable = defineComponent22({
1262
+ name: "VPressable",
1263
+ props: {
1264
+ style: Object,
1265
+ disabled: {
1266
+ type: Boolean,
1267
+ default: false
1268
+ },
1269
+ activeOpacity: {
1270
+ type: Number,
1271
+ default: 0.7
1272
+ },
1273
+ onPress: Function,
1274
+ onPressIn: Function,
1275
+ onPressOut: Function,
1276
+ onLongPress: Function,
1277
+ accessibilityLabel: String,
1278
+ accessibilityRole: String,
1279
+ accessibilityHint: String,
1280
+ accessibilityState: Object
1281
+ },
1282
+ setup(props, { slots }) {
1283
+ return () => h22(
1284
+ "VPressable",
1285
+ {
1286
+ ...props,
1287
+ onPress: props.disabled ? void 0 : props.onPress,
1288
+ onPressIn: props.disabled ? void 0 : props.onPressIn,
1289
+ onPressOut: props.disabled ? void 0 : props.onPressOut,
1290
+ onLongPress: props.disabled ? void 0 : props.onLongPress
1291
+ },
1292
+ slots.default?.()
1293
+ );
1294
+ }
1295
+ });
1296
+
1297
+ // src/components/VSectionList.ts
1298
+ import { defineComponent as defineComponent23, h as h23 } from "@vue/runtime-core";
1299
+ var VSectionList = defineComponent23({
1300
+ name: "VSectionList",
1301
+ props: {
1302
+ /** Array of section objects, each with a title and data array */
1303
+ sections: {
1304
+ type: Array,
1305
+ required: true
1306
+ },
1307
+ /** Extract a unique key from each item. Defaults to index as string. */
1308
+ keyExtractor: {
1309
+ type: Function,
1310
+ default: (_item, index) => String(index)
1311
+ },
1312
+ /** Estimated height per row in points. Default: 44 */
1313
+ estimatedItemHeight: {
1314
+ type: Number,
1315
+ default: 44
1316
+ },
1317
+ /** Whether section headers stick to the top when scrolling. Default: true */
1318
+ stickySectionHeaders: {
1319
+ type: Boolean,
1320
+ default: true
1321
+ },
1322
+ /** Show vertical scroll indicator. Default: true */
1323
+ showsScrollIndicator: {
1324
+ type: Boolean,
1325
+ default: true
1326
+ },
1327
+ /** Enable bounce at scroll boundaries. Default: true */
1328
+ bounces: {
1329
+ type: Boolean,
1330
+ default: true
1331
+ },
1332
+ style: {
1333
+ type: Object,
1334
+ default: () => ({})
1335
+ }
1336
+ },
1337
+ emits: ["scroll", "endReached"],
1338
+ setup(props, { slots, emit }) {
1339
+ return () => {
1340
+ const sections = props.sections ?? [];
1341
+ const children = [];
1342
+ if (slots.header) {
1343
+ children.push(
1344
+ h23("VView", { key: "__header__", style: { flexShrink: 0 } }, slots.header())
1345
+ );
1346
+ }
1347
+ const totalItems = sections.reduce((sum, s) => sum + (s.data?.length ?? 0), 0);
1348
+ if (totalItems === 0 && slots.empty) {
1349
+ children.push(
1350
+ h23("VView", { key: "__empty__", style: { flexShrink: 0 } }, slots.empty())
1351
+ );
1352
+ }
1353
+ for (let sectionIndex = 0; sectionIndex < sections.length; sectionIndex++) {
1354
+ const section = sections[sectionIndex];
1355
+ if (slots.sectionHeader) {
1356
+ children.push(
1357
+ h23(
1358
+ "VView",
1359
+ {
1360
+ key: `__section_header_${sectionIndex}__`,
1361
+ __sectionHeader: true,
1362
+ style: { flexShrink: 0 }
1363
+ },
1364
+ slots.sectionHeader({ section, index: sectionIndex })
1365
+ )
1366
+ );
1367
+ }
1368
+ const items = section.data ?? [];
1369
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
1370
+ const item = items[itemIndex];
1371
+ children.push(
1372
+ h23(
1373
+ "VView",
1374
+ {
1375
+ key: `${sectionIndex}_${props.keyExtractor(item, itemIndex)}`,
1376
+ style: { flexShrink: 0 }
1377
+ },
1378
+ slots.item?.({ item, index: itemIndex, section }) ?? []
1379
+ )
1380
+ );
1381
+ }
1382
+ if (slots.sectionFooter) {
1383
+ children.push(
1384
+ h23(
1385
+ "VView",
1386
+ {
1387
+ key: `__section_footer_${sectionIndex}__`,
1388
+ style: { flexShrink: 0 }
1389
+ },
1390
+ slots.sectionFooter({ section, index: sectionIndex })
1391
+ )
1392
+ );
1393
+ }
1394
+ }
1395
+ if (slots.footer) {
1396
+ children.push(
1397
+ h23("VView", { key: "__footer__", style: { flexShrink: 0 } }, slots.footer())
1398
+ );
1399
+ }
1400
+ return h23(
1401
+ "VSectionList",
1402
+ {
1403
+ style: props.style,
1404
+ estimatedItemHeight: props.estimatedItemHeight,
1405
+ stickySectionHeaders: props.stickySectionHeaders,
1406
+ showsScrollIndicator: props.showsScrollIndicator,
1407
+ bounces: props.bounces,
1408
+ onScroll: (e) => emit("scroll", e),
1409
+ onEndReached: () => emit("endReached")
1410
+ },
1411
+ children
1412
+ );
1413
+ };
1414
+ }
1415
+ });
1416
+
1417
+ // src/components/VCheckbox.ts
1418
+ import { defineComponent as defineComponent24, h as h24 } from "@vue/runtime-core";
1419
+ var VCheckbox = defineComponent24({
1420
+ name: "VCheckbox",
1421
+ props: {
1422
+ modelValue: {
1423
+ type: Boolean,
1424
+ default: false
1425
+ },
1426
+ disabled: {
1427
+ type: Boolean,
1428
+ default: false
1429
+ },
1430
+ label: {
1431
+ type: String,
1432
+ default: void 0
1433
+ },
1434
+ checkColor: String,
1435
+ tintColor: String,
1436
+ style: Object,
1437
+ accessibilityLabel: String,
1438
+ accessibilityHint: String
1439
+ },
1440
+ emits: ["update:modelValue", "change"],
1441
+ setup(props, { emit }) {
1442
+ const onChange = (payload) => {
1443
+ const value = typeof payload === "boolean" ? payload : !!(payload?.value ?? payload);
1444
+ emit("update:modelValue", value);
1445
+ emit("change", value);
1446
+ };
1447
+ return () => h24("VCheckbox", {
1448
+ value: props.modelValue,
1449
+ disabled: props.disabled,
1450
+ label: props.label,
1451
+ checkColor: props.checkColor,
1452
+ tintColor: props.tintColor,
1453
+ style: props.style,
1454
+ accessibilityLabel: props.accessibilityLabel,
1455
+ accessibilityHint: props.accessibilityHint,
1456
+ onChange
1457
+ });
1458
+ }
1459
+ });
1460
+
1461
+ // src/components/VRadio.ts
1462
+ import { defineComponent as defineComponent25, h as h25 } from "@vue/runtime-core";
1463
+ var VRadio = defineComponent25({
1464
+ name: "VRadio",
1465
+ props: {
1466
+ modelValue: {
1467
+ type: String,
1468
+ default: void 0
1469
+ },
1470
+ options: {
1471
+ type: Array,
1472
+ required: true
1473
+ },
1474
+ disabled: {
1475
+ type: Boolean,
1476
+ default: false
1477
+ },
1478
+ tintColor: String,
1479
+ style: Object,
1480
+ accessibilityLabel: String
1481
+ },
1482
+ emits: ["update:modelValue", "change"],
1483
+ setup(props, { emit }) {
1484
+ const onChange = (payload) => {
1485
+ const value = payload?.value ?? payload;
1486
+ emit("update:modelValue", value);
1487
+ emit("change", value);
1488
+ };
1489
+ return () => h25("VRadio", {
1490
+ selectedValue: props.modelValue,
1491
+ options: props.options,
1492
+ disabled: props.disabled,
1493
+ tintColor: props.tintColor,
1494
+ style: props.style,
1495
+ accessibilityLabel: props.accessibilityLabel,
1496
+ onChange
1497
+ });
1498
+ }
1499
+ });
1500
+
1501
+ // src/components/VDropdown.ts
1502
+ import { defineComponent as defineComponent26, h as h26 } from "@vue/runtime-core";
1503
+ var VDropdown = defineComponent26({
1504
+ name: "VDropdown",
1505
+ props: {
1506
+ modelValue: {
1507
+ type: String,
1508
+ default: void 0
1509
+ },
1510
+ options: {
1511
+ type: Array,
1512
+ required: true
1513
+ },
1514
+ placeholder: {
1515
+ type: String,
1516
+ default: "Select..."
1517
+ },
1518
+ disabled: {
1519
+ type: Boolean,
1520
+ default: false
1521
+ },
1522
+ tintColor: String,
1523
+ style: Object,
1524
+ accessibilityLabel: String
1525
+ },
1526
+ emits: ["update:modelValue", "change"],
1527
+ setup(props, { emit }) {
1528
+ const onChange = (payload) => {
1529
+ const value = payload?.value ?? payload;
1530
+ emit("update:modelValue", value);
1531
+ emit("change", value);
1532
+ };
1533
+ return () => h26("VDropdown", {
1534
+ selectedValue: props.modelValue,
1535
+ options: props.options,
1536
+ placeholder: props.placeholder,
1537
+ disabled: props.disabled,
1538
+ tintColor: props.tintColor,
1539
+ style: props.style,
1540
+ accessibilityLabel: props.accessibilityLabel,
1541
+ onChange
1542
+ });
1543
+ }
1544
+ });
1545
+
1546
+ // src/components/VVideo.ts
1547
+ import { defineComponent as defineComponent27, h as h27 } from "@vue/runtime-core";
1548
+ var VVideo = defineComponent27({
1549
+ name: "VVideo",
1550
+ props: {
1551
+ source: Object,
1552
+ autoplay: { type: Boolean, default: false },
1553
+ loop: { type: Boolean, default: false },
1554
+ muted: { type: Boolean, default: false },
1555
+ paused: { type: Boolean, default: false },
1556
+ controls: { type: Boolean, default: true },
1557
+ volume: { type: Number, default: 1 },
1558
+ resizeMode: {
1559
+ type: String,
1560
+ default: "cover"
1561
+ },
1562
+ poster: String,
1563
+ style: Object,
1564
+ testID: String,
1565
+ accessibilityLabel: String
1566
+ },
1567
+ emits: ["ready", "play", "pause", "end", "error", "progress"],
1568
+ setup(props, { emit }) {
1569
+ return () => h27("VVideo", {
1570
+ ...props,
1571
+ onReady: (e) => emit("ready", e),
1572
+ onPlay: () => emit("play"),
1573
+ onPause: () => emit("pause"),
1574
+ onEnd: () => emit("end"),
1575
+ onError: (e) => emit("error", e),
1576
+ onProgress: (e) => emit("progress", e)
1577
+ });
1578
+ }
1579
+ });
1580
+
1161
1581
  // src/directives/vShow.ts
1162
1582
  var vShow = {
1163
1583
  beforeMount(el, { value }) {
@@ -1169,16 +1589,61 @@ var vShow = {
1169
1589
  }
1170
1590
  };
1171
1591
 
1172
- // src/index.ts
1173
- export * from "@vue/runtime-core";
1174
-
1175
- // src/stylesheet.ts
1176
- var validStyleProperties = /* @__PURE__ */ new Set([
1177
- // Layout (Yoga / Flexbox)
1178
- "flex",
1179
- "flexDirection",
1180
- "flexWrap",
1181
- "flexGrow",
1592
+ // src/errorBoundary.ts
1593
+ import { defineComponent as defineComponent28, ref, watch, onErrorCaptured } from "@vue/runtime-core";
1594
+ var ErrorBoundary = defineComponent28({
1595
+ name: "ErrorBoundary",
1596
+ props: {
1597
+ onError: Function,
1598
+ resetKeys: {
1599
+ type: Array,
1600
+ default: () => []
1601
+ }
1602
+ },
1603
+ setup(props, { slots }) {
1604
+ const error = ref(null);
1605
+ const errorInfo = ref("");
1606
+ onErrorCaptured((err, _instance, info) => {
1607
+ const normalizedError = err instanceof Error ? err : new Error(String(err));
1608
+ error.value = normalizedError;
1609
+ errorInfo.value = info;
1610
+ if (props.onError) {
1611
+ props.onError(normalizedError, info);
1612
+ }
1613
+ return false;
1614
+ });
1615
+ function reset() {
1616
+ error.value = null;
1617
+ errorInfo.value = "";
1618
+ }
1619
+ watch(
1620
+ () => props.resetKeys,
1621
+ () => {
1622
+ if (error.value) {
1623
+ reset();
1624
+ }
1625
+ },
1626
+ { deep: true }
1627
+ );
1628
+ return () => {
1629
+ if (error.value && slots.fallback) {
1630
+ return slots.fallback({ error: error.value, errorInfo: errorInfo.value, reset });
1631
+ }
1632
+ return slots.default?.();
1633
+ };
1634
+ }
1635
+ });
1636
+
1637
+ // src/index.ts
1638
+ export * from "@vue/runtime-core";
1639
+
1640
+ // src/stylesheet.ts
1641
+ var validStyleProperties = /* @__PURE__ */ new Set([
1642
+ // Layout (Yoga / Flexbox)
1643
+ "flex",
1644
+ "flexDirection",
1645
+ "flexWrap",
1646
+ "flexGrow",
1182
1647
  "flexShrink",
1183
1648
  "flexBasis",
1184
1649
  "justifyContent",
@@ -1213,6 +1678,7 @@ var validStyleProperties = /* @__PURE__ */ new Set([
1213
1678
  "gap",
1214
1679
  "rowGap",
1215
1680
  "columnGap",
1681
+ "direction",
1216
1682
  "display",
1217
1683
  "overflow",
1218
1684
  "zIndex",
@@ -1260,7 +1726,15 @@ var validStyleProperties = /* @__PURE__ */ new Set([
1260
1726
  "resizeMode",
1261
1727
  "tintColor",
1262
1728
  // Transform
1263
- "transform"
1729
+ "transform",
1730
+ // Accessibility
1731
+ "accessibilityLabel",
1732
+ "accessibilityRole",
1733
+ "accessibilityHint",
1734
+ "accessibilityState",
1735
+ "accessibilityValue",
1736
+ "accessible",
1737
+ "importantForAccessibility"
1264
1738
  ]);
1265
1739
  function createStyleSheet(styles) {
1266
1740
  const isDev = typeof __DEV__ !== "undefined" ? __DEV__ : true;
@@ -1318,9 +1792,9 @@ function useAsyncStorage() {
1318
1792
  }
1319
1793
 
1320
1794
  // src/composables/useClipboard.ts
1321
- import { ref } from "@vue/runtime-core";
1795
+ import { ref as ref2 } from "@vue/runtime-core";
1322
1796
  function useClipboard() {
1323
- const content = ref("");
1797
+ const content = ref2("");
1324
1798
  function copy(text) {
1325
1799
  return NativeBridge.invokeNativeModule("Clipboard", "copy", [text]).then(() => void 0);
1326
1800
  }
@@ -1334,16 +1808,16 @@ function useClipboard() {
1334
1808
  }
1335
1809
 
1336
1810
  // src/composables/useDeviceInfo.ts
1337
- import { ref as ref2, onMounted } from "@vue/runtime-core";
1811
+ import { ref as ref3, onMounted } from "@vue/runtime-core";
1338
1812
  function useDeviceInfo() {
1339
- const model = ref2("");
1340
- const systemVersion = ref2("");
1341
- const systemName = ref2("");
1342
- const name = ref2("");
1343
- const screenWidth = ref2(0);
1344
- const screenHeight = ref2(0);
1345
- const scale = ref2(1);
1346
- const isLoaded = ref2(false);
1813
+ const model = ref3("");
1814
+ const systemVersion = ref3("");
1815
+ const systemName = ref3("");
1816
+ const name = ref3("");
1817
+ const screenWidth = ref3(0);
1818
+ const screenHeight = ref3(0);
1819
+ const scale = ref3(1);
1820
+ const isLoaded = ref3(false);
1347
1821
  async function fetchInfo() {
1348
1822
  const info = await NativeBridge.invokeNativeModule("DeviceInfo", "getInfo", []);
1349
1823
  model.value = info.model ?? "";
@@ -1372,10 +1846,10 @@ function useDeviceInfo() {
1372
1846
  }
1373
1847
 
1374
1848
  // src/composables/useKeyboard.ts
1375
- import { ref as ref3 } from "@vue/runtime-core";
1849
+ import { ref as ref4 } from "@vue/runtime-core";
1376
1850
  function useKeyboard() {
1377
- const isVisible = ref3(false);
1378
- const height = ref3(0);
1851
+ const isVisible = ref4(false);
1852
+ const height = ref4(0);
1379
1853
  function dismiss() {
1380
1854
  return NativeBridge.invokeNativeModule("Keyboard", "dismiss", []).then(() => void 0);
1381
1855
  }
@@ -1439,10 +1913,10 @@ function useAnimation() {
1439
1913
  }
1440
1914
 
1441
1915
  // src/composables/useNetwork.ts
1442
- import { ref as ref4, onUnmounted } from "@vue/runtime-core";
1916
+ import { ref as ref5, onUnmounted } from "@vue/runtime-core";
1443
1917
  function useNetwork() {
1444
- const isConnected = ref4(true);
1445
- const connectionType = ref4("unknown");
1918
+ const isConnected = ref5(true);
1919
+ const connectionType = ref5("unknown");
1446
1920
  NativeBridge.invokeNativeModule("Network", "getStatus").then((status) => {
1447
1921
  isConnected.value = status.isConnected;
1448
1922
  connectionType.value = status.connectionType;
@@ -1457,9 +1931,9 @@ function useNetwork() {
1457
1931
  }
1458
1932
 
1459
1933
  // src/composables/useAppState.ts
1460
- import { ref as ref5, onUnmounted as onUnmounted2 } from "@vue/runtime-core";
1934
+ import { ref as ref6, onUnmounted as onUnmounted2 } from "@vue/runtime-core";
1461
1935
  function useAppState() {
1462
- const state = ref5("active");
1936
+ const state = ref6("active");
1463
1937
  NativeBridge.invokeNativeModule("AppState", "getState").then((s) => {
1464
1938
  state.value = s;
1465
1939
  }).catch(() => {
@@ -1502,10 +1976,10 @@ function usePermissions() {
1502
1976
  }
1503
1977
 
1504
1978
  // src/composables/useGeolocation.ts
1505
- import { ref as ref6, onUnmounted as onUnmounted3 } from "@vue/runtime-core";
1979
+ import { ref as ref7, onUnmounted as onUnmounted3 } from "@vue/runtime-core";
1506
1980
  function useGeolocation() {
1507
- const coords = ref6(null);
1508
- const error = ref6(null);
1981
+ const coords = ref7(null);
1982
+ const error = ref7(null);
1509
1983
  let watchId = null;
1510
1984
  async function getCurrentPosition() {
1511
1985
  const result = await NativeBridge.invokeNativeModule("Geolocation", "getCurrentPosition");
@@ -1532,20 +2006,43 @@ function useGeolocation() {
1532
2006
  }
1533
2007
 
1534
2008
  // src/composables/useCamera.ts
2009
+ import { onUnmounted as onUnmounted4 } from "@vue/runtime-core";
1535
2010
  function useCamera() {
2011
+ const qrCleanups = [];
1536
2012
  async function launchCamera(options = {}) {
1537
2013
  return NativeBridge.invokeNativeModule("Camera", "launchCamera", [options]);
1538
2014
  }
1539
2015
  async function launchImageLibrary(options = {}) {
1540
2016
  return NativeBridge.invokeNativeModule("Camera", "launchImageLibrary", [options]);
1541
2017
  }
1542
- return { launchCamera, launchImageLibrary };
2018
+ async function captureVideo(options = {}) {
2019
+ return NativeBridge.invokeNativeModule("Camera", "captureVideo", [options]);
2020
+ }
2021
+ async function scanQRCode() {
2022
+ return NativeBridge.invokeNativeModule("Camera", "scanQRCode");
2023
+ }
2024
+ async function stopQRScan() {
2025
+ return NativeBridge.invokeNativeModule("Camera", "stopQRScan");
2026
+ }
2027
+ function onQRCodeDetected(callback) {
2028
+ const unsubscribe = NativeBridge.onGlobalEvent("camera:qrDetected", callback);
2029
+ qrCleanups.push(unsubscribe);
2030
+ return unsubscribe;
2031
+ }
2032
+ onUnmounted4(() => {
2033
+ NativeBridge.invokeNativeModule("Camera", "stopQRScan").catch(() => {
2034
+ });
2035
+ qrCleanups.forEach((fn) => fn());
2036
+ qrCleanups.length = 0;
2037
+ });
2038
+ return { launchCamera, launchImageLibrary, captureVideo, scanQRCode, stopQRScan, onQRCodeDetected };
1543
2039
  }
1544
2040
 
1545
2041
  // src/composables/useNotifications.ts
1546
- import { ref as ref7, onUnmounted as onUnmounted4 } from "@vue/runtime-core";
2042
+ import { ref as ref8, onUnmounted as onUnmounted5 } from "@vue/runtime-core";
1547
2043
  function useNotifications() {
1548
- const isGranted = ref7(false);
2044
+ const isGranted = ref8(false);
2045
+ const pushToken = ref8(null);
1549
2046
  async function requestPermission() {
1550
2047
  const granted = await NativeBridge.invokeNativeModule("Notifications", "requestPermission");
1551
2048
  isGranted.value = granted;
@@ -1565,10 +2062,44 @@ function useNotifications() {
1565
2062
  }
1566
2063
  function onNotification(handler) {
1567
2064
  const unsubscribe = NativeBridge.onGlobalEvent("notification:received", handler);
1568
- onUnmounted4(unsubscribe);
2065
+ onUnmounted5(unsubscribe);
2066
+ return unsubscribe;
2067
+ }
2068
+ async function registerForPush() {
2069
+ await NativeBridge.invokeNativeModule("Notifications", "registerForPush");
2070
+ }
2071
+ async function getToken() {
2072
+ return NativeBridge.invokeNativeModule("Notifications", "getToken");
2073
+ }
2074
+ function onPushToken(handler) {
2075
+ const unsubscribe = NativeBridge.onGlobalEvent("push:token", (payload) => {
2076
+ pushToken.value = payload.token;
2077
+ handler(payload.token);
2078
+ });
2079
+ onUnmounted5(unsubscribe);
2080
+ return unsubscribe;
2081
+ }
2082
+ function onPushReceived(handler) {
2083
+ const unsubscribe = NativeBridge.onGlobalEvent("push:received", handler);
2084
+ onUnmounted5(unsubscribe);
1569
2085
  return unsubscribe;
1570
2086
  }
1571
- return { isGranted, requestPermission, getPermissionStatus, scheduleLocal, cancel, cancelAll, onNotification };
2087
+ return {
2088
+ // Local
2089
+ isGranted,
2090
+ requestPermission,
2091
+ getPermissionStatus,
2092
+ scheduleLocal,
2093
+ cancel,
2094
+ cancelAll,
2095
+ onNotification,
2096
+ // Push
2097
+ pushToken,
2098
+ registerForPush,
2099
+ getToken,
2100
+ onPushToken,
2101
+ onPushReceived
2102
+ };
1572
2103
  }
1573
2104
 
1574
2105
  // src/composables/useBiometry.ts
@@ -1586,10 +2117,18 @@ function useBiometry() {
1586
2117
  }
1587
2118
 
1588
2119
  // src/composables/useHttp.ts
1589
- import { ref as ref8 } from "@vue/runtime-core";
2120
+ import { ref as ref9 } from "@vue/runtime-core";
1590
2121
  function useHttp(config = {}) {
1591
- const loading = ref8(false);
1592
- const error = ref8(null);
2122
+ if (config.pins && Object.keys(config.pins).length > 0) {
2123
+ const configurePins = globalThis.__VN_configurePins;
2124
+ if (typeof configurePins === "function") {
2125
+ configurePins(JSON.stringify(config.pins));
2126
+ } else {
2127
+ NativeBridge.invokeNativeModule("Http", "configurePins", [config.pins]);
2128
+ }
2129
+ }
2130
+ const loading = ref9(false);
2131
+ const error = ref9(null);
1593
2132
  async function request(method, url, options = {}) {
1594
2133
  const fullUrl = config.baseURL ? `${config.baseURL}${url}` : url;
1595
2134
  loading.value = true;
@@ -1635,10 +2174,10 @@ function useHttp(config = {}) {
1635
2174
  }
1636
2175
 
1637
2176
  // src/composables/useColorScheme.ts
1638
- import { ref as ref9, onUnmounted as onUnmounted5 } from "@vue/runtime-core";
2177
+ import { ref as ref10, onUnmounted as onUnmounted6 } from "@vue/runtime-core";
1639
2178
  function useColorScheme() {
1640
- const colorScheme = ref9("light");
1641
- const isDark = ref9(false);
2179
+ const colorScheme = ref10("light");
2180
+ const isDark = ref10(false);
1642
2181
  const unsubscribe = NativeBridge.onGlobalEvent(
1643
2182
  "colorScheme:change",
1644
2183
  (payload) => {
@@ -1646,12 +2185,12 @@ function useColorScheme() {
1646
2185
  isDark.value = payload.colorScheme === "dark";
1647
2186
  }
1648
2187
  );
1649
- onUnmounted5(unsubscribe);
2188
+ onUnmounted6(unsubscribe);
1650
2189
  return { colorScheme, isDark };
1651
2190
  }
1652
2191
 
1653
2192
  // src/composables/useBackHandler.ts
1654
- import { onMounted as onMounted2, onUnmounted as onUnmounted6 } from "@vue/runtime-core";
2193
+ import { onMounted as onMounted2, onUnmounted as onUnmounted7 } from "@vue/runtime-core";
1655
2194
  function useBackHandler(handler) {
1656
2195
  let unsubscribe = null;
1657
2196
  onMounted2(() => {
@@ -1659,10 +2198,1054 @@ function useBackHandler(handler) {
1659
2198
  handler();
1660
2199
  });
1661
2200
  });
1662
- onUnmounted6(() => {
2201
+ onUnmounted7(() => {
2202
+ unsubscribe?.();
2203
+ unsubscribe = null;
2204
+ });
2205
+ }
2206
+
2207
+ // src/composables/useSecureStorage.ts
2208
+ function useSecureStorage() {
2209
+ function getItem(key) {
2210
+ return NativeBridge.invokeNativeModule("SecureStorage", "get", [key]);
2211
+ }
2212
+ function setItem(key, value) {
2213
+ return NativeBridge.invokeNativeModule("SecureStorage", "set", [key, value]).then(() => void 0);
2214
+ }
2215
+ function removeItem(key) {
2216
+ return NativeBridge.invokeNativeModule("SecureStorage", "remove", [key]).then(() => void 0);
2217
+ }
2218
+ function clear() {
2219
+ return NativeBridge.invokeNativeModule("SecureStorage", "clear", []).then(() => void 0);
2220
+ }
2221
+ return { getItem, setItem, removeItem, clear };
2222
+ }
2223
+
2224
+ // src/composables/useI18n.ts
2225
+ import { ref as ref11, onMounted as onMounted3 } from "@vue/runtime-core";
2226
+ function useI18n() {
2227
+ const isRTL = ref11(false);
2228
+ const locale = ref11("en");
2229
+ onMounted3(async () => {
2230
+ try {
2231
+ const info = await NativeBridge.invokeNativeModule("DeviceInfo", "getDeviceInfo", []);
2232
+ locale.value = info?.locale || "en";
2233
+ isRTL.value = ["ar", "he", "fa", "ur"].some((l) => locale.value.startsWith(l));
2234
+ } catch {
2235
+ }
2236
+ });
2237
+ return { isRTL, locale };
2238
+ }
2239
+
2240
+ // src/composables/usePlatform.ts
2241
+ function usePlatform() {
2242
+ const platform = typeof __PLATFORM__ !== "undefined" ? __PLATFORM__ : "ios";
2243
+ const isIOS = platform === "ios";
2244
+ const isAndroid = platform === "android";
2245
+ return { platform, isIOS, isAndroid };
2246
+ }
2247
+
2248
+ // src/composables/useDimensions.ts
2249
+ import { ref as ref12, onMounted as onMounted4, onUnmounted as onUnmounted8 } from "@vue/runtime-core";
2250
+ function useDimensions() {
2251
+ const width = ref12(0);
2252
+ const height = ref12(0);
2253
+ const scale = ref12(1);
2254
+ onMounted4(async () => {
2255
+ try {
2256
+ const info = await NativeBridge.invokeNativeModule("DeviceInfo", "getInfo", []);
2257
+ width.value = info?.screenWidth || 0;
2258
+ height.value = info?.screenHeight || 0;
2259
+ scale.value = info?.scale || 1;
2260
+ } catch {
2261
+ }
2262
+ });
2263
+ const cleanup = NativeBridge.onGlobalEvent("dimensionsChange", (payload) => {
2264
+ if (payload.width != null) width.value = payload.width;
2265
+ if (payload.height != null) height.value = payload.height;
2266
+ if (payload.scale != null) scale.value = payload.scale;
2267
+ });
2268
+ onUnmounted8(cleanup);
2269
+ return { width, height, scale };
2270
+ }
2271
+
2272
+ // src/composables/useWebSocket.ts
2273
+ import { ref as ref13, onUnmounted as onUnmounted9 } from "@vue/runtime-core";
2274
+ var connectionCounter = 0;
2275
+ function useWebSocket(url, options = {}) {
2276
+ const {
2277
+ autoConnect = true,
2278
+ autoReconnect = false,
2279
+ maxReconnectAttempts = 3,
2280
+ reconnectInterval = 1e3
2281
+ } = options;
2282
+ const connectionId = `ws_${++connectionCounter}_${Date.now()}`;
2283
+ const status = ref13("CLOSED");
2284
+ const lastMessage = ref13(null);
2285
+ const error = ref13(null);
2286
+ let reconnectAttempts = 0;
2287
+ let reconnectTimer = null;
2288
+ const unsubscribers = [];
2289
+ unsubscribers.push(
2290
+ NativeBridge.onGlobalEvent("websocket:open", (payload) => {
2291
+ if (payload.connectionId !== connectionId) return;
2292
+ status.value = "OPEN";
2293
+ error.value = null;
2294
+ reconnectAttempts = 0;
2295
+ })
2296
+ );
2297
+ unsubscribers.push(
2298
+ NativeBridge.onGlobalEvent("websocket:message", (payload) => {
2299
+ if (payload.connectionId !== connectionId) return;
2300
+ lastMessage.value = payload.data;
2301
+ })
2302
+ );
2303
+ unsubscribers.push(
2304
+ NativeBridge.onGlobalEvent("websocket:close", (payload) => {
2305
+ if (payload.connectionId !== connectionId) return;
2306
+ status.value = "CLOSED";
2307
+ if (autoReconnect && reconnectAttempts < maxReconnectAttempts && payload.code !== 1e3) {
2308
+ reconnectAttempts++;
2309
+ reconnectTimer = setTimeout(() => {
2310
+ open();
2311
+ }, reconnectInterval);
2312
+ }
2313
+ })
2314
+ );
2315
+ unsubscribers.push(
2316
+ NativeBridge.onGlobalEvent("websocket:error", (payload) => {
2317
+ if (payload.connectionId !== connectionId) return;
2318
+ error.value = payload.message;
2319
+ })
2320
+ );
2321
+ function open() {
2322
+ if (status.value === "OPEN" || status.value === "CONNECTING") return;
2323
+ status.value = "CONNECTING";
2324
+ error.value = null;
2325
+ NativeBridge.invokeNativeModule("WebSocket", "connect", [url, connectionId]).catch((err) => {
2326
+ status.value = "CLOSED";
2327
+ error.value = err.message;
2328
+ });
2329
+ }
2330
+ function send(data) {
2331
+ if (status.value !== "OPEN") return;
2332
+ const message = typeof data === "string" ? data : JSON.stringify(data);
2333
+ NativeBridge.invokeNativeModule("WebSocket", "send", [connectionId, message]).catch((err) => {
2334
+ error.value = err.message;
2335
+ });
2336
+ }
2337
+ function close(code, reason) {
2338
+ if (status.value === "CLOSED" || status.value === "CLOSING") return;
2339
+ status.value = "CLOSING";
2340
+ if (reconnectTimer) {
2341
+ clearTimeout(reconnectTimer);
2342
+ reconnectTimer = null;
2343
+ }
2344
+ reconnectAttempts = maxReconnectAttempts;
2345
+ NativeBridge.invokeNativeModule("WebSocket", "close", [connectionId, code ?? 1e3, reason ?? ""]).catch(() => {
2346
+ status.value = "CLOSED";
2347
+ });
2348
+ }
2349
+ if (autoConnect) {
2350
+ open();
2351
+ }
2352
+ onUnmounted9(() => {
2353
+ if (reconnectTimer) {
2354
+ clearTimeout(reconnectTimer);
2355
+ }
2356
+ if (status.value === "OPEN" || status.value === "CONNECTING") {
2357
+ reconnectAttempts = maxReconnectAttempts;
2358
+ NativeBridge.invokeNativeModule("WebSocket", "close", [connectionId, 1e3, ""]).catch(() => {
2359
+ });
2360
+ }
2361
+ unsubscribers.forEach((unsub) => unsub());
2362
+ });
2363
+ return { status, lastMessage, error, send, close, open };
2364
+ }
2365
+
2366
+ // src/composables/useFileSystem.ts
2367
+ function useFileSystem() {
2368
+ function readFile(path, encoding) {
2369
+ return NativeBridge.invokeNativeModule("FileSystem", "readFile", [path, encoding ?? "utf8"]);
2370
+ }
2371
+ function writeFile(path, content, encoding) {
2372
+ return NativeBridge.invokeNativeModule("FileSystem", "writeFile", [path, content, encoding ?? "utf8"]).then(() => void 0);
2373
+ }
2374
+ function deleteFile(path) {
2375
+ return NativeBridge.invokeNativeModule("FileSystem", "deleteFile", [path]).then(() => void 0);
2376
+ }
2377
+ function exists(path) {
2378
+ return NativeBridge.invokeNativeModule("FileSystem", "exists", [path]);
2379
+ }
2380
+ function listDirectory(path) {
2381
+ return NativeBridge.invokeNativeModule("FileSystem", "listDirectory", [path]);
2382
+ }
2383
+ function downloadFile(url, destPath) {
2384
+ return NativeBridge.invokeNativeModule("FileSystem", "downloadFile", [url, destPath]);
2385
+ }
2386
+ function getDocumentsPath() {
2387
+ return NativeBridge.invokeNativeModule("FileSystem", "getDocumentsPath", []);
2388
+ }
2389
+ function getCachesPath() {
2390
+ return NativeBridge.invokeNativeModule("FileSystem", "getCachesPath", []);
2391
+ }
2392
+ function stat(path) {
2393
+ return NativeBridge.invokeNativeModule("FileSystem", "stat", [path]);
2394
+ }
2395
+ function mkdir(path) {
2396
+ return NativeBridge.invokeNativeModule("FileSystem", "mkdir", [path]).then(() => void 0);
2397
+ }
2398
+ function copyFile(srcPath, destPath) {
2399
+ return NativeBridge.invokeNativeModule("FileSystem", "copyFile", [srcPath, destPath]).then(() => void 0);
2400
+ }
2401
+ function moveFile(srcPath, destPath) {
2402
+ return NativeBridge.invokeNativeModule("FileSystem", "moveFile", [srcPath, destPath]).then(() => void 0);
2403
+ }
2404
+ return {
2405
+ readFile,
2406
+ writeFile,
2407
+ deleteFile,
2408
+ exists,
2409
+ listDirectory,
2410
+ downloadFile,
2411
+ getDocumentsPath,
2412
+ getCachesPath,
2413
+ stat,
2414
+ mkdir,
2415
+ copyFile,
2416
+ moveFile
2417
+ };
2418
+ }
2419
+
2420
+ // src/composables/useSensors.ts
2421
+ import { ref as ref14, onUnmounted as onUnmounted10 } from "@vue/runtime-core";
2422
+ function useAccelerometer(options = {}) {
2423
+ const x = ref14(0);
2424
+ const y = ref14(0);
2425
+ const z = ref14(0);
2426
+ const isAvailable = ref14(false);
2427
+ let running = false;
2428
+ let unsubscribe = null;
2429
+ NativeBridge.invokeNativeModule("Sensors", "isAvailable", ["accelerometer"]).then((result) => {
2430
+ isAvailable.value = result.available;
2431
+ }).catch(() => {
2432
+ });
2433
+ function start() {
2434
+ if (running) return;
2435
+ running = true;
2436
+ unsubscribe = NativeBridge.onGlobalEvent("sensor:accelerometer", (payload) => {
2437
+ x.value = payload.x;
2438
+ y.value = payload.y;
2439
+ z.value = payload.z;
2440
+ });
2441
+ NativeBridge.invokeNativeModule("Sensors", "startAccelerometer", [
2442
+ options.interval ?? 100
2443
+ ]).catch(() => {
2444
+ });
2445
+ }
2446
+ function stop() {
2447
+ if (!running) return;
2448
+ running = false;
1663
2449
  unsubscribe?.();
1664
2450
  unsubscribe = null;
2451
+ NativeBridge.invokeNativeModule("Sensors", "stopAccelerometer").catch(() => {
2452
+ });
2453
+ }
2454
+ onUnmounted10(() => {
2455
+ stop();
2456
+ });
2457
+ return { x, y, z, isAvailable, start, stop };
2458
+ }
2459
+ function useGyroscope(options = {}) {
2460
+ const x = ref14(0);
2461
+ const y = ref14(0);
2462
+ const z = ref14(0);
2463
+ const isAvailable = ref14(false);
2464
+ let running = false;
2465
+ let unsubscribe = null;
2466
+ NativeBridge.invokeNativeModule("Sensors", "isAvailable", ["gyroscope"]).then((result) => {
2467
+ isAvailable.value = result.available;
2468
+ }).catch(() => {
1665
2469
  });
2470
+ function start() {
2471
+ if (running) return;
2472
+ running = true;
2473
+ unsubscribe = NativeBridge.onGlobalEvent("sensor:gyroscope", (payload) => {
2474
+ x.value = payload.x;
2475
+ y.value = payload.y;
2476
+ z.value = payload.z;
2477
+ });
2478
+ NativeBridge.invokeNativeModule("Sensors", "startGyroscope", [
2479
+ options.interval ?? 100
2480
+ ]).catch(() => {
2481
+ });
2482
+ }
2483
+ function stop() {
2484
+ if (!running) return;
2485
+ running = false;
2486
+ unsubscribe?.();
2487
+ unsubscribe = null;
2488
+ NativeBridge.invokeNativeModule("Sensors", "stopGyroscope").catch(() => {
2489
+ });
2490
+ }
2491
+ onUnmounted10(() => {
2492
+ stop();
2493
+ });
2494
+ return { x, y, z, isAvailable, start, stop };
2495
+ }
2496
+
2497
+ // src/composables/useAudio.ts
2498
+ import { ref as ref15, onUnmounted as onUnmounted11 } from "@vue/runtime-core";
2499
+ function useAudio() {
2500
+ const duration = ref15(0);
2501
+ const position = ref15(0);
2502
+ const isPlaying = ref15(false);
2503
+ const isRecording = ref15(false);
2504
+ const error = ref15(null);
2505
+ const unsubProgress = NativeBridge.onGlobalEvent("audio:progress", (payload) => {
2506
+ position.value = payload.currentTime ?? 0;
2507
+ duration.value = payload.duration ?? 0;
2508
+ });
2509
+ const unsubComplete = NativeBridge.onGlobalEvent("audio:complete", () => {
2510
+ isPlaying.value = false;
2511
+ position.value = 0;
2512
+ });
2513
+ const unsubError = NativeBridge.onGlobalEvent("audio:error", (payload) => {
2514
+ error.value = payload.message ?? "Unknown audio error";
2515
+ isPlaying.value = false;
2516
+ });
2517
+ onUnmounted11(() => {
2518
+ unsubProgress();
2519
+ unsubComplete();
2520
+ unsubError();
2521
+ NativeBridge.invokeNativeModule("Audio", "stop", []).catch(() => {
2522
+ });
2523
+ if (isRecording.value) {
2524
+ NativeBridge.invokeNativeModule("Audio", "stopRecording", []).catch(() => {
2525
+ });
2526
+ }
2527
+ });
2528
+ async function play(uri, options = {}) {
2529
+ error.value = null;
2530
+ const result = await NativeBridge.invokeNativeModule("Audio", "play", [uri, options]);
2531
+ if (result?.duration != null) {
2532
+ duration.value = result.duration;
2533
+ }
2534
+ isPlaying.value = true;
2535
+ }
2536
+ async function pause() {
2537
+ await NativeBridge.invokeNativeModule("Audio", "pause", []);
2538
+ isPlaying.value = false;
2539
+ }
2540
+ async function resume() {
2541
+ await NativeBridge.invokeNativeModule("Audio", "resume", []);
2542
+ isPlaying.value = true;
2543
+ }
2544
+ async function stop() {
2545
+ await NativeBridge.invokeNativeModule("Audio", "stop", []);
2546
+ isPlaying.value = false;
2547
+ position.value = 0;
2548
+ duration.value = 0;
2549
+ }
2550
+ async function seek(positionSec) {
2551
+ await NativeBridge.invokeNativeModule("Audio", "seek", [positionSec]);
2552
+ }
2553
+ async function setVolume(volume) {
2554
+ await NativeBridge.invokeNativeModule("Audio", "setVolume", [volume]);
2555
+ }
2556
+ async function startRecording(options = {}) {
2557
+ error.value = null;
2558
+ const result = await NativeBridge.invokeNativeModule("Audio", "startRecording", [options]);
2559
+ isRecording.value = true;
2560
+ return result?.uri ?? "";
2561
+ }
2562
+ async function stopRecording() {
2563
+ const result = await NativeBridge.invokeNativeModule("Audio", "stopRecording", []);
2564
+ isRecording.value = false;
2565
+ return { uri: result?.uri ?? "", duration: result?.duration ?? 0 };
2566
+ }
2567
+ async function pauseRecording() {
2568
+ await NativeBridge.invokeNativeModule("Audio", "pauseRecording", []);
2569
+ }
2570
+ async function resumeRecording() {
2571
+ await NativeBridge.invokeNativeModule("Audio", "resumeRecording", []);
2572
+ }
2573
+ return {
2574
+ // Playback
2575
+ play,
2576
+ pause,
2577
+ resume,
2578
+ stop,
2579
+ seek,
2580
+ setVolume,
2581
+ // Recording
2582
+ startRecording,
2583
+ stopRecording,
2584
+ pauseRecording,
2585
+ resumeRecording,
2586
+ // Reactive state
2587
+ duration,
2588
+ position,
2589
+ isPlaying,
2590
+ isRecording,
2591
+ error
2592
+ };
2593
+ }
2594
+
2595
+ // src/composables/useDatabase.ts
2596
+ import { ref as ref16, onUnmounted as onUnmounted12 } from "@vue/runtime-core";
2597
+ function useDatabase(name = "default") {
2598
+ const isOpen = ref16(false);
2599
+ let opened = false;
2600
+ async function ensureOpen() {
2601
+ if (opened) return;
2602
+ await NativeBridge.invokeNativeModule("Database", "open", [name]);
2603
+ opened = true;
2604
+ isOpen.value = true;
2605
+ }
2606
+ async function execute(sql, params) {
2607
+ await ensureOpen();
2608
+ return NativeBridge.invokeNativeModule("Database", "execute", [name, sql, params ?? []]);
2609
+ }
2610
+ async function query(sql, params) {
2611
+ await ensureOpen();
2612
+ return NativeBridge.invokeNativeModule("Database", "query", [name, sql, params ?? []]);
2613
+ }
2614
+ async function transaction(callback) {
2615
+ await ensureOpen();
2616
+ const statements = [];
2617
+ const ctx = {
2618
+ execute: async (sql, params) => {
2619
+ statements.push({ sql, params: params ?? [] });
2620
+ return { rowsAffected: 0 };
2621
+ },
2622
+ query: async (sql, params) => {
2623
+ if (statements.length > 0) {
2624
+ await NativeBridge.invokeNativeModule("Database", "executeTransaction", [name, statements.splice(0)]);
2625
+ }
2626
+ return NativeBridge.invokeNativeModule("Database", "query", [name, sql, params ?? []]);
2627
+ }
2628
+ };
2629
+ await callback(ctx);
2630
+ if (statements.length > 0) {
2631
+ await NativeBridge.invokeNativeModule("Database", "executeTransaction", [name, statements]);
2632
+ }
2633
+ }
2634
+ async function close() {
2635
+ if (!opened) return;
2636
+ await NativeBridge.invokeNativeModule("Database", "close", [name]);
2637
+ opened = false;
2638
+ isOpen.value = false;
2639
+ }
2640
+ onUnmounted12(() => {
2641
+ if (opened) {
2642
+ NativeBridge.invokeNativeModule("Database", "close", [name]).catch(() => {
2643
+ });
2644
+ opened = false;
2645
+ isOpen.value = false;
2646
+ }
2647
+ });
2648
+ return { execute, query, transaction, close, isOpen };
2649
+ }
2650
+
2651
+ // src/composables/usePerformance.ts
2652
+ import { ref as ref17, onUnmounted as onUnmounted13 } from "@vue/runtime-core";
2653
+ function usePerformance() {
2654
+ const isProfiling = ref17(false);
2655
+ const fps = ref17(0);
2656
+ const memoryMB = ref17(0);
2657
+ const bridgeOps = ref17(0);
2658
+ let unsubscribe = null;
2659
+ function handleMetrics(payload) {
2660
+ fps.value = payload.fps ?? 0;
2661
+ memoryMB.value = payload.memoryMB ?? 0;
2662
+ bridgeOps.value = payload.bridgeOps ?? 0;
2663
+ }
2664
+ async function startProfiling() {
2665
+ if (isProfiling.value) return;
2666
+ unsubscribe = NativeBridge.onGlobalEvent("perf:metrics", handleMetrics);
2667
+ await NativeBridge.invokeNativeModule("Performance", "startProfiling", []);
2668
+ isProfiling.value = true;
2669
+ }
2670
+ async function stopProfiling() {
2671
+ if (!isProfiling.value) return;
2672
+ await NativeBridge.invokeNativeModule("Performance", "stopProfiling", []);
2673
+ isProfiling.value = false;
2674
+ if (unsubscribe) {
2675
+ unsubscribe();
2676
+ unsubscribe = null;
2677
+ }
2678
+ }
2679
+ async function getMetrics() {
2680
+ return NativeBridge.invokeNativeModule("Performance", "getMetrics", []);
2681
+ }
2682
+ onUnmounted13(() => {
2683
+ if (isProfiling.value) {
2684
+ NativeBridge.invokeNativeModule("Performance", "stopProfiling", []).catch(() => {
2685
+ });
2686
+ isProfiling.value = false;
2687
+ }
2688
+ if (unsubscribe) {
2689
+ unsubscribe();
2690
+ unsubscribe = null;
2691
+ }
2692
+ });
2693
+ return {
2694
+ startProfiling,
2695
+ stopProfiling,
2696
+ getMetrics,
2697
+ isProfiling,
2698
+ fps,
2699
+ memoryMB,
2700
+ bridgeOps
2701
+ };
2702
+ }
2703
+
2704
+ // src/composables/useSharedElementTransition.ts
2705
+ import { ref as ref18, onUnmounted as onUnmounted14 } from "@vue/runtime-core";
2706
+ var sharedElementRegistry = /* @__PURE__ */ new Map();
2707
+ function useSharedElementTransition(elementId) {
2708
+ const viewId = ref18(null);
2709
+ function register(nativeViewId) {
2710
+ viewId.value = nativeViewId;
2711
+ sharedElementRegistry.set(elementId, nativeViewId);
2712
+ }
2713
+ function unregister() {
2714
+ viewId.value = null;
2715
+ sharedElementRegistry.delete(elementId);
2716
+ }
2717
+ onUnmounted14(() => {
2718
+ unregister();
2719
+ });
2720
+ return {
2721
+ id: elementId,
2722
+ viewId,
2723
+ register,
2724
+ unregister
2725
+ };
2726
+ }
2727
+ async function measureViewFrame(nativeViewId) {
2728
+ return NativeBridge.invokeNativeModule("Animation", "measureView", [nativeViewId]);
2729
+ }
2730
+ function getSharedElementViewId(elementId) {
2731
+ return sharedElementRegistry.get(elementId);
2732
+ }
2733
+ function getRegisteredSharedElements() {
2734
+ return Array.from(sharedElementRegistry.keys());
2735
+ }
2736
+ function clearSharedElementRegistry() {
2737
+ sharedElementRegistry.clear();
2738
+ }
2739
+
2740
+ // src/composables/useIAP.ts
2741
+ import { ref as ref19, onUnmounted as onUnmounted15 } from "@vue/runtime-core";
2742
+ function useIAP() {
2743
+ const products = ref19([]);
2744
+ const isReady = ref19(false);
2745
+ const error = ref19(null);
2746
+ const cleanups = [];
2747
+ const unsubscribe = NativeBridge.onGlobalEvent("iap:transactionUpdate", (payload) => {
2748
+ if (payload.state === "failed" && payload.error) {
2749
+ error.value = payload.error;
2750
+ }
2751
+ });
2752
+ cleanups.push(unsubscribe);
2753
+ NativeBridge.invokeNativeModule("IAP", "initialize").then(() => {
2754
+ isReady.value = true;
2755
+ }).catch((err) => {
2756
+ error.value = String(err);
2757
+ });
2758
+ async function getProducts(skus) {
2759
+ error.value = null;
2760
+ try {
2761
+ const result = await NativeBridge.invokeNativeModule("IAP", "getProducts", [skus]);
2762
+ const productList = result;
2763
+ products.value = productList;
2764
+ return productList;
2765
+ } catch (err) {
2766
+ error.value = String(err);
2767
+ return [];
2768
+ }
2769
+ }
2770
+ async function purchase(sku) {
2771
+ error.value = null;
2772
+ try {
2773
+ return await NativeBridge.invokeNativeModule("IAP", "purchase", [sku]);
2774
+ } catch (err) {
2775
+ error.value = String(err);
2776
+ return null;
2777
+ }
2778
+ }
2779
+ async function restorePurchases() {
2780
+ error.value = null;
2781
+ try {
2782
+ return await NativeBridge.invokeNativeModule("IAP", "restorePurchases");
2783
+ } catch (err) {
2784
+ error.value = String(err);
2785
+ return [];
2786
+ }
2787
+ }
2788
+ async function getActiveSubscriptions() {
2789
+ error.value = null;
2790
+ try {
2791
+ return await NativeBridge.invokeNativeModule("IAP", "getActiveSubscriptions");
2792
+ } catch (err) {
2793
+ error.value = String(err);
2794
+ return [];
2795
+ }
2796
+ }
2797
+ function onTransactionUpdate(callback) {
2798
+ const unsub = NativeBridge.onGlobalEvent("iap:transactionUpdate", callback);
2799
+ cleanups.push(unsub);
2800
+ return unsub;
2801
+ }
2802
+ onUnmounted15(() => {
2803
+ cleanups.forEach((fn) => fn());
2804
+ cleanups.length = 0;
2805
+ });
2806
+ return {
2807
+ products,
2808
+ isReady,
2809
+ error,
2810
+ getProducts,
2811
+ purchase,
2812
+ restorePurchases,
2813
+ getActiveSubscriptions,
2814
+ onTransactionUpdate
2815
+ };
2816
+ }
2817
+
2818
+ // src/composables/useAppleSignIn.ts
2819
+ import { ref as ref20, onUnmounted as onUnmounted16 } from "@vue/runtime-core";
2820
+ function useAppleSignIn() {
2821
+ const user = ref20(null);
2822
+ const isAuthenticated = ref20(false);
2823
+ const error = ref20(null);
2824
+ const cleanups = [];
2825
+ const unsubscribe = NativeBridge.onGlobalEvent("auth:appleCredentialRevoked", () => {
2826
+ user.value = null;
2827
+ isAuthenticated.value = false;
2828
+ });
2829
+ cleanups.push(unsubscribe);
2830
+ NativeBridge.invokeNativeModule("SocialAuth", "getCurrentUser", ["apple"]).then((result) => {
2831
+ if (result && result.userId) {
2832
+ user.value = { ...result, provider: "apple" };
2833
+ isAuthenticated.value = true;
2834
+ }
2835
+ }).catch(() => {
2836
+ });
2837
+ async function signIn() {
2838
+ error.value = null;
2839
+ try {
2840
+ const result = await NativeBridge.invokeNativeModule("SocialAuth", "signInWithApple");
2841
+ const socialUser = { ...result, provider: "apple" };
2842
+ user.value = socialUser;
2843
+ isAuthenticated.value = true;
2844
+ return { success: true, user: socialUser };
2845
+ } catch (err) {
2846
+ const message = String(err);
2847
+ error.value = message;
2848
+ return { success: false, error: message };
2849
+ }
2850
+ }
2851
+ async function signOut() {
2852
+ error.value = null;
2853
+ try {
2854
+ await NativeBridge.invokeNativeModule("SocialAuth", "signOut", ["apple"]);
2855
+ user.value = null;
2856
+ isAuthenticated.value = false;
2857
+ } catch (err) {
2858
+ error.value = String(err);
2859
+ }
2860
+ }
2861
+ onUnmounted16(() => {
2862
+ cleanups.forEach((fn) => fn());
2863
+ cleanups.length = 0;
2864
+ });
2865
+ return { signIn, signOut, user, isAuthenticated, error };
2866
+ }
2867
+
2868
+ // src/composables/useGoogleSignIn.ts
2869
+ import { ref as ref21, onUnmounted as onUnmounted17 } from "@vue/runtime-core";
2870
+ function useGoogleSignIn(clientId) {
2871
+ const user = ref21(null);
2872
+ const isAuthenticated = ref21(false);
2873
+ const error = ref21(null);
2874
+ const cleanups = [];
2875
+ NativeBridge.invokeNativeModule("SocialAuth", "getCurrentUser", ["google"]).then((result) => {
2876
+ if (result && result.userId) {
2877
+ user.value = { ...result, provider: "google" };
2878
+ isAuthenticated.value = true;
2879
+ }
2880
+ }).catch(() => {
2881
+ });
2882
+ async function signIn() {
2883
+ error.value = null;
2884
+ try {
2885
+ const result = await NativeBridge.invokeNativeModule("SocialAuth", "signInWithGoogle", [clientId]);
2886
+ const socialUser = { ...result, provider: "google" };
2887
+ user.value = socialUser;
2888
+ isAuthenticated.value = true;
2889
+ return { success: true, user: socialUser };
2890
+ } catch (err) {
2891
+ const message = String(err);
2892
+ error.value = message;
2893
+ return { success: false, error: message };
2894
+ }
2895
+ }
2896
+ async function signOut() {
2897
+ error.value = null;
2898
+ try {
2899
+ await NativeBridge.invokeNativeModule("SocialAuth", "signOut", ["google"]);
2900
+ user.value = null;
2901
+ isAuthenticated.value = false;
2902
+ } catch (err) {
2903
+ error.value = String(err);
2904
+ }
2905
+ }
2906
+ onUnmounted17(() => {
2907
+ cleanups.forEach((fn) => fn());
2908
+ cleanups.length = 0;
2909
+ });
2910
+ return { signIn, signOut, user, isAuthenticated, error };
2911
+ }
2912
+
2913
+ // src/composables/useBackgroundTask.ts
2914
+ import { ref as ref22, onUnmounted as onUnmounted18 } from "@vue/runtime-core";
2915
+ function useBackgroundTask() {
2916
+ const taskHandlers = /* @__PURE__ */ new Map();
2917
+ const defaultHandler = ref22(null);
2918
+ const unsubscribe = NativeBridge.onGlobalEvent("background:taskExecute", (payload) => {
2919
+ const handler = taskHandlers.get(payload.taskId) || defaultHandler.value;
2920
+ if (handler) {
2921
+ handler(payload.taskId);
2922
+ }
2923
+ });
2924
+ onUnmounted18(unsubscribe);
2925
+ function registerTask(taskId) {
2926
+ return NativeBridge.invokeNativeModule("BackgroundTask", "registerTask", [taskId]).then(() => void 0);
2927
+ }
2928
+ function scheduleTask(taskId, options = {}) {
2929
+ const type = options.type ?? "refresh";
2930
+ return NativeBridge.invokeNativeModule("BackgroundTask", "scheduleTask", [taskId, type, {
2931
+ earliestBeginDate: options.earliestBeginDate,
2932
+ requiresNetworkConnectivity: options.requiresNetworkConnectivity,
2933
+ requiresExternalPower: options.requiresExternalPower,
2934
+ interval: options.interval
2935
+ }]).then(() => void 0);
2936
+ }
2937
+ function cancelTask(taskId) {
2938
+ return NativeBridge.invokeNativeModule("BackgroundTask", "cancelTask", [taskId]).then(() => void 0);
2939
+ }
2940
+ function cancelAllTasks() {
2941
+ return NativeBridge.invokeNativeModule("BackgroundTask", "cancelAllTasks", []).then(() => void 0);
2942
+ }
2943
+ function completeTask(taskId, success = true) {
2944
+ return NativeBridge.invokeNativeModule("BackgroundTask", "completeTask", [taskId, success]).then(() => void 0);
2945
+ }
2946
+ function onTaskExecute(handler, taskId) {
2947
+ if (taskId) {
2948
+ taskHandlers.set(taskId, handler);
2949
+ return () => {
2950
+ taskHandlers.delete(taskId);
2951
+ };
2952
+ } else {
2953
+ defaultHandler.value = handler;
2954
+ return () => {
2955
+ defaultHandler.value = null;
2956
+ };
2957
+ }
2958
+ }
2959
+ return { registerTask, scheduleTask, cancelTask, cancelAllTasks, completeTask, onTaskExecute };
2960
+ }
2961
+
2962
+ // src/composables/useOTAUpdate.ts
2963
+ import { ref as ref23, onUnmounted as onUnmounted19 } from "@vue/runtime-core";
2964
+ function useOTAUpdate(serverUrl) {
2965
+ const currentVersion = ref23("embedded");
2966
+ const availableVersion = ref23(null);
2967
+ const downloadProgress = ref23(0);
2968
+ const isChecking = ref23(false);
2969
+ const isDownloading = ref23(false);
2970
+ const status = ref23("idle");
2971
+ const error = ref23(null);
2972
+ let lastUpdateInfo = null;
2973
+ const unsubscribe = NativeBridge.onGlobalEvent("ota:downloadProgress", (payload) => {
2974
+ downloadProgress.value = payload.progress;
2975
+ });
2976
+ onUnmounted19(unsubscribe);
2977
+ NativeBridge.invokeNativeModule("OTA", "getCurrentVersion", []).then((info) => {
2978
+ currentVersion.value = info.version;
2979
+ }).catch(() => {
2980
+ });
2981
+ async function checkForUpdate() {
2982
+ isChecking.value = true;
2983
+ status.value = "checking";
2984
+ error.value = null;
2985
+ try {
2986
+ const info = await NativeBridge.invokeNativeModule("OTA", "checkForUpdate", [serverUrl]);
2987
+ lastUpdateInfo = info;
2988
+ if (info.updateAvailable) {
2989
+ availableVersion.value = info.version;
2990
+ } else {
2991
+ availableVersion.value = null;
2992
+ }
2993
+ status.value = info.updateAvailable ? "idle" : "idle";
2994
+ return info;
2995
+ } catch (err) {
2996
+ error.value = err?.message || String(err);
2997
+ status.value = "error";
2998
+ throw err;
2999
+ } finally {
3000
+ isChecking.value = false;
3001
+ }
3002
+ }
3003
+ async function downloadUpdate(url, hash) {
3004
+ const downloadUrl = url || lastUpdateInfo?.downloadUrl;
3005
+ const expectedHash = hash || lastUpdateInfo?.hash;
3006
+ if (!downloadUrl) {
3007
+ const msg = "No download URL. Call checkForUpdate() first or provide a URL.";
3008
+ error.value = msg;
3009
+ status.value = "error";
3010
+ throw new Error(msg);
3011
+ }
3012
+ isDownloading.value = true;
3013
+ downloadProgress.value = 0;
3014
+ status.value = "downloading";
3015
+ error.value = null;
3016
+ try {
3017
+ await NativeBridge.invokeNativeModule("OTA", "downloadUpdate", [downloadUrl, expectedHash || ""]);
3018
+ status.value = "ready";
3019
+ } catch (err) {
3020
+ error.value = err?.message || String(err);
3021
+ status.value = "error";
3022
+ throw err;
3023
+ } finally {
3024
+ isDownloading.value = false;
3025
+ }
3026
+ }
3027
+ async function applyUpdate() {
3028
+ error.value = null;
3029
+ try {
3030
+ await NativeBridge.invokeNativeModule("OTA", "applyUpdate", []);
3031
+ const info = await NativeBridge.invokeNativeModule("OTA", "getCurrentVersion", []);
3032
+ currentVersion.value = info.version;
3033
+ availableVersion.value = null;
3034
+ status.value = "idle";
3035
+ } catch (err) {
3036
+ error.value = err?.message || String(err);
3037
+ status.value = "error";
3038
+ throw err;
3039
+ }
3040
+ }
3041
+ async function rollback() {
3042
+ error.value = null;
3043
+ try {
3044
+ await NativeBridge.invokeNativeModule("OTA", "rollback", []);
3045
+ const info = await NativeBridge.invokeNativeModule("OTA", "getCurrentVersion", []);
3046
+ currentVersion.value = info.version;
3047
+ status.value = "idle";
3048
+ } catch (err) {
3049
+ error.value = err?.message || String(err);
3050
+ status.value = "error";
3051
+ throw err;
3052
+ }
3053
+ }
3054
+ async function getCurrentVersion() {
3055
+ const info = await NativeBridge.invokeNativeModule("OTA", "getCurrentVersion", []);
3056
+ currentVersion.value = info.version;
3057
+ return info;
3058
+ }
3059
+ return {
3060
+ checkForUpdate,
3061
+ downloadUpdate,
3062
+ applyUpdate,
3063
+ rollback,
3064
+ getCurrentVersion,
3065
+ currentVersion,
3066
+ availableVersion,
3067
+ downloadProgress,
3068
+ isChecking,
3069
+ isDownloading,
3070
+ status,
3071
+ error
3072
+ };
3073
+ }
3074
+
3075
+ // src/composables/useBluetooth.ts
3076
+ import { ref as ref24, onUnmounted as onUnmounted20 } from "@vue/runtime-core";
3077
+ function useBluetooth() {
3078
+ const devices = ref24([]);
3079
+ const connectedDevice = ref24(null);
3080
+ const isScanning = ref24(false);
3081
+ const isAvailable = ref24(false);
3082
+ const error = ref24(null);
3083
+ const cleanups = [];
3084
+ NativeBridge.invokeNativeModule("Bluetooth", "getState").then((state) => {
3085
+ isAvailable.value = state === "poweredOn";
3086
+ }).catch(() => {
3087
+ isAvailable.value = false;
3088
+ });
3089
+ const unsubState = NativeBridge.onGlobalEvent("ble:stateChanged", (payload) => {
3090
+ isAvailable.value = payload.state === "poweredOn";
3091
+ });
3092
+ cleanups.push(unsubState);
3093
+ const unsubFound = NativeBridge.onGlobalEvent("ble:deviceFound", (payload) => {
3094
+ const existing = devices.value.findIndex((d) => d.id === payload.id);
3095
+ if (existing >= 0) {
3096
+ devices.value[existing] = payload;
3097
+ } else {
3098
+ devices.value = [...devices.value, payload];
3099
+ }
3100
+ });
3101
+ cleanups.push(unsubFound);
3102
+ const unsubConnected = NativeBridge.onGlobalEvent("ble:connected", (payload) => {
3103
+ connectedDevice.value = payload;
3104
+ });
3105
+ cleanups.push(unsubConnected);
3106
+ const unsubDisconnected = NativeBridge.onGlobalEvent("ble:disconnected", () => {
3107
+ connectedDevice.value = null;
3108
+ });
3109
+ cleanups.push(unsubDisconnected);
3110
+ const unsubError = NativeBridge.onGlobalEvent("ble:error", (payload) => {
3111
+ error.value = payload.message;
3112
+ });
3113
+ cleanups.push(unsubError);
3114
+ async function scan(serviceUUIDs) {
3115
+ devices.value = [];
3116
+ isScanning.value = true;
3117
+ error.value = null;
3118
+ try {
3119
+ await NativeBridge.invokeNativeModule("Bluetooth", "startScan", [serviceUUIDs]);
3120
+ } catch (e) {
3121
+ error.value = e?.message || String(e);
3122
+ isScanning.value = false;
3123
+ }
3124
+ }
3125
+ async function stopScan() {
3126
+ await NativeBridge.invokeNativeModule("Bluetooth", "stopScan");
3127
+ isScanning.value = false;
3128
+ }
3129
+ async function connect(deviceId) {
3130
+ error.value = null;
3131
+ const result = await NativeBridge.invokeNativeModule("Bluetooth", "connect", [deviceId]);
3132
+ return result;
3133
+ }
3134
+ async function disconnect(deviceId) {
3135
+ await NativeBridge.invokeNativeModule("Bluetooth", "disconnect", [deviceId]);
3136
+ connectedDevice.value = null;
3137
+ }
3138
+ async function read(deviceId, serviceUUID, charUUID) {
3139
+ return NativeBridge.invokeNativeModule("Bluetooth", "readCharacteristic", [deviceId, serviceUUID, charUUID]);
3140
+ }
3141
+ async function write(deviceId, serviceUUID, charUUID, data) {
3142
+ return NativeBridge.invokeNativeModule("Bluetooth", "writeCharacteristic", [deviceId, serviceUUID, charUUID, data]);
3143
+ }
3144
+ async function subscribe(deviceId, serviceUUID, charUUID, callback) {
3145
+ await NativeBridge.invokeNativeModule("Bluetooth", "subscribeToCharacteristic", [deviceId, serviceUUID, charUUID]);
3146
+ const unsubscribe = NativeBridge.onGlobalEvent("ble:characteristicChanged", (payload) => {
3147
+ if (payload.deviceId === deviceId && payload.serviceUUID === serviceUUID && payload.characteristicUUID === charUUID) {
3148
+ callback(payload);
3149
+ }
3150
+ });
3151
+ cleanups.push(unsubscribe);
3152
+ return async () => {
3153
+ unsubscribe();
3154
+ await NativeBridge.invokeNativeModule("Bluetooth", "unsubscribeFromCharacteristic", [
3155
+ deviceId,
3156
+ serviceUUID,
3157
+ charUUID
3158
+ ]);
3159
+ };
3160
+ }
3161
+ onUnmounted20(() => {
3162
+ if (isScanning.value) {
3163
+ NativeBridge.invokeNativeModule("Bluetooth", "stopScan").catch(() => {
3164
+ });
3165
+ }
3166
+ cleanups.forEach((fn) => fn());
3167
+ cleanups.length = 0;
3168
+ });
3169
+ return {
3170
+ scan,
3171
+ stopScan,
3172
+ connect,
3173
+ disconnect,
3174
+ read,
3175
+ write,
3176
+ subscribe,
3177
+ devices,
3178
+ connectedDevice,
3179
+ isScanning,
3180
+ isAvailable,
3181
+ error
3182
+ };
3183
+ }
3184
+
3185
+ // src/composables/useCalendar.ts
3186
+ import { ref as ref25 } from "@vue/runtime-core";
3187
+ function useCalendar() {
3188
+ const hasAccess = ref25(false);
3189
+ const error = ref25(null);
3190
+ async function requestAccess() {
3191
+ try {
3192
+ const result = await NativeBridge.invokeNativeModule("Calendar", "requestAccess");
3193
+ hasAccess.value = result.granted;
3194
+ return result.granted;
3195
+ } catch (e) {
3196
+ error.value = e?.message || String(e);
3197
+ return false;
3198
+ }
3199
+ }
3200
+ async function getEvents(startDate, endDate) {
3201
+ return NativeBridge.invokeNativeModule("Calendar", "getEvents", [startDate, endDate]);
3202
+ }
3203
+ async function createEvent(options) {
3204
+ return NativeBridge.invokeNativeModule("Calendar", "createEvent", [
3205
+ options.title,
3206
+ options.startDate,
3207
+ options.endDate,
3208
+ options.notes,
3209
+ options.calendarId
3210
+ ]);
3211
+ }
3212
+ async function deleteEvent(eventId) {
3213
+ return NativeBridge.invokeNativeModule("Calendar", "deleteEvent", [eventId]);
3214
+ }
3215
+ async function getCalendars() {
3216
+ return NativeBridge.invokeNativeModule("Calendar", "getCalendars");
3217
+ }
3218
+ return { requestAccess, getEvents, createEvent, deleteEvent, getCalendars, hasAccess, error };
3219
+ }
3220
+
3221
+ // src/composables/useContacts.ts
3222
+ import { ref as ref26 } from "@vue/runtime-core";
3223
+ function useContacts() {
3224
+ const hasAccess = ref26(false);
3225
+ const error = ref26(null);
3226
+ async function requestAccess() {
3227
+ try {
3228
+ const result = await NativeBridge.invokeNativeModule("Contacts", "requestAccess");
3229
+ hasAccess.value = result.granted;
3230
+ return result.granted;
3231
+ } catch (e) {
3232
+ error.value = e?.message || String(e);
3233
+ return false;
3234
+ }
3235
+ }
3236
+ async function getContacts(query) {
3237
+ return NativeBridge.invokeNativeModule("Contacts", "getContacts", [query]);
3238
+ }
3239
+ async function getContact(id) {
3240
+ return NativeBridge.invokeNativeModule("Contacts", "getContact", [id]);
3241
+ }
3242
+ async function createContact(data) {
3243
+ return NativeBridge.invokeNativeModule("Contacts", "createContact", [data]);
3244
+ }
3245
+ async function deleteContact(id) {
3246
+ return NativeBridge.invokeNativeModule("Contacts", "deleteContact", [id]);
3247
+ }
3248
+ return { requestAccess, getContacts, getContact, createContact, deleteContact, hasAccess, error };
1666
3249
  }
1667
3250
 
1668
3251
  // src/index.ts
@@ -1688,6 +3271,15 @@ function createApp(rootComponent, rootProps) {
1688
3271
  app.component("VPicker", VPicker);
1689
3272
  app.component("VSegmentedControl", VSegmentedControl);
1690
3273
  app.component("VActionSheet", VActionSheet);
3274
+ app.component("VRefreshControl", VRefreshControl);
3275
+ app.component("VPressable", VPressable);
3276
+ app.component("VSectionList", VSectionList);
3277
+ app.component("VCheckbox", VCheckbox);
3278
+ app.component("VRadio", VRadio);
3279
+ app.component("VDropdown", VDropdown);
3280
+ app.component("VVideo", VVideo);
3281
+ app.component("ErrorBoundary", ErrorBoundary);
3282
+ app.component("VErrorBoundary", ErrorBoundary);
1691
3283
  app.directive("show", vShow);
1692
3284
  app.config.errorHandler = (err, instance, info) => {
1693
3285
  const error = err instanceof Error ? err : new Error(String(err));
@@ -1705,7 +3297,7 @@ function createApp(rootComponent, rootProps) {
1705
3297
  }
1706
3298
  };
1707
3299
  if (typeof __DEV__ !== "undefined" && __DEV__) {
1708
- app.config.warnHandler = (msg, instance, trace) => {
3300
+ app.config.warnHandler = (msg, instance, _trace) => {
1709
3301
  const componentName = instance?.$options?.name || instance?.$.type?.name || "Anonymous";
1710
3302
  console.warn(`[VueNative] Warning in ${componentName}: ${msg}`);
1711
3303
  };
@@ -1722,52 +3314,84 @@ function createApp(rootComponent, rootProps) {
1722
3314
  return app;
1723
3315
  }
1724
3316
  export {
3317
+ ErrorBoundary,
1725
3318
  NativeBridge,
1726
3319
  VActionSheet,
1727
3320
  VActivityIndicator,
1728
3321
  VAlertDialog,
1729
3322
  VButton,
3323
+ VCheckbox,
3324
+ VDropdown,
1730
3325
  VImage,
1731
3326
  VInput,
1732
3327
  VKeyboardAvoiding,
1733
3328
  VList,
1734
3329
  VModal,
1735
3330
  VPicker,
3331
+ VPressable,
1736
3332
  VProgressBar,
3333
+ VRadio,
3334
+ VRefreshControl,
1737
3335
  VSafeArea,
1738
3336
  VScrollView,
3337
+ VSectionList,
1739
3338
  VSegmentedControl,
1740
3339
  VSlider,
1741
3340
  VStatusBar,
1742
3341
  VSwitch,
1743
3342
  VText,
3343
+ VVideo,
1744
3344
  VView,
1745
3345
  VWebView,
3346
+ clearSharedElementRegistry,
1746
3347
  createApp,
1747
3348
  createCommentNode,
1748
3349
  createNativeNode,
1749
3350
  createStyleSheet,
1750
3351
  createTextNode,
3352
+ getRegisteredSharedElements,
3353
+ getSharedElementViewId,
3354
+ measureViewFrame,
1751
3355
  render,
1752
3356
  resetNodeId,
3357
+ useAccelerometer,
1753
3358
  useAnimation,
1754
3359
  useAppState,
3360
+ useAppleSignIn,
1755
3361
  useAsyncStorage,
3362
+ useAudio,
1756
3363
  useBackHandler,
3364
+ useBackgroundTask,
1757
3365
  useBiometry,
3366
+ useBluetooth,
3367
+ useCalendar,
1758
3368
  useCamera,
1759
3369
  useClipboard,
1760
3370
  useColorScheme,
3371
+ useContacts,
3372
+ useDatabase,
1761
3373
  useDeviceInfo,
3374
+ useDimensions,
3375
+ useFileSystem,
1762
3376
  useGeolocation,
3377
+ useGoogleSignIn,
3378
+ useGyroscope,
1763
3379
  useHaptics,
1764
3380
  useHttp,
3381
+ useI18n,
3382
+ useIAP,
1765
3383
  useKeyboard,
1766
3384
  useLinking,
1767
3385
  useNetwork,
1768
3386
  useNotifications,
3387
+ useOTAUpdate,
3388
+ usePerformance,
1769
3389
  usePermissions,
3390
+ usePlatform,
3391
+ useSecureStorage,
1770
3392
  useShare,
3393
+ useSharedElementTransition,
3394
+ useWebSocket,
1771
3395
  vShow,
1772
3396
  validStyleProperties
1773
3397
  };