@npmtapi/embed 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,8 +44,12 @@ Los tipos están incluidos — no necesitas `@types/tapipay`.
44
44
  identifier: "CLI-001"
45
45
  });
46
46
 
47
- tapipay.on("paymentPending", function(data) {
48
- console.log("Pago en proceso:", data);
47
+ tapipay.on("paymentWindowOpened", function() {
48
+ console.log("Ventana de pago abierta");
49
+ });
50
+
51
+ tapipay.on("paymentSubmitted", function(data) {
52
+ console.log("Pago enviado:", data);
49
53
  });
50
54
  </script>
51
55
  ```
@@ -74,7 +78,8 @@ export function PagoPage({ clienteId }: { clienteId: string }) {
74
78
  <TapipayWidget
75
79
  organization="acme"
76
80
  identifier={clienteId}
77
- onPending={(data) => console.log("Pago en proceso:", data)}
81
+ onPaymentWindowOpened={() => console.log("Ventana de pago abierta")}
82
+ onPaymentSubmitted={(data) => console.log("Pago enviado:", data)}
78
83
  onCancelled={() => console.log("Pago cancelado por el usuario")}
79
84
  />
80
85
  );
@@ -83,17 +88,18 @@ export function PagoPage({ clienteId }: { clienteId: string }) {
83
88
 
84
89
  ### Props
85
90
 
86
- | Prop | Tipo | Requerido | Descripción |
87
- |------|------|-----------|-------------|
88
- | `organization` | `string` | Sí | Alias de la organización en TapiPay |
89
- | `identifier` | `string` | Sí | Identificador del cliente |
90
- | `externalRequestId` | `string` | No | ID de deuda a preseleccionar |
91
- | `selectionStrategy` | `"oldestCreated"` | No | Selecciona automáticamente la deuda pendiente más antigua |
92
- | `environment` | `'production' \| 'homo'` | No | Entorno del SDK. Por defecto `'production'` |
93
- | `onPending` | `(data) => void` | No | Callback cuando Yuno redirige al callback (pago en proceso) |
94
- | `onCancelled` | `() => void` | No | Callback cuando el usuario cierra el popup sin completar el pago |
95
- | `className` | `string` | No | Clases CSS del contenedor |
96
- | `style` | `CSSProperties` | No | Estilos inline del contenedor |
91
+ | Prop | Tipo | Requerido | Por defecto | Descripción |
92
+ |------|------|-----------|-------------|-------------|
93
+ | `organization` | `string` | Sí | — | Alias de la organización en TapiPay |
94
+ | `identifier` | `string` | Sí | — | Identificador del cliente |
95
+ | `externalRequestId` | `string` | No | — | ID de deuda a preseleccionar. Tiene precedencia sobre `selectionStrategy` |
96
+ | `selectionStrategy` | `"oldestCreated"` | No | más reciente | Estrategia de selección automática de deuda pendiente. `"oldestCreated"`: la más antigua. Por defecto (omitido): la más reciente |
97
+ | `environment` | `'production' \| 'homo'` | No | `'production'` | Entorno del SDK |
98
+ | `onPaymentWindowOpened` | `() => void` | No | — | Callback cuando el popup de Yuno se abre exitosamente |
99
+ | `onPaymentSubmitted` | `(data) => void` | No | — | Callback cuando el usuario completó el formulario de Yuno y fue redirigido al callback |
100
+ | `onCancelled` | `() => void` | No | — | Callback cuando el usuario cierra el popup sin completar el pago |
101
+ | `className` | `string` | No | — | Clases CSS del contenedor |
102
+ | `style` | `CSSProperties` | No | — | Estilos inline del contenedor |
97
103
 
98
104
  ### Next.js App Router
99
105
 
@@ -110,7 +116,7 @@ export default function PagarPage() {
110
116
  <TapipayWidget
111
117
  organization={process.env.NEXT_PUBLIC_TAPIPAY_ORGANIZATION!}
112
118
  identifier="CLI-001"
113
- onPending={() => router.push("/procesando")}
119
+ onPaymentSubmitted={() => router.push("/procesando")}
114
120
  />
115
121
  );
116
122
  }
@@ -140,7 +146,7 @@ onMounted(async () => {
140
146
  organization: props.organization,
141
147
  identifier: props.identifier,
142
148
  });
143
- tapipay.on("paymentPending", (data) => console.log("Pago en proceso:", data));
149
+ tapipay.on("paymentSubmitted", (data) => console.log("Pago enviado:", data));
144
150
  });
145
151
 
146
152
  onUnmounted(() => tapipay?.destroy(widgetRef.value));
@@ -187,28 +193,34 @@ export class TapipayWidgetComponent implements OnInit, OnDestroy {
187
193
 
188
194
  ### `loadTapipay(options?)`
189
195
 
190
- | Parámetro | Tipo | Requerido | Descripción |
191
- |-----------|------|-----------|-------------|
192
- | `environment` | `'production' \| 'homo'` | No | Entorno del SDK a cargar. Por defecto `'production'`. |
196
+ | Parámetro | Tipo | Requerido | Por defecto | Descripción |
197
+ |-----------|------|-----------|-------------|-------------|
198
+ | `environment` | `'production' \| 'homo'` | No | `'production'` | Entorno del SDK a cargar |
193
199
 
194
200
  ### `initialize(options)`
195
201
 
196
- | Parámetro | Tipo | Requerido | Descripción |
197
- |-----------|------|-----------|-------------|
198
- | `container` | `string \| HTMLElement` | Sí | Selector CSS o referencia DOM. Solo para `initialize()`. |
199
- | `organization` | `string` | Sí | Alias de la organización en TapiPay. |
200
- | `identifier` | `string` | Sí | Identificador del cliente (DNI, número de cuenta, etc.). |
201
- | `externalRequestId` | `string` | No | ID externo de una deuda específica a preseleccionar. |
202
- | `selectionStrategy` | `"oldestCreated"` | No | Selección automática: `"oldestCreated"` elige la deuda pendiente más antigua. |
202
+ | Parámetro | Tipo | Requerido | Por defecto | Descripción |
203
+ |-----------|------|-----------|-------------|-------------|
204
+ | `container` | `string \| HTMLElement` | Sí | — | Selector CSS o referencia DOM |
205
+ | `organization` | `string` | Sí | — | Alias de la organización en TapiPay |
206
+ | `identifier` | `string` | Sí | — | Identificador del cliente (DNI, número de cuenta, etc.) |
207
+ | `externalRequestId` | `string` | No | — | ID externo de una deuda específica a preseleccionar. Tiene precedencia sobre `selectionStrategy` |
208
+ | `selectionStrategy` | `"oldestCreated"` | No | más reciente | Estrategia de selección automática de deuda pendiente. `"oldestCreated"`: la más antigua. Por defecto (omitido): la más reciente |
203
209
 
204
210
  ---
205
211
 
206
212
  ## Eventos
207
213
 
208
214
  ```js
209
- // Yuno redirigió al callback (pago en proceso)
210
- tapipay.on("paymentPending", function(data) {
211
- console.log("Pago en proceso:", data);
215
+ // El popup de Yuno se abrió exitosamente (útil para mostrar un overlay mientras el usuario paga)
216
+ tapipay.on("paymentWindowOpened", function() {
217
+ console.log("Ventana de pago abierta");
218
+ // Mostrar overlay/spinner mientras el usuario completa el formulario
219
+ });
220
+
221
+ // El usuario completó el formulario de Yuno y fue redirigido al callback
222
+ tapipay.on("paymentSubmitted", function(data) {
223
+ console.log("Pago enviado:", data);
212
224
  // Mostrar pantalla de "procesando" y esperar webhook
213
225
  });
214
226
 
@@ -218,13 +230,21 @@ tapipay.on("paymentCancelled", function() {
218
230
  });
219
231
 
220
232
  // Remover un listener
221
- tapipay.off("paymentPending", handler);
233
+ tapipay.off("paymentSubmitted", handler);
234
+ ```
235
+
236
+ ### `TapipayPaymentWindowOpenedEvent`
237
+
238
+ ```ts
239
+ interface TapipayPaymentWindowOpenedEvent {
240
+ type: "paymentWindowOpened";
241
+ }
222
242
  ```
223
243
 
224
- ### `TapipayPaymentPendingEvent`
244
+ ### `TapipayPaymentSubmittedEvent`
225
245
 
226
246
  ```ts
227
- interface TapipayPaymentPendingEvent {
247
+ interface TapipayPaymentSubmittedEvent {
228
248
  type: string; // "TAPIPAY_CALLBACK"
229
249
  status: "pending";
230
250
  data: Record<string, string>; // Parámetros que Yuno haya enviado (pueden estar vacíos)
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/loader.ts"],"sourcesContent":["export { loadTapipay } from \"./loader\";\nexport type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n\tTapipayOptions,\n\tTapipayPaymentCancelledEvent,\n\tTapipayPaymentPendingEvent,\n} from \"./types\";\n","import type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n} from \"./types\";\n\nconst SDK_URLS: Record<TapipayEnvironment, string> = {\n\tproduction: \"https://app.tapipay.la/embed.js\",\n\thomo: \"https://homo.tapipay.la/embed.js\",\n};\n\n// Idempotencia por entorno\nconst loadPromises = new Map<TapipayEnvironment, Promise<TapipayInstance>>();\n\n/**\n * Carga el SDK de TapiPay de forma asíncrona inyectando el script en el DOM.\n *\n * - Idempotente por entorno: múltiples llamadas con el mismo `environment` retornan la misma Promise.\n * - Si window.tapipay ya existe (script cargado sync), resuelve inmediatamente.\n * - Compatible con React Strict Mode (doble mount/unmount).\n *\n * @example\n * // Producción (default)\n * const tapipay = await loadTapipay();\n *\n * // Homologación\n * const tapipay = await loadTapipay({ environment: 'homo' });\n *\n * tapipay.initialize({ container: \"#widget\", organization: \"acme\", identifier: \"CLI-001\" });\n */\nexport function loadTapipay(\n\toptions?: LoadTapipayOptions,\n): Promise<TapipayInstance> {\n\tconst env: TapipayEnvironment = options?.environment ?? \"production\";\n\tconst SDK_URL = SDK_URLS[env];\n\tconst SCRIPT_ID = `tapipay-embed-sdk-${env}`;\n\n\t// SSR guard\n\tif (typeof window === \"undefined\") {\n\t\treturn Promise.reject(\n\t\t\tnew Error(\"[TapiPay] loadTapipay() requires a browser environment.\"),\n\t\t);\n\t}\n\n\t// Ya cargado de forma síncrona (script tag directo)\n\tif (window.tapipay && !window.tapipay._q) {\n\t\treturn Promise.resolve(window.tapipay);\n\t}\n\n\t// Reutilizar promise existente (idempotencia por entorno)\n\tconst existing = loadPromises.get(env);\n\tif (existing) return existing;\n\n\tconst promise = new Promise<TapipayInstance>((resolve, reject) => {\n\t\t// Si ya hay un script inyectado, esperar a que cargue\n\t\tconst existingScript = document.getElementById(\n\t\t\tSCRIPT_ID,\n\t\t) as HTMLScriptElement | null;\n\n\t\tconst onLoad = () => {\n\t\t\tif (window.tapipay) {\n\t\t\t\tresolve(window.tapipay);\n\t\t\t} else {\n\t\t\t\treject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"[TapiPay] El script cargó pero window.tapipay no está definido.\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tconst onError = () => {\n\t\t\tloadPromises.delete(env);\n\t\t\treject(new Error(`[TapiPay] Error al cargar el SDK desde ${SDK_URL}`));\n\t\t};\n\n\t\tif (existingScript) {\n\t\t\texistingScript.addEventListener(\"load\", onLoad);\n\t\t\texistingScript.addEventListener(\"error\", onError);\n\t\t\treturn;\n\t\t}\n\n\t\tconst script = document.createElement(\"script\");\n\t\tscript.id = SCRIPT_ID;\n\t\tscript.src = SDK_URL;\n\t\tscript.async = true;\n\t\tscript.addEventListener(\"load\", onLoad);\n\t\tscript.addEventListener(\"error\", onError);\n\t\tdocument.head.appendChild(script);\n\t});\n\n\tloadPromises.set(env, promise);\n\treturn promise;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACMA,IAAM,WAA+C;AAAA,EACpD,YAAY;AAAA,EACZ,MAAM;AACP;AAGA,IAAM,eAAe,oBAAI,IAAkD;AAkBpE,SAAS,YACf,SAC2B;AAhC5B;AAiCC,QAAM,OAA0B,wCAAS,gBAAT,YAAwB;AACxD,QAAM,UAAU,SAAS,GAAG;AAC5B,QAAM,YAAY,qBAAqB,GAAG;AAG1C,MAAI,OAAO,WAAW,aAAa;AAClC,WAAO,QAAQ;AAAA,MACd,IAAI,MAAM,yDAAyD;AAAA,IACpE;AAAA,EACD;AAGA,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,IAAI;AACzC,WAAO,QAAQ,QAAQ,OAAO,OAAO;AAAA,EACtC;AAGA,QAAM,WAAW,aAAa,IAAI,GAAG;AACrC,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,IAAI,QAAyB,CAAC,SAAS,WAAW;AAEjE,UAAM,iBAAiB,SAAS;AAAA,MAC/B;AAAA,IACD;AAEA,UAAM,SAAS,MAAM;AACpB,UAAI,OAAO,SAAS;AACnB,gBAAQ,OAAO,OAAO;AAAA,MACvB,OAAO;AACN;AAAA,UACC,IAAI;AAAA,YACH;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,UAAM,UAAU,MAAM;AACrB,mBAAa,OAAO,GAAG;AACvB,aAAO,IAAI,MAAM,0CAA0C,OAAO,EAAE,CAAC;AAAA,IACtE;AAEA,QAAI,gBAAgB;AACnB,qBAAe,iBAAiB,QAAQ,MAAM;AAC9C,qBAAe,iBAAiB,SAAS,OAAO;AAChD;AAAA,IACD;AAEA,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,KAAK;AACZ,WAAO,MAAM;AACb,WAAO,QAAQ;AACf,WAAO,iBAAiB,QAAQ,MAAM;AACtC,WAAO,iBAAiB,SAAS,OAAO;AACxC,aAAS,KAAK,YAAY,MAAM;AAAA,EACjC,CAAC;AAED,eAAa,IAAI,KAAK,OAAO;AAC7B,SAAO;AACR;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/loader.ts"],"sourcesContent":["export { loadTapipay } from \"./loader\";\nexport type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n\tTapipayOptions,\n\tTapipayPaymentCancelledEvent,\n\tTapipayPaymentSubmittedEvent,\n\tTapipayPaymentWindowOpenedEvent,\n} from \"./types\";\n","import type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n} from \"./types\";\n\nconst SDK_URLS: Record<TapipayEnvironment, string> = {\n\tproduction: \"https://app.tapipay.la/embed.js\",\n\thomo: \"https://homo.tapipay.la/embed.js\",\n};\n\n// Idempotencia por entorno\nconst loadPromises = new Map<TapipayEnvironment, Promise<TapipayInstance>>();\n\n/**\n * Carga el SDK de TapiPay de forma asíncrona inyectando el script en el DOM.\n *\n * - Idempotente por entorno: múltiples llamadas con el mismo `environment` retornan la misma Promise.\n * - Si window.tapipay ya existe (script cargado sync), resuelve inmediatamente.\n * - Compatible con React Strict Mode (doble mount/unmount).\n *\n * @example\n * // Producción (default)\n * const tapipay = await loadTapipay();\n *\n * // Homologación\n * const tapipay = await loadTapipay({ environment: 'homo' });\n *\n * tapipay.initialize({ container: \"#widget\", organization: \"acme\", identifier: \"CLI-001\" });\n */\nexport function loadTapipay(\n\toptions?: LoadTapipayOptions,\n): Promise<TapipayInstance> {\n\tconst env: TapipayEnvironment = options?.environment ?? \"production\";\n\tconst SDK_URL = SDK_URLS[env];\n\tconst SCRIPT_ID = `tapipay-embed-sdk-${env}`;\n\n\t// SSR guard\n\tif (typeof window === \"undefined\") {\n\t\treturn Promise.reject(\n\t\t\tnew Error(\"[TapiPay] loadTapipay() requires a browser environment.\"),\n\t\t);\n\t}\n\n\t// Ya cargado de forma síncrona (script tag directo)\n\tif (window.tapipay && !window.tapipay._q) {\n\t\treturn Promise.resolve(window.tapipay);\n\t}\n\n\t// Reutilizar promise existente (idempotencia por entorno)\n\tconst existing = loadPromises.get(env);\n\tif (existing) return existing;\n\n\tconst promise = new Promise<TapipayInstance>((resolve, reject) => {\n\t\t// Si ya hay un script inyectado, esperar a que cargue\n\t\tconst existingScript = document.getElementById(\n\t\t\tSCRIPT_ID,\n\t\t) as HTMLScriptElement | null;\n\n\t\tconst onLoad = () => {\n\t\t\tif (window.tapipay) {\n\t\t\t\tresolve(window.tapipay);\n\t\t\t} else {\n\t\t\t\treject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"[TapiPay] El script cargó pero window.tapipay no está definido.\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tconst onError = () => {\n\t\t\tloadPromises.delete(env);\n\t\t\treject(new Error(`[TapiPay] Error al cargar el SDK desde ${SDK_URL}`));\n\t\t};\n\n\t\tif (existingScript) {\n\t\t\texistingScript.addEventListener(\"load\", onLoad);\n\t\t\texistingScript.addEventListener(\"error\", onError);\n\t\t\treturn;\n\t\t}\n\n\t\tconst script = document.createElement(\"script\");\n\t\tscript.id = SCRIPT_ID;\n\t\tscript.src = SDK_URL;\n\t\tscript.async = true;\n\t\tscript.addEventListener(\"load\", onLoad);\n\t\tscript.addEventListener(\"error\", onError);\n\t\tdocument.head.appendChild(script);\n\t});\n\n\tloadPromises.set(env, promise);\n\treturn promise;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACMA,IAAM,WAA+C;AAAA,EACpD,YAAY;AAAA,EACZ,MAAM;AACP;AAGA,IAAM,eAAe,oBAAI,IAAkD;AAkBpE,SAAS,YACf,SAC2B;AAhC5B;AAiCC,QAAM,OAA0B,wCAAS,gBAAT,YAAwB;AACxD,QAAM,UAAU,SAAS,GAAG;AAC5B,QAAM,YAAY,qBAAqB,GAAG;AAG1C,MAAI,OAAO,WAAW,aAAa;AAClC,WAAO,QAAQ;AAAA,MACd,IAAI,MAAM,yDAAyD;AAAA,IACpE;AAAA,EACD;AAGA,MAAI,OAAO,WAAW,CAAC,OAAO,QAAQ,IAAI;AACzC,WAAO,QAAQ,QAAQ,OAAO,OAAO;AAAA,EACtC;AAGA,QAAM,WAAW,aAAa,IAAI,GAAG;AACrC,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,IAAI,QAAyB,CAAC,SAAS,WAAW;AAEjE,UAAM,iBAAiB,SAAS;AAAA,MAC/B;AAAA,IACD;AAEA,UAAM,SAAS,MAAM;AACpB,UAAI,OAAO,SAAS;AACnB,gBAAQ,OAAO,OAAO;AAAA,MACvB,OAAO;AACN;AAAA,UACC,IAAI;AAAA,YACH;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,UAAM,UAAU,MAAM;AACrB,mBAAa,OAAO,GAAG;AACvB,aAAO,IAAI,MAAM,0CAA0C,OAAO,EAAE,CAAC;AAAA,IACtE;AAEA,QAAI,gBAAgB;AACnB,qBAAe,iBAAiB,QAAQ,MAAM;AAC9C,qBAAe,iBAAiB,SAAS,OAAO;AAChD;AAAA,IACD;AAEA,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,KAAK;AACZ,WAAO,MAAM;AACb,WAAO,QAAQ;AACf,WAAO,iBAAiB,QAAQ,MAAM;AACtC,WAAO,iBAAiB,SAAS,OAAO;AACxC,aAAS,KAAK,YAAY,MAAM;AAAA,EACjC,CAAC;AAED,eAAa,IAAI,KAAK,OAAO;AAC7B,SAAO;AACR;","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { L as LoadTapipayOptions, T as TapipayInstance } from './types-DmkYbkBI.cjs';
2
- export { a as TapipayEnvironment, b as TapipayOptions, c as TapipayPaymentCancelledEvent, d as TapipayPaymentPendingEvent } from './types-DmkYbkBI.cjs';
1
+ import { L as LoadTapipayOptions, T as TapipayInstance } from './types-DYcwsDwH.cjs';
2
+ export { a as TapipayEnvironment, b as TapipayOptions, c as TapipayPaymentCancelledEvent, d as TapipayPaymentSubmittedEvent, e as TapipayPaymentWindowOpenedEvent } from './types-DYcwsDwH.cjs';
3
3
 
4
4
  /**
5
5
  * Carga el SDK de TapiPay de forma asíncrona inyectando el script en el DOM.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { L as LoadTapipayOptions, T as TapipayInstance } from './types-DmkYbkBI.js';
2
- export { a as TapipayEnvironment, b as TapipayOptions, c as TapipayPaymentCancelledEvent, d as TapipayPaymentPendingEvent } from './types-DmkYbkBI.js';
1
+ import { L as LoadTapipayOptions, T as TapipayInstance } from './types-DYcwsDwH.js';
2
+ export { a as TapipayEnvironment, b as TapipayOptions, c as TapipayPaymentCancelledEvent, d as TapipayPaymentSubmittedEvent, e as TapipayPaymentWindowOpenedEvent } from './types-DYcwsDwH.js';
3
3
 
4
4
  /**
5
5
  * Carga el SDK de TapiPay de forma asíncrona inyectando el script en el DOM.
package/dist/react.cjs CHANGED
@@ -108,17 +108,22 @@ function TapipayWidget({
108
108
  externalRequestId,
109
109
  selectionStrategy,
110
110
  environment,
111
- onPending,
111
+ onPaymentWindowOpened,
112
+ onPaymentSubmitted,
112
113
  onCancelled,
113
114
  className,
114
115
  style
115
116
  }) {
116
117
  const containerRef = (0, import_react.useRef)(null);
117
- const onPendingRef = (0, import_react.useRef)(onPending);
118
+ const onPaymentWindowOpenedRef = (0, import_react.useRef)(onPaymentWindowOpened);
119
+ const onPaymentSubmittedRef = (0, import_react.useRef)(onPaymentSubmitted);
118
120
  const onCancelledRef = (0, import_react.useRef)(onCancelled);
119
121
  (0, import_react.useEffect)(() => {
120
- onPendingRef.current = onPending;
121
- }, [onPending]);
122
+ onPaymentWindowOpenedRef.current = onPaymentWindowOpened;
123
+ }, [onPaymentWindowOpened]);
124
+ (0, import_react.useEffect)(() => {
125
+ onPaymentSubmittedRef.current = onPaymentSubmitted;
126
+ }, [onPaymentSubmitted]);
122
127
  (0, import_react.useEffect)(() => {
123
128
  onCancelledRef.current = onCancelled;
124
129
  }, [onCancelled]);
@@ -127,9 +132,13 @@ function TapipayWidget({
127
132
  const container = containerRef.current;
128
133
  let tapipayInstance = null;
129
134
  let cancelled = false;
130
- const handlePending = (data) => {
135
+ const handlePaymentWindowOpened = (data) => {
136
+ var _a;
137
+ (_a = onPaymentWindowOpenedRef.current) == null ? void 0 : _a.call(onPaymentWindowOpenedRef, data);
138
+ };
139
+ const handlePaymentSubmitted = (data) => {
131
140
  var _a;
132
- (_a = onPendingRef.current) == null ? void 0 : _a.call(onPendingRef, data);
141
+ (_a = onPaymentSubmittedRef.current) == null ? void 0 : _a.call(onPaymentSubmittedRef, data);
133
142
  };
134
143
  const handleCancelled = (data) => {
135
144
  var _a;
@@ -138,7 +147,8 @@ function TapipayWidget({
138
147
  loadTapipay({ environment }).then((instance) => {
139
148
  if (cancelled) return;
140
149
  tapipayInstance = instance;
141
- instance.on("paymentPending", handlePending);
150
+ instance.on("paymentWindowOpened", handlePaymentWindowOpened);
151
+ instance.on("paymentSubmitted", handlePaymentSubmitted);
142
152
  instance.on("paymentCancelled", handleCancelled);
143
153
  instance.initialize({
144
154
  container,
@@ -151,7 +161,8 @@ function TapipayWidget({
151
161
  return () => {
152
162
  cancelled = true;
153
163
  if (tapipayInstance) {
154
- tapipayInstance.off("paymentPending", handlePending);
164
+ tapipayInstance.off("paymentWindowOpened", handlePaymentWindowOpened);
165
+ tapipayInstance.off("paymentSubmitted", handlePaymentSubmitted);
155
166
  tapipayInstance.off("paymentCancelled", handleCancelled);
156
167
  tapipayInstance.destroy(container);
157
168
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react.tsx","../src/loader.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { loadTapipay } from \"./loader\";\nimport type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n\tTapipayOptions,\n\tTapipayPaymentCancelledEvent,\n\tTapipayPaymentPendingEvent,\n} from \"./types\";\n\n// ─── useTapipay hook ──────────────────────────────────────────────────────────\n\n/**\n * Hook de bajo nivel que carga el SDK y retorna la instancia.\n * Útil cuando necesitas control manual sobre initialize/destroy.\n *\n * @example\n * const { tapipay, error } = useTapipay();\n * const { tapipay, error } = useTapipay({ environment: 'homo' });\n */\nexport function useTapipay(options?: LoadTapipayOptions): {\n\ttapipay: TapipayInstance | null;\n\terror: Error | null;\n} {\n\tconst [tapipay, setTapipay] = useState<TapipayInstance | null>(null);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst environment = options?.environment;\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\t\tloadTapipay({ environment })\n\t\t\t.then((instance) => {\n\t\t\t\tif (!cancelled) setTapipay(instance);\n\t\t\t})\n\t\t\t.catch((err: Error) => {\n\t\t\t\tif (!cancelled) setError(err);\n\t\t\t});\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [environment]);\n\n\treturn { tapipay, error };\n}\n\n// ─── TapipayWidget component ──────────────────────────────────────────────────\n\nexport interface TapipayWidgetProps extends Omit<TapipayOptions, \"container\"> {\n\t/** Entorno del SDK a cargar. Por defecto `'production'`. Usar `'homo'` para homologación. */\n\tenvironment?: TapipayEnvironment;\n\t/** Callback invocado cuando Yuno redirige al callback (pago en proceso). */\n\tonPending?: (data: TapipayPaymentPendingEvent) => void;\n\t/** Callback invocado cuando el usuario cierra el popup sin completar el pago. */\n\tonCancelled?: (data: TapipayPaymentCancelledEvent) => void;\n\t/** Clases CSS adicionales para el contenedor del widget. */\n\tclassName?: string;\n\t/** Estilos inline adicionales para el contenedor del widget. */\n\tstyle?: React.CSSProperties;\n}\n\n/**\n * Componente React que encapsula el widget de pago TapiPay.\n *\n * Maneja internamente la carga del SDK, el ciclo de vida del widget\n * y el cleanup al desmontar. Compatible con React Strict Mode.\n *\n * @example\n * <TapipayWidget\n * organization=\"acme\"\n * identifier=\"CLI-001\"\n * externalRequestId=\"FAC-2024-001\"\n * onPending={(data) => console.log(\"Pago en proceso\", data)}\n * onCancelled={() => console.log(\"Pago cancelado por el usuario\")}\n * />\n */\nexport function TapipayWidget({\n\torganization,\n\tidentifier,\n\texternalRequestId,\n\tselectionStrategy,\n\tenvironment,\n\tonPending,\n\tonCancelled,\n\tclassName,\n\tstyle,\n}: TapipayWidgetProps) {\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\t// Refs para evitar re-renders innecesarios y closures estáticos en useEffect\n\tconst onPendingRef = useRef(onPending);\n\tconst onCancelledRef = useRef(onCancelled);\n\n\tuseEffect(() => {\n\t\tonPendingRef.current = onPending;\n\t}, [onPending]);\n\n\tuseEffect(() => {\n\t\tonCancelledRef.current = onCancelled;\n\t}, [onCancelled]);\n\n\tuseEffect(() => {\n\t\tif (!containerRef.current) return;\n\t\tconst container = containerRef.current;\n\n\t\tlet tapipayInstance: TapipayInstance | null = null;\n\t\tlet cancelled = false;\n\n\t\tconst handlePending = (data: TapipayPaymentPendingEvent) => {\n\t\t\tonPendingRef.current?.(data);\n\t\t};\n\t\tconst handleCancelled = (data: TapipayPaymentCancelledEvent) => {\n\t\t\tonCancelledRef.current?.(data);\n\t\t};\n\n\t\tloadTapipay({ environment }).then((instance) => {\n\t\t\tif (cancelled) return;\n\t\t\ttapipayInstance = instance;\n\n\t\t\tinstance.on(\"paymentPending\", handlePending);\n\t\t\tinstance.on(\"paymentCancelled\", handleCancelled);\n\n\t\t\tinstance.initialize({\n\t\t\t\tcontainer,\n\t\t\t\torganization,\n\t\t\t\tidentifier,\n\t\t\t\texternalRequestId,\n\t\t\t\tselectionStrategy,\n\t\t\t});\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t\tif (tapipayInstance) {\n\t\t\t\ttapipayInstance.off(\"paymentPending\", handlePending);\n\t\t\t\ttapipayInstance.off(\"paymentCancelled\", handleCancelled);\n\t\t\t\ttapipayInstance.destroy(container);\n\t\t\t}\n\t\t};\n\t\t// El widget se re-monta si cambian los parámetros de identificación o entorno\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [\n\t\torganization,\n\t\tidentifier,\n\t\texternalRequestId,\n\t\tselectionStrategy,\n\t\tenvironment,\n\t]);\n\n\treturn <div ref={containerRef} className={className} style={style} />;\n}\n","import type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n} from \"./types\";\n\nconst SDK_URLS: Record<TapipayEnvironment, string> = {\n\tproduction: \"https://app.tapipay.la/embed.js\",\n\thomo: \"https://homo.tapipay.la/embed.js\",\n};\n\n// Idempotencia por entorno\nconst loadPromises = new Map<TapipayEnvironment, Promise<TapipayInstance>>();\n\n/**\n * Carga el SDK de TapiPay de forma asíncrona inyectando el script en el DOM.\n *\n * - Idempotente por entorno: múltiples llamadas con el mismo `environment` retornan la misma Promise.\n * - Si window.tapipay ya existe (script cargado sync), resuelve inmediatamente.\n * - Compatible con React Strict Mode (doble mount/unmount).\n *\n * @example\n * // Producción (default)\n * const tapipay = await loadTapipay();\n *\n * // Homologación\n * const tapipay = await loadTapipay({ environment: 'homo' });\n *\n * tapipay.initialize({ container: \"#widget\", organization: \"acme\", identifier: \"CLI-001\" });\n */\nexport function loadTapipay(\n\toptions?: LoadTapipayOptions,\n): Promise<TapipayInstance> {\n\tconst env: TapipayEnvironment = options?.environment ?? \"production\";\n\tconst SDK_URL = SDK_URLS[env];\n\tconst SCRIPT_ID = `tapipay-embed-sdk-${env}`;\n\n\t// SSR guard\n\tif (typeof window === \"undefined\") {\n\t\treturn Promise.reject(\n\t\t\tnew Error(\"[TapiPay] loadTapipay() requires a browser environment.\"),\n\t\t);\n\t}\n\n\t// Ya cargado de forma síncrona (script tag directo)\n\tif (window.tapipay && !window.tapipay._q) {\n\t\treturn Promise.resolve(window.tapipay);\n\t}\n\n\t// Reutilizar promise existente (idempotencia por entorno)\n\tconst existing = loadPromises.get(env);\n\tif (existing) return existing;\n\n\tconst promise = new Promise<TapipayInstance>((resolve, reject) => {\n\t\t// Si ya hay un script inyectado, esperar a que cargue\n\t\tconst existingScript = document.getElementById(\n\t\t\tSCRIPT_ID,\n\t\t) as HTMLScriptElement | null;\n\n\t\tconst onLoad = () => {\n\t\t\tif (window.tapipay) {\n\t\t\t\tresolve(window.tapipay);\n\t\t\t} else {\n\t\t\t\treject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"[TapiPay] El script cargó pero window.tapipay no está definido.\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tconst onError = () => {\n\t\t\tloadPromises.delete(env);\n\t\t\treject(new Error(`[TapiPay] Error al cargar el SDK desde ${SDK_URL}`));\n\t\t};\n\n\t\tif (existingScript) {\n\t\t\texistingScript.addEventListener(\"load\", onLoad);\n\t\t\texistingScript.addEventListener(\"error\", onError);\n\t\t\treturn;\n\t\t}\n\n\t\tconst script = document.createElement(\"script\");\n\t\tscript.id = SCRIPT_ID;\n\t\tscript.src = SDK_URL;\n\t\tscript.async = true;\n\t\tscript.addEventListener(\"load\", onLoad);\n\t\tscript.addEventListener(\"error\", onError);\n\t\tdocument.head.appendChild(script);\n\t});\n\n\tloadPromises.set(env, promise);\n\treturn promise;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/react.tsx","../src/loader.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { loadTapipay } from \"./loader\";\nimport type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n\tTapipayOptions,\n\tTapipayPaymentCancelledEvent,\n\tTapipayPaymentSubmittedEvent,\n\tTapipayPaymentWindowOpenedEvent,\n} from \"./types\";\n\n// ─── useTapipay hook ──────────────────────────────────────────────────────────\n\n/**\n * Hook de bajo nivel que carga el SDK y retorna la instancia.\n * Útil cuando necesitas control manual sobre initialize/destroy.\n *\n * @example\n * const { tapipay, error } = useTapipay();\n * const { tapipay, error } = useTapipay({ environment: 'homo' });\n */\nexport function useTapipay(options?: LoadTapipayOptions): {\n\ttapipay: TapipayInstance | null;\n\terror: Error | null;\n} {\n\tconst [tapipay, setTapipay] = useState<TapipayInstance | null>(null);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst environment = options?.environment;\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\t\tloadTapipay({ environment })\n\t\t\t.then((instance) => {\n\t\t\t\tif (!cancelled) setTapipay(instance);\n\t\t\t})\n\t\t\t.catch((err: Error) => {\n\t\t\t\tif (!cancelled) setError(err);\n\t\t\t});\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [environment]);\n\n\treturn { tapipay, error };\n}\n\n// ─── TapipayWidget component ──────────────────────────────────────────────────\n\nexport interface TapipayWidgetProps extends Omit<TapipayOptions, \"container\"> {\n\t/** Entorno del SDK a cargar. Por defecto `'production'`. Usar `'homo'` para homologación. */\n\tenvironment?: TapipayEnvironment;\n\t/** Callback invocado cuando el popup de Yuno se abre exitosamente. */\n\tonPaymentWindowOpened?: (data: TapipayPaymentWindowOpenedEvent) => void;\n\t/** Callback invocado cuando el usuario completó el formulario de Yuno y fue redirigido al callback. */\n\tonPaymentSubmitted?: (data: TapipayPaymentSubmittedEvent) => void;\n\t/** Callback invocado cuando el usuario cierra el popup sin completar el pago. */\n\tonCancelled?: (data: TapipayPaymentCancelledEvent) => void;\n\t/** Clases CSS adicionales para el contenedor del widget. */\n\tclassName?: string;\n\t/** Estilos inline adicionales para el contenedor del widget. */\n\tstyle?: React.CSSProperties;\n}\n\n/**\n * Componente React que encapsula el widget de pago TapiPay.\n *\n * Maneja internamente la carga del SDK, el ciclo de vida del widget\n * y el cleanup al desmontar. Compatible con React Strict Mode.\n *\n * @example\n * <TapipayWidget\n * organization=\"acme\"\n * identifier=\"CLI-001\"\n * externalRequestId=\"FAC-2024-001\"\n * onPending={(data) => console.log(\"Pago en proceso\", data)}\n * onCancelled={() => console.log(\"Pago cancelado por el usuario\")}\n * />\n */\nexport function TapipayWidget({\n\torganization,\n\tidentifier,\n\texternalRequestId,\n\tselectionStrategy,\n\tenvironment,\n\tonPaymentWindowOpened,\n\tonPaymentSubmitted,\n\tonCancelled,\n\tclassName,\n\tstyle,\n}: TapipayWidgetProps) {\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\t// Refs para evitar re-renders innecesarios y closures estáticos en useEffect\n\tconst onPaymentWindowOpenedRef = useRef(onPaymentWindowOpened);\n\tconst onPaymentSubmittedRef = useRef(onPaymentSubmitted);\n\tconst onCancelledRef = useRef(onCancelled);\n\n\tuseEffect(() => {\n\t\tonPaymentWindowOpenedRef.current = onPaymentWindowOpened;\n\t}, [onPaymentWindowOpened]);\n\n\tuseEffect(() => {\n\t\tonPaymentSubmittedRef.current = onPaymentSubmitted;\n\t}, [onPaymentSubmitted]);\n\n\tuseEffect(() => {\n\t\tonCancelledRef.current = onCancelled;\n\t}, [onCancelled]);\n\n\tuseEffect(() => {\n\t\tif (!containerRef.current) return;\n\t\tconst container = containerRef.current;\n\n\t\tlet tapipayInstance: TapipayInstance | null = null;\n\t\tlet cancelled = false;\n\n\t\tconst handlePaymentWindowOpened = (\n\t\t\tdata: TapipayPaymentWindowOpenedEvent,\n\t\t) => {\n\t\t\tonPaymentWindowOpenedRef.current?.(data);\n\t\t};\n\t\tconst handlePaymentSubmitted = (data: TapipayPaymentSubmittedEvent) => {\n\t\t\tonPaymentSubmittedRef.current?.(data);\n\t\t};\n\t\tconst handleCancelled = (data: TapipayPaymentCancelledEvent) => {\n\t\t\tonCancelledRef.current?.(data);\n\t\t};\n\n\t\tloadTapipay({ environment }).then((instance) => {\n\t\t\tif (cancelled) return;\n\t\t\ttapipayInstance = instance;\n\n\t\t\tinstance.on(\"paymentWindowOpened\", handlePaymentWindowOpened);\n\t\t\tinstance.on(\"paymentSubmitted\", handlePaymentSubmitted);\n\t\t\tinstance.on(\"paymentCancelled\", handleCancelled);\n\n\t\t\tinstance.initialize({\n\t\t\t\tcontainer,\n\t\t\t\torganization,\n\t\t\t\tidentifier,\n\t\t\t\texternalRequestId,\n\t\t\t\tselectionStrategy,\n\t\t\t});\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t\tif (tapipayInstance) {\n\t\t\t\ttapipayInstance.off(\"paymentWindowOpened\", handlePaymentWindowOpened);\n\t\t\t\ttapipayInstance.off(\"paymentSubmitted\", handlePaymentSubmitted);\n\t\t\t\ttapipayInstance.off(\"paymentCancelled\", handleCancelled);\n\t\t\t\ttapipayInstance.destroy(container);\n\t\t\t}\n\t\t};\n\t\t// El widget se re-monta si cambian los parámetros de identificación o entorno\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [\n\t\torganization,\n\t\tidentifier,\n\t\texternalRequestId,\n\t\tselectionStrategy,\n\t\tenvironment,\n\t]);\n\n\treturn <div ref={containerRef} className={className} style={style} />;\n}\n","import type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n} from \"./types\";\n\nconst SDK_URLS: Record<TapipayEnvironment, string> = {\n\tproduction: \"https://app.tapipay.la/embed.js\",\n\thomo: \"https://homo.tapipay.la/embed.js\",\n};\n\n// Idempotencia por entorno\nconst loadPromises = new Map<TapipayEnvironment, Promise<TapipayInstance>>();\n\n/**\n * Carga el SDK de TapiPay de forma asíncrona inyectando el script en el DOM.\n *\n * - Idempotente por entorno: múltiples llamadas con el mismo `environment` retornan la misma Promise.\n * - Si window.tapipay ya existe (script cargado sync), resuelve inmediatamente.\n * - Compatible con React Strict Mode (doble mount/unmount).\n *\n * @example\n * // Producción (default)\n * const tapipay = await loadTapipay();\n *\n * // Homologación\n * const tapipay = await loadTapipay({ environment: 'homo' });\n *\n * tapipay.initialize({ container: \"#widget\", organization: \"acme\", identifier: \"CLI-001\" });\n */\nexport function loadTapipay(\n\toptions?: LoadTapipayOptions,\n): Promise<TapipayInstance> {\n\tconst env: TapipayEnvironment = options?.environment ?? \"production\";\n\tconst SDK_URL = SDK_URLS[env];\n\tconst SCRIPT_ID = `tapipay-embed-sdk-${env}`;\n\n\t// SSR guard\n\tif (typeof window === \"undefined\") {\n\t\treturn Promise.reject(\n\t\t\tnew Error(\"[TapiPay] loadTapipay() requires a browser environment.\"),\n\t\t);\n\t}\n\n\t// Ya cargado de forma síncrona (script tag directo)\n\tif (window.tapipay && !window.tapipay._q) {\n\t\treturn Promise.resolve(window.tapipay);\n\t}\n\n\t// Reutilizar promise existente (idempotencia por entorno)\n\tconst existing = loadPromises.get(env);\n\tif (existing) return existing;\n\n\tconst promise = new Promise<TapipayInstance>((resolve, reject) => {\n\t\t// Si ya hay un script inyectado, esperar a que cargue\n\t\tconst existingScript = document.getElementById(\n\t\t\tSCRIPT_ID,\n\t\t) as HTMLScriptElement | null;\n\n\t\tconst onLoad = () => {\n\t\t\tif (window.tapipay) {\n\t\t\t\tresolve(window.tapipay);\n\t\t\t} else {\n\t\t\t\treject(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\"[TapiPay] El script cargó pero window.tapipay no está definido.\",\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\n\t\tconst onError = () => {\n\t\t\tloadPromises.delete(env);\n\t\t\treject(new Error(`[TapiPay] Error al cargar el SDK desde ${SDK_URL}`));\n\t\t};\n\n\t\tif (existingScript) {\n\t\t\texistingScript.addEventListener(\"load\", onLoad);\n\t\t\texistingScript.addEventListener(\"error\", onError);\n\t\t\treturn;\n\t\t}\n\n\t\tconst script = document.createElement(\"script\");\n\t\tscript.id = SCRIPT_ID;\n\t\tscript.src = SDK_URL;\n\t\tscript.async = true;\n\t\tscript.addEventListener(\"load\", onLoad);\n\t\tscript.addEventListener(\"error\", onError);\n\t\tdocument.head.appendChild(script);\n\t});\n\n\tloadPromises.set(env, promise);\n\treturn promise;\n}\n"],"mappings":"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","names":[]}
package/dist/react.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { b as TapipayOptions, a as TapipayEnvironment, d as TapipayPaymentPendingEvent, c as TapipayPaymentCancelledEvent, L as LoadTapipayOptions, T as TapipayInstance } from './types-DmkYbkBI.cjs';
2
+ import { b as TapipayOptions, a as TapipayEnvironment, e as TapipayPaymentWindowOpenedEvent, d as TapipayPaymentSubmittedEvent, c as TapipayPaymentCancelledEvent, L as LoadTapipayOptions, T as TapipayInstance } from './types-DYcwsDwH.cjs';
3
3
 
4
4
  /**
5
5
  * Hook de bajo nivel que carga el SDK y retorna la instancia.
@@ -16,8 +16,10 @@ declare function useTapipay(options?: LoadTapipayOptions): {
16
16
  interface TapipayWidgetProps extends Omit<TapipayOptions, "container"> {
17
17
  /** Entorno del SDK a cargar. Por defecto `'production'`. Usar `'homo'` para homologación. */
18
18
  environment?: TapipayEnvironment;
19
- /** Callback invocado cuando Yuno redirige al callback (pago en proceso). */
20
- onPending?: (data: TapipayPaymentPendingEvent) => void;
19
+ /** Callback invocado cuando el popup de Yuno se abre exitosamente. */
20
+ onPaymentWindowOpened?: (data: TapipayPaymentWindowOpenedEvent) => void;
21
+ /** Callback invocado cuando el usuario completó el formulario de Yuno y fue redirigido al callback. */
22
+ onPaymentSubmitted?: (data: TapipayPaymentSubmittedEvent) => void;
21
23
  /** Callback invocado cuando el usuario cierra el popup sin completar el pago. */
22
24
  onCancelled?: (data: TapipayPaymentCancelledEvent) => void;
23
25
  /** Clases CSS adicionales para el contenedor del widget. */
@@ -40,6 +42,6 @@ interface TapipayWidgetProps extends Omit<TapipayOptions, "container"> {
40
42
  * onCancelled={() => console.log("Pago cancelado por el usuario")}
41
43
  * />
42
44
  */
43
- declare function TapipayWidget({ organization, identifier, externalRequestId, selectionStrategy, environment, onPending, onCancelled, className, style, }: TapipayWidgetProps): react_jsx_runtime.JSX.Element;
45
+ declare function TapipayWidget({ organization, identifier, externalRequestId, selectionStrategy, environment, onPaymentWindowOpened, onPaymentSubmitted, onCancelled, className, style, }: TapipayWidgetProps): react_jsx_runtime.JSX.Element;
44
46
 
45
47
  export { TapipayWidget, type TapipayWidgetProps, useTapipay };
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { b as TapipayOptions, a as TapipayEnvironment, d as TapipayPaymentPendingEvent, c as TapipayPaymentCancelledEvent, L as LoadTapipayOptions, T as TapipayInstance } from './types-DmkYbkBI.js';
2
+ import { b as TapipayOptions, a as TapipayEnvironment, e as TapipayPaymentWindowOpenedEvent, d as TapipayPaymentSubmittedEvent, c as TapipayPaymentCancelledEvent, L as LoadTapipayOptions, T as TapipayInstance } from './types-DYcwsDwH.js';
3
3
 
4
4
  /**
5
5
  * Hook de bajo nivel que carga el SDK y retorna la instancia.
@@ -16,8 +16,10 @@ declare function useTapipay(options?: LoadTapipayOptions): {
16
16
  interface TapipayWidgetProps extends Omit<TapipayOptions, "container"> {
17
17
  /** Entorno del SDK a cargar. Por defecto `'production'`. Usar `'homo'` para homologación. */
18
18
  environment?: TapipayEnvironment;
19
- /** Callback invocado cuando Yuno redirige al callback (pago en proceso). */
20
- onPending?: (data: TapipayPaymentPendingEvent) => void;
19
+ /** Callback invocado cuando el popup de Yuno se abre exitosamente. */
20
+ onPaymentWindowOpened?: (data: TapipayPaymentWindowOpenedEvent) => void;
21
+ /** Callback invocado cuando el usuario completó el formulario de Yuno y fue redirigido al callback. */
22
+ onPaymentSubmitted?: (data: TapipayPaymentSubmittedEvent) => void;
21
23
  /** Callback invocado cuando el usuario cierra el popup sin completar el pago. */
22
24
  onCancelled?: (data: TapipayPaymentCancelledEvent) => void;
23
25
  /** Clases CSS adicionales para el contenedor del widget. */
@@ -40,6 +42,6 @@ interface TapipayWidgetProps extends Omit<TapipayOptions, "container"> {
40
42
  * onCancelled={() => console.log("Pago cancelado por el usuario")}
41
43
  * />
42
44
  */
43
- declare function TapipayWidget({ organization, identifier, externalRequestId, selectionStrategy, environment, onPending, onCancelled, className, style, }: TapipayWidgetProps): react_jsx_runtime.JSX.Element;
45
+ declare function TapipayWidget({ organization, identifier, externalRequestId, selectionStrategy, environment, onPaymentWindowOpened, onPaymentSubmitted, onCancelled, className, style, }: TapipayWidgetProps): react_jsx_runtime.JSX.Element;
44
46
 
45
47
  export { TapipayWidget, type TapipayWidgetProps, useTapipay };
package/dist/react.js CHANGED
@@ -28,17 +28,22 @@ function TapipayWidget({
28
28
  externalRequestId,
29
29
  selectionStrategy,
30
30
  environment,
31
- onPending,
31
+ onPaymentWindowOpened,
32
+ onPaymentSubmitted,
32
33
  onCancelled,
33
34
  className,
34
35
  style
35
36
  }) {
36
37
  const containerRef = useRef(null);
37
- const onPendingRef = useRef(onPending);
38
+ const onPaymentWindowOpenedRef = useRef(onPaymentWindowOpened);
39
+ const onPaymentSubmittedRef = useRef(onPaymentSubmitted);
38
40
  const onCancelledRef = useRef(onCancelled);
39
41
  useEffect(() => {
40
- onPendingRef.current = onPending;
41
- }, [onPending]);
42
+ onPaymentWindowOpenedRef.current = onPaymentWindowOpened;
43
+ }, [onPaymentWindowOpened]);
44
+ useEffect(() => {
45
+ onPaymentSubmittedRef.current = onPaymentSubmitted;
46
+ }, [onPaymentSubmitted]);
42
47
  useEffect(() => {
43
48
  onCancelledRef.current = onCancelled;
44
49
  }, [onCancelled]);
@@ -47,9 +52,13 @@ function TapipayWidget({
47
52
  const container = containerRef.current;
48
53
  let tapipayInstance = null;
49
54
  let cancelled = false;
50
- const handlePending = (data) => {
55
+ const handlePaymentWindowOpened = (data) => {
56
+ var _a;
57
+ (_a = onPaymentWindowOpenedRef.current) == null ? void 0 : _a.call(onPaymentWindowOpenedRef, data);
58
+ };
59
+ const handlePaymentSubmitted = (data) => {
51
60
  var _a;
52
- (_a = onPendingRef.current) == null ? void 0 : _a.call(onPendingRef, data);
61
+ (_a = onPaymentSubmittedRef.current) == null ? void 0 : _a.call(onPaymentSubmittedRef, data);
53
62
  };
54
63
  const handleCancelled = (data) => {
55
64
  var _a;
@@ -58,7 +67,8 @@ function TapipayWidget({
58
67
  loadTapipay({ environment }).then((instance) => {
59
68
  if (cancelled) return;
60
69
  tapipayInstance = instance;
61
- instance.on("paymentPending", handlePending);
70
+ instance.on("paymentWindowOpened", handlePaymentWindowOpened);
71
+ instance.on("paymentSubmitted", handlePaymentSubmitted);
62
72
  instance.on("paymentCancelled", handleCancelled);
63
73
  instance.initialize({
64
74
  container,
@@ -71,7 +81,8 @@ function TapipayWidget({
71
81
  return () => {
72
82
  cancelled = true;
73
83
  if (tapipayInstance) {
74
- tapipayInstance.off("paymentPending", handlePending);
84
+ tapipayInstance.off("paymentWindowOpened", handlePaymentWindowOpened);
85
+ tapipayInstance.off("paymentSubmitted", handlePaymentSubmitted);
75
86
  tapipayInstance.off("paymentCancelled", handleCancelled);
76
87
  tapipayInstance.destroy(container);
77
88
  }
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { loadTapipay } from \"./loader\";\nimport type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n\tTapipayOptions,\n\tTapipayPaymentCancelledEvent,\n\tTapipayPaymentPendingEvent,\n} from \"./types\";\n\n// ─── useTapipay hook ──────────────────────────────────────────────────────────\n\n/**\n * Hook de bajo nivel que carga el SDK y retorna la instancia.\n * Útil cuando necesitas control manual sobre initialize/destroy.\n *\n * @example\n * const { tapipay, error } = useTapipay();\n * const { tapipay, error } = useTapipay({ environment: 'homo' });\n */\nexport function useTapipay(options?: LoadTapipayOptions): {\n\ttapipay: TapipayInstance | null;\n\terror: Error | null;\n} {\n\tconst [tapipay, setTapipay] = useState<TapipayInstance | null>(null);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst environment = options?.environment;\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\t\tloadTapipay({ environment })\n\t\t\t.then((instance) => {\n\t\t\t\tif (!cancelled) setTapipay(instance);\n\t\t\t})\n\t\t\t.catch((err: Error) => {\n\t\t\t\tif (!cancelled) setError(err);\n\t\t\t});\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [environment]);\n\n\treturn { tapipay, error };\n}\n\n// ─── TapipayWidget component ──────────────────────────────────────────────────\n\nexport interface TapipayWidgetProps extends Omit<TapipayOptions, \"container\"> {\n\t/** Entorno del SDK a cargar. Por defecto `'production'`. Usar `'homo'` para homologación. */\n\tenvironment?: TapipayEnvironment;\n\t/** Callback invocado cuando Yuno redirige al callback (pago en proceso). */\n\tonPending?: (data: TapipayPaymentPendingEvent) => void;\n\t/** Callback invocado cuando el usuario cierra el popup sin completar el pago. */\n\tonCancelled?: (data: TapipayPaymentCancelledEvent) => void;\n\t/** Clases CSS adicionales para el contenedor del widget. */\n\tclassName?: string;\n\t/** Estilos inline adicionales para el contenedor del widget. */\n\tstyle?: React.CSSProperties;\n}\n\n/**\n * Componente React que encapsula el widget de pago TapiPay.\n *\n * Maneja internamente la carga del SDK, el ciclo de vida del widget\n * y el cleanup al desmontar. Compatible con React Strict Mode.\n *\n * @example\n * <TapipayWidget\n * organization=\"acme\"\n * identifier=\"CLI-001\"\n * externalRequestId=\"FAC-2024-001\"\n * onPending={(data) => console.log(\"Pago en proceso\", data)}\n * onCancelled={() => console.log(\"Pago cancelado por el usuario\")}\n * />\n */\nexport function TapipayWidget({\n\torganization,\n\tidentifier,\n\texternalRequestId,\n\tselectionStrategy,\n\tenvironment,\n\tonPending,\n\tonCancelled,\n\tclassName,\n\tstyle,\n}: TapipayWidgetProps) {\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\t// Refs para evitar re-renders innecesarios y closures estáticos en useEffect\n\tconst onPendingRef = useRef(onPending);\n\tconst onCancelledRef = useRef(onCancelled);\n\n\tuseEffect(() => {\n\t\tonPendingRef.current = onPending;\n\t}, [onPending]);\n\n\tuseEffect(() => {\n\t\tonCancelledRef.current = onCancelled;\n\t}, [onCancelled]);\n\n\tuseEffect(() => {\n\t\tif (!containerRef.current) return;\n\t\tconst container = containerRef.current;\n\n\t\tlet tapipayInstance: TapipayInstance | null = null;\n\t\tlet cancelled = false;\n\n\t\tconst handlePending = (data: TapipayPaymentPendingEvent) => {\n\t\t\tonPendingRef.current?.(data);\n\t\t};\n\t\tconst handleCancelled = (data: TapipayPaymentCancelledEvent) => {\n\t\t\tonCancelledRef.current?.(data);\n\t\t};\n\n\t\tloadTapipay({ environment }).then((instance) => {\n\t\t\tif (cancelled) return;\n\t\t\ttapipayInstance = instance;\n\n\t\t\tinstance.on(\"paymentPending\", handlePending);\n\t\t\tinstance.on(\"paymentCancelled\", handleCancelled);\n\n\t\t\tinstance.initialize({\n\t\t\t\tcontainer,\n\t\t\t\torganization,\n\t\t\t\tidentifier,\n\t\t\t\texternalRequestId,\n\t\t\t\tselectionStrategy,\n\t\t\t});\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t\tif (tapipayInstance) {\n\t\t\t\ttapipayInstance.off(\"paymentPending\", handlePending);\n\t\t\t\ttapipayInstance.off(\"paymentCancelled\", handleCancelled);\n\t\t\t\ttapipayInstance.destroy(container);\n\t\t\t}\n\t\t};\n\t\t// El widget se re-monta si cambian los parámetros de identificación o entorno\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [\n\t\torganization,\n\t\tidentifier,\n\t\texternalRequestId,\n\t\tselectionStrategy,\n\t\tenvironment,\n\t]);\n\n\treturn <div ref={containerRef} className={className} style={style} />;\n}\n"],"mappings":";;;;;AAAA,SAAS,WAAW,QAAQ,gBAAgB;AAoJpC;AA/HD,SAAS,WAAW,SAGzB;AACD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAiC,IAAI;AACnE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,IAAI;AACrD,QAAM,cAAc,mCAAS;AAE7B,YAAU,MAAM;AACf,QAAI,YAAY;AAChB,gBAAY,EAAE,YAAY,CAAC,EACzB,KAAK,CAAC,aAAa;AACnB,UAAI,CAAC,UAAW,YAAW,QAAQ;AAAA,IACpC,CAAC,EACA,MAAM,CAAC,QAAe;AACtB,UAAI,CAAC,UAAW,UAAS,GAAG;AAAA,IAC7B,CAAC;AACF,WAAO,MAAM;AACZ,kBAAY;AAAA,IACb;AAAA,EACD,GAAG,CAAC,WAAW,CAAC;AAEhB,SAAO,EAAE,SAAS,MAAM;AACzB;AAgCO,SAAS,cAAc;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAuB;AACtB,QAAM,eAAe,OAAuB,IAAI;AAEhD,QAAM,eAAe,OAAO,SAAS;AACrC,QAAM,iBAAiB,OAAO,WAAW;AAEzC,YAAU,MAAM;AACf,iBAAa,UAAU;AAAA,EACxB,GAAG,CAAC,SAAS,CAAC;AAEd,YAAU,MAAM;AACf,mBAAe,UAAU;AAAA,EAC1B,GAAG,CAAC,WAAW,CAAC;AAEhB,YAAU,MAAM;AACf,QAAI,CAAC,aAAa,QAAS;AAC3B,UAAM,YAAY,aAAa;AAE/B,QAAI,kBAA0C;AAC9C,QAAI,YAAY;AAEhB,UAAM,gBAAgB,CAAC,SAAqC;AA3G9D;AA4GG,yBAAa,YAAb,sCAAuB;AAAA,IACxB;AACA,UAAM,kBAAkB,CAAC,SAAuC;AA9GlE;AA+GG,2BAAe,YAAf,wCAAyB;AAAA,IAC1B;AAEA,gBAAY,EAAE,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa;AAC/C,UAAI,UAAW;AACf,wBAAkB;AAElB,eAAS,GAAG,kBAAkB,aAAa;AAC3C,eAAS,GAAG,oBAAoB,eAAe;AAE/C,eAAS,WAAW;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AACZ,kBAAY;AACZ,UAAI,iBAAiB;AACpB,wBAAgB,IAAI,kBAAkB,aAAa;AACnD,wBAAgB,IAAI,oBAAoB,eAAe;AACvD,wBAAgB,QAAQ,SAAS;AAAA,MAClC;AAAA,IACD;AAAA,EAGD,GAAG;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AAED,SAAO,oBAAC,SAAI,KAAK,cAAc,WAAsB,OAAc;AACpE;","names":[]}
1
+ {"version":3,"sources":["../src/react.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { loadTapipay } from \"./loader\";\nimport type {\n\tLoadTapipayOptions,\n\tTapipayEnvironment,\n\tTapipayInstance,\n\tTapipayOptions,\n\tTapipayPaymentCancelledEvent,\n\tTapipayPaymentSubmittedEvent,\n\tTapipayPaymentWindowOpenedEvent,\n} from \"./types\";\n\n// ─── useTapipay hook ──────────────────────────────────────────────────────────\n\n/**\n * Hook de bajo nivel que carga el SDK y retorna la instancia.\n * Útil cuando necesitas control manual sobre initialize/destroy.\n *\n * @example\n * const { tapipay, error } = useTapipay();\n * const { tapipay, error } = useTapipay({ environment: 'homo' });\n */\nexport function useTapipay(options?: LoadTapipayOptions): {\n\ttapipay: TapipayInstance | null;\n\terror: Error | null;\n} {\n\tconst [tapipay, setTapipay] = useState<TapipayInstance | null>(null);\n\tconst [error, setError] = useState<Error | null>(null);\n\tconst environment = options?.environment;\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\t\tloadTapipay({ environment })\n\t\t\t.then((instance) => {\n\t\t\t\tif (!cancelled) setTapipay(instance);\n\t\t\t})\n\t\t\t.catch((err: Error) => {\n\t\t\t\tif (!cancelled) setError(err);\n\t\t\t});\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [environment]);\n\n\treturn { tapipay, error };\n}\n\n// ─── TapipayWidget component ──────────────────────────────────────────────────\n\nexport interface TapipayWidgetProps extends Omit<TapipayOptions, \"container\"> {\n\t/** Entorno del SDK a cargar. Por defecto `'production'`. Usar `'homo'` para homologación. */\n\tenvironment?: TapipayEnvironment;\n\t/** Callback invocado cuando el popup de Yuno se abre exitosamente. */\n\tonPaymentWindowOpened?: (data: TapipayPaymentWindowOpenedEvent) => void;\n\t/** Callback invocado cuando el usuario completó el formulario de Yuno y fue redirigido al callback. */\n\tonPaymentSubmitted?: (data: TapipayPaymentSubmittedEvent) => void;\n\t/** Callback invocado cuando el usuario cierra el popup sin completar el pago. */\n\tonCancelled?: (data: TapipayPaymentCancelledEvent) => void;\n\t/** Clases CSS adicionales para el contenedor del widget. */\n\tclassName?: string;\n\t/** Estilos inline adicionales para el contenedor del widget. */\n\tstyle?: React.CSSProperties;\n}\n\n/**\n * Componente React que encapsula el widget de pago TapiPay.\n *\n * Maneja internamente la carga del SDK, el ciclo de vida del widget\n * y el cleanup al desmontar. Compatible con React Strict Mode.\n *\n * @example\n * <TapipayWidget\n * organization=\"acme\"\n * identifier=\"CLI-001\"\n * externalRequestId=\"FAC-2024-001\"\n * onPending={(data) => console.log(\"Pago en proceso\", data)}\n * onCancelled={() => console.log(\"Pago cancelado por el usuario\")}\n * />\n */\nexport function TapipayWidget({\n\torganization,\n\tidentifier,\n\texternalRequestId,\n\tselectionStrategy,\n\tenvironment,\n\tonPaymentWindowOpened,\n\tonPaymentSubmitted,\n\tonCancelled,\n\tclassName,\n\tstyle,\n}: TapipayWidgetProps) {\n\tconst containerRef = useRef<HTMLDivElement>(null);\n\t// Refs para evitar re-renders innecesarios y closures estáticos en useEffect\n\tconst onPaymentWindowOpenedRef = useRef(onPaymentWindowOpened);\n\tconst onPaymentSubmittedRef = useRef(onPaymentSubmitted);\n\tconst onCancelledRef = useRef(onCancelled);\n\n\tuseEffect(() => {\n\t\tonPaymentWindowOpenedRef.current = onPaymentWindowOpened;\n\t}, [onPaymentWindowOpened]);\n\n\tuseEffect(() => {\n\t\tonPaymentSubmittedRef.current = onPaymentSubmitted;\n\t}, [onPaymentSubmitted]);\n\n\tuseEffect(() => {\n\t\tonCancelledRef.current = onCancelled;\n\t}, [onCancelled]);\n\n\tuseEffect(() => {\n\t\tif (!containerRef.current) return;\n\t\tconst container = containerRef.current;\n\n\t\tlet tapipayInstance: TapipayInstance | null = null;\n\t\tlet cancelled = false;\n\n\t\tconst handlePaymentWindowOpened = (\n\t\t\tdata: TapipayPaymentWindowOpenedEvent,\n\t\t) => {\n\t\t\tonPaymentWindowOpenedRef.current?.(data);\n\t\t};\n\t\tconst handlePaymentSubmitted = (data: TapipayPaymentSubmittedEvent) => {\n\t\t\tonPaymentSubmittedRef.current?.(data);\n\t\t};\n\t\tconst handleCancelled = (data: TapipayPaymentCancelledEvent) => {\n\t\t\tonCancelledRef.current?.(data);\n\t\t};\n\n\t\tloadTapipay({ environment }).then((instance) => {\n\t\t\tif (cancelled) return;\n\t\t\ttapipayInstance = instance;\n\n\t\t\tinstance.on(\"paymentWindowOpened\", handlePaymentWindowOpened);\n\t\t\tinstance.on(\"paymentSubmitted\", handlePaymentSubmitted);\n\t\t\tinstance.on(\"paymentCancelled\", handleCancelled);\n\n\t\t\tinstance.initialize({\n\t\t\t\tcontainer,\n\t\t\t\torganization,\n\t\t\t\tidentifier,\n\t\t\t\texternalRequestId,\n\t\t\t\tselectionStrategy,\n\t\t\t});\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t\tif (tapipayInstance) {\n\t\t\t\ttapipayInstance.off(\"paymentWindowOpened\", handlePaymentWindowOpened);\n\t\t\t\ttapipayInstance.off(\"paymentSubmitted\", handlePaymentSubmitted);\n\t\t\t\ttapipayInstance.off(\"paymentCancelled\", handleCancelled);\n\t\t\t\ttapipayInstance.destroy(container);\n\t\t\t}\n\t\t};\n\t\t// El widget se re-monta si cambian los parámetros de identificación o entorno\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [\n\t\torganization,\n\t\tidentifier,\n\t\texternalRequestId,\n\t\tselectionStrategy,\n\t\tenvironment,\n\t]);\n\n\treturn <div ref={containerRef} className={className} style={style} />;\n}\n"],"mappings":";;;;;AAAA,SAAS,WAAW,QAAQ,gBAAgB;AAoKpC;AA9ID,SAAS,WAAW,SAGzB;AACD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAiC,IAAI;AACnE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,IAAI;AACrD,QAAM,cAAc,mCAAS;AAE7B,YAAU,MAAM;AACf,QAAI,YAAY;AAChB,gBAAY,EAAE,YAAY,CAAC,EACzB,KAAK,CAAC,aAAa;AACnB,UAAI,CAAC,UAAW,YAAW,QAAQ;AAAA,IACpC,CAAC,EACA,MAAM,CAAC,QAAe;AACtB,UAAI,CAAC,UAAW,UAAS,GAAG;AAAA,IAC7B,CAAC;AACF,WAAO,MAAM;AACZ,kBAAY;AAAA,IACb;AAAA,EACD,GAAG,CAAC,WAAW,CAAC;AAEhB,SAAO,EAAE,SAAS,MAAM;AACzB;AAkCO,SAAS,cAAc;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAuB;AACtB,QAAM,eAAe,OAAuB,IAAI;AAEhD,QAAM,2BAA2B,OAAO,qBAAqB;AAC7D,QAAM,wBAAwB,OAAO,kBAAkB;AACvD,QAAM,iBAAiB,OAAO,WAAW;AAEzC,YAAU,MAAM;AACf,6BAAyB,UAAU;AAAA,EACpC,GAAG,CAAC,qBAAqB,CAAC;AAE1B,YAAU,MAAM;AACf,0BAAsB,UAAU;AAAA,EACjC,GAAG,CAAC,kBAAkB,CAAC;AAEvB,YAAU,MAAM;AACf,mBAAe,UAAU;AAAA,EAC1B,GAAG,CAAC,WAAW,CAAC;AAEhB,YAAU,MAAM;AACf,QAAI,CAAC,aAAa,QAAS;AAC3B,UAAM,YAAY,aAAa;AAE/B,QAAI,kBAA0C;AAC9C,QAAI,YAAY;AAEhB,UAAM,4BAA4B,CACjC,SACI;AAtHP;AAuHG,qCAAyB,YAAzB,kDAAmC;AAAA,IACpC;AACA,UAAM,yBAAyB,CAAC,SAAuC;AAzHzE;AA0HG,kCAAsB,YAAtB,+CAAgC;AAAA,IACjC;AACA,UAAM,kBAAkB,CAAC,SAAuC;AA5HlE;AA6HG,2BAAe,YAAf,wCAAyB;AAAA,IAC1B;AAEA,gBAAY,EAAE,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa;AAC/C,UAAI,UAAW;AACf,wBAAkB;AAElB,eAAS,GAAG,uBAAuB,yBAAyB;AAC5D,eAAS,GAAG,oBAAoB,sBAAsB;AACtD,eAAS,GAAG,oBAAoB,eAAe;AAE/C,eAAS,WAAW;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD,CAAC;AAAA,IACF,CAAC;AAED,WAAO,MAAM;AACZ,kBAAY;AACZ,UAAI,iBAAiB;AACpB,wBAAgB,IAAI,uBAAuB,yBAAyB;AACpE,wBAAgB,IAAI,oBAAoB,sBAAsB;AAC9D,wBAAgB,IAAI,oBAAoB,eAAe;AACvD,wBAAgB,QAAQ,SAAS;AAAA,MAClC;AAAA,IACD;AAAA,EAGD,GAAG;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,CAAC;AAED,SAAO,oBAAC,SAAI,KAAK,cAAc,WAAsB,OAAc;AACpE;","names":[]}
@@ -30,11 +30,18 @@ interface TapipayOptions {
30
30
  selectionStrategy?: "oldestCreated";
31
31
  }
32
32
  /**
33
- * Payload del evento paymentPending.
34
- * El usuario completó el flujo de Yuno; el pago está en proceso.
33
+ * Payload del evento paymentWindowOpened.
34
+ * El popup de Yuno fue abierto exitosamente.
35
+ */
36
+ interface TapipayPaymentWindowOpenedEvent {
37
+ type: "paymentWindowOpened";
38
+ }
39
+ /**
40
+ * Payload del evento paymentSubmitted.
41
+ * El usuario completó el formulario de Yuno y fue redirigido al callback.
35
42
  * El estado real del pago se confirma vía webhooks en el backend.
36
43
  */
37
- interface TapipayPaymentPendingEvent {
44
+ interface TapipayPaymentSubmittedEvent {
38
45
  /** Siempre "TAPIPAY_CALLBACK" */
39
46
  type: string;
40
47
  /** Estado del pago: siempre "pending" */
@@ -53,9 +60,11 @@ type TapipayPaymentCancelledEvent = {};
53
60
  interface TapipayInstance {
54
61
  initialize(options: TapipayOptions): void;
55
62
  destroy(container: string | HTMLElement): void;
56
- on(event: "paymentPending", handler: (data: TapipayPaymentPendingEvent) => void): void;
63
+ on(event: "paymentWindowOpened", handler: (data: TapipayPaymentWindowOpenedEvent) => void): void;
64
+ on(event: "paymentSubmitted", handler: (data: TapipayPaymentSubmittedEvent) => void): void;
57
65
  on(event: "paymentCancelled", handler: (data: TapipayPaymentCancelledEvent) => void): void;
58
- off(event: "paymentPending", handler: (data: TapipayPaymentPendingEvent) => void): void;
66
+ off(event: "paymentWindowOpened", handler: (data: TapipayPaymentWindowOpenedEvent) => void): void;
67
+ off(event: "paymentSubmitted", handler: (data: TapipayPaymentSubmittedEvent) => void): void;
59
68
  off(event: "paymentCancelled", handler: (data: TapipayPaymentCancelledEvent) => void): void;
60
69
  off(event: string, handler: (...args: unknown[]) => unknown): void;
61
70
  /** Cola interna usada por el stub antes de que cargue el SDK real. */
@@ -67,4 +76,4 @@ declare global {
67
76
  }
68
77
  }
69
78
 
70
- export type { LoadTapipayOptions as L, TapipayInstance as T, TapipayEnvironment as a, TapipayOptions as b, TapipayPaymentCancelledEvent as c, TapipayPaymentPendingEvent as d };
79
+ export type { LoadTapipayOptions as L, TapipayInstance as T, TapipayEnvironment as a, TapipayOptions as b, TapipayPaymentCancelledEvent as c, TapipayPaymentSubmittedEvent as d, TapipayPaymentWindowOpenedEvent as e };
@@ -30,11 +30,18 @@ interface TapipayOptions {
30
30
  selectionStrategy?: "oldestCreated";
31
31
  }
32
32
  /**
33
- * Payload del evento paymentPending.
34
- * El usuario completó el flujo de Yuno; el pago está en proceso.
33
+ * Payload del evento paymentWindowOpened.
34
+ * El popup de Yuno fue abierto exitosamente.
35
+ */
36
+ interface TapipayPaymentWindowOpenedEvent {
37
+ type: "paymentWindowOpened";
38
+ }
39
+ /**
40
+ * Payload del evento paymentSubmitted.
41
+ * El usuario completó el formulario de Yuno y fue redirigido al callback.
35
42
  * El estado real del pago se confirma vía webhooks en el backend.
36
43
  */
37
- interface TapipayPaymentPendingEvent {
44
+ interface TapipayPaymentSubmittedEvent {
38
45
  /** Siempre "TAPIPAY_CALLBACK" */
39
46
  type: string;
40
47
  /** Estado del pago: siempre "pending" */
@@ -53,9 +60,11 @@ type TapipayPaymentCancelledEvent = {};
53
60
  interface TapipayInstance {
54
61
  initialize(options: TapipayOptions): void;
55
62
  destroy(container: string | HTMLElement): void;
56
- on(event: "paymentPending", handler: (data: TapipayPaymentPendingEvent) => void): void;
63
+ on(event: "paymentWindowOpened", handler: (data: TapipayPaymentWindowOpenedEvent) => void): void;
64
+ on(event: "paymentSubmitted", handler: (data: TapipayPaymentSubmittedEvent) => void): void;
57
65
  on(event: "paymentCancelled", handler: (data: TapipayPaymentCancelledEvent) => void): void;
58
- off(event: "paymentPending", handler: (data: TapipayPaymentPendingEvent) => void): void;
66
+ off(event: "paymentWindowOpened", handler: (data: TapipayPaymentWindowOpenedEvent) => void): void;
67
+ off(event: "paymentSubmitted", handler: (data: TapipayPaymentSubmittedEvent) => void): void;
59
68
  off(event: "paymentCancelled", handler: (data: TapipayPaymentCancelledEvent) => void): void;
60
69
  off(event: string, handler: (...args: unknown[]) => unknown): void;
61
70
  /** Cola interna usada por el stub antes de que cargue el SDK real. */
@@ -67,4 +76,4 @@ declare global {
67
76
  }
68
77
  }
69
78
 
70
- export type { LoadTapipayOptions as L, TapipayInstance as T, TapipayEnvironment as a, TapipayOptions as b, TapipayPaymentCancelledEvent as c, TapipayPaymentPendingEvent as d };
79
+ export type { LoadTapipayOptions as L, TapipayInstance as T, TapipayEnvironment as a, TapipayOptions as b, TapipayPaymentCancelledEvent as c, TapipayPaymentSubmittedEvent as d, TapipayPaymentWindowOpenedEvent as e };
package/package.json CHANGED
@@ -1,44 +1,43 @@
1
1
  {
2
- "name": "@npmtapi/embed",
3
- "version": "1.0.0",
4
- "description": "TapiPay Embed SDK — carga y controla el widget de pago embebido",
5
- "type": "module",
6
- "exports": {
7
- ".": {
8
- "types": "./dist/index.d.ts",
9
- "import": "./dist/index.js",
10
- "require": "./dist/index.cjs"
11
- },
12
- "./react": {
13
- "types": "./dist/react.d.ts",
14
- "import": "./dist/react.js",
15
- "require": "./dist/react.cjs"
16
- }
17
- },
18
- "files": [
19
- "dist"
20
- ],
21
- "scripts": {
22
- "build": "tsup",
23
- "dev": "tsup --watch",
24
- "prepublishOnly": "pnpm build"
25
- },
26
- "author": "tapipay",
27
- "publishConfig": {
28
- "access": "public"
29
- },
30
- "peerDependencies": {
31
- "react": ">=18"
32
- },
33
- "peerDependenciesMeta": {
34
- "react": {
35
- "optional": true
36
- }
37
- },
38
- "devDependencies": {
39
- "@types/react": "^18.0.0",
40
- "react": "^18.0.0",
41
- "tsup": "^8.0.0",
42
- "typescript": "^5.0.0"
43
- }
44
- }
2
+ "name": "@npmtapi/embed",
3
+ "version": "1.1.0",
4
+ "description": "TapiPay Embed SDK — carga y controla el widget de pago embebido",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js",
10
+ "require": "./dist/index.cjs"
11
+ },
12
+ "./react": {
13
+ "types": "./dist/react.d.ts",
14
+ "import": "./dist/react.js",
15
+ "require": "./dist/react.cjs"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "author": "tapipay",
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "peerDependencies": {
26
+ "react": ">=18"
27
+ },
28
+ "peerDependenciesMeta": {
29
+ "react": {
30
+ "optional": true
31
+ }
32
+ },
33
+ "devDependencies": {
34
+ "@types/react": "^18.0.0",
35
+ "react": "^18.0.0",
36
+ "tsup": "^8.0.0",
37
+ "typescript": "^5.0.0"
38
+ },
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "dev": "tsup --watch"
42
+ }
43
+ }