@vetc-miniapp/ui-react 0.0.11 → 0.0.13

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
@@ -5,21 +5,98 @@ SDK giúp Mini App giao tiếp với Super App host thông qua JS Bridge.
5
5
  ## Cài đặt
6
6
 
7
7
  ```bash
8
- npm install @yourcompany/miniapp-sdk
8
+ npm install @vetc-miniapp/ui-react
9
9
  ```
10
10
  ## Sử dụng
11
+ # useNavigate – Điều hướng Mini App qua Native (Flutter)
11
12
 
12
- import MiniApp from "@vetc/miniapp-sdk";
13
+ `useNavigate` hook dùng trong **mini app React** để điều hướng **thông qua host app (Flutter)**, thay vì tự điều hướng nội bộ bằng `react-router-dom`.
13
14
 
14
- MiniApp.getScopedToken().then(console.log);
15
+ Hook này giúp:
15
16
 
16
- MiniApp.pickImage({ source: "camera" }).then(console.log);
17
+ - Mini app **không phụ thuộc URL thực**
18
+ - Toàn bộ navigation được **native kiểm soát**
19
+ - **Đồng bộ header, back stack, animation** giữa mini app & app chính
17
20
 
18
- MiniApp.on("TOKEN_REFRESH", data => {
19
- console.log("Token updated:", data);
21
+ ---
22
+
23
+ ## 📦 Import
24
+
25
+ ```ts
26
+ import { useNavigate } from '@vetc-miniapp/ui-react';
27
+
28
+ const navigate = useNavigate();
29
+
30
+ navigate(
31
+ path: string,
32
+ title: string,
33
+ params?: Record<string, any>,
34
+ options?: {
35
+ replace?: boolean;
36
+ popTo?: string;
37
+ }
38
+ ): void
39
+
40
+ ```
41
+
42
+ ## 🚀 Cách sử dụng cơ bản
43
+ # Điều hướng sang page khác
44
+ ```ts
45
+ const navigate = useNavigate();
46
+
47
+ <button onClick={() => navigate('/about', { title: "About", params: {}})}>
48
+ Go to About
49
+ </button>
50
+
51
+ Truyền params
52
+ navigate('/vehicle-detail', {
53
+ title: "About",
54
+ params: {
55
+ id: 'abc123',
56
+ source: 'homepage',
57
+ }
20
58
  });
59
+ ```
21
60
 
22
- npm run build
23
- npm publish --access public
61
+ # Flutter sẽ nhận được URL dạng:
24
62
 
63
+ /miniapp/vehicle-detail?id=abc123&source=homepage
25
64
 
65
+ ## 🔁 Replace route (không giữ back stack)
66
+ ```
67
+ navigate('/login', { mode: 'replace' });
68
+
69
+
70
+ navigate('/home', { popTo: '/home' });
71
+ ```
72
+ ## 🧩 Ví dụ đầy đủ trong Component
73
+ ```
74
+
75
+ import { useNavigate } from '@vetc-miniapp/ui-react';
76
+
77
+ function VehicleItem({ vehicle }) {
78
+ const navigate = useNavigate();
79
+
80
+ return (
81
+ <div onClick={() => navigate('/vehicle-detail', { title: "Chi tiết xe"}, { mode: "replace" })}>
82
+ {vehicle.name}
83
+ </div>
84
+ );
85
+ }
86
+ ```
87
+
88
+ ## ⚠️ Lưu ý quan trọng
89
+ # ❌ Không dùng react-router-dom
90
+ ```
91
+
92
+ // KHÔNG dùng
93
+ import { useNavigate } from 'react-router-dom';
94
+
95
+
96
+ Mini app không quản lý history nội bộ.
97
+ ```
98
+
99
+ # ❌ Không dùng window.location
100
+ ```
101
+ window.location.href = '/about'; // ❌
102
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vetc-miniapp/ui-react",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "MiniApp Platform UI React",
5
5
  "main": "src/ui-react/index.js",
6
6
  "types": "src/ui-react/index.ts",
@@ -1,2 +1,2 @@
1
1
  /*! For license information please see index.js.LICENSE.txt */
2
- !function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r(require("react")):"function"==typeof define&&define.amd?define(["react"],r):"object"==typeof exports?exports["vetc-miniapp/ui-react"]=r(require("react")):e["vetc-miniapp/ui-react"]=r(e.react)}(this,e=>(()=>{"use strict";var r={155(r){r.exports=e},698(e,r){var t=Symbol.for("react.transitional.element"),n=Symbol.for("react.fragment");function o(e,r,n){var o=null;if(void 0!==n&&(o=""+n),void 0!==r.key&&(o=""+r.key),"key"in r)for(var i in n={},r)"key"!==i&&(n[i]=r[i]);else n=r;return r=n.ref,{$$typeof:t,type:e,key:o,ref:void 0!==r?r:null,props:n}}r.Fragment=n,r.jsx=o,r.jsxs=o},848(e,r,t){e.exports=t(698)}},t={};function n(e){var o=t[e];if(void 0!==o)return o.exports;var i=t[e]={exports:{}};return r[e](i,i.exports,n),i.exports}n.d=(e,r)=>{for(var t in r)n.o(r,t)&&!n.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},n.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};n.r(o),n.d(o,{App:()=>m,appConfig:()=>u,getCurrentPage:()=>y,initRouter:()=>v,setCurrentPath:()=>g,useNavigate:()=>l});var i="undefined"!=typeof window,a=function(e){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},t=i&&window.flutter_inappwebview?window.flutter_inappwebview:null;return t?t.callHandler("MiniAppBridge",{action:e,payload:r}):Promise.reject(new Error("MiniApp bridge not available"))};function l(){return function(e){a("navigate",{type:"native",route:e,params:arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},options:arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}})}}var u={locale:"vi",theme:"light",pages:[]},c=n(155),f=n(848);function p(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,n=Array(r);t<r;t++)n[t]=e[t];return n}var s=new Map,d="/";function v(e){console.log(e),s=new Map(e.pages.map(function(e){return[e.path,e]})),console.log(s)}function y(){return s.get(d)}function g(e){d=e}function m(e){var r,t,n=e.config,o=e.children,i=(r=(0,c.useState)(null),t=2,function(e){if(Array.isArray(e))return e}(r)||function(e,r){var t=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=t){var n,o,i,a,l=[],u=!0,c=!1;try{if(i=(t=t.call(e)).next,0===r){if(Object(t)!==t)return;u=!1}else for(;!(u=(n=i.call(t)).done)&&(l.push(n.value),l.length!==r);u=!0);}catch(e){c=!0,o=e}finally{try{if(!u&&null!=t.return&&(a=t.return(),Object(a)!==a))return}finally{if(c)throw o}}return l}}(r,t)||function(e,r){if(e){if("string"==typeof e)return p(e,r);var t={}.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?p(e,r):void 0}}(r,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),l=i[0],u=i[1];(0,c.useEffect)(function(){var e;if(console.warn("SDK useEffect fired"),null!=n&&null!==(e=n.pages)&&void 0!==e&&e.length){v(n),console.warn(n),g((window.location.path||"/").replace("/miniapp","")||"/");var r=y();console.warn(r),r||(g("/"),r=y()),u(r),a("registerAppConfig",{config:n})}},[n]),console.warn("SDK fired"),l&&l.Component||console.warn("MiniApp: Page not found for current route");var s=l.Component||(0,f.jsx)("div",{});return(0,f.jsxs)(f.Fragment,{children:[(0,f.jsx)(s,{}),o]})}return o})());
2
+ !function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n(require("react")):"function"==typeof define&&define.amd?define(["react"],n):"object"==typeof exports?exports["vetc-miniapp/ui-react"]=n(require("react")):e["vetc-miniapp/ui-react"]=n(e.react)}(this,e=>(()=>{"use strict";var n={155(n){n.exports=e},698(e,n){var r=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function o(e,n,t){var o=null;if(void 0!==t&&(o=""+t),void 0!==n.key&&(o=""+n.key),"key"in n)for(var i in t={},n)"key"!==i&&(t[i]=n[i]);else t=n;return n=t.ref,{$$typeof:r,type:e,key:o,ref:void 0!==n?n:null,props:t}}n.Fragment=t,n.jsx=o,n.jsxs=o},848(e,n,r){e.exports=r(698)}},r={};function t(e){var o=r[e];if(void 0!==o)return o.exports;var i=r[e]={exports:{}};return n[e](i,i.exports,t),i.exports}t.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return t.d(n,{a:n}),n},t.d=(e,n)=>{for(var r in n)t.o(n,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:n[r]})},t.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),t.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};t.r(o),t.d(o,{App:()=>O,appConfig:()=>m,getCurrentPage:()=>S,initRouter:()=>M,setCurrentPath:()=>x,useAppPause:()=>a,useAppResume:()=>c,useDidHide:()=>p,useDidShow:()=>f,useNavigate:()=>g});var i=t(155),u=t.n(i);function a(e){var n=(0,i.useRef)(e);(0,i.useEffect)(function(){n.current=e},[e]),(0,i.useEffect)(function(){if("undefined"!=typeof window&&window.MiniApp){var e=function(){try{n.current&&n.current()}catch(e){console.error("[useAppPause error]",e)}};return window.MiniApp.on("appPause",e),function(){window.MiniApp.off("appPause",e)}}},[])}function c(e){var n=(0,i.useRef)(e);(0,i.useEffect)(function(){n.current=e},[e]),(0,i.useEffect)(function(){if(console.warn("MiniApp: useAppResume"),console.warn(window.MiniApp),"undefined"!=typeof window&&window.MiniApp){var e=function(){try{n.current&&n.current()}catch(e){console.error("[useAppResume error]",e)}};return window.MiniApp.on("appResume",e),function(){window.MiniApp.off("appResume",e)}}},[])}function f(e,n){var r=(0,i.useRef)(n);(0,i.useEffect)(function(){r.current=n},[n]),(0,i.useEffect)(function(){if(window.MiniApp){var n=function(n){var t;(null==n?void 0:n.pathname)===e&&(null===(t=r.current)||void 0===t||t.call(r,n))};return window.MiniApp.on("didShow",n),function(){window.MiniApp.off("didShow",n)}}},[e])}function p(e,n){var r=(0,i.useRef)(n);(0,i.useEffect)(function(){r.current=n},[n]),(0,i.useEffect)(function(){if(window.MiniApp){var n=function(n){var t;(null==n?void 0:n.pathname)===e&&(null===(t=r.current)||void 0===t||t.call(r,n))};return window.MiniApp.on("didHide",n),function(){window.MiniApp.off("didHide",n)}}},[e])}function l(){var e,n,r="function"==typeof Symbol?Symbol:{},t=r.iterator||"@@iterator",o=r.toStringTag||"@@toStringTag";function i(r,t,o,i){var c=t&&t.prototype instanceof a?t:a,f=Object.create(c.prototype);return s(f,"_invoke",function(r,t,o){var i,a,c,f=0,p=o||[],l=!1,s={p:0,n:0,v:e,a:d,f:d.bind(e,4),d:function(n,r){return i=n,a=0,c=e,s.n=r,u}};function d(r,t){for(a=r,c=t,n=0;!l&&f&&!o&&n<p.length;n++){var o,i=p[n],d=s.p,v=i[2];r>3?(o=v===t)&&(c=i[(a=i[4])?5:(a=3,3)],i[4]=i[5]=e):i[0]<=d&&((o=r<2&&d<i[1])?(a=0,s.v=t,s.n=i[1]):d<v&&(o=r<3||i[0]>t||t>v)&&(i[4]=r,i[5]=t,s.n=v,a=0))}if(o||r>1)return u;throw l=!0,t}return function(o,p,v){if(f>1)throw TypeError("Generator is already running");for(l&&1===p&&d(p,v),a=p,c=v;(n=a<2?e:c)||!l;){i||(a?a<3?(a>1&&(s.n=-1),d(a,c)):s.n=c:s.v=c);try{if(f=2,i){if(a||(o="next"),n=i[o]){if(!(n=n.call(i,c)))throw TypeError("iterator result is not an object");if(!n.done)return n;c=n.value,a<2&&(a=0)}else 1===a&&(n=i.return)&&n.call(i),a<2&&(c=TypeError("The iterator does not provide a '"+o+"' method"),a=1);i=e}else if((n=(l=s.n<0)?c:r.call(t,s))!==u)break}catch(n){i=e,a=1,c=n}finally{f=1}}return{value:n,done:l}}}(r,o,i),!0),f}var u={};function a(){}function c(){}function f(){}n=Object.getPrototypeOf;var p=[][t]?n(n([][t]())):(s(n={},t,function(){return this}),n),d=f.prototype=a.prototype=Object.create(p);function v(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,f):(e.__proto__=f,s(e,o,"GeneratorFunction")),e.prototype=Object.create(d),e}return c.prototype=f,s(d,"constructor",f),s(f,"constructor",c),c.displayName="GeneratorFunction",s(f,o,"GeneratorFunction"),s(d),s(d,o,"Generator"),s(d,t,function(){return this}),s(d,"toString",function(){return"[object Generator]"}),(l=function(){return{w:i,m:v}})()}function s(e,n,r,t){var o=Object.defineProperty;try{o({},"",{})}catch(e){o=0}s=function(e,n,r,t){function i(n,r){s(e,n,function(e){return this._invoke(n,r,e)})}n?o?o(e,n,{value:r,enumerable:!t,configurable:!t,writable:!t}):e[n]=r:(i("next",0),i("throw",1),i("return",2))},s(e,n,r,t)}function d(e,n,r,t,o,i,u){try{var a=e[i](u),c=a.value}catch(e){return void r(e)}a.done?n(c):Promise.resolve(c).then(t,o)}var v="undefined"!=typeof window,y=function(){return v&&window.flutter_inappwebview?window.flutter_inappwebview:null},w=function(){var e,n=(e=l().m(function e(n){var r,t,o,i,u=arguments;return l().w(function(e){for(;;)switch(e.p=e.n){case 0:if(r=u.length>1&&void 0!==u[1]?u[1]:{},t=y()){e.n=1;break}return e.a(2,Promise.reject(new Error("MiniApp bridge not available")));case 1:return e.p=1,e.n=2,t.callHandler("MiniAppBridge",{action:n,payload:r});case 2:return o=e.v,e.a(2,o);case 3:throw e.p=3,i=e.v,console.error("Bridge error:",i),i;case 4:return e.a(2)}},e,null,[[1,3]])}),function(){var n=this,r=arguments;return new Promise(function(t,o){var i=e.apply(n,r);function u(e){d(i,t,o,u,a,"next",e)}function a(e){d(i,t,o,u,a,"throw",e)}u(void 0)})});return function(e){return n.apply(this,arguments)}}();function g(){return function(e){w("navigate",{type:"native",route:e,params:arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},options:arguments.length>2&&void 0!==arguments[2]?arguments[2]:{}})}}var m={locale:"vi",theme:"light",pages:[]},h=t(848);function b(e,n){(null==n||n>e.length)&&(n=e.length);for(var r=0,t=Array(n);r<n;r++)t[r]=e[r];return t}var A=new Map,j="/";function M(e){console.log(e),A=new Map(e.pages.map(function(e){return[e.path,e]})),console.log(A)}function S(){return A.get(j)}function x(e){j=e}function O(e){var n,r,t=e.config,o=e.children,u=(n=(0,i.useState)(null),r=2,function(e){if(Array.isArray(e))return e}(n)||function(e,n){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var t,o,i,u,a=[],c=!0,f=!1;try{if(i=(r=r.call(e)).next,0===n){if(Object(r)!==r)return;c=!1}else for(;!(c=(t=i.call(r)).done)&&(a.push(t.value),a.length!==n);c=!0);}catch(e){f=!0,o=e}finally{try{if(!c&&null!=r.return&&(u=r.return(),Object(u)!==u))return}finally{if(f)throw o}}return a}}(n,r)||function(e,n){if(e){if("string"==typeof e)return b(e,n);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?b(e,n):void 0}}(n,r)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),a=u[0],c=u[1];if((0,i.useEffect)(function(){var e;if(null!=t&&null!==(e=t.pages)&&void 0!==e&&e.length){M(t);var n=window.location.pathname||"/",r=n.replace("/miniapp","")||"/";console.log(n),x(r);var o=S();console.warn(o),o||(x("/"),o=S()),c(o),w("registerAppConfig",{config:t})}},[t]),!a||!a.Component)return console.warn("MiniApp: Page not found for current route"),(0,h.jsx)(h.Fragment,{children:(0,h.jsx)("div",{})});var f=a.Component||(0,h.jsx)("div",{});return(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(f,{}),o]})}return console.log("SDK React object:",u()),o})());
@@ -1,3 +1,5 @@
1
+ /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
2
+
1
3
  /**
2
4
  * @license React
3
5
  * react-jsx-runtime.production.js
@@ -0,0 +1,35 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ /**
4
+ * useAppPause
5
+ *
6
+ * Trigger khi Native App đi vào background.
7
+ */
8
+ export function useAppPause(callback) {
9
+ const savedCallback = useRef(callback);
10
+
11
+ // Luôn giữ callback mới nhất
12
+ useEffect(() => {
13
+ savedCallback.current = callback;
14
+ }, [callback]);
15
+
16
+ useEffect(() => {
17
+ if (typeof window === "undefined" || !window.MiniApp) return;
18
+
19
+ const handler = () => {
20
+ try {
21
+ if (savedCallback.current) {
22
+ savedCallback.current();
23
+ }
24
+ } catch (err) {
25
+ console.error("[useAppPause error]", err);
26
+ }
27
+ };
28
+
29
+ window.MiniApp.on("appPause", handler);
30
+
31
+ return () => {
32
+ window.MiniApp.off("appPause", handler);
33
+ };
34
+ }, []);
35
+ }
@@ -0,0 +1,33 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ /**
4
+ * useAppPause
5
+ *
6
+ * Trigger khi Native App đi vào background.
7
+ */
8
+ export function useAppPause(callback: () => void) {
9
+ const savedCallback = useRef(callback);
10
+
11
+ // giữ callback luôn mới nhất
12
+ useEffect(() => {
13
+ savedCallback.current = callback;
14
+ }, [callback]);
15
+
16
+ useEffect(() => {
17
+ if (typeof window === "undefined" || !window.MiniApp) return;
18
+
19
+ const handler = () => {
20
+ try {
21
+ savedCallback.current?.();
22
+ } catch (err) {
23
+ console.error("[useAppPause error]", err);
24
+ }
25
+ };
26
+
27
+ window.MiniApp.on("appPause", handler);
28
+
29
+ return () => {
30
+ window.MiniApp.off("appPause", handler);
31
+ };
32
+ }, []);
33
+ }
@@ -0,0 +1,38 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ /**
4
+ * useAppResume
5
+ *
6
+ * Trigger khi Native App quay lại foreground.
7
+ */
8
+ export function useAppResume(callback) {
9
+ const savedCallback = useRef(callback);
10
+
11
+ // Cập nhật callback mới nhất
12
+ useEffect(() => {
13
+ savedCallback.current = callback;
14
+ }, [callback]);
15
+
16
+ useEffect(() => {
17
+ console.warn("MiniApp: useAppResume");
18
+ console.warn(window.MiniApp);
19
+
20
+ if (typeof window === "undefined" || !window.MiniApp) return;
21
+
22
+ const handler = () => {
23
+ try {
24
+ if (savedCallback.current) {
25
+ savedCallback.current();
26
+ }
27
+ } catch (err) {
28
+ console.error("[useAppResume error]", err);
29
+ }
30
+ };
31
+
32
+ window.MiniApp.on("appResume", handler);
33
+
34
+ return () => {
35
+ window.MiniApp.off("appResume", handler);
36
+ };
37
+ }, []);
38
+ }
@@ -0,0 +1,32 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ /**
4
+ * useAppResume
5
+ *
6
+ * Trigger khi Native App quay lại foreground.
7
+ */
8
+ export function useAppResume(callback: () => void) {
9
+ const savedCallback = useRef(callback);
10
+
11
+ useEffect(() => {
12
+ savedCallback.current = callback;
13
+ }, [callback]);
14
+
15
+ useEffect(() => {
16
+ if (typeof window === "undefined" || !window.MiniApp) return;
17
+
18
+ const handler = () => {
19
+ try {
20
+ savedCallback.current?.();
21
+ } catch (err) {
22
+ console.error("[useAppResume error]", err);
23
+ }
24
+ };
25
+
26
+ window.MiniApp.on("appResume", handler);
27
+
28
+ return () => {
29
+ window.MiniApp.off("appResume", handler);
30
+ };
31
+ }, []);
32
+ }
@@ -0,0 +1,25 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ export function useDidHide(pathname, callback) {
4
+ const saved = useRef(callback);
5
+
6
+ useEffect(() => {
7
+ saved.current = callback;
8
+ }, [callback]);
9
+
10
+ useEffect(() => {
11
+ if (!window.MiniApp) return;
12
+
13
+ const handler = (data) => {
14
+ if (data?.pathname === pathname) {
15
+ saved.current?.(data);
16
+ }
17
+ };
18
+
19
+ window.MiniApp.on("didHide", handler);
20
+
21
+ return () => {
22
+ window.MiniApp.off("didHide", handler);
23
+ };
24
+ }, [pathname]);
25
+ }
@@ -0,0 +1,34 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ type DidHidePayload = {
4
+ pathname?: string;
5
+ [key: string]: any;
6
+ };
7
+
8
+ export function useDidHide(
9
+ pathname: string,
10
+ callback: (data?: DidHidePayload) => void
11
+ ): void {
12
+ const saved = useRef(callback);
13
+
14
+ // luôn giữ callback mới nhất
15
+ useEffect(() => {
16
+ saved.current = callback;
17
+ }, [callback]);
18
+
19
+ useEffect(() => {
20
+ if (typeof window === "undefined" || !window.MiniApp) return;
21
+
22
+ const handler = (data?: DidHidePayload) => {
23
+ if (data?.pathname === pathname) {
24
+ saved.current?.(data);
25
+ }
26
+ };
27
+
28
+ window.MiniApp.on("didHide", handler);
29
+
30
+ return () => {
31
+ window.MiniApp.off("didHide", handler);
32
+ };
33
+ }, [pathname]);
34
+ }
@@ -0,0 +1,25 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ export function useDidShow(pathname, callback) {
4
+ const saved = useRef(callback);
5
+
6
+ useEffect(() => {
7
+ saved.current = callback;
8
+ }, [callback]);
9
+
10
+ useEffect(() => {
11
+ if (!window.MiniApp) return;
12
+
13
+ const handler = (data) => {
14
+ if (data?.pathname === pathname) {
15
+ saved.current?.(data);
16
+ }
17
+ };
18
+
19
+ window.MiniApp.on("didShow", handler);
20
+
21
+ return () => {
22
+ window.MiniApp.off("didShow", handler);
23
+ };
24
+ }, [pathname]);
25
+ }
@@ -0,0 +1,34 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ type DidShowPayload = {
4
+ pathname?: string;
5
+ [key: string]: any;
6
+ };
7
+
8
+ export function useDidShow(
9
+ pathname: string,
10
+ callback: (data?: DidShowPayload) => void
11
+ ): void {
12
+ const saved = useRef(callback);
13
+
14
+ // luôn giữ callback mới nhất
15
+ useEffect(() => {
16
+ saved.current = callback;
17
+ }, [callback]);
18
+
19
+ useEffect(() => {
20
+ if (typeof window === "undefined" || !window.MiniApp) return;
21
+
22
+ const handler = (data?: DidShowPayload) => {
23
+ if (data?.pathname === pathname) {
24
+ saved.current?.(data);
25
+ }
26
+ };
27
+
28
+ window.MiniApp.on("didShow", handler);
29
+
30
+ return () => {
31
+ window.MiniApp.off("didShow", handler);
32
+ };
33
+ }, [pathname]);
34
+ }
@@ -1,3 +1,7 @@
1
+ export * from './hooks/use-app-pause.js';
2
+ export * from './hooks/use-app-resume.js';
3
+ export * from './hooks/use-did-show.js';
4
+ export * from './hooks/use-did-hide.js';
1
5
  export * from './hooks/use-navigate.js';
2
6
  export * from './hooks/use-app-state.js';
3
7
  export * from './components/app.jsx';
@@ -1,3 +1,7 @@
1
+ export * from './hooks/use-app-resume';
2
+ export * from './hooks/use-app-pause';
3
+ export * from './hooks/use-did-show';
4
+ export * from './hooks/use-did-hide';
1
5
  export * from './hooks/use-navigate';
2
6
  export * from './hooks/use-app-state';
3
7
  // export * from './components/app';