@thelacanians/vue-native-runtime 0.4.13 → 0.4.15

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.cjs CHANGED
@@ -29,6 +29,7 @@ __export(index_exports, {
29
29
  VButton: () => VButton,
30
30
  VCheckbox: () => VCheckbox,
31
31
  VDropdown: () => VDropdown,
32
+ VFlatList: () => VFlatList,
32
33
  VImage: () => VImage,
33
34
  VInput: () => VInput,
34
35
  VKeyboardAvoiding: () => VKeyboardAvoiding,
@@ -53,9 +54,11 @@ __export(index_exports, {
53
54
  clearSharedElementRegistry: () => clearSharedElementRegistry,
54
55
  createApp: () => createApp,
55
56
  createCommentNode: () => createCommentNode,
57
+ createDynamicStyleSheet: () => createDynamicStyleSheet,
56
58
  createNativeNode: () => createNativeNode,
57
59
  createStyleSheet: () => createStyleSheet,
58
60
  createTextNode: () => createTextNode,
61
+ createTheme: () => createTheme,
59
62
  getRegisteredSharedElements: () => getRegisteredSharedElements,
60
63
  getSharedElementViewId: () => getSharedElementViewId,
61
64
  measureViewFrame: () => measureViewFrame,
@@ -103,7 +106,7 @@ __export(index_exports, {
103
106
  validStyleProperties: () => validStyleProperties
104
107
  });
105
108
  module.exports = __toCommonJS(index_exports);
106
- var import_runtime_core57 = require("@vue/runtime-core");
109
+ var import_runtime_core59 = require("@vue/runtime-core");
107
110
 
108
111
  // src/renderer.ts
109
112
  var import_runtime_core = require("@vue/runtime-core");
@@ -112,16 +115,25 @@ var import_runtime_core = require("@vue/runtime-core");
112
115
  var import_reactivity = require("@vue/reactivity");
113
116
  var nextNodeId = 1;
114
117
  var MAX_NODE_ID = 2147483647;
118
+ var activeNodeIds = /* @__PURE__ */ new Set();
115
119
  function resetNodeId() {
116
120
  nextNodeId = 1;
121
+ activeNodeIds.clear();
122
+ }
123
+ function releaseNodeId(id) {
124
+ activeNodeIds.delete(id);
117
125
  }
118
126
  function getNextNodeId() {
119
127
  const id = nextNodeId;
120
128
  if (nextNodeId >= MAX_NODE_ID) {
121
129
  nextNodeId = 1;
130
+ while (activeNodeIds.has(nextNodeId) && nextNodeId < MAX_NODE_ID) {
131
+ nextNodeId++;
132
+ }
122
133
  } else {
123
134
  nextNodeId++;
124
135
  }
136
+ activeNodeIds.add(id);
125
137
  return id;
126
138
  }
127
139
  function createNativeNode(type) {
@@ -281,6 +293,16 @@ var _NativeBridgeImpl = class _NativeBridgeImpl {
281
293
  updateStyle(nodeId, key, value) {
282
294
  this.enqueue("updateStyle", [nodeId, { [key]: value }]);
283
295
  }
296
+ /**
297
+ * Update multiple style properties on a native view in a single bridge op.
298
+ * Swift/Kotlin handler: handleUpdateStyle(args: [nodeId, { key1: val1, key2: val2, ... }])
299
+ *
300
+ * More efficient than calling updateStyle() per property — sends one op
301
+ * instead of N ops, reducing JSON overhead and bridge dispatch.
302
+ */
303
+ updateStyles(nodeId, styles) {
304
+ this.enqueue("updateStyle", [nodeId, styles]);
305
+ }
284
306
  // ---------------------------------------------------------------------------
285
307
  // Tree mutations
286
308
  // ---------------------------------------------------------------------------
@@ -455,9 +477,9 @@ var _NativeBridgeImpl = class _NativeBridgeImpl {
455
477
  }
456
478
  const handlers = this.globalEventHandlers.get(eventName);
457
479
  if (handlers) {
458
- handlers.forEach((h28) => {
480
+ handlers.forEach((h29) => {
459
481
  try {
460
- h28(payload);
482
+ h29(payload);
461
483
  } catch (err) {
462
484
  console.error(`[VueNative] Error in global event handler "${eventName}":`, err);
463
485
  }
@@ -474,6 +496,9 @@ var _NativeBridgeImpl = class _NativeBridgeImpl {
474
496
  this.pendingOps = [];
475
497
  this.flushScheduled = false;
476
498
  this.eventHandlers.clear();
499
+ for (const pending of this.pendingCallbacks.values()) {
500
+ clearTimeout(pending.timeoutId);
501
+ }
477
502
  this.pendingCallbacks.clear();
478
503
  this.nextCallbackId = 1;
479
504
  this.globalEventHandlers.clear();
@@ -505,16 +530,23 @@ function patchStyle(nodeId, prevStyle, nextStyle) {
505
530
  try {
506
531
  const prev = prevStyle || {};
507
532
  const next = nextStyle || {};
533
+ const changes = {};
534
+ let hasChanges = false;
508
535
  for (const key in next) {
509
536
  if (next[key] !== prev[key]) {
510
- NativeBridge.updateStyle(nodeId, key, next[key]);
537
+ changes[key] = next[key];
538
+ hasChanges = true;
511
539
  }
512
540
  }
513
541
  for (const key in prev) {
514
542
  if (!(key in next)) {
515
- NativeBridge.updateStyle(nodeId, key, null);
543
+ changes[key] = null;
544
+ hasChanges = true;
516
545
  }
517
546
  }
547
+ if (hasChanges) {
548
+ NativeBridge.updateStyles(nodeId, changes);
549
+ }
518
550
  } catch (err) {
519
551
  console.error(`[VueNative] Error patching style on node ${nodeId}:`, err);
520
552
  }
@@ -651,6 +683,7 @@ var nodeOps = {
651
683
  } catch (err) {
652
684
  console.error(`[VueNative] Error removing node ${child.id}:`, err);
653
685
  }
686
+ releaseNodeId(child.id);
654
687
  }
655
688
  },
656
689
  /**
@@ -1804,20 +1837,201 @@ var VVideo = (0, import_runtime_core28.defineComponent)({
1804
1837
  }
1805
1838
  });
1806
1839
 
1840
+ // src/components/VFlatList.ts
1841
+ var import_runtime_core29 = require("@vue/runtime-core");
1842
+ var VFlatList = (0, import_runtime_core29.defineComponent)({
1843
+ name: "VFlatList",
1844
+ props: {
1845
+ /** Array of data items to render. */
1846
+ data: {
1847
+ type: Array,
1848
+ required: true
1849
+ },
1850
+ /**
1851
+ * Render function for each item. Receives { item, index } and returns a VNode.
1852
+ * If not provided, the `#item` slot is used instead.
1853
+ */
1854
+ renderItem: {
1855
+ type: Function,
1856
+ default: void 0
1857
+ },
1858
+ /** Extract a unique key from each item. Defaults to item.id, item.key, or index. */
1859
+ keyExtractor: {
1860
+ type: Function,
1861
+ default: (item, index) => item?.id ?? item?.key ?? index
1862
+ },
1863
+ /** Fixed height for each item in points. Required for virtualization math. */
1864
+ itemHeight: {
1865
+ type: Number,
1866
+ required: true
1867
+ },
1868
+ /**
1869
+ * Number of viewport-heights to render above and below the visible area.
1870
+ * Higher values reduce blank flashes during fast scrolling but use more memory.
1871
+ * Default: 3 (3 viewports above + 3 below = 7 total viewports of items).
1872
+ */
1873
+ windowSize: {
1874
+ type: Number,
1875
+ default: 3
1876
+ },
1877
+ /** Style for the outer scroll container. */
1878
+ style: {
1879
+ type: Object,
1880
+ default: () => ({})
1881
+ },
1882
+ /** Show vertical scroll indicator. Default: true */
1883
+ showsScrollIndicator: {
1884
+ type: Boolean,
1885
+ default: true
1886
+ },
1887
+ /** Enable bounce at scroll boundaries. Default: true */
1888
+ bounces: {
1889
+ type: Boolean,
1890
+ default: true
1891
+ },
1892
+ /** Height of the header slot in points. Used to offset items below the header. */
1893
+ headerHeight: {
1894
+ type: Number,
1895
+ default: 0
1896
+ },
1897
+ /**
1898
+ * How far from the end (in viewport fractions) to trigger endReached.
1899
+ * Default: 0.5 (trigger when within 50% of a viewport from the bottom).
1900
+ */
1901
+ endReachedThreshold: {
1902
+ type: Number,
1903
+ default: 0.5
1904
+ }
1905
+ },
1906
+ emits: ["scroll", "endReached"],
1907
+ setup(props, { slots, emit }) {
1908
+ const scrollOffset = (0, import_runtime_core29.ref)(0);
1909
+ const viewportHeight = (0, import_runtime_core29.ref)(0);
1910
+ let endReachedFired = false;
1911
+ const hasHeader = (0, import_runtime_core29.computed)(() => !!slots.header);
1912
+ const totalHeight = (0, import_runtime_core29.computed)(() => {
1913
+ const itemsHeight = (props.data?.length ?? 0) * props.itemHeight;
1914
+ return itemsHeight + (hasHeader.value ? props.headerHeight : 0);
1915
+ });
1916
+ const visibleRange = (0, import_runtime_core29.computed)(() => {
1917
+ const vh = viewportHeight.value || props.itemHeight * 20;
1918
+ const buffer = vh * props.windowSize;
1919
+ const startPx = Math.max(0, scrollOffset.value - buffer);
1920
+ const endPx = scrollOffset.value + vh + buffer;
1921
+ const startIdx = Math.floor(startPx / props.itemHeight);
1922
+ const endIdx = Math.min(
1923
+ Math.ceil(endPx / props.itemHeight),
1924
+ props.data?.length ?? 0
1925
+ );
1926
+ return { start: startIdx, end: endIdx };
1927
+ });
1928
+ function onScroll(event) {
1929
+ scrollOffset.value = event.y ?? 0;
1930
+ if (event.layoutHeight && event.layoutHeight > 0) {
1931
+ viewportHeight.value = event.layoutHeight;
1932
+ }
1933
+ emit("scroll", event);
1934
+ const contentLength = totalHeight.value;
1935
+ const offset = scrollOffset.value;
1936
+ const vh = viewportHeight.value || props.itemHeight * 20;
1937
+ const distanceFromEnd = contentLength - vh - offset;
1938
+ const threshold = vh * props.endReachedThreshold;
1939
+ if (distanceFromEnd < threshold && !endReachedFired) {
1940
+ endReachedFired = true;
1941
+ emit("endReached");
1942
+ } else if (distanceFromEnd >= threshold) {
1943
+ endReachedFired = false;
1944
+ }
1945
+ }
1946
+ return () => {
1947
+ const items = props.data ?? [];
1948
+ const { start, end } = visibleRange.value;
1949
+ const children = [];
1950
+ for (let i = start; i < end; i++) {
1951
+ const item = items[i];
1952
+ if (item === void 0) continue;
1953
+ const key = props.keyExtractor(item, i);
1954
+ const itemContent = props.renderItem ? [props.renderItem({ item, index: i })] : slots.item?.({ item, index: i }) ?? [];
1955
+ children.push(
1956
+ (0, import_runtime_core29.h)(
1957
+ "VView",
1958
+ {
1959
+ key,
1960
+ style: {
1961
+ position: "absolute",
1962
+ top: (hasHeader.value ? props.headerHeight : 0) + i * props.itemHeight,
1963
+ left: 0,
1964
+ right: 0,
1965
+ height: props.itemHeight
1966
+ }
1967
+ },
1968
+ itemContent
1969
+ )
1970
+ );
1971
+ }
1972
+ if (slots.header) {
1973
+ children.unshift(
1974
+ (0, import_runtime_core29.h)("VView", { key: "__vfl_header__", style: { position: "absolute", top: 0, left: 0, right: 0 } }, slots.header())
1975
+ );
1976
+ }
1977
+ if (items.length === 0 && slots.empty) {
1978
+ return (0, import_runtime_core29.h)(
1979
+ "VScrollView",
1980
+ {
1981
+ style: { ...props.style, flex: props.style?.flex ?? 1 },
1982
+ showsVerticalScrollIndicator: props.showsScrollIndicator,
1983
+ bounces: props.bounces
1984
+ },
1985
+ [(0, import_runtime_core29.h)("VView", { style: { flex: 1 } }, slots.empty())]
1986
+ );
1987
+ }
1988
+ const innerContainer = (0, import_runtime_core29.h)(
1989
+ "VView",
1990
+ {
1991
+ key: "__vfl_container__",
1992
+ style: {
1993
+ height: totalHeight.value,
1994
+ width: "100%"
1995
+ }
1996
+ },
1997
+ children
1998
+ );
1999
+ return (0, import_runtime_core29.h)(
2000
+ "VScrollView",
2001
+ {
2002
+ style: { ...props.style, flex: props.style?.flex ?? 1 },
2003
+ showsVerticalScrollIndicator: props.showsScrollIndicator,
2004
+ bounces: props.bounces,
2005
+ onScroll
2006
+ },
2007
+ [innerContainer]
2008
+ );
2009
+ };
2010
+ }
2011
+ });
2012
+
1807
2013
  // src/directives/vShow.ts
1808
2014
  var vShow = {
1809
2015
  beforeMount(el, { value }) {
1810
- NativeBridge.updateProp(el.id, "hidden", !value);
2016
+ try {
2017
+ NativeBridge.updateProp(el.id, "hidden", !value);
2018
+ } catch (err) {
2019
+ console.error("[VueNative] v-show beforeMount error:", err);
2020
+ }
1811
2021
  },
1812
2022
  updated(el, { value, oldValue }) {
1813
2023
  if (value === oldValue) return;
1814
- NativeBridge.updateProp(el.id, "hidden", !value);
2024
+ try {
2025
+ NativeBridge.updateProp(el.id, "hidden", !value);
2026
+ } catch (err) {
2027
+ console.error("[VueNative] v-show updated error:", err);
2028
+ }
1815
2029
  }
1816
2030
  };
1817
2031
 
1818
2032
  // src/errorBoundary.ts
1819
- var import_runtime_core29 = require("@vue/runtime-core");
1820
- var ErrorBoundary = (0, import_runtime_core29.defineComponent)({
2033
+ var import_runtime_core30 = require("@vue/runtime-core");
2034
+ var ErrorBoundary = (0, import_runtime_core30.defineComponent)({
1821
2035
  name: "ErrorBoundary",
1822
2036
  props: {
1823
2037
  onError: Function,
@@ -1827,9 +2041,9 @@ var ErrorBoundary = (0, import_runtime_core29.defineComponent)({
1827
2041
  }
1828
2042
  },
1829
2043
  setup(props, { slots }) {
1830
- const error = (0, import_runtime_core29.ref)(null);
1831
- const errorInfo = (0, import_runtime_core29.ref)("");
1832
- (0, import_runtime_core29.onErrorCaptured)((err, _instance, info) => {
2044
+ const error = (0, import_runtime_core30.ref)(null);
2045
+ const errorInfo = (0, import_runtime_core30.ref)("");
2046
+ (0, import_runtime_core30.onErrorCaptured)((err, _instance, info) => {
1833
2047
  const normalizedError = err instanceof Error ? err : new Error(String(err));
1834
2048
  error.value = normalizedError;
1835
2049
  errorInfo.value = info;
@@ -1842,7 +2056,7 @@ var ErrorBoundary = (0, import_runtime_core29.defineComponent)({
1842
2056
  error.value = null;
1843
2057
  errorInfo.value = "";
1844
2058
  }
1845
- (0, import_runtime_core29.watch)(
2059
+ (0, import_runtime_core30.watch)(
1846
2060
  () => props.resetKeys,
1847
2061
  () => {
1848
2062
  if (error.value) {
@@ -2036,9 +2250,9 @@ function useAsyncStorage() {
2036
2250
  }
2037
2251
 
2038
2252
  // src/composables/useClipboard.ts
2039
- var import_runtime_core30 = require("@vue/runtime-core");
2253
+ var import_runtime_core31 = require("@vue/runtime-core");
2040
2254
  function useClipboard() {
2041
- const content = (0, import_runtime_core30.ref)("");
2255
+ const content = (0, import_runtime_core31.ref)("");
2042
2256
  function copy(text) {
2043
2257
  return NativeBridge.invokeNativeModule("Clipboard", "copy", [text]).then(() => void 0);
2044
2258
  }
@@ -2052,16 +2266,16 @@ function useClipboard() {
2052
2266
  }
2053
2267
 
2054
2268
  // src/composables/useDeviceInfo.ts
2055
- var import_runtime_core31 = require("@vue/runtime-core");
2269
+ var import_runtime_core32 = require("@vue/runtime-core");
2056
2270
  function useDeviceInfo() {
2057
- const model = (0, import_runtime_core31.ref)("");
2058
- const systemVersion = (0, import_runtime_core31.ref)("");
2059
- const systemName = (0, import_runtime_core31.ref)("");
2060
- const name = (0, import_runtime_core31.ref)("");
2061
- const screenWidth = (0, import_runtime_core31.ref)(0);
2062
- const screenHeight = (0, import_runtime_core31.ref)(0);
2063
- const scale = (0, import_runtime_core31.ref)(1);
2064
- const isLoaded = (0, import_runtime_core31.ref)(false);
2271
+ const model = (0, import_runtime_core32.ref)("");
2272
+ const systemVersion = (0, import_runtime_core32.ref)("");
2273
+ const systemName = (0, import_runtime_core32.ref)("");
2274
+ const name = (0, import_runtime_core32.ref)("");
2275
+ const screenWidth = (0, import_runtime_core32.ref)(0);
2276
+ const screenHeight = (0, import_runtime_core32.ref)(0);
2277
+ const scale = (0, import_runtime_core32.ref)(1);
2278
+ const isLoaded = (0, import_runtime_core32.ref)(false);
2065
2279
  async function fetchInfo() {
2066
2280
  const info = await NativeBridge.invokeNativeModule("DeviceInfo", "getInfo", []);
2067
2281
  model.value = info.model ?? "";
@@ -2073,7 +2287,7 @@ function useDeviceInfo() {
2073
2287
  scale.value = info.scale ?? 1;
2074
2288
  isLoaded.value = true;
2075
2289
  }
2076
- (0, import_runtime_core31.onMounted)(() => {
2290
+ (0, import_runtime_core32.onMounted)(() => {
2077
2291
  fetchInfo();
2078
2292
  });
2079
2293
  return {
@@ -2090,10 +2304,10 @@ function useDeviceInfo() {
2090
2304
  }
2091
2305
 
2092
2306
  // src/composables/useKeyboard.ts
2093
- var import_runtime_core32 = require("@vue/runtime-core");
2307
+ var import_runtime_core33 = require("@vue/runtime-core");
2094
2308
  function useKeyboard() {
2095
- const isVisible = (0, import_runtime_core32.ref)(false);
2096
- const height = (0, import_runtime_core32.ref)(0);
2309
+ const isVisible = (0, import_runtime_core33.ref)(false);
2310
+ const height = (0, import_runtime_core33.ref)(0);
2097
2311
  function dismiss() {
2098
2312
  return NativeBridge.invokeNativeModule("Keyboard", "dismiss", []).then(() => void 0);
2099
2313
  }
@@ -2114,15 +2328,25 @@ var Easing = {
2114
2328
  easeOut: "easeOut",
2115
2329
  easeInOut: "easeInOut"
2116
2330
  };
2331
+ function resolveViewId(target) {
2332
+ if (typeof target === "number") return target;
2333
+ if (target && typeof target === "object" && "value" in target) {
2334
+ const val = target.value;
2335
+ if (val && typeof val.id === "number") return val.id;
2336
+ throw new Error("[VueNative] Animation target ref has no .value.id \u2014 is the ref attached to a component?");
2337
+ }
2338
+ if (target && typeof target.id === "number") return target.id;
2339
+ throw new Error("[VueNative] Invalid animation target. Pass a number, template ref, or NativeNode.");
2340
+ }
2117
2341
  function useAnimation() {
2118
- function timing(viewId, toStyles, config = {}) {
2119
- return NativeBridge.invokeNativeModule("Animation", "timing", [viewId, toStyles, config]);
2342
+ function timing(target, toStyles, config = {}) {
2343
+ return NativeBridge.invokeNativeModule("Animation", "timing", [resolveViewId(target), toStyles, config]);
2120
2344
  }
2121
- function spring(viewId, toStyles, config = {}) {
2122
- return NativeBridge.invokeNativeModule("Animation", "spring", [viewId, toStyles, config]);
2345
+ function spring(target, toStyles, config = {}) {
2346
+ return NativeBridge.invokeNativeModule("Animation", "spring", [resolveViewId(target), toStyles, config]);
2123
2347
  }
2124
- function keyframe(viewId, steps, config = {}) {
2125
- return NativeBridge.invokeNativeModule("Animation", "keyframe", [viewId, steps, config]);
2348
+ function keyframe(target, steps, config = {}) {
2349
+ return NativeBridge.invokeNativeModule("Animation", "keyframe", [resolveViewId(target), steps, config]);
2126
2350
  }
2127
2351
  function sequence(animations) {
2128
2352
  return NativeBridge.invokeNativeModule("Animation", "sequence", [animations]);
@@ -2130,17 +2354,20 @@ function useAnimation() {
2130
2354
  function parallel(animations) {
2131
2355
  return NativeBridge.invokeNativeModule("Animation", "parallel", [animations]);
2132
2356
  }
2133
- function fadeOut(viewId, duration = 300) {
2134
- return timing(viewId, { opacity: 0 }, { duration });
2357
+ function fadeOut(target, duration = 300) {
2358
+ return timing(target, { opacity: 0 }, { duration });
2359
+ }
2360
+ function fadeIn(target, duration = 300) {
2361
+ return timing(target, { opacity: 1 }, { duration });
2135
2362
  }
2136
- function fadeIn(viewId, duration = 300) {
2137
- return timing(viewId, { opacity: 1 }, { duration });
2363
+ function slideInFromRight(target, duration = 300) {
2364
+ return timing(target, { translateX: 0 }, { duration, easing: "easeOut" });
2138
2365
  }
2139
- function slideInFromRight(viewId, duration = 300) {
2140
- return timing(viewId, { translateX: 0 }, { duration, easing: "easeOut" });
2366
+ function slideOutToRight(target, duration = 300) {
2367
+ return timing(target, { translateX: 400 }, { duration, easing: "easeIn" });
2141
2368
  }
2142
- function slideOutToRight(viewId, duration = 300) {
2143
- return timing(viewId, { translateX: 400 }, { duration, easing: "easeIn" });
2369
+ function resolveId(target) {
2370
+ return resolveViewId(target);
2144
2371
  }
2145
2372
  return {
2146
2373
  timing,
@@ -2152,15 +2379,16 @@ function useAnimation() {
2152
2379
  fadeOut,
2153
2380
  slideInFromRight,
2154
2381
  slideOutToRight,
2382
+ resolveId,
2155
2383
  Easing
2156
2384
  };
2157
2385
  }
2158
2386
 
2159
2387
  // src/composables/useNetwork.ts
2160
- var import_runtime_core33 = require("@vue/runtime-core");
2388
+ var import_runtime_core34 = require("@vue/runtime-core");
2161
2389
  function useNetwork() {
2162
- const isConnected = (0, import_runtime_core33.ref)(true);
2163
- const connectionType = (0, import_runtime_core33.ref)("unknown");
2390
+ const isConnected = (0, import_runtime_core34.ref)(true);
2391
+ const connectionType = (0, import_runtime_core34.ref)("unknown");
2164
2392
  let lastEventTime = 0;
2165
2393
  const unsubscribe = NativeBridge.onGlobalEvent("network:change", (payload) => {
2166
2394
  lastEventTime = Date.now();
@@ -2175,14 +2403,14 @@ function useNetwork() {
2175
2403
  }
2176
2404
  }).catch(() => {
2177
2405
  });
2178
- (0, import_runtime_core33.onUnmounted)(unsubscribe);
2406
+ (0, import_runtime_core34.onUnmounted)(unsubscribe);
2179
2407
  return { isConnected, connectionType };
2180
2408
  }
2181
2409
 
2182
2410
  // src/composables/useAppState.ts
2183
- var import_runtime_core34 = require("@vue/runtime-core");
2411
+ var import_runtime_core35 = require("@vue/runtime-core");
2184
2412
  function useAppState() {
2185
- const state = (0, import_runtime_core34.ref)("active");
2413
+ const state = (0, import_runtime_core35.ref)("active");
2186
2414
  NativeBridge.invokeNativeModule("AppState", "getState").then((s) => {
2187
2415
  state.value = s;
2188
2416
  }).catch(() => {
@@ -2190,7 +2418,7 @@ function useAppState() {
2190
2418
  const unsubscribe = NativeBridge.onGlobalEvent("appState:change", (payload) => {
2191
2419
  state.value = payload.state;
2192
2420
  });
2193
- (0, import_runtime_core34.onUnmounted)(unsubscribe);
2421
+ (0, import_runtime_core35.onUnmounted)(unsubscribe);
2194
2422
  return { state };
2195
2423
  }
2196
2424
 
@@ -2225,10 +2453,10 @@ function usePermissions() {
2225
2453
  }
2226
2454
 
2227
2455
  // src/composables/useGeolocation.ts
2228
- var import_runtime_core35 = require("@vue/runtime-core");
2456
+ var import_runtime_core36 = require("@vue/runtime-core");
2229
2457
  function useGeolocation() {
2230
- const coords = (0, import_runtime_core35.ref)(null);
2231
- const error = (0, import_runtime_core35.ref)(null);
2458
+ const coords = (0, import_runtime_core36.ref)(null);
2459
+ const error = (0, import_runtime_core36.ref)(null);
2232
2460
  let watchId = null;
2233
2461
  async function getCurrentPosition() {
2234
2462
  try {
@@ -2253,7 +2481,7 @@ function useGeolocation() {
2253
2481
  const unsubscribeError = NativeBridge.onGlobalEvent("location:error", (payload) => {
2254
2482
  error.value = payload.message;
2255
2483
  });
2256
- (0, import_runtime_core35.onUnmounted)(() => {
2484
+ (0, import_runtime_core36.onUnmounted)(() => {
2257
2485
  unsubscribe();
2258
2486
  unsubscribeError();
2259
2487
  if (watchId !== null) clearWatch(watchId);
@@ -2273,7 +2501,7 @@ function useGeolocation() {
2273
2501
  }
2274
2502
 
2275
2503
  // src/composables/useCamera.ts
2276
- var import_runtime_core36 = require("@vue/runtime-core");
2504
+ var import_runtime_core37 = require("@vue/runtime-core");
2277
2505
  function useCamera() {
2278
2506
  const qrCleanups = [];
2279
2507
  async function launchCamera(options = {}) {
@@ -2296,7 +2524,7 @@ function useCamera() {
2296
2524
  qrCleanups.push(unsubscribe);
2297
2525
  return unsubscribe;
2298
2526
  }
2299
- (0, import_runtime_core36.onUnmounted)(() => {
2527
+ (0, import_runtime_core37.onUnmounted)(() => {
2300
2528
  NativeBridge.invokeNativeModule("Camera", "stopQRScan").catch(() => {
2301
2529
  });
2302
2530
  qrCleanups.forEach((fn) => fn());
@@ -2306,10 +2534,10 @@ function useCamera() {
2306
2534
  }
2307
2535
 
2308
2536
  // src/composables/useNotifications.ts
2309
- var import_runtime_core37 = require("@vue/runtime-core");
2537
+ var import_runtime_core38 = require("@vue/runtime-core");
2310
2538
  function useNotifications() {
2311
- const isGranted = (0, import_runtime_core37.ref)(false);
2312
- const pushToken = (0, import_runtime_core37.ref)(null);
2539
+ const isGranted = (0, import_runtime_core38.ref)(false);
2540
+ const pushToken = (0, import_runtime_core38.ref)(null);
2313
2541
  async function requestPermission() {
2314
2542
  const granted = await NativeBridge.invokeNativeModule("Notifications", "requestPermission");
2315
2543
  isGranted.value = granted;
@@ -2329,7 +2557,7 @@ function useNotifications() {
2329
2557
  }
2330
2558
  function onNotification(handler) {
2331
2559
  const unsubscribe = NativeBridge.onGlobalEvent("notification:received", handler);
2332
- (0, import_runtime_core37.onUnmounted)(unsubscribe);
2560
+ (0, import_runtime_core38.onUnmounted)(unsubscribe);
2333
2561
  return unsubscribe;
2334
2562
  }
2335
2563
  async function registerForPush() {
@@ -2343,12 +2571,12 @@ function useNotifications() {
2343
2571
  pushToken.value = payload.token;
2344
2572
  handler(payload.token);
2345
2573
  });
2346
- (0, import_runtime_core37.onUnmounted)(unsubscribe);
2574
+ (0, import_runtime_core38.onUnmounted)(unsubscribe);
2347
2575
  return unsubscribe;
2348
2576
  }
2349
2577
  function onPushReceived(handler) {
2350
2578
  const unsubscribe = NativeBridge.onGlobalEvent("push:received", handler);
2351
- (0, import_runtime_core37.onUnmounted)(unsubscribe);
2579
+ (0, import_runtime_core38.onUnmounted)(unsubscribe);
2352
2580
  return unsubscribe;
2353
2581
  }
2354
2582
  return {
@@ -2384,7 +2612,7 @@ function useBiometry() {
2384
2612
  }
2385
2613
 
2386
2614
  // src/composables/useHttp.ts
2387
- var import_runtime_core38 = require("@vue/runtime-core");
2615
+ var import_runtime_core39 = require("@vue/runtime-core");
2388
2616
  function useHttp(config = {}) {
2389
2617
  if (config.pins && Object.keys(config.pins).length > 0) {
2390
2618
  const configurePins = globalThis.__VN_configurePins;
@@ -2394,39 +2622,70 @@ function useHttp(config = {}) {
2394
2622
  NativeBridge.invokeNativeModule("Http", "configurePins", [config.pins]);
2395
2623
  }
2396
2624
  }
2397
- const loading = (0, import_runtime_core38.ref)(false);
2398
- const error = (0, import_runtime_core38.ref)(null);
2625
+ const loading = (0, import_runtime_core39.ref)(false);
2626
+ const error = (0, import_runtime_core39.ref)(null);
2399
2627
  let isMounted = true;
2400
- (0, import_runtime_core38.onUnmounted)(() => {
2628
+ (0, import_runtime_core39.onUnmounted)(() => {
2401
2629
  isMounted = false;
2402
2630
  });
2631
+ const BODY_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH"]);
2632
+ function parseResponseHeaders(response) {
2633
+ const result = {};
2634
+ if (!response.headers) return result;
2635
+ try {
2636
+ if (typeof response.headers.forEach === "function") {
2637
+ response.headers.forEach((value, key) => {
2638
+ result[key] = value;
2639
+ });
2640
+ } else if (typeof response.headers.entries === "function") {
2641
+ for (const [key, value] of response.headers.entries()) {
2642
+ result[key] = value;
2643
+ }
2644
+ }
2645
+ } catch {
2646
+ }
2647
+ return result;
2648
+ }
2403
2649
  async function request(method, url, options = {}) {
2404
2650
  const fullUrl = config.baseURL ? `${config.baseURL}${url}` : url;
2405
2651
  loading.value = true;
2406
2652
  error.value = null;
2653
+ let controller;
2654
+ let timeoutId;
2655
+ if (config.timeout && config.timeout > 0 && typeof AbortController !== "undefined") {
2656
+ controller = new AbortController();
2657
+ timeoutId = setTimeout(() => controller.abort(), config.timeout);
2658
+ }
2407
2659
  try {
2660
+ const upperMethod = method.toUpperCase();
2408
2661
  const mergedHeaders = {
2409
- "Content-Type": "application/json",
2410
2662
  ...config.headers ?? {},
2411
2663
  ...options.headers ?? {}
2412
2664
  };
2665
+ if (BODY_METHODS.has(upperMethod) && !mergedHeaders["Content-Type"]) {
2666
+ mergedHeaders["Content-Type"] = "application/json";
2667
+ }
2413
2668
  const fetchOptions = {
2414
- method: method.toUpperCase(),
2669
+ method: upperMethod,
2415
2670
  headers: mergedHeaders
2416
2671
  };
2672
+ if (controller) {
2673
+ fetchOptions.signal = controller.signal;
2674
+ }
2417
2675
  if (options.body !== void 0) {
2418
2676
  fetchOptions.body = JSON.stringify(options.body);
2419
2677
  }
2420
2678
  const response = await fetch(fullUrl, fetchOptions);
2421
2679
  const data = await response.json();
2680
+ const responseHeaders = parseResponseHeaders(response);
2422
2681
  if (!isMounted) {
2423
- return { data, status: response.status, ok: response.ok, headers: {} };
2682
+ return { data, status: response.status, ok: response.ok, headers: responseHeaders };
2424
2683
  }
2425
2684
  return {
2426
2685
  data,
2427
2686
  status: response.status,
2428
2687
  ok: response.ok,
2429
- headers: {}
2688
+ headers: responseHeaders
2430
2689
  };
2431
2690
  } catch (e) {
2432
2691
  const msg = e instanceof Error ? e.message : String(e);
@@ -2435,6 +2694,9 @@ function useHttp(config = {}) {
2435
2694
  }
2436
2695
  throw e;
2437
2696
  } finally {
2697
+ if (timeoutId !== void 0) {
2698
+ clearTimeout(timeoutId);
2699
+ }
2438
2700
  if (isMounted) {
2439
2701
  loading.value = false;
2440
2702
  }
@@ -2469,10 +2731,10 @@ function useHttp(config = {}) {
2469
2731
  }
2470
2732
 
2471
2733
  // src/composables/useColorScheme.ts
2472
- var import_runtime_core39 = require("@vue/runtime-core");
2734
+ var import_runtime_core40 = require("@vue/runtime-core");
2473
2735
  function useColorScheme() {
2474
- const colorScheme = (0, import_runtime_core39.ref)("light");
2475
- const isDark = (0, import_runtime_core39.ref)(false);
2736
+ const colorScheme = (0, import_runtime_core40.ref)("light");
2737
+ const isDark = (0, import_runtime_core40.ref)(false);
2476
2738
  const unsubscribe = NativeBridge.onGlobalEvent(
2477
2739
  "colorScheme:change",
2478
2740
  (payload) => {
@@ -2480,15 +2742,15 @@ function useColorScheme() {
2480
2742
  isDark.value = payload.colorScheme === "dark";
2481
2743
  }
2482
2744
  );
2483
- (0, import_runtime_core39.onUnmounted)(unsubscribe);
2745
+ (0, import_runtime_core40.onUnmounted)(unsubscribe);
2484
2746
  return { colorScheme, isDark };
2485
2747
  }
2486
2748
 
2487
2749
  // src/composables/useBackHandler.ts
2488
- var import_runtime_core40 = require("@vue/runtime-core");
2750
+ var import_runtime_core41 = require("@vue/runtime-core");
2489
2751
  function useBackHandler(handler) {
2490
2752
  let unsubscribe = null;
2491
- (0, import_runtime_core40.onMounted)(() => {
2753
+ (0, import_runtime_core41.onMounted)(() => {
2492
2754
  unsubscribe = NativeBridge.onGlobalEvent("hardware:backPress", () => {
2493
2755
  const handled = handler();
2494
2756
  if (!handled) {
@@ -2497,7 +2759,7 @@ function useBackHandler(handler) {
2497
2759
  }
2498
2760
  });
2499
2761
  });
2500
- (0, import_runtime_core40.onUnmounted)(() => {
2762
+ (0, import_runtime_core41.onUnmounted)(() => {
2501
2763
  unsubscribe?.();
2502
2764
  unsubscribe = null;
2503
2765
  });
@@ -2521,11 +2783,11 @@ function useSecureStorage() {
2521
2783
  }
2522
2784
 
2523
2785
  // src/composables/useI18n.ts
2524
- var import_runtime_core41 = require("@vue/runtime-core");
2786
+ var import_runtime_core42 = require("@vue/runtime-core");
2525
2787
  function useI18n() {
2526
- const isRTL = (0, import_runtime_core41.ref)(false);
2527
- const locale = (0, import_runtime_core41.ref)("en");
2528
- (0, import_runtime_core41.onMounted)(async () => {
2788
+ const isRTL = (0, import_runtime_core42.ref)(false);
2789
+ const locale = (0, import_runtime_core42.ref)("en");
2790
+ (0, import_runtime_core42.onMounted)(async () => {
2529
2791
  try {
2530
2792
  const info = await NativeBridge.invokeNativeModule("DeviceInfo", "getDeviceInfo", []);
2531
2793
  locale.value = info?.locale || "en";
@@ -2545,12 +2807,12 @@ function usePlatform() {
2545
2807
  }
2546
2808
 
2547
2809
  // src/composables/useDimensions.ts
2548
- var import_runtime_core42 = require("@vue/runtime-core");
2810
+ var import_runtime_core43 = require("@vue/runtime-core");
2549
2811
  function useDimensions() {
2550
- const width = (0, import_runtime_core42.ref)(0);
2551
- const height = (0, import_runtime_core42.ref)(0);
2552
- const scale = (0, import_runtime_core42.ref)(1);
2553
- (0, import_runtime_core42.onMounted)(async () => {
2812
+ const width = (0, import_runtime_core43.ref)(0);
2813
+ const height = (0, import_runtime_core43.ref)(0);
2814
+ const scale = (0, import_runtime_core43.ref)(1);
2815
+ (0, import_runtime_core43.onMounted)(async () => {
2554
2816
  try {
2555
2817
  const info = await NativeBridge.invokeNativeModule("DeviceInfo", "getInfo", []);
2556
2818
  width.value = info?.screenWidth || 0;
@@ -2564,12 +2826,12 @@ function useDimensions() {
2564
2826
  if (payload.height != null) height.value = payload.height;
2565
2827
  if (payload.scale != null) scale.value = payload.scale;
2566
2828
  });
2567
- (0, import_runtime_core42.onUnmounted)(cleanup);
2829
+ (0, import_runtime_core43.onUnmounted)(cleanup);
2568
2830
  return { width, height, scale };
2569
2831
  }
2570
2832
 
2571
2833
  // src/composables/useWebSocket.ts
2572
- var import_runtime_core43 = require("@vue/runtime-core");
2834
+ var import_runtime_core44 = require("@vue/runtime-core");
2573
2835
  var connectionCounter = 0;
2574
2836
  function useWebSocket(url, options = {}) {
2575
2837
  const {
@@ -2579,9 +2841,9 @@ function useWebSocket(url, options = {}) {
2579
2841
  reconnectInterval = 1e3
2580
2842
  } = options;
2581
2843
  const connectionId = `ws_${++connectionCounter}_${Date.now()}`;
2582
- const status = (0, import_runtime_core43.ref)("CLOSED");
2583
- const lastMessage = (0, import_runtime_core43.ref)(null);
2584
- const error = (0, import_runtime_core43.ref)(null);
2844
+ const status = (0, import_runtime_core44.ref)("CLOSED");
2845
+ const lastMessage = (0, import_runtime_core44.ref)(null);
2846
+ const error = (0, import_runtime_core44.ref)(null);
2585
2847
  let reconnectAttempts = 0;
2586
2848
  let reconnectTimer = null;
2587
2849
  const MAX_PENDING_MESSAGES = 100;
@@ -2666,7 +2928,7 @@ function useWebSocket(url, options = {}) {
2666
2928
  if (autoConnect) {
2667
2929
  open();
2668
2930
  }
2669
- (0, import_runtime_core43.onUnmounted)(() => {
2931
+ (0, import_runtime_core44.onUnmounted)(() => {
2670
2932
  if (reconnectTimer) {
2671
2933
  clearTimeout(reconnectTimer);
2672
2934
  }
@@ -2735,12 +2997,12 @@ function useFileSystem() {
2735
2997
  }
2736
2998
 
2737
2999
  // src/composables/useSensors.ts
2738
- var import_runtime_core44 = require("@vue/runtime-core");
3000
+ var import_runtime_core45 = require("@vue/runtime-core");
2739
3001
  function useAccelerometer(options = {}) {
2740
- const x = (0, import_runtime_core44.ref)(0);
2741
- const y = (0, import_runtime_core44.ref)(0);
2742
- const z = (0, import_runtime_core44.ref)(0);
2743
- const isAvailable = (0, import_runtime_core44.ref)(false);
3002
+ const x = (0, import_runtime_core45.ref)(0);
3003
+ const y = (0, import_runtime_core45.ref)(0);
3004
+ const z = (0, import_runtime_core45.ref)(0);
3005
+ const isAvailable = (0, import_runtime_core45.ref)(false);
2744
3006
  let running = false;
2745
3007
  let unsubscribe = null;
2746
3008
  NativeBridge.invokeNativeModule("Sensors", "isAvailable", ["accelerometer"]).then((result) => {
@@ -2768,16 +3030,16 @@ function useAccelerometer(options = {}) {
2768
3030
  NativeBridge.invokeNativeModule("Sensors", "stopAccelerometer").catch(() => {
2769
3031
  });
2770
3032
  }
2771
- (0, import_runtime_core44.onUnmounted)(() => {
3033
+ (0, import_runtime_core45.onUnmounted)(() => {
2772
3034
  stop();
2773
3035
  });
2774
3036
  return { x, y, z, isAvailable, start, stop };
2775
3037
  }
2776
3038
  function useGyroscope(options = {}) {
2777
- const x = (0, import_runtime_core44.ref)(0);
2778
- const y = (0, import_runtime_core44.ref)(0);
2779
- const z = (0, import_runtime_core44.ref)(0);
2780
- const isAvailable = (0, import_runtime_core44.ref)(false);
3039
+ const x = (0, import_runtime_core45.ref)(0);
3040
+ const y = (0, import_runtime_core45.ref)(0);
3041
+ const z = (0, import_runtime_core45.ref)(0);
3042
+ const isAvailable = (0, import_runtime_core45.ref)(false);
2781
3043
  let running = false;
2782
3044
  let unsubscribe = null;
2783
3045
  NativeBridge.invokeNativeModule("Sensors", "isAvailable", ["gyroscope"]).then((result) => {
@@ -2805,20 +3067,20 @@ function useGyroscope(options = {}) {
2805
3067
  NativeBridge.invokeNativeModule("Sensors", "stopGyroscope").catch(() => {
2806
3068
  });
2807
3069
  }
2808
- (0, import_runtime_core44.onUnmounted)(() => {
3070
+ (0, import_runtime_core45.onUnmounted)(() => {
2809
3071
  stop();
2810
3072
  });
2811
3073
  return { x, y, z, isAvailable, start, stop };
2812
3074
  }
2813
3075
 
2814
3076
  // src/composables/useAudio.ts
2815
- var import_runtime_core45 = require("@vue/runtime-core");
3077
+ var import_runtime_core46 = require("@vue/runtime-core");
2816
3078
  function useAudio() {
2817
- const duration = (0, import_runtime_core45.ref)(0);
2818
- const position = (0, import_runtime_core45.ref)(0);
2819
- const isPlaying = (0, import_runtime_core45.ref)(false);
2820
- const isRecording = (0, import_runtime_core45.ref)(false);
2821
- const error = (0, import_runtime_core45.ref)(null);
3079
+ const duration = (0, import_runtime_core46.ref)(0);
3080
+ const position = (0, import_runtime_core46.ref)(0);
3081
+ const isPlaying = (0, import_runtime_core46.ref)(false);
3082
+ const isRecording = (0, import_runtime_core46.ref)(false);
3083
+ const error = (0, import_runtime_core46.ref)(null);
2822
3084
  const unsubProgress = NativeBridge.onGlobalEvent("audio:progress", (payload) => {
2823
3085
  position.value = payload.currentTime ?? 0;
2824
3086
  duration.value = payload.duration ?? 0;
@@ -2831,7 +3093,7 @@ function useAudio() {
2831
3093
  error.value = payload.message ?? "Unknown audio error";
2832
3094
  isPlaying.value = false;
2833
3095
  });
2834
- (0, import_runtime_core45.onUnmounted)(() => {
3096
+ (0, import_runtime_core46.onUnmounted)(() => {
2835
3097
  unsubProgress();
2836
3098
  unsubComplete();
2837
3099
  unsubError();
@@ -2910,9 +3172,9 @@ function useAudio() {
2910
3172
  }
2911
3173
 
2912
3174
  // src/composables/useDatabase.ts
2913
- var import_runtime_core46 = require("@vue/runtime-core");
3175
+ var import_runtime_core47 = require("@vue/runtime-core");
2914
3176
  function useDatabase(name = "default") {
2915
- const isOpen = (0, import_runtime_core46.ref)(false);
3177
+ const isOpen = (0, import_runtime_core47.ref)(false);
2916
3178
  let opened = false;
2917
3179
  async function ensureOpen() {
2918
3180
  if (opened) return;
@@ -2954,7 +3216,7 @@ function useDatabase(name = "default") {
2954
3216
  opened = false;
2955
3217
  isOpen.value = false;
2956
3218
  }
2957
- (0, import_runtime_core46.onUnmounted)(() => {
3219
+ (0, import_runtime_core47.onUnmounted)(() => {
2958
3220
  if (opened) {
2959
3221
  NativeBridge.invokeNativeModule("Database", "close", [name]).catch(() => {
2960
3222
  });
@@ -2966,12 +3228,12 @@ function useDatabase(name = "default") {
2966
3228
  }
2967
3229
 
2968
3230
  // src/composables/usePerformance.ts
2969
- var import_runtime_core47 = require("@vue/runtime-core");
3231
+ var import_runtime_core48 = require("@vue/runtime-core");
2970
3232
  function usePerformance() {
2971
- const isProfiling = (0, import_runtime_core47.ref)(false);
2972
- const fps = (0, import_runtime_core47.ref)(0);
2973
- const memoryMB = (0, import_runtime_core47.ref)(0);
2974
- const bridgeOps = (0, import_runtime_core47.ref)(0);
3233
+ const isProfiling = (0, import_runtime_core48.ref)(false);
3234
+ const fps = (0, import_runtime_core48.ref)(0);
3235
+ const memoryMB = (0, import_runtime_core48.ref)(0);
3236
+ const bridgeOps = (0, import_runtime_core48.ref)(0);
2975
3237
  let unsubscribe = null;
2976
3238
  function handleMetrics(payload) {
2977
3239
  fps.value = payload.fps ?? 0;
@@ -2996,7 +3258,7 @@ function usePerformance() {
2996
3258
  async function getMetrics() {
2997
3259
  return NativeBridge.invokeNativeModule("Performance", "getMetrics", []);
2998
3260
  }
2999
- (0, import_runtime_core47.onUnmounted)(() => {
3261
+ (0, import_runtime_core48.onUnmounted)(() => {
3000
3262
  if (isProfiling.value) {
3001
3263
  NativeBridge.invokeNativeModule("Performance", "stopProfiling", []).catch(() => {
3002
3264
  });
@@ -3019,10 +3281,10 @@ function usePerformance() {
3019
3281
  }
3020
3282
 
3021
3283
  // src/composables/useSharedElementTransition.ts
3022
- var import_runtime_core48 = require("@vue/runtime-core");
3284
+ var import_runtime_core49 = require("@vue/runtime-core");
3023
3285
  var sharedElementRegistry = /* @__PURE__ */ new Map();
3024
3286
  function useSharedElementTransition(elementId) {
3025
- const viewId = (0, import_runtime_core48.ref)(null);
3287
+ const viewId = (0, import_runtime_core49.ref)(null);
3026
3288
  function register(nativeViewId) {
3027
3289
  viewId.value = nativeViewId;
3028
3290
  sharedElementRegistry.set(elementId, nativeViewId);
@@ -3031,7 +3293,7 @@ function useSharedElementTransition(elementId) {
3031
3293
  viewId.value = null;
3032
3294
  sharedElementRegistry.delete(elementId);
3033
3295
  }
3034
- (0, import_runtime_core48.onUnmounted)(() => {
3296
+ (0, import_runtime_core49.onUnmounted)(() => {
3035
3297
  unregister();
3036
3298
  });
3037
3299
  return {
@@ -3055,11 +3317,11 @@ function clearSharedElementRegistry() {
3055
3317
  }
3056
3318
 
3057
3319
  // src/composables/useIAP.ts
3058
- var import_runtime_core49 = require("@vue/runtime-core");
3320
+ var import_runtime_core50 = require("@vue/runtime-core");
3059
3321
  function useIAP() {
3060
- const products = (0, import_runtime_core49.ref)([]);
3061
- const isReady = (0, import_runtime_core49.ref)(false);
3062
- const error = (0, import_runtime_core49.ref)(null);
3322
+ const products = (0, import_runtime_core50.ref)([]);
3323
+ const isReady = (0, import_runtime_core50.ref)(false);
3324
+ const error = (0, import_runtime_core50.ref)(null);
3063
3325
  const cleanups = [];
3064
3326
  const unsubscribe = NativeBridge.onGlobalEvent("iap:transactionUpdate", (payload) => {
3065
3327
  if (payload.state === "failed" && payload.error) {
@@ -3116,7 +3378,7 @@ function useIAP() {
3116
3378
  cleanups.push(unsub);
3117
3379
  return unsub;
3118
3380
  }
3119
- (0, import_runtime_core49.onUnmounted)(() => {
3381
+ (0, import_runtime_core50.onUnmounted)(() => {
3120
3382
  cleanups.forEach((fn) => fn());
3121
3383
  cleanups.length = 0;
3122
3384
  });
@@ -3133,11 +3395,11 @@ function useIAP() {
3133
3395
  }
3134
3396
 
3135
3397
  // src/composables/useAppleSignIn.ts
3136
- var import_runtime_core50 = require("@vue/runtime-core");
3398
+ var import_runtime_core51 = require("@vue/runtime-core");
3137
3399
  function useAppleSignIn() {
3138
- const user = (0, import_runtime_core50.ref)(null);
3139
- const isAuthenticated = (0, import_runtime_core50.ref)(false);
3140
- const error = (0, import_runtime_core50.ref)(null);
3400
+ const user = (0, import_runtime_core51.ref)(null);
3401
+ const isAuthenticated = (0, import_runtime_core51.ref)(false);
3402
+ const error = (0, import_runtime_core51.ref)(null);
3141
3403
  const cleanups = [];
3142
3404
  const unsubscribe = NativeBridge.onGlobalEvent("auth:appleCredentialRevoked", () => {
3143
3405
  user.value = null;
@@ -3175,7 +3437,7 @@ function useAppleSignIn() {
3175
3437
  error.value = String(err);
3176
3438
  }
3177
3439
  }
3178
- (0, import_runtime_core50.onUnmounted)(() => {
3440
+ (0, import_runtime_core51.onUnmounted)(() => {
3179
3441
  cleanups.forEach((fn) => fn());
3180
3442
  cleanups.length = 0;
3181
3443
  });
@@ -3183,11 +3445,11 @@ function useAppleSignIn() {
3183
3445
  }
3184
3446
 
3185
3447
  // src/composables/useGoogleSignIn.ts
3186
- var import_runtime_core51 = require("@vue/runtime-core");
3448
+ var import_runtime_core52 = require("@vue/runtime-core");
3187
3449
  function useGoogleSignIn(clientId) {
3188
- const user = (0, import_runtime_core51.ref)(null);
3189
- const isAuthenticated = (0, import_runtime_core51.ref)(false);
3190
- const error = (0, import_runtime_core51.ref)(null);
3450
+ const user = (0, import_runtime_core52.ref)(null);
3451
+ const isAuthenticated = (0, import_runtime_core52.ref)(false);
3452
+ const error = (0, import_runtime_core52.ref)(null);
3191
3453
  const cleanups = [];
3192
3454
  NativeBridge.invokeNativeModule("SocialAuth", "getCurrentUser", ["google"]).then((result) => {
3193
3455
  if (result && result.userId) {
@@ -3220,7 +3482,7 @@ function useGoogleSignIn(clientId) {
3220
3482
  error.value = String(err);
3221
3483
  }
3222
3484
  }
3223
- (0, import_runtime_core51.onUnmounted)(() => {
3485
+ (0, import_runtime_core52.onUnmounted)(() => {
3224
3486
  cleanups.forEach((fn) => fn());
3225
3487
  cleanups.length = 0;
3226
3488
  });
@@ -3228,17 +3490,17 @@ function useGoogleSignIn(clientId) {
3228
3490
  }
3229
3491
 
3230
3492
  // src/composables/useBackgroundTask.ts
3231
- var import_runtime_core52 = require("@vue/runtime-core");
3493
+ var import_runtime_core53 = require("@vue/runtime-core");
3232
3494
  function useBackgroundTask() {
3233
3495
  const taskHandlers = /* @__PURE__ */ new Map();
3234
- const defaultHandler = (0, import_runtime_core52.ref)(null);
3496
+ const defaultHandler = (0, import_runtime_core53.ref)(null);
3235
3497
  const unsubscribe = NativeBridge.onGlobalEvent("background:taskExecute", (payload) => {
3236
3498
  const handler = taskHandlers.get(payload.taskId) || defaultHandler.value;
3237
3499
  if (handler) {
3238
3500
  handler(payload.taskId);
3239
3501
  }
3240
3502
  });
3241
- (0, import_runtime_core52.onUnmounted)(unsubscribe);
3503
+ (0, import_runtime_core53.onUnmounted)(unsubscribe);
3242
3504
  function registerTask(taskId) {
3243
3505
  return NativeBridge.invokeNativeModule("BackgroundTask", "registerTask", [taskId]).then(() => void 0);
3244
3506
  }
@@ -3277,20 +3539,20 @@ function useBackgroundTask() {
3277
3539
  }
3278
3540
 
3279
3541
  // src/composables/useOTAUpdate.ts
3280
- var import_runtime_core53 = require("@vue/runtime-core");
3542
+ var import_runtime_core54 = require("@vue/runtime-core");
3281
3543
  function useOTAUpdate(serverUrl) {
3282
- const currentVersion = (0, import_runtime_core53.ref)("embedded");
3283
- const availableVersion = (0, import_runtime_core53.ref)(null);
3284
- const downloadProgress = (0, import_runtime_core53.ref)(0);
3285
- const isChecking = (0, import_runtime_core53.ref)(false);
3286
- const isDownloading = (0, import_runtime_core53.ref)(false);
3287
- const status = (0, import_runtime_core53.ref)("idle");
3288
- const error = (0, import_runtime_core53.ref)(null);
3544
+ const currentVersion = (0, import_runtime_core54.ref)("embedded");
3545
+ const availableVersion = (0, import_runtime_core54.ref)(null);
3546
+ const downloadProgress = (0, import_runtime_core54.ref)(0);
3547
+ const isChecking = (0, import_runtime_core54.ref)(false);
3548
+ const isDownloading = (0, import_runtime_core54.ref)(false);
3549
+ const status = (0, import_runtime_core54.ref)("idle");
3550
+ const error = (0, import_runtime_core54.ref)(null);
3289
3551
  let lastUpdateInfo = null;
3290
3552
  const unsubscribe = NativeBridge.onGlobalEvent("ota:downloadProgress", (payload) => {
3291
3553
  downloadProgress.value = payload.progress;
3292
3554
  });
3293
- (0, import_runtime_core53.onUnmounted)(unsubscribe);
3555
+ (0, import_runtime_core54.onUnmounted)(unsubscribe);
3294
3556
  NativeBridge.invokeNativeModule("OTA", "getCurrentVersion", []).then((info) => {
3295
3557
  currentVersion.value = info.version;
3296
3558
  }).catch(() => {
@@ -3402,13 +3664,13 @@ function useOTAUpdate(serverUrl) {
3402
3664
  }
3403
3665
 
3404
3666
  // src/composables/useBluetooth.ts
3405
- var import_runtime_core54 = require("@vue/runtime-core");
3667
+ var import_runtime_core55 = require("@vue/runtime-core");
3406
3668
  function useBluetooth() {
3407
- const devices = (0, import_runtime_core54.ref)([]);
3408
- const connectedDevice = (0, import_runtime_core54.ref)(null);
3409
- const isScanning = (0, import_runtime_core54.ref)(false);
3410
- const isAvailable = (0, import_runtime_core54.ref)(false);
3411
- const error = (0, import_runtime_core54.ref)(null);
3669
+ const devices = (0, import_runtime_core55.ref)([]);
3670
+ const connectedDevice = (0, import_runtime_core55.ref)(null);
3671
+ const isScanning = (0, import_runtime_core55.ref)(false);
3672
+ const isAvailable = (0, import_runtime_core55.ref)(false);
3673
+ const error = (0, import_runtime_core55.ref)(null);
3412
3674
  const cleanups = [];
3413
3675
  NativeBridge.invokeNativeModule("Bluetooth", "getState").then((state) => {
3414
3676
  isAvailable.value = state === "poweredOn";
@@ -3487,7 +3749,7 @@ function useBluetooth() {
3487
3749
  ]);
3488
3750
  };
3489
3751
  }
3490
- (0, import_runtime_core54.onUnmounted)(() => {
3752
+ (0, import_runtime_core55.onUnmounted)(() => {
3491
3753
  if (isScanning.value) {
3492
3754
  NativeBridge.invokeNativeModule("Bluetooth", "stopScan").catch(() => {
3493
3755
  });
@@ -3512,10 +3774,10 @@ function useBluetooth() {
3512
3774
  }
3513
3775
 
3514
3776
  // src/composables/useCalendar.ts
3515
- var import_runtime_core55 = require("@vue/runtime-core");
3777
+ var import_runtime_core56 = require("@vue/runtime-core");
3516
3778
  function useCalendar() {
3517
- const hasAccess = (0, import_runtime_core55.ref)(false);
3518
- const error = (0, import_runtime_core55.ref)(null);
3779
+ const hasAccess = (0, import_runtime_core56.ref)(false);
3780
+ const error = (0, import_runtime_core56.ref)(null);
3519
3781
  async function requestAccess() {
3520
3782
  try {
3521
3783
  const result = await NativeBridge.invokeNativeModule("Calendar", "requestAccess");
@@ -3548,10 +3810,10 @@ function useCalendar() {
3548
3810
  }
3549
3811
 
3550
3812
  // src/composables/useContacts.ts
3551
- var import_runtime_core56 = require("@vue/runtime-core");
3813
+ var import_runtime_core57 = require("@vue/runtime-core");
3552
3814
  function useContacts() {
3553
- const hasAccess = (0, import_runtime_core56.ref)(false);
3554
- const error = (0, import_runtime_core56.ref)(null);
3815
+ const hasAccess = (0, import_runtime_core57.ref)(false);
3816
+ const error = (0, import_runtime_core57.ref)(null);
3555
3817
  async function requestAccess() {
3556
3818
  try {
3557
3819
  const result = await NativeBridge.invokeNativeModule("Contacts", "requestAccess");
@@ -3577,6 +3839,52 @@ function useContacts() {
3577
3839
  return { requestAccess, getContacts, getContact, createContact, deleteContact, hasAccess, error };
3578
3840
  }
3579
3841
 
3842
+ // src/theme.ts
3843
+ var import_runtime_core58 = require("@vue/runtime-core");
3844
+ function createTheme(definition) {
3845
+ const key = /* @__PURE__ */ Symbol("vue-native-theme");
3846
+ const ThemeProvider = (0, import_runtime_core58.defineComponent)({
3847
+ name: "ThemeProvider",
3848
+ props: {
3849
+ initialColorScheme: {
3850
+ type: String,
3851
+ default: "light"
3852
+ }
3853
+ },
3854
+ setup(props, { slots }) {
3855
+ const colorScheme = (0, import_runtime_core58.ref)(props.initialColorScheme);
3856
+ const theme = (0, import_runtime_core58.computed)(() => {
3857
+ return colorScheme.value === "dark" ? definition.dark : definition.light;
3858
+ });
3859
+ const ctx = {
3860
+ theme,
3861
+ colorScheme,
3862
+ toggleColorScheme: () => {
3863
+ colorScheme.value = colorScheme.value === "light" ? "dark" : "light";
3864
+ },
3865
+ setColorScheme: (scheme) => {
3866
+ colorScheme.value = scheme;
3867
+ }
3868
+ };
3869
+ (0, import_runtime_core58.provide)(key, ctx);
3870
+ return () => slots.default?.();
3871
+ }
3872
+ });
3873
+ function useTheme() {
3874
+ const ctx = (0, import_runtime_core58.inject)(key);
3875
+ if (!ctx) {
3876
+ throw new Error(
3877
+ "[Vue Native] useTheme() was called outside of a <ThemeProvider>. Wrap your app root with <ThemeProvider> to provide theme context."
3878
+ );
3879
+ }
3880
+ return ctx;
3881
+ }
3882
+ return { ThemeProvider, useTheme };
3883
+ }
3884
+ function createDynamicStyleSheet(theme, factory) {
3885
+ return (0, import_runtime_core58.computed)(() => createStyleSheet(factory(theme.value)));
3886
+ }
3887
+
3580
3888
  // src/index.ts
3581
3889
  function createApp(rootComponent, rootProps) {
3582
3890
  const app = baseCreateApp(rootComponent, rootProps);
@@ -3607,6 +3915,7 @@ function createApp(rootComponent, rootProps) {
3607
3915
  app.component("VRadio", VRadio);
3608
3916
  app.component("VDropdown", VDropdown);
3609
3917
  app.component("VVideo", VVideo);
3918
+ app.component("VFlatList", VFlatList);
3610
3919
  app.component("ErrorBoundary", ErrorBoundary);
3611
3920
  app.component("VErrorBoundary", ErrorBoundary);
3612
3921
  app.directive("show", vShow);
@@ -3635,7 +3944,7 @@ function createApp(rootComponent, rootProps) {
3635
3944
  const root = createNativeNode("__ROOT__");
3636
3945
  NativeBridge.createNode(root.id, "__ROOT__");
3637
3946
  NativeBridge.setRootView(root.id);
3638
- const vnode = (0, import_runtime_core57.createVNode)(rootComponent, rootProps);
3947
+ const vnode = (0, import_runtime_core59.createVNode)(rootComponent, rootProps);
3639
3948
  vnode.appContext = app._context;
3640
3949
  render(vnode, root);
3641
3950
  return root;
@@ -3652,6 +3961,7 @@ function createApp(rootComponent, rootProps) {
3652
3961
  VButton,
3653
3962
  VCheckbox,
3654
3963
  VDropdown,
3964
+ VFlatList,
3655
3965
  VImage,
3656
3966
  VInput,
3657
3967
  VKeyboardAvoiding,
@@ -3676,9 +3986,11 @@ function createApp(rootComponent, rootProps) {
3676
3986
  clearSharedElementRegistry,
3677
3987
  createApp,
3678
3988
  createCommentNode,
3989
+ createDynamicStyleSheet,
3679
3990
  createNativeNode,
3680
3991
  createStyleSheet,
3681
3992
  createTextNode,
3993
+ createTheme,
3682
3994
  getRegisteredSharedElements,
3683
3995
  getSharedElementViewId,
3684
3996
  measureViewFrame,