npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ejsc-mna-router

v1.0.3

Published

High-performance React Router tailored for 365 Mini App ecosystem. Features Framer Motion page transitions, declarative navigation config, and strict mobile stack-based navigation paradigms.

Readme

ejsc-mna-router 🚀

npm version License: MIT React Version TypeScript

The High-Performance Stack Router & Lifecycle Management Suite for 365 Mini App Ecosystem.

ejsc-mna-router là giải pháp điều hướng (Navigation Router) chuyên biệt cho các ứng dụng 365 Mini App. Khác với các web router thông thường, ejsc-mna-router được tối ưu hóa hoàn toàn cho mô hình điều hướng ngăn xếp di động (Stack-Based Mobile Navigation), hỗ trợ cơ chế duy trì trạng thái (Keep-Alive / Freeze DOM), hiệu ứng chuyển trang mượt mà cùng hệ thống vòng đời đặc thù (useDidShow, useDidHide, useAppPause, useAppResume).


📑 Mục Lục


1. Tính Năng Nổi Bật

  • 📚 Stack-Based Navigation: Điều hướng dạng ngăn xếp tương tự ứng dụng Native di động (PUSH, POP, REPLACE).
  • 🧊 Smart Keep-Alive & Freeze: Giữ lại DOM của các trang đã mở trong ngăn xếp và tạm dừng (suspend) rendering để tối ưu bộ nhớ.
  • Fluid Page Transitions: Hiệu ứng chuyển trang mượt mà 60fps (slide_left, slide_up, fade_in, none) hỗ trợ cả CSS Transitions lẫn Web View Transitions API.
  • 🔄 Native Mini App Lifecycles: Hỗ trợ đầy đủ các lifecycle hook như useDidShow (onShow), useDidHide (onHide), useAppPause, useAppResume.
  • ☝️ Gesture Swipe Back: Lắng nghe cử chỉ vuốt tay từ mép màn hình để quay lại trang trước.
  • Zustand State Engine: Quản lý lịch sử và trạng thái ngăn xếp điều hướng siêu nhẹ và an toàn.

2. Yêu Cầu Hệ Thống & Cài Đặt

Yêu cầu:

  • React & React DOM: Phiên bản >= 19.0.0
  • Node.js: Phiên bản >= 18.0.0

Cài đặt:

# Sử dụng pnpm (khuyên dùng)
pnpm add [email protected]

# Sử dụng npm
npm install [email protected]

3. Hướng Dẫn Sử Dụng Nhanh

3.1 Cấu Hình Router (app.config.ts)

Định nghĩa danh sách các trang và cấu hình hiệu ứng điều hướng:

import { lazy } from 'react';
import type { IRouterConfig } from 'ejsc-mna-router';

const config: IRouterConfig = {
  pages: [
    {
      pathname: '/pages/home/index',
      Component: lazy(() => import('./pages/home')),
    },
    {
      pathname: '/pages/profile/index',
      Component: lazy(() => import('./pages/profile')),
    },
    {
      pathname: '/pages/detail/index',
      Component: lazy(() => import('./pages/detail')),
    },
  ],
  animation: {
    type: 'slide_left',
    mode: 'style-transition',
  },
  keepAlive: {
    enable: true,
    maxStack: 5,
    freeze: true,
    freezeDelay: 300,
  },
};

export default config;

3.2 Tích Hợp Vào App (main.tsx)

import React from 'react';
import ReactDOM from 'react-dom/client';
import { Router } from 'ejsc-mna-router';
import 'ejsc-mna-router/dist/styles.css';
import config from './app.config';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <Router config={config} />
);

4. Chi Tiết Các Component & Hooks API

4.1 Component <Link />

Điều hướng dạng khai báo JSX thay thế thẻ HTML <a>:

import { Link } from 'ejsc-mna-router';

// Điều hướng cơ bản
<Link to="/pages/profile/index">Trang cá nhân</Link>

// Truyền parameters và state dữ liệu
<Link 
  to="/pages/detail/index" 
  params={{ id: '1024' }} 
  state={{ from: 'home' }}
>
  Xem Chi Tiết
</Link>

// Thay thế trang hiện tại (REPLACE)
<Link to="/pages/login/index" replace>Đăng nhập</Link>

// Quay lại trang trước (Delta)
<Link to={-1}>Quay lại</Link>

4.2 Hook useNavigate()

Hook thực thi điều hướng bằng mã lệnh Javascript:

import { useNavigate } from 'ejsc-mna-router';

const navigate = useNavigate();

// Điều hướng PUSH tới trang mới
navigate('/pages/detail/index');

// Truyền kèm parameters
navigate('/pages/detail/index', { params: { id: '42' } });

// Đổi trang dạng REPLACE
navigate('/pages/home/index', { replace: true });

// Quay lại 1 hoặc nhiều bước
navigate(-1);
navigate(-2);

// Ghi đè animation cho thao tác cụ thể này
navigate('/pages/modal/index', {
  animation: { type: 'slide_up' },
});

4.3 Hook useLocation()

Đọc thông tin location hiện tại của trang đang hoạt động:

import { useLocation } from 'ejsc-mna-router';

const location = useLocation();

console.log('Pathname:', location.pathname); // '/pages/detail/index'
console.log('Params:', location.params?.id);  // '42'
console.log('State:', location.state);

4.4 Custom Hooks Vòng Đời Trang (Lifecycle Hooks)

useDidShow

Kích hoạt khi trang trở nên active (hiển thị trên màn hình). Tương đương onShow trong Mini App Native.

import { useDidShow } from 'ejsc-mna-router';

useDidShow(() => {
  console.log('Trang đã hiển thị -> Tải lại dữ liệu');
  fetchLatestData();
});

useDidHide

Kích hoạt khi trang bị chuyển sang trạng thái ẩn (khi mở trang mới đè lên ngăn xếp).

import { useDidHide } from 'ejsc-mna-router';

useDidHide(() => {
  console.log('Trang bị ẩn -> Dừng timer');
  clearInterval(timerRef.current);
});

useAppPause & useAppResume

Kích hoạt khi toàn bộ ứng dụng chuyển sang nền (Background) hoặc quay lại giao diện chính (Foreground).

import { useAppPause, useAppResume } from 'ejsc-mna-router';

useAppPause(() => console.log('App vào background'));
useAppResume(() => console.log('App trở lại foreground'));

4.5 Cử Chỉ Vuốt Quay Lại (Swipe Navigation)

import { useSwipeNavigation, onSwipeNavigation } from 'ejsc-mna-router';

// Hook kiểm tra trạng thái đang swipe
const isSwipingRef = useSwipeNavigation();

// Đăng ký sự kiện swipe bên ngoài component
const unsubscribe = onSwipeNavigation((isSwiping) => {
  console.log('Đang thực hiện cử chỉ swipe back:', isSwiping);
});

5. Cấu Hình Chi Tiết (IRouterConfig)

type IRouterConfig = {
  pages: IRouterPageConfig[];         // Danh sách các trang (Bắt buộc)
  animation?: IAnimationConfig;       // Hiệu ứng mặc định toàn app
  keepAlive?: IKeepAliveState;        // Cấu hình Keep-Alive toàn app
  Layouts?: ILayout[];                // Layout wrappers dùng chung
  NotFoundPage?: ComponentType;       // Component hiển thị khi không tìm thấy trang (404)
  ErrorPage?: ComponentType;          // Component ErrorBoundary fallback khi xảy ra lỗi
};

6. Sự Kiện Điều Hướng (routerEvents)

Lắng nghe các sự kiện điều hướng bên ngoài React component tree:

import { routerEvents } from 'ejsc-mna-router';

// Lắng nghe trước khi chuyển trang
const off = routerEvents.on('beforeNavigate', ({ to, history }) => {
  console.log('Chuẩn bị chuyển tới:', to);
});

// Lắng nghe sau khi chuyển trang thành công
routerEvents.on('afterNavigate', ({ to, history }) => {
  console.log('Đã tới trang:', history.location.pathname);
});

// Cleanup listener
off();

7. Giấy Phép & Bản Quyền

© 2026 365EJSC Teams. Distributed under the MIT License.