@srsergio/taptapp-ar 1.0.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.
Files changed (207) hide show
  1. package/README.md +62 -0
  2. package/dist/compiler/aframe.d.ts +1 -0
  3. package/dist/compiler/aframe.js +275 -0
  4. package/dist/compiler/compiler-base.d.ts +12 -0
  5. package/dist/compiler/compiler-base.js +165 -0
  6. package/dist/compiler/compiler.d.ts +9 -0
  7. package/dist/compiler/compiler.js +24 -0
  8. package/dist/compiler/compiler.worker.d.ts +1 -0
  9. package/dist/compiler/compiler.worker.js +28 -0
  10. package/dist/compiler/controller.d.ts +101 -0
  11. package/dist/compiler/controller.js +400 -0
  12. package/dist/compiler/controller.worker.d.ts +1 -0
  13. package/dist/compiler/controller.worker.js +61 -0
  14. package/dist/compiler/detector/crop-detector.d.ts +65 -0
  15. package/dist/compiler/detector/crop-detector.js +59 -0
  16. package/dist/compiler/detector/detector.d.ts +98 -0
  17. package/dist/compiler/detector/detector.js +1049 -0
  18. package/dist/compiler/detector/freak.d.ts +1 -0
  19. package/dist/compiler/detector/freak.js +89 -0
  20. package/dist/compiler/detector/kernels/cpu/binomialFilter.d.ts +6 -0
  21. package/dist/compiler/detector/kernels/cpu/binomialFilter.js +51 -0
  22. package/dist/compiler/detector/kernels/cpu/buildExtremas.d.ts +6 -0
  23. package/dist/compiler/detector/kernels/cpu/buildExtremas.js +89 -0
  24. package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.d.ts +7 -0
  25. package/dist/compiler/detector/kernels/cpu/computeExtremaAngles.js +79 -0
  26. package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.d.ts +6 -0
  27. package/dist/compiler/detector/kernels/cpu/computeExtremaFreak.js +68 -0
  28. package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.d.ts +6 -0
  29. package/dist/compiler/detector/kernels/cpu/computeFreakDescriptors.js +57 -0
  30. package/dist/compiler/detector/kernels/cpu/computeLocalization.d.ts +6 -0
  31. package/dist/compiler/detector/kernels/cpu/computeLocalization.js +54 -0
  32. package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.d.ts +6 -0
  33. package/dist/compiler/detector/kernels/cpu/computeOrientationHistograms.js +118 -0
  34. package/dist/compiler/detector/kernels/cpu/downsampleBilinear.d.ts +6 -0
  35. package/dist/compiler/detector/kernels/cpu/downsampleBilinear.js +29 -0
  36. package/dist/compiler/detector/kernels/cpu/extremaReduction.d.ts +6 -0
  37. package/dist/compiler/detector/kernels/cpu/extremaReduction.js +50 -0
  38. package/dist/compiler/detector/kernels/cpu/fakeShader.d.ts +20 -0
  39. package/dist/compiler/detector/kernels/cpu/fakeShader.js +80 -0
  40. package/dist/compiler/detector/kernels/cpu/index.d.ts +1 -0
  41. package/dist/compiler/detector/kernels/cpu/index.js +25 -0
  42. package/dist/compiler/detector/kernels/cpu/prune.d.ts +1 -0
  43. package/dist/compiler/detector/kernels/cpu/prune.js +103 -0
  44. package/dist/compiler/detector/kernels/cpu/smoothHistograms.d.ts +6 -0
  45. package/dist/compiler/detector/kernels/cpu/smoothHistograms.js +47 -0
  46. package/dist/compiler/detector/kernels/cpu/upsampleBilinear.d.ts +6 -0
  47. package/dist/compiler/detector/kernels/cpu/upsampleBilinear.js +43 -0
  48. package/dist/compiler/detector/kernels/index.d.ts +1 -0
  49. package/dist/compiler/detector/kernels/index.js +2 -0
  50. package/dist/compiler/detector/kernels/webgl/binomialFilter.d.ts +6 -0
  51. package/dist/compiler/detector/kernels/webgl/binomialFilter.js +67 -0
  52. package/dist/compiler/detector/kernels/webgl/buildExtremas.d.ts +6 -0
  53. package/dist/compiler/detector/kernels/webgl/buildExtremas.js +101 -0
  54. package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.d.ts +6 -0
  55. package/dist/compiler/detector/kernels/webgl/computeExtremaAngles.js +78 -0
  56. package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.d.ts +6 -0
  57. package/dist/compiler/detector/kernels/webgl/computeExtremaFreak.js +86 -0
  58. package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.d.ts +6 -0
  59. package/dist/compiler/detector/kernels/webgl/computeFreakDescriptors.js +52 -0
  60. package/dist/compiler/detector/kernels/webgl/computeLocalization.d.ts +6 -0
  61. package/dist/compiler/detector/kernels/webgl/computeLocalization.js +58 -0
  62. package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.d.ts +6 -0
  63. package/dist/compiler/detector/kernels/webgl/computeOrientationHistograms.js +116 -0
  64. package/dist/compiler/detector/kernels/webgl/downsampleBilinear.d.ts +6 -0
  65. package/dist/compiler/detector/kernels/webgl/downsampleBilinear.js +46 -0
  66. package/dist/compiler/detector/kernels/webgl/extremaReduction.d.ts +6 -0
  67. package/dist/compiler/detector/kernels/webgl/extremaReduction.js +48 -0
  68. package/dist/compiler/detector/kernels/webgl/index.d.ts +1 -0
  69. package/dist/compiler/detector/kernels/webgl/index.js +25 -0
  70. package/dist/compiler/detector/kernels/webgl/smoothHistograms.d.ts +6 -0
  71. package/dist/compiler/detector/kernels/webgl/smoothHistograms.js +49 -0
  72. package/dist/compiler/detector/kernels/webgl/upsampleBilinear.d.ts +6 -0
  73. package/dist/compiler/detector/kernels/webgl/upsampleBilinear.js +56 -0
  74. package/dist/compiler/estimation/esimate-experiment.d.ts +5 -0
  75. package/dist/compiler/estimation/esimate-experiment.js +267 -0
  76. package/dist/compiler/estimation/estimate.d.ts +5 -0
  77. package/dist/compiler/estimation/estimate.js +51 -0
  78. package/dist/compiler/estimation/estimator.d.ts +13 -0
  79. package/dist/compiler/estimation/estimator.js +30 -0
  80. package/dist/compiler/estimation/refine-estimate-experiment.d.ts +6 -0
  81. package/dist/compiler/estimation/refine-estimate-experiment.js +429 -0
  82. package/dist/compiler/estimation/refine-estimate.d.ts +6 -0
  83. package/dist/compiler/estimation/refine-estimate.js +299 -0
  84. package/dist/compiler/estimation/utils.d.ts +10 -0
  85. package/dist/compiler/estimation/utils.js +80 -0
  86. package/dist/compiler/image-list.d.ts +13 -0
  87. package/dist/compiler/image-list.js +52 -0
  88. package/dist/compiler/index.d.ts +3 -0
  89. package/dist/compiler/index.js +10 -0
  90. package/dist/compiler/input-loader.d.ts +23 -0
  91. package/dist/compiler/input-loader.js +88 -0
  92. package/dist/compiler/matching/hamming-distance.d.ts +1 -0
  93. package/dist/compiler/matching/hamming-distance.js +20 -0
  94. package/dist/compiler/matching/hierarchical-clustering.d.ts +7 -0
  95. package/dist/compiler/matching/hierarchical-clustering.js +109 -0
  96. package/dist/compiler/matching/hough.d.ts +1 -0
  97. package/dist/compiler/matching/hough.js +169 -0
  98. package/dist/compiler/matching/matcher.d.ts +28 -0
  99. package/dist/compiler/matching/matcher.js +48 -0
  100. package/dist/compiler/matching/matching.d.ts +41 -0
  101. package/dist/compiler/matching/matching.js +197 -0
  102. package/dist/compiler/matching/ransacHomography.d.ts +1 -0
  103. package/dist/compiler/matching/ransacHomography.js +136 -0
  104. package/dist/compiler/offline-compiler.d.ts +10 -0
  105. package/dist/compiler/offline-compiler.js +450 -0
  106. package/dist/compiler/tensorflow-setup.d.ts +7 -0
  107. package/dist/compiler/tensorflow-setup.js +73 -0
  108. package/dist/compiler/three.d.ts +66 -0
  109. package/dist/compiler/three.js +310 -0
  110. package/dist/compiler/tracker/extract-utils.d.ts +1 -0
  111. package/dist/compiler/tracker/extract-utils.js +29 -0
  112. package/dist/compiler/tracker/extract.d.ts +4 -0
  113. package/dist/compiler/tracker/extract.js +349 -0
  114. package/dist/compiler/tracker/tracker.d.ts +38 -0
  115. package/dist/compiler/tracker/tracker.js +327 -0
  116. package/dist/compiler/utils/cumsum.d.ts +5 -0
  117. package/dist/compiler/utils/cumsum.js +39 -0
  118. package/dist/compiler/utils/geometry.d.ts +8 -0
  119. package/dist/compiler/utils/geometry.js +101 -0
  120. package/dist/compiler/utils/homography.d.ts +1 -0
  121. package/dist/compiler/utils/homography.js +138 -0
  122. package/dist/compiler/utils/images.d.ts +24 -0
  123. package/dist/compiler/utils/images.js +99 -0
  124. package/dist/compiler/utils/randomizer.d.ts +5 -0
  125. package/dist/compiler/utils/randomizer.js +25 -0
  126. package/dist/index.d.ts +6 -0
  127. package/dist/index.js +7 -0
  128. package/dist/react/AREditor.d.ts +5 -0
  129. package/dist/react/AREditor.js +159 -0
  130. package/dist/react/ProgressDialog.d.ts +13 -0
  131. package/dist/react/ProgressDialog.js +57 -0
  132. package/dist/react/types.d.ts +22 -0
  133. package/dist/react/types.js +14 -0
  134. package/package.json +53 -0
  135. package/src/astro/ARScene.astro +59 -0
  136. package/src/astro/ARVideoTrigger.astro +73 -0
  137. package/src/astro/overlays/ErrorOverlay.astro +40 -0
  138. package/src/astro/overlays/LoadingOverlay.astro +28 -0
  139. package/src/astro/overlays/ScanningOverlay.astro +119 -0
  140. package/src/astro/scripts/ARScripts.astro +118 -0
  141. package/src/astro/styles/ARStyles.astro +147 -0
  142. package/src/compiler/aframe.js +343 -0
  143. package/src/compiler/compiler-base.js +195 -0
  144. package/src/compiler/compiler.js +25 -0
  145. package/src/compiler/compiler.worker.js +30 -0
  146. package/src/compiler/controller.js +473 -0
  147. package/src/compiler/controller.worker.js +77 -0
  148. package/src/compiler/detector/crop-detector.js +68 -0
  149. package/src/compiler/detector/detector.js +1130 -0
  150. package/src/compiler/detector/freak.js +91 -0
  151. package/src/compiler/detector/kernels/cpu/binomialFilter.js +59 -0
  152. package/src/compiler/detector/kernels/cpu/buildExtremas.js +108 -0
  153. package/src/compiler/detector/kernels/cpu/computeExtremaAngles.js +91 -0
  154. package/src/compiler/detector/kernels/cpu/computeExtremaFreak.js +92 -0
  155. package/src/compiler/detector/kernels/cpu/computeFreakDescriptors.js +68 -0
  156. package/src/compiler/detector/kernels/cpu/computeLocalization.js +71 -0
  157. package/src/compiler/detector/kernels/cpu/computeOrientationHistograms.js +141 -0
  158. package/src/compiler/detector/kernels/cpu/downsampleBilinear.js +33 -0
  159. package/src/compiler/detector/kernels/cpu/extremaReduction.js +53 -0
  160. package/src/compiler/detector/kernels/cpu/fakeShader.js +88 -0
  161. package/src/compiler/detector/kernels/cpu/index.js +26 -0
  162. package/src/compiler/detector/kernels/cpu/prune.js +114 -0
  163. package/src/compiler/detector/kernels/cpu/smoothHistograms.js +57 -0
  164. package/src/compiler/detector/kernels/cpu/upsampleBilinear.js +51 -0
  165. package/src/compiler/detector/kernels/index.js +2 -0
  166. package/src/compiler/detector/kernels/webgl/binomialFilter.js +72 -0
  167. package/src/compiler/detector/kernels/webgl/buildExtremas.js +109 -0
  168. package/src/compiler/detector/kernels/webgl/computeExtremaAngles.js +82 -0
  169. package/src/compiler/detector/kernels/webgl/computeExtremaFreak.js +105 -0
  170. package/src/compiler/detector/kernels/webgl/computeFreakDescriptors.js +56 -0
  171. package/src/compiler/detector/kernels/webgl/computeLocalization.js +70 -0
  172. package/src/compiler/detector/kernels/webgl/computeOrientationHistograms.js +129 -0
  173. package/src/compiler/detector/kernels/webgl/downsampleBilinear.js +50 -0
  174. package/src/compiler/detector/kernels/webgl/extremaReduction.js +50 -0
  175. package/src/compiler/detector/kernels/webgl/index.js +26 -0
  176. package/src/compiler/detector/kernels/webgl/smoothHistograms.js +53 -0
  177. package/src/compiler/detector/kernels/webgl/upsampleBilinear.js +62 -0
  178. package/src/compiler/estimation/esimate-experiment.js +316 -0
  179. package/src/compiler/estimation/estimate.js +67 -0
  180. package/src/compiler/estimation/estimator.js +34 -0
  181. package/src/compiler/estimation/refine-estimate-experiment.js +512 -0
  182. package/src/compiler/estimation/refine-estimate.js +365 -0
  183. package/src/compiler/estimation/utils.js +97 -0
  184. package/src/compiler/image-list.js +62 -0
  185. package/src/compiler/index.js +13 -0
  186. package/src/compiler/input-loader.js +107 -0
  187. package/src/compiler/matching/hamming-distance.js +23 -0
  188. package/src/compiler/matching/hierarchical-clustering.js +131 -0
  189. package/src/compiler/matching/hough.js +206 -0
  190. package/src/compiler/matching/matcher.js +59 -0
  191. package/src/compiler/matching/matching.js +237 -0
  192. package/src/compiler/matching/ransacHomography.js +192 -0
  193. package/src/compiler/offline-compiler.js +553 -0
  194. package/src/compiler/tensorflow-setup.js +88 -0
  195. package/src/compiler/three.js +368 -0
  196. package/src/compiler/tracker/extract-utils.js +34 -0
  197. package/src/compiler/tracker/extract.js +419 -0
  198. package/src/compiler/tracker/tracker.js +397 -0
  199. package/src/compiler/utils/cumsum.js +40 -0
  200. package/src/compiler/utils/geometry.js +114 -0
  201. package/src/compiler/utils/homography.js +150 -0
  202. package/src/compiler/utils/images.js +111 -0
  203. package/src/compiler/utils/randomizer.js +29 -0
  204. package/src/index.ts +8 -0
  205. package/src/react/AREditor.tsx +394 -0
  206. package/src/react/ProgressDialog.tsx +185 -0
  207. package/src/react/types.ts +35 -0
@@ -0,0 +1,99 @@
1
+ // simpler version of upsampling. better performance
2
+ const _upsampleBilinear = ({ image, padOneWidth, padOneHeight }) => {
3
+ const { width, height, data } = image;
4
+ const dstWidth = image.width * 2 + (padOneWidth ? 1 : 0);
5
+ const dstHeight = image.height * 2 + (padOneHeight ? 1 : 0);
6
+ const temp = new Float32Array(dstWidth * dstHeight);
7
+ for (let i = 0; i < width; i++) {
8
+ for (let j = 0; j < height; j++) {
9
+ const v = 0.25 * data[j * width + i];
10
+ const ii = Math.floor(i / 2);
11
+ const jj = Math.floor(j / 2);
12
+ const pos = Math.floor(j / 2) * dstWidth + Math.floor(i / 2);
13
+ temp[pos] += v;
14
+ temp[pos + 1] += v;
15
+ temp[pos + dstWidth] += v;
16
+ temp[pos + dstWidth + 1] += v;
17
+ }
18
+ }
19
+ return { data: temp, width: dstWidth, height: dstHeight };
20
+ };
21
+ // artoolkit version. slower. is it necessary?
22
+ const upsampleBilinear = ({ image, padOneWidth, padOneHeight }) => {
23
+ const { width, height, data } = image;
24
+ const dstWidth = image.width * 2 + (padOneWidth ? 1 : 0);
25
+ const dstHeight = image.height * 2 + (padOneHeight ? 1 : 0);
26
+ const temp = new Float32Array(dstWidth * dstHeight);
27
+ for (let i = 0; i < dstWidth; i++) {
28
+ const si = 0.5 * i - 0.25;
29
+ let si0 = Math.floor(si);
30
+ let si1 = Math.ceil(si);
31
+ if (si0 < 0)
32
+ si0 = 0; // border
33
+ if (si1 >= width)
34
+ si1 = width - 1; // border
35
+ for (let j = 0; j < dstHeight; j++) {
36
+ const sj = 0.5 * j - 0.25;
37
+ let sj0 = Math.floor(sj);
38
+ let sj1 = Math.ceil(sj);
39
+ if (sj0 < 0)
40
+ sj0 = 0; // border
41
+ if (sj1 >= height)
42
+ sj1 = height - 1; //border
43
+ const value = (si1 - si) * (sj1 - sj) * data[sj0 * width + si0] +
44
+ (si1 - si) * (sj - sj0) * data[sj1 * width + si0] +
45
+ (si - si0) * (sj1 - sj) * data[sj0 * width + si1] +
46
+ (si - si0) * (sj - sj0) * data[sj1 * width + si1];
47
+ temp[j * dstWidth + i] = value;
48
+ }
49
+ }
50
+ return { data: temp, width: dstWidth, height: dstHeight };
51
+ };
52
+ const downsampleBilinear = ({ image }) => {
53
+ const { data, width, height } = image;
54
+ const dstWidth = Math.floor(width / 2);
55
+ const dstHeight = Math.floor(height / 2);
56
+ const temp = new Float32Array(dstWidth * dstHeight);
57
+ const offsets = [0, 1, width, width + 1];
58
+ for (let j = 0; j < dstHeight; j++) {
59
+ for (let i = 0; i < dstWidth; i++) {
60
+ let srcPos = j * 2 * width + i * 2;
61
+ let value = 0.0;
62
+ for (let d = 0; d < offsets.length; d++) {
63
+ value += data[srcPos + offsets[d]];
64
+ }
65
+ value *= 0.25;
66
+ temp[j * dstWidth + i] = value;
67
+ }
68
+ }
69
+ return { data: temp, width: dstWidth, height: dstHeight };
70
+ };
71
+ const resize = ({ image, ratio }) => {
72
+ const width = Math.round(image.width * ratio);
73
+ const height = Math.round(image.height * ratio);
74
+ //const imageData = new Float32Array(width * height);
75
+ const imageData = new Uint8Array(width * height);
76
+ for (let i = 0; i < width; i++) {
77
+ let si1 = Math.round((1.0 * i) / ratio);
78
+ let si2 = Math.round((1.0 * (i + 1)) / ratio) - 1;
79
+ if (si2 >= image.width)
80
+ si2 = image.width - 1;
81
+ for (let j = 0; j < height; j++) {
82
+ let sj1 = Math.round((1.0 * j) / ratio);
83
+ let sj2 = Math.round((1.0 * (j + 1)) / ratio) - 1;
84
+ if (sj2 >= image.height)
85
+ sj2 = image.height - 1;
86
+ let sum = 0;
87
+ let count = 0;
88
+ for (let ii = si1; ii <= si2; ii++) {
89
+ for (let jj = sj1; jj <= sj2; jj++) {
90
+ sum += 1.0 * image.data[jj * image.width + ii];
91
+ count += 1;
92
+ }
93
+ }
94
+ imageData[j * width + i] = Math.floor(sum / count);
95
+ }
96
+ }
97
+ return { data: imageData, width: width, height: height };
98
+ };
99
+ export { downsampleBilinear, upsampleBilinear, resize };
@@ -0,0 +1,5 @@
1
+ export function createRandomizer(): {
2
+ seed: number;
3
+ arrayShuffle(options: any): void;
4
+ nextInt(maxValue: any): number;
5
+ };
@@ -0,0 +1,25 @@
1
+ const mRandSeed = 1234;
2
+ const createRandomizer = () => {
3
+ const randomizer = {
4
+ seed: mRandSeed,
5
+ arrayShuffle(options) {
6
+ const { arr, sampleSize } = options;
7
+ for (let i = 0; i < sampleSize; i++) {
8
+ this.seed = (214013 * this.seed + 2531011) % (1 << 31);
9
+ let k = (this.seed >> 16) & 0x7fff;
10
+ k = k % arr.length;
11
+ let tmp = arr[i];
12
+ arr[i] = arr[k];
13
+ arr[k] = tmp;
14
+ }
15
+ },
16
+ nextInt(maxValue) {
17
+ this.seed = (214013 * this.seed + 2531011) % (1 << 31);
18
+ let k = (this.seed >> 16) & 0x7fff;
19
+ k = k % maxValue;
20
+ return k;
21
+ },
22
+ };
23
+ return randomizer;
24
+ };
25
+ export { createRandomizer };
@@ -0,0 +1,6 @@
1
+ export * from "./react/AREditor";
2
+ export * from "./react/ProgressDialog";
3
+ export * from "./react/types";
4
+ export * from "./compiler/offline-compiler";
5
+ export { Controller } from "./compiler/controller";
6
+ export { Compiler } from "./compiler/compiler";
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export * from "./react/AREditor";
2
+ export * from "./react/ProgressDialog";
3
+ export * from "./react/types";
4
+ export * from "./compiler/offline-compiler";
5
+ // Re-export specific compiler components if needed
6
+ export { Controller } from "./compiler/controller";
7
+ export { Compiler } from "./compiler/compiler";
@@ -0,0 +1,5 @@
1
+ interface AREditorProps {
2
+ adminId: string;
3
+ }
4
+ export declare const AREditor: React.FC<AREditorProps>;
5
+ export {};
@@ -0,0 +1,159 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useRef, useCallback } from "react";
3
+ import { customAlphabet } from "nanoid";
4
+ import { Image, Video, Upload, Camera, LoaderCircle } from "lucide-react";
5
+ const ALLOWED_MIME_TYPES = ["image/jpeg", "image/png", "image/webp"];
6
+ const ALLOWED_VIDEO_TYPES = ["video/mp4", "video/webm"];
7
+ const useFileUpload = (allowedTypes) => {
8
+ const [fileState, setFileState] = useState({ file: null, preview: "" });
9
+ const [dimensions, setDimensions] = useState({});
10
+ const fileInputRef = useRef(null);
11
+ const handleFileChange = useCallback((file) => {
12
+ if (fileState.preview) {
13
+ URL.revokeObjectURL(fileState.preview);
14
+ }
15
+ if (!file) {
16
+ setFileState({ file: null, preview: "" });
17
+ return;
18
+ }
19
+ // Para archivos .mind, validar la extensión en lugar del tipo MIME
20
+ if (allowedTypes.includes(".mind")) {
21
+ if (!file.name.toLowerCase().endsWith(".mind")) {
22
+ throw new Error("El archivo debe tener extensión .mind");
23
+ }
24
+ }
25
+ else if (!allowedTypes.includes(file.type)) {
26
+ throw new Error("Tipo de archivo no permitido");
27
+ }
28
+ if (file.type.includes("video")) {
29
+ const video = document.createElement("video");
30
+ video.src = URL.createObjectURL(file);
31
+ }
32
+ console.log("Archivo cargado:", {
33
+ nombre: file.name,
34
+ tamaño: (file.size / 1024).toFixed(2) + " KB",
35
+ tipo: file.type || "application/octet-stream",
36
+ });
37
+ const preview = URL.createObjectURL(file);
38
+ if (file.type.includes("video")) {
39
+ const video = document.createElement("video");
40
+ video.src = URL.createObjectURL(file);
41
+ video.addEventListener("loadedmetadata", () => {
42
+ const width = video.videoWidth;
43
+ const height = video.videoHeight;
44
+ setDimensions({ width, height });
45
+ console.log("Ancho y alto del video:", width, height);
46
+ });
47
+ }
48
+ setFileState({ file, preview });
49
+ }, [allowedTypes, fileState.preview]);
50
+ const reset = useCallback(() => {
51
+ if (fileState.preview) {
52
+ URL.revokeObjectURL(fileState.preview);
53
+ }
54
+ setFileState({ file: null, preview: "" });
55
+ if (fileInputRef.current) {
56
+ fileInputRef.current.value = "";
57
+ }
58
+ }, [fileState.preview]);
59
+ return { fileState, handleFileChange, reset, fileInputRef, dimensions };
60
+ };
61
+ const useUploadFile = () => {
62
+ const uploadFile = async (file, type) => {
63
+ const customNanoid = customAlphabet("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ", 21);
64
+ const id = customNanoid();
65
+ const formData = new FormData();
66
+ formData.append("file", file);
67
+ const endpoint = type === "video"
68
+ ? `https://r2-worker.sergiolazaromondargo.workers.dev/video/${id}`
69
+ : type === "mind"
70
+ ? `https://r2-worker.sergiolazaromondargo.workers.dev/mind/${id}`
71
+ : `https://r2-worker.sergiolazaromondargo.workers.dev/${id}`;
72
+ const response = await fetch(endpoint, {
73
+ method: "PUT",
74
+ body: formData,
75
+ });
76
+ if (!response.ok) {
77
+ throw new Error(`Error al subir ${type}: ${response.status} ${response.statusText}`);
78
+ }
79
+ return await response.json();
80
+ };
81
+ return { uploadFile };
82
+ };
83
+ export const AREditor = ({ adminId }) => {
84
+ const { fileState: imageState, handleFileChange: handleImageChange, reset: resetImage, fileInputRef: imageInputRef, } = useFileUpload(ALLOWED_MIME_TYPES);
85
+ const { fileState: mindState, handleFileChange: handleMindChange, reset: resetMind, fileInputRef: mindInputRef, } = useFileUpload([".mind"]);
86
+ const { fileState: videoState, handleFileChange: handleVideoChange, reset: resetVideo, fileInputRef: videoInputRef, dimensions: videoDimensions, } = useFileUpload(ALLOWED_VIDEO_TYPES);
87
+ const [videoScale, setVideoScale] = useState(1);
88
+ const [loading, setLoading] = useState(false);
89
+ const [error, setError] = useState("");
90
+ const { uploadFile } = useUploadFile();
91
+ const handleSave = async () => {
92
+ try {
93
+ setLoading(true);
94
+ setError("");
95
+ if (!imageState.file || !mindState.file || !videoState.file) {
96
+ throw new Error("Se requieren una imagen, un archivo .mind y un video");
97
+ }
98
+ const [imageResult, mindResult, videoResult] = await Promise.all([
99
+ uploadFile(imageState.file, "image"),
100
+ uploadFile(mindState.file, "mind"),
101
+ uploadFile(videoState.file, "video"),
102
+ ]);
103
+ const data = {
104
+ adminId,
105
+ data: [
106
+ {
107
+ id: `photos-${Date.now()}`,
108
+ type: "photos",
109
+ images: [{ image: imageResult.url, fileId: imageResult.fileId }],
110
+ },
111
+ {
112
+ id: `videoNative-${Date.now()}`,
113
+ type: "videoNative",
114
+ url: videoResult.url,
115
+ fileId: videoResult.fileId,
116
+ scale: videoScale,
117
+ width: videoDimensions.width,
118
+ height: videoDimensions.height,
119
+ },
120
+ {
121
+ id: `ar-${Date.now()}`,
122
+ type: "ar",
123
+ url: mindResult.url,
124
+ fileId: mindResult.fileId,
125
+ },
126
+ ],
127
+ type: "ar",
128
+ };
129
+ const response = await fetch("/api/updateadmin.json", {
130
+ method: "POST",
131
+ headers: { "Content-Type": "application/json" },
132
+ body: JSON.stringify(data),
133
+ });
134
+ if (!response.ok) {
135
+ throw new Error(`Error actualizando datos AR: ${response.status}`);
136
+ }
137
+ alert("¡Guardado exitosamente!");
138
+ resetImage();
139
+ resetMind();
140
+ resetVideo();
141
+ }
142
+ catch (error) {
143
+ setError(error.message);
144
+ }
145
+ finally {
146
+ setLoading(false);
147
+ }
148
+ };
149
+ const FileUploadSection = ({ type, icon: Icon, fileState, inputRef, onFileChange, allowedTypes, label, }) => (_jsxs("div", { className: "group relative overflow-hidden rounded-xl shadow-lg bg-white/80 backdrop-blur-sm transition-all duration-300 hover:shadow-xl hover:scale-[1.02] border border-gray-100", children: [_jsx("input", { ref: inputRef, type: "file", accept: allowedTypes.join(","), onChange: (e) => {
150
+ try {
151
+ const file = e.target.files?.[0] || null;
152
+ onFileChange(file);
153
+ }
154
+ catch (error) {
155
+ setError(error.message);
156
+ }
157
+ }, className: "hidden" }), !fileState.file ? (_jsxs("label", { htmlFor: inputRef.current?.id, onClick: () => inputRef.current?.click(), className: "flex cursor-pointer flex-col items-center justify-center p-10 bg-gradient-to-br from-gray-50 to-white transition-colors group-hover:from-blue-50 group-hover:to-purple-50", children: [_jsx("div", { className: "transform transition-transform duration-300 group-hover:scale-110", children: _jsx(Icon, { className: "h-16 w-16 text-gray-400 group-hover:text-blue-500" }) }), _jsx("span", { className: "mt-4 text-lg font-medium bg-gradient-to-r from-gray-600 to-gray-800 bg-clip-text text-transparent group-hover:from-blue-600 group-hover:to-purple-600", children: label }), _jsx("span", { className: "mt-2 text-sm text-gray-400 group-hover:text-gray-500", children: allowedTypes.join(", ") })] })) : (_jsxs("div", { className: "p-6 space-y-4", children: [_jsx("div", { className: "relative aspect-video w-full overflow-hidden rounded-lg ring-1 ring-gray-100", children: type === "video" ? (_jsx("video", { src: fileState.preview, controls: true, className: "h-full w-full object-cover", children: "Tu navegador no soporta la reproducci\u00F3n de videos." })) : type === "image" ? (_jsx("img", { src: fileState.preview, alt: "Preview", className: "h-full w-full object-cover" })) : (_jsxs("div", { className: "flex h-full flex-col items-center justify-center space-y-3 bg-gradient-to-br from-blue-50 to-purple-50 p-4", children: [_jsx("div", { className: "flex items-center justify-center rounded-full bg-gradient-to-r from-blue-400 to-purple-400 p-3", children: _jsx(Upload, { className: "h-6 w-6 text-white" }) }), _jsxs("div", { className: "text-center space-y-2", children: [_jsx("span", { className: "block text-lg font-medium text-gray-600", children: fileState.file.name }), _jsxs("span", { className: "block text-sm text-gray-500", children: ["Tama\u00F1o: ", (fileState.file.size / 1024).toFixed(2), " KB"] }), _jsx("span", { className: "mt-1 block text-sm font-medium text-green-600", children: "\u2713 Archivo AR cargado correctamente" })] })] })) }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center space-x-3", children: [_jsx(Icon, { className: "h-5 w-5 text-blue-500" }), _jsx("span", { className: "text-sm font-medium text-gray-600", children: fileState.file.name })] }), _jsx("button", { onClick: () => onFileChange(null), className: "rounded-full bg-gradient-to-r from-blue-500 to-purple-500 px-4 py-2 text-sm font-medium text-white shadow-md transition-all hover:from-blue-600 hover:to-purple-600 hover:shadow-lg active:scale-95", children: "Cambiar" })] })] }))] }));
158
+ return (_jsx("div", { className: "min-h-screen w-full bg-gradient-to-br from-blue-50 via-white to-purple-50 p-4 md:p-8", children: _jsxs("div", { className: "mx-auto max-w-3xl rounded-3xl bg-white/90 backdrop-blur-md p-6 md:p-10 shadow-2xl ring-1 ring-black/10", children: [_jsxs("div", { className: "flex flex-col items-center justify-center space-y-8", children: [_jsx("div", { className: "rounded-2xl bg-gradient-to-br from-blue-500 to-purple-500 p-6 shadow-xl shadow-blue-300/30 hover:scale-105 transition-transform", children: _jsx(Camera, { className: "h-12 w-12 text-white" }) }), _jsx("h1", { className: "bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-5xl font-bold text-transparent text-center", children: "Editor de Experiencia AR" }), _jsx("p", { className: "text-2xl text-gray-600 text-center font-light", children: "Crea una experiencia de realidad aumentada \u00FAnica" })] }), _jsxs("div", { className: "mt-12 space-y-8", children: [_jsx(FileUploadSection, { type: "image", icon: Image, fileState: imageState, inputRef: imageInputRef, onFileChange: handleImageChange, allowedTypes: ALLOWED_MIME_TYPES, label: "Haz clic para seleccionar una imagen" }), _jsx(FileUploadSection, { type: "mind", icon: Upload, fileState: mindState, inputRef: mindInputRef, onFileChange: handleMindChange, allowedTypes: [".mind"], label: "Haz clic para seleccionar archivo .mind" }), _jsx(FileUploadSection, { type: "video", icon: Video, fileState: videoState, inputRef: videoInputRef, onFileChange: handleVideoChange, allowedTypes: ALLOWED_VIDEO_TYPES, label: "Haz clic para seleccionar un video" }), _jsxs("div", { className: "space-y-4 rounded-2xl border border-gray-200/50 bg-white/90 backdrop-blur-md p-8 shadow-lg ring-1 ring-black/10", children: [_jsxs("label", { className: "flex items-center justify-between text-2xl font-semibold text-gray-800", children: [_jsx("span", { children: "Escala del Video" }), _jsxs("span", { className: "bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent font-bold", children: [videoScale, "x"] })] }), _jsxs("div", { className: "relative py-8", children: [_jsx("div", { className: "absolute h-3 w-full rounded-full bg-gradient-to-r from-blue-400 to-purple-400 opacity-20" }), _jsx("div", { className: "absolute h-3 rounded-full bg-gradient-to-r from-blue-400 to-purple-400 shadow-lg", style: { width: `${(videoScale / 2) * 100}%` } }), _jsx("input", { type: "range", min: "0.1", max: "2", step: "0.1", value: videoScale, onChange: (e) => setVideoScale(Number(e.target.value)), className: "relative h-3 w-full cursor-pointer appearance-none rounded-lg bg-transparent focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-offset-4", style: { WebkitAppearance: "none" } })] })] })] }), error && (_jsx("div", { className: "mt-6 rounded-xl bg-red-50 p-4 text-red-700 shadow-sm ring-1 ring-red-100", children: error })), _jsx("button", { onClick: handleSave, disabled: loading, className: "mt-10 w-full rounded-xl bg-gradient-to-r from-blue-600 to-purple-600 py-5 text-xl font-semibold text-white shadow-xl transition-all hover:from-blue-700 hover:to-purple-700 disabled:from-gray-400 disabled:to-gray-400 disabled:shadow-none focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-offset-4", children: loading ? (_jsxs("div", { className: "flex items-center justify-center space-x-3", children: [_jsx(LoaderCircle, { className: "h-7 w-7 animate-spin" }), _jsx("span", { children: "Guardando..." })] })) : ("Guardar") })] }) }));
159
+ };
@@ -0,0 +1,13 @@
1
+ interface ProgressDialogProps {
2
+ open: boolean;
3
+ imageStatus: "pending" | "processing" | "completed" | "error";
4
+ videoStatus: "pending" | "processing" | "completed" | "error";
5
+ arProcessingStatus: "pending" | "processing" | "completed" | "error";
6
+ arUploadStatus: "pending" | "processing" | "completed" | "error";
7
+ imageProgress?: number;
8
+ videoProgress?: number;
9
+ arProcessingProgress?: number;
10
+ arUploadProgress?: number;
11
+ }
12
+ export declare function ProgressDialog({ open, imageStatus, videoStatus, arProcessingStatus, arUploadStatus, imageProgress, videoProgress, arProcessingProgress, arUploadProgress, }: ProgressDialogProps): import("react/jsx-runtime").JSX.Element | null;
13
+ export {};
@@ -0,0 +1,57 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect } from "react";
3
+ import { CheckCircle2, Loader2, Upload, Image as ImageIcon, Video as VideoIcon, } from "lucide-react";
4
+ export function ProgressDialog({ open, imageStatus, videoStatus, arProcessingStatus, arUploadStatus, imageProgress = 0, videoProgress = 0, arProcessingProgress = 0, arUploadProgress = 0, }) {
5
+ // Configurar las etapas del progreso
6
+ const stages = [
7
+ {
8
+ label: "Subiendo imagen",
9
+ status: imageStatus,
10
+ progress: imageProgress,
11
+ icon: _jsx(ImageIcon, { className: "h-5 w-5" }),
12
+ },
13
+ {
14
+ label: "Subiendo video",
15
+ status: videoStatus,
16
+ progress: videoProgress,
17
+ icon: _jsx(VideoIcon, { className: "h-5 w-5" }),
18
+ },
19
+ {
20
+ label: "Procesando imagen para AR",
21
+ status: arProcessingStatus,
22
+ progress: arProcessingProgress,
23
+ icon: _jsx(Loader2, { className: "h-5 w-5" }),
24
+ },
25
+ {
26
+ label: "Subiendo experiencia AR",
27
+ status: arUploadStatus,
28
+ progress: arUploadProgress,
29
+ icon: _jsx(Upload, { className: "h-5 w-5" }),
30
+ },
31
+ ];
32
+ // Calcular el progreso total (promedio de todos los procesos)
33
+ const completedSteps = stages.filter((stage) => stage.status === "completed").length;
34
+ const totalProgress = (imageProgress + videoProgress + arProcessingProgress + arUploadProgress) / 4;
35
+ const overallProgress = Math.min(Math.max(totalProgress, completedSteps * 25), 100);
36
+ // Bloquear el scroll cuando el modal está abierto
37
+ useEffect(() => {
38
+ if (open) {
39
+ document.body.style.overflow = "hidden";
40
+ }
41
+ else {
42
+ document.body.style.overflow = "auto";
43
+ }
44
+ return () => {
45
+ document.body.style.overflow = "auto";
46
+ };
47
+ }, [open]);
48
+ if (!open)
49
+ return null;
50
+ return (_jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center overflow-y-auto bg-black bg-opacity-50 p-4", children: _jsxs("div", { className: "relative max-h-full w-full max-w-md overflow-hidden rounded-lg bg-white p-6 shadow-xl", children: [_jsx("div", { className: "mb-4 flex items-center justify-between", children: _jsx("h2", { className: "text-center font-semibold text-xl", children: "Guardando experiencia AR" }) }), _jsx("div", { className: "mt-2", children: _jsx("div", { className: "relative pt-1", children: _jsxs("div", { className: "mb-6", children: [_jsx("div", { className: "h-2 w-full rounded-full bg-gray-200", children: _jsx("div", { className: "h-2 rounded-full bg-blue-600 transition-all duration-500", style: { width: `${overallProgress}%` } }) }), _jsxs("div", { className: "mt-2 text-center text-gray-600 text-sm", children: ["Progreso total: ", Math.round(overallProgress), "%"] })] }) }) }), _jsx("div", { className: "mt-2 space-y-5", children: stages.map((stage, index) => (_jsx("div", { className: "relative", children: _jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: `mr-3 flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full ${stage.status === "completed"
51
+ ? "bg-green-100"
52
+ : stage.status === "processing"
53
+ ? "bg-blue-100"
54
+ : stage.status === "error"
55
+ ? "bg-red-100"
56
+ : "bg-gray-100"}`, children: stage.status === "completed" ? (_jsx(CheckCircle2, { className: "h-6 w-6 text-green-600" })) : stage.status === "processing" ? (_jsx("div", { className: "text-blue-600", children: stage.icon })) : stage.status === "error" ? (_jsx("div", { className: "text-red-600", children: stage.icon })) : (_jsx("div", { className: "text-gray-400", children: stage.icon })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-sm", children: stage.label }), stage.status === "processing" && (_jsxs("div", { className: "mt-1", children: [_jsx("div", { className: "h-1.5 w-full rounded-full bg-gray-200", children: _jsx("div", { className: "h-1.5 rounded-full bg-blue-600 transition-all duration-300", style: { width: `${stage.progress || 0}%` } }) }), _jsxs("div", { className: "mt-1 text-gray-500 text-xs", children: [Math.round(stage.progress || 0), "%"] })] })), stage.status === "completed" && (_jsx("div", { className: "mt-1 text-green-600 text-xs", children: "Completado" })), stage.status === "error" && (_jsx("div", { className: "mt-1 text-red-600 text-xs", children: "Error" })), stage.status === "pending" && (_jsx("div", { className: "mt-1 text-gray-500 text-xs", children: "Pendiente" }))] })] }) }, index))) }), completedSteps === stages.length && (_jsxs("div", { className: "mt-4 rounded-lg bg-green-50 p-4 text-center", children: [_jsx(CheckCircle2, { className: "mx-auto mb-2 h-8 w-8 text-green-500" }), _jsx("p", { className: "font-medium text-green-800", children: "\u00A1Experiencia AR guardada con \u00E9xito!" }), _jsx("p", { className: "text-green-700 text-sm", children: "Tu contenido est\u00E1 listo para ser visualizado." })] }))] }) }));
57
+ }
@@ -0,0 +1,22 @@
1
+ export interface PropsConfig {
2
+ cardId: string;
3
+ targetImageSrc: string;
4
+ targetMindSrc: string;
5
+ videoSrc: string;
6
+ videoWidth: number;
7
+ videoHeight: number;
8
+ scale: number;
9
+ }
10
+ export interface DataItem {
11
+ id: string;
12
+ type: "photos" | "videoNative" | "ar";
13
+ images?: {
14
+ image: string;
15
+ fileId: string;
16
+ }[];
17
+ url?: string;
18
+ scale?: number;
19
+ width?: number;
20
+ height?: number;
21
+ }
22
+ export declare function mapDataToPropsConfig(data: any[]): PropsConfig;
@@ -0,0 +1,14 @@
1
+ export function mapDataToPropsConfig(data) {
2
+ const photos = data.find((item) => item.type === "photos");
3
+ const video = data.find((item) => item.type === "videoNative");
4
+ const ar = data.find((item) => item.type === "ar");
5
+ return {
6
+ cardId: photos?.id || "",
7
+ targetImageSrc: photos?.images?.[0]?.image || "",
8
+ targetMindSrc: ar?.url || "",
9
+ videoSrc: video?.url || "",
10
+ videoWidth: video?.width || 0,
11
+ videoHeight: video?.height || 0,
12
+ scale: video?.scale || 1,
13
+ };
14
+ }
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@srsergio/taptapp-ar",
3
+ "version": "1.0.0",
4
+ "description": "AR Visualizer and Compiler for Astro and React",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./astro/*": "./src/astro/*.astro",
15
+ "./compiler/*": "./src/compiler/*.js"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "src",
20
+ "README.md"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "prepublishOnly": "npm run build"
25
+ },
26
+ "peerDependencies": {
27
+ "astro": ">=4.0.0",
28
+ "react": ">=18.0.0",
29
+ "react-dom": ">=18.0.0",
30
+ "three": ">=0.160.0",
31
+ "aframe": ">=1.5.0"
32
+ },
33
+ "dependencies": {
34
+ "@tensorflow/tfjs": "^4.22.0",
35
+ "@tensorflow/tfjs-backend-cpu": "^4.22.0",
36
+ "@tensorflow/tfjs-backend-webgl": "^4.22.0",
37
+ "ml-matrix": "^6.10.4",
38
+ "svd-js": "^1.1.1",
39
+ "tinyqueue": "^2.0.3",
40
+ "lucide-react": "^0.477.0",
41
+ "nanoid": "^5.0.7"
42
+ },
43
+ "devDependencies": {
44
+ "typescript": "^5.4.5",
45
+ "@types/react": "^18.3.3",
46
+ "@types/react-dom": "^18.3.0",
47
+ "@types/three": "^0.170.0",
48
+ "astro": "5.16.4"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ }
53
+ }
@@ -0,0 +1,59 @@
1
+ ---
2
+ import type { PropsConfig } from "../react/types";
3
+ interface Props {
4
+ config: PropsConfig;
5
+ }
6
+
7
+ const { config } = Astro.props;
8
+ ---
9
+
10
+ <a-scene
11
+ mindar-image={`imageTargetSrc: ${config.targetMindSrc};uiLoading: #loading-overlay;uiScanning: #scanning-overlay;uiError: #error-overlay`}
12
+ color-space="sRGB"
13
+ renderer="colorManagement: true, physicallyCorrectLights"
14
+ vr-mode-ui="enabled: false"
15
+ device-orientation-permission-ui="enabled: false"
16
+ >
17
+ <a-assets>
18
+ <img id="target-image" crossorigin="anonymous" src={config.targetImageSrc} />
19
+ <video
20
+ id="ar-video"
21
+ src={config.videoSrc}
22
+ preload="auto"
23
+ loop
24
+ autoplay
25
+ playsinline
26
+ webkit-playsinline
27
+ muted
28
+ crossorigin="anonymous"
29
+ class="absolute opacity-0"
30
+ width="1"
31
+ height="1"></video></a-assets
32
+ >
33
+ <a-camera position="0 0 0" look-controls="enabled: false"></a-camera>
34
+
35
+ <a-entity mindar-image-target="targetIndex: 0">
36
+ <a-video
37
+ id="main-video"
38
+ src="#ar-video"
39
+ position="0 0 0"
40
+ opacity="1"
41
+ width={(config.videoWidth / config.videoHeight) * config.scale}
42
+ height={1 * config.scale}
43
+ rotation="0 0 0"
44
+ visible="true"
45
+ play-on-click
46
+ autoplay></a-video>
47
+ </a-entity>
48
+ </a-scene>
49
+
50
+ <style>
51
+ video {
52
+ width: 100% !important;
53
+ height: 100% !important;
54
+ object-fit: cover !important;
55
+ position: absolute !important;
56
+ top: 0 !important;
57
+ left: 0 !important;
58
+ }
59
+ </style>
@@ -0,0 +1,73 @@
1
+ ---
2
+ import ARStyles from "./styles/ARStyles.astro";
3
+ import LoadingOverlay from "./overlays/LoadingOverlay.astro";
4
+ import ScanningOverlay from "./overlays/ScanningOverlay.astro";
5
+ import ErrorOverlay from "./overlays/ErrorOverlay.astro";
6
+ import ARScene from "./ARScene.astro";
7
+ import ARScripts from "./scripts/ARScripts.astro";
8
+ import type { PropsConfig } from "../react/types";
9
+ interface Props {
10
+ config: PropsConfig;
11
+ }
12
+
13
+ const {config} = Astro.props ;
14
+ ---
15
+
16
+ <!doctype html>
17
+ <html lang="es-PE">
18
+ <head>
19
+ <meta charset="UTF-8" />
20
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
21
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
22
+ <meta name="robots" content="index, follow" />
23
+ <link rel="canonical" href="https://go.taptapp.xyz" />
24
+
25
+ <meta name="apple-mobile-web-app-capable" content="yes" />
26
+ <link rel="icon" href="/favicon.svg" type="image/svg+xml" sizes="any" />
27
+ <meta name="theme-color" content="#3367D6" />
28
+ <meta
29
+ name="description"
30
+ content="Crea impacto duradero y genera confianza en tus clientes con la tarjeta digital TapTapp. Presenta tu información de manera clara y atractiva para conectar con el futuro."
31
+ />
32
+ <meta name="keywords" content="tarjeta digital, identidad, futuro, confianza, clientes" />
33
+ <meta name="author" content="@srsergiolazaro" />
34
+
35
+ <meta property="og:title" content="TapTapp AR Experience" />
36
+ <meta
37
+ property="og:description"
38
+ content="Descubre nuestra experiencia de realidad aumentada y da vida a tu tarjeta digital TapTapp."
39
+ />
40
+ <meta property="og:image" content="https://go.taptapp.xyz/Imgsocial.jpg" />
41
+ <meta property="og:url" content="https://go.taptapp.xyz" />
42
+ <link rel="manifest" href="/manifest.webmanifest" crossorigin="anonymous" />
43
+
44
+ <title>TapTapp AR Experience</title>
45
+ <script is:inline src="https://aframe.io/releases/1.4.2/aframe.min.js"></script>
46
+ <script is:inline src="https://r2-worker.sergiolazaromondargo.workers.dev/taptapp-ar.prod.js"
47
+ ></script>
48
+ <link
49
+ href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&display=swap"
50
+ rel="stylesheet"
51
+ />
52
+ <ARStyles />
53
+ <ARScripts />
54
+ <style>
55
+ body {
56
+ font-family: "Montserrat", sans-serif;
57
+ margin: 0;
58
+ overflow: hidden;
59
+ }
60
+ @view-transition {
61
+ navigation: auto;
62
+ }
63
+ </style>
64
+ </head>
65
+ <body>
66
+ <!-- Custom UI Overlays -->
67
+ <LoadingOverlay />
68
+ <ScanningOverlay targetImage={config.targetImageSrc} />
69
+ <ErrorOverlay />
70
+
71
+ <ARScene config={config} />
72
+ </body>
73
+ </html>