JSPM

@zapstra/core-router

0.1.0
    • ESM via JSPM
    • ES Module Entrypoint
    • Export Map
    • Keywords
    • License
    • Repository URL
    • TypeScript Types
    • README
    • Created
    • Published
    • Downloads 10
    • Score
      100M100P100Q47393F
    • License MIT

    Query-preserving router for Zapstra platform apps

    Package Exports

      This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@zapstra/core-router) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

      Readme

      @zapstra/core-router

      Query-preserving router and navigation utilities for Zapstra platform apps.

      Features

      • Query parameter preservation during navigation (essential for Shopify apps)
      • Built-in loading states and progress indicators
      • React context for navigation state management
      • TypeScript support with full type safety
      • Customizable loading spinner with gradient design
      • Path matching utilities for active state detection

      Installation

      npm install @zapstra/core-router

      Usage

      Basic Setup

      import { AppRouterProvider } from '@zapstra/core-router';
      
      export default function App() {
        return (
          <AppRouterProvider>
            {/* Your app content */}
          </AppRouterProvider>
        );
      }
      import { useAppRouter } from '@zapstra/core-router';
      
      function NavigationComponent() {
        const { route, isNavigating } = useAppRouter();
      
        const handleNavigate = () => {
          // Automatically preserves ?host, ?shop, and other query params
          route('/app/settings');
        };
      
        return (
          <button
            onClick={handleNavigate}
            disabled={isNavigating}
          >
            Go to Settings
          </button>
        );
      }

      Direct Navigation Utilities

      import { useNavigateWithQuery, useQueryParams, useIsPathActive } from '@zapstra/core-router';
      
      function MyComponent() {
        const navigate = useNavigateWithQuery();
        const queryParams = useQueryParams();
        const isActive = useIsPathActive();
      
        // Navigate preserving query params
        const goToHome = () => navigate('/app');
      
        // Access current query parameters
        const shopDomain = queryParams.shop;
        const host = queryParams.host;
      
        // Check if path is active
        const isSettingsActive = isActive('/app/settings');
        const isExactHome = isActive('/app', true); // exact match
      
        return (
          <div>
            <button onClick={goToHome}>Home</button>
            <p>Current shop: {shopDomain}</p>
            <p>Settings active: {isSettingsActive}</p>
          </div>
        );
      }

      Custom Loading Spinner

      import { AppRouterProvider } from '@zapstra/core-router';
      
      export default function App() {
        return (
          <AppRouterProvider
            showLoadingSpinner={true}
            spinnerProps={{
              size: 100,
              strokeWidth: 6
            }}
          >
            {/* Your app */}
          </AppRouterProvider>
        );
      }

      Without Built-in Spinner

      import { AppRouterProvider, useAppRouter, GradientProgressSpinner } from '@zapstra/core-router';
      
      function CustomLoadingWrapper({ children }) {
        const { isNavigating } = useAppRouter();
      
        return (
          <>
            {isNavigating && <div>Custom loading...</div>}
            {children}
          </>
        );
      }
      
      export default function App() {
        return (
          <AppRouterProvider showLoadingSpinner={false}>
            <CustomLoadingWrapper>
              {/* Your app */}
            </CustomLoadingWrapper>
          </AppRouterProvider>
        );
      }

      Higher-Order Component

      import { withAppRouter } from '@zapstra/core-router';
      
      function MyApp() {
        return <div>My App Content</div>;
      }
      
      export default withAppRouter(MyApp, {
        showLoadingSpinner: true,
        spinnerProps: { size: 80 }
      });

      Why Query Preservation?

      Shopify apps run in embedded iframes and require specific query parameters like ?host and ?shop to function correctly. Standard navigation can lose these parameters, breaking the app. This router automatically preserves all query parameters during navigation.

      // Without @zapstra/core-router - BREAKS SHOPIFY APPS
      navigate('/app/settings'); // Loses ?host=... and ?shop=...
      
      // With @zapstra/core-router - WORKS CORRECTLY
      const { route } = useAppRouter();
      route('/app/settings'); // Preserves ?host=... and ?shop=...

      API Reference

      Components

      AppRouterProvider

      Main provider component that wraps your app.

      Props:

      • children: ReactNode - Your app content
      • showLoadingSpinner?: boolean - Show built-in loading spinner (default: true)
      • spinnerProps?: object - Customize spinner appearance

      GradientProgressSpinner

      Standalone loading spinner component.

      Props:

      • isLoading: boolean - Whether to show spinner
      • size?: number - Spinner size in pixels (default: 80)
      • strokeWidth?: number - Stroke width (default: 4)

      Hooks

      useAppRouter()

      Main navigation hook.

      Returns:

      • route: (path: string) => void - Navigate function with query preservation
      • isNavigating: boolean - Current navigation state

      useNavigateWithQuery()

      Low-level navigation hook.

      Returns:

      • (path: string) => void - Navigate function with query preservation

      useQueryParams()

      Get current query parameters as object.

      Returns:

      • Record<string, string> - Current query parameters

      useIsPathActive()

      Check if paths are active.

      Returns:

      • (path: string, exact?: boolean) => boolean - Path matching function

      Utilities

      Navigate while preserving query parameters.

      withAppRouter(Component, options?)

      Higher-order component to wrap apps with router provider.