create-bluecopa-react-app 1.0.39 → 1.0.41

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
@@ -1,8 +1,8 @@
1
1
  # create-bluecopa-react-app [![npm version](https://img.shields.io/npm/v/create-bluecopa-react-app)](https://www.npmjs.com/package/create-bluecopa-react-app) [![License](https://img.shields.io/npm/l/create-bluecopa-react-app)](LICENSE)
2
2
 
3
- ## A CLI Tool for BlueCopa React Applications
3
+ ## A CLI Tool for Bluecopa React Applications
4
4
 
5
- A command-line interface for bootstrapping modern React applications with BlueCopa integration, featuring opinionated best practices and pre-configured tooling.
5
+ A command-line interface for bootstrapping modern React applications with Bluecopa integration, featuring opinionated best practices and pre-configured tooling.
6
6
 
7
7
  ## Table of Contents
8
8
 
@@ -50,9 +50,9 @@ export BLUECOPA_BOILERPLATE_REGISTRY=https://registry.npmjs.org
50
50
  - 🌐 **Microfrontend Support**: Single-spa compatible with module federation
51
51
  - 📊 **Data Visualization**: Recharts integration for charts and analytics
52
52
  - 🎨 **UI Components**: shadcn/ui components built on Radix UI primitives
53
- - 📡 **BlueCopa React Components**: Pre-configured [`@bluecopa/react`](packages/react:1) package with hooks (includes TanStack Query integration)
53
+ - 📡 **Bluecopa React Components**: Pre-configured [`@bluecopa/react`](packages/react:1) package with hooks (includes TanStack Query integration)
54
54
  - 🎯 **Type Safety**: Full TypeScript support
55
- - 📱 **Responsive Design**: Tailwind CSS v4 with mobile-first approach and BlueCopa design system
55
+ - 📱 **Responsive Design**: Tailwind CSS v4 with mobile-first approach and Bluecopa design system
56
56
  - 🛠️ **Development Tools**: ESLint, TypeScript checking, and Vite fast build system
57
57
  - ⚡ **Fast Development**: Hot module replacement with Vite
58
58
  - 🔄 **Server-side Rendering**: React Router v7 with SSR support
@@ -93,7 +93,7 @@ npx create-bluecopa-react-app my-dashboard --template shadcn
93
93
 
94
94
  ### `create-bluecopa-react-app [project-name] [options]`
95
95
 
96
- Creates a new BlueCopa React application.
96
+ Creates a new Bluecopa React application.
97
97
 
98
98
  **Parameters:**
99
99
  - `project-name`: Name of the new project directory
@@ -143,21 +143,21 @@ npx create-bluecopa-react-app my-dashboard
143
143
  - **React Router v7** - Modern routing with SSR support
144
144
  - **Vite 6** - Fast build tool and development server
145
145
  - **TypeScript** - Full type safety and developer experience
146
- - **[`@bluecopa/react`](packages/react:1)** - BlueCopa-specific React components and hooks
146
+ - **[`@bluecopa/react`](packages/react:1)** - Bluecopa-specific React components and hooks
147
147
  - **shadcn/ui** - Accessible component library built on Radix UI
148
148
  - **Radix UI** - Unstyled, accessible UI primitives
149
149
  - **TanStack Table** - Headless table library for React
150
150
  - **Recharts** - Composable charting library for React
151
151
  - **DND Kit** - Drag and drop toolkit for React
152
- - **Tailwind CSS v4** - Utility-first CSS framework with BlueCopa design system
152
+ - **Tailwind CSS v4** - Utility-first CSS framework with Bluecopa design system
153
153
  - **next-themes** - Theme switching with dark mode support
154
154
  - **Lucide React** - Beautiful, customizable icons
155
155
 
156
156
  ## Monorepo Integration
157
157
 
158
- This CLI tool is part of the BlueCopa UI monorepo and integrates with the following packages:
158
+ This CLI tool is part of the Bluecopa UI monorepo and integrates with the following packages:
159
159
 
160
- - **[`@bluecopa/react`](packages/react:1)** - BlueCopa-specific React components and hooks
160
+ - **[`@bluecopa/react`](packages/react:1)** - Bluecopa-specific React components and hooks
161
161
 
162
162
  ### Standalone Development
163
163
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-bluecopa-react-app",
3
- "version": "1.0.39",
3
+ "version": "1.0.41",
4
4
  "description": "CLI tool to create bluecopa React applications",
5
5
  "type": "module",
6
6
  "main": "./bin/create-bluecopa-react-app.js",
@@ -1,6 +1,6 @@
1
- # AI Agent Guide for BlueCopa React UI Template
1
+ # AI Agent Guide for Bluecopa React UI Template
2
2
 
3
- This guide helps AI assistants and developers understand the project structure, patterns, and best practices for working with this BlueCopa React application template.
3
+ This guide helps AI assistants and developers understand the project structure, patterns, and best practices for working with this Bluecopa React application template.
4
4
 
5
5
  ## 🏗️ Project Architecture Overview
6
6
 
@@ -8,7 +8,7 @@ This guide helps AI assistants and developers understand the project structure,
8
8
  - **React 18** with TypeScript
9
9
  - **React Router v7** with SSR support
10
10
  - **shadcn/ui** components built on Radix UI
11
- - **BlueCopa UI** components from `@bluecopa-ui` registry (built on Radix UI)
11
+ - **Bluecopa UI** components from `@bluecopa-ui` registry (built on Radix UI)
12
12
  - **Tailwind CSS v4** with CSS variables
13
13
  - **Vite 6** for build tooling
14
14
  - **TanStack Query** (via @bluecopa/react)
@@ -17,7 +17,7 @@ This guide helps AI assistants and developers understand the project structure,
17
17
  ```
18
18
  app/
19
19
  ├── components/ # Reusable UI components
20
- │ ├── ui/ # BlueCopa UI or shadcn/ui components
20
+ │ ├── ui/ # Bluecopa UI or shadcn/ui components
21
21
  │ ├── app-sidebar.tsx # Main navigation
22
22
  │ ├── data-table.tsx # TanStack Table wrapper
23
23
  │ └── chart-*.tsx # Recharts components
@@ -33,10 +33,10 @@ app/
33
33
 
34
34
  This project supports components from two registries:
35
35
 
36
- 1. **BlueCopa UI Registry** (Preferred for BlueCopa-specific components)
36
+ 1. **Bluecopa UI Registry** (Preferred for Bluecopa-specific components)
37
37
  - Registry URL: https://blui.vercel.app
38
38
  - Registry JSON: https://blui.vercel.app/r/registry.json
39
- - Custom BlueCopa components built on Radix UI
39
+ - Custom Bluecopa components built on Radix UI
40
40
 
41
41
  2. **shadcn/ui Registry** (Standard components)
42
42
  - Registry URL: https://ui.shadcn.com
@@ -51,9 +51,9 @@ Both registries:
51
51
 
52
52
  ### Adding Components
53
53
 
54
- #### From BlueCopa UI Registry
54
+ #### From Bluecopa UI Registry
55
55
 
56
- To add a component from the BlueCopa UI registry (preferred for BlueCopa-specific components):
56
+ To add a component from the Bluecopa UI registry (preferred for Bluecopa-specific components):
57
57
 
58
58
  ```bash
59
59
  pnpm dlx shadcn@latest add @bluecopa-ui/button
@@ -80,7 +80,7 @@ The registries are configured in `components.json`:
80
80
  }
81
81
  ```
82
82
 
83
- **Note**: When no registry prefix is specified, components are added from the default shadcn/ui registry. Use `@bluecopa-ui/` prefix for BlueCopa-specific components.
83
+ **Note**: When no registry prefix is specified, components are added from the default shadcn/ui registry. Use `@bluecopa-ui/` prefix for Bluecopa-specific components.
84
84
 
85
85
  ### Custom Components
86
86
  - Use TypeScript interfaces for props
@@ -128,14 +128,14 @@ A React library providing opinionated custom hooks for TanStack React Query inte
128
128
 
129
129
  ## Table of Contents
130
130
 
131
- - [AI Agent Guide for BlueCopa React UI Template](#ai-agent-guide-for-bluecopa-react-ui-template)
131
+ - [AI Agent Guide for Bluecopa React UI Template](#ai-agent-guide-for-bluecopa-react-ui-template)
132
132
  - [🏗️ Project Architecture Overview](#️-project-architecture-overview)
133
133
  - [Core Stack](#core-stack)
134
134
  - [Key Directories](#key-directories)
135
135
  - [🎨 Component Patterns](#-component-patterns)
136
136
  - [UI Component Registries](#ui-component-registries)
137
137
  - [Adding Components](#adding-components)
138
- - [From BlueCopa UI Registry](#from-bluecopa-ui-registry)
138
+ - [From Bluecopa UI Registry](#from-bluecopa-ui-registry)
139
139
  - [From shadcn/ui Registry](#from-shadcnui-registry)
140
140
  - [Custom Components](#custom-components)
141
141
  - [Example Component Structure](#example-component-structure)
@@ -211,7 +211,7 @@ A React library providing opinionated custom hooks for TanStack React Query inte
211
211
  - [Development Tools](#development-tools)
212
212
  - [📚 Useful Resources](#-useful-resources)
213
213
  - [Documentation](#documentation)
214
- - [BlueCopa Specific](#bluecopa-specific)
214
+ - [Bluecopa Specific](#bluecopa-specific)
215
215
  - [🎯 Best Practices Summary](#-best-practices-summary)
216
216
  - [🔄 Common Workflows](#-common-workflows)
217
217
  - [Adding a New Feature](#adding-a-new-feature)
@@ -775,20 +775,20 @@ import {
775
775
 
776
776
  ### Adding New Components
777
777
  1. Add components from either registry:
778
- - BlueCopa UI: `pnpm dlx shadcn@latest add @bluecopa-ui/component-name`
778
+ - Bluecopa UI: `pnpm dlx shadcn@latest add @bluecopa-ui/component-name`
779
779
  - shadcn/ui: `pnpm dlx shadcn@latest add component-name`
780
780
  2. Components are installed in `app/components/ui/`
781
- 3. Prefer BlueCopa UI registry for BlueCopa-specific components
782
- 4. Use shadcn/ui registry for standard components not available in BlueCopa UI
781
+ 3. Prefer Bluecopa UI registry for Bluecopa-specific components
782
+ 4. Use shadcn/ui registry for standard components not available in Bluecopa UI
783
783
  5. Define TypeScript interface for props if extending components
784
784
  6. Implement responsive design
785
785
  7. Add proper accessibility attributes
786
786
 
787
787
  ### Working with Forms
788
788
  1. Use form components from either registry:
789
- - BlueCopa UI: `pnpm dlx shadcn@latest add @bluecopa-ui/form`
789
+ - Bluecopa UI: `pnpm dlx shadcn@latest add @bluecopa-ui/form`
790
790
  - shadcn/ui: `pnpm dlx shadcn@latest add form`
791
- 2. Prefer BlueCopa UI form components when available
791
+ 2. Prefer Bluecopa UI form components when available
792
792
  3. Implement validation with Zod
793
793
  4. Handle form state with React hooks
794
794
  5. Show loading and error states
@@ -886,21 +886,21 @@ import {
886
886
 
887
887
  ### Documentation
888
888
  - [React Router v7 Docs](https://reactrouter.com/)
889
- - [BlueCopa UI Registry](https://blui.vercel.app)
889
+ - [Bluecopa UI Registry](https://blui.vercel.app)
890
890
  - [shadcn/ui Components](https://ui.shadcn.com/)
891
891
  - [Tailwind CSS v4](https://tailwindcss.com/)
892
892
  - [TanStack Table](https://tanstack.com/table)
893
893
  - [Recharts](https://recharts.org/)
894
894
 
895
- ### BlueCopa Specific
895
+ ### Bluecopa Specific
896
896
  - [@bluecopa/react Package](packages/react:1)
897
- - BlueCopa Design System
897
+ - Bluecopa Design System
898
898
  - API Integration Patterns
899
899
 
900
900
  ## 🎯 Best Practices Summary
901
901
 
902
902
  1. **Always use TypeScript** - Define proper interfaces and types
903
- 2. **Use appropriate registry** - Prefer BlueCopa UI (`@bluecopa-ui/component-name`) for BlueCopa-specific components, use shadcn/ui (`component-name`) for standard components
903
+ 2. **Use appropriate registry** - Prefer Bluecopa UI (`@bluecopa-ui/component-name`) for Bluecopa-specific components, use shadcn/ui (`component-name`) for standard components
904
904
  3. **Follow component patterns** - Use established component structure from both registries
905
905
  4. **Implement accessibility** - Use semantic HTML and ARIA attributes
906
906
  5. **Optimize for performance** - Use proper React patterns and code splitting
@@ -916,7 +916,7 @@ import {
916
916
  ### Adding a New Feature
917
917
  1. Create feature branch
918
918
  2. Add required UI components from appropriate registry:
919
- - BlueCopa UI: `pnpm dlx shadcn@latest add @bluecopa-ui/component-name`
919
+ - Bluecopa UI: `pnpm dlx shadcn@latest add @bluecopa-ui/component-name`
920
920
  - shadcn/ui: `pnpm dlx shadcn@latest add component-name`
921
921
  3. Implement components with TypeScript
922
922
  4. Add proper styling with Tailwind
@@ -933,4 +933,4 @@ import {
933
933
  5. Verify responsive behavior
934
934
  6. Test accessibility features
935
935
 
936
- This guide should help AI assistants and developers work effectively with this BlueCopa React template, ensuring consistent patterns and best practices are followed throughout development.
936
+ This guide should help AI assistants and developers work effectively with this Bluecopa React template, ensuring consistent patterns and best practices are followed throughout development.
@@ -1,4 +1,4 @@
1
- # BlueCopa React App with shadcn/ui
1
+ # Bluecopa React App with shadcn/ui
2
2
 
3
3
  A modern, production-ready template for building full-stack React applications using React Router v7 and shadcn/ui components.
4
4
 
@@ -17,7 +17,7 @@ A modern, production-ready template for building full-stack React applications u
17
17
  - 🎯 **Drag & Drop** - DND Kit integration for interactive interfaces
18
18
  - 📱 **Responsive Design** - Mobile-first approach with sidebar navigation
19
19
  - 🌙 **Dark Mode** - Built-in theme switching with next-themes
20
- - 🔗 **BlueCopa API integration** - Pre-configured with `@bluecopa/react` hooks
20
+ - 🔗 **Bluecopa API integration** - Pre-configured with `@bluecopa/react` hooks
21
21
  - 📖 [React Router docs](https://reactrouter.com/)
22
22
  - 🎨 [shadcn/ui docs](https://ui.shadcn.com/)
23
23
 
@@ -37,11 +37,11 @@ pnpm install
37
37
 
38
38
  ## Quick Start
39
39
 
40
- This template is designed to work both as a standalone application and as a microfrontend within the BlueCopa ecosystem. It includes:
40
+ This template is designed to work both as a standalone application and as a microfrontend within the Bluecopa ecosystem. It includes:
41
41
 
42
42
  - **Single-spa integration** for microfrontend architecture
43
43
  - **Module federation** support for dynamic imports
44
- - **BlueCopa API integration** with pre-configured hooks
44
+ - **Bluecopa API integration** with pre-configured hooks
45
45
  - **Production-ready** Docker configuration
46
46
 
47
47
  ### Development
@@ -114,7 +114,7 @@ If the API errors out or is not configured, the application will show "Set Envir
114
114
 
115
115
  ### Statement Hooks Example
116
116
 
117
- This template includes a comprehensive example of using BlueCopa statement hooks at `/statements`. The example demonstrates:
117
+ This template includes a comprehensive example of using Bluecopa statement hooks at `/statements`. The example demonstrates:
118
118
 
119
119
  - **useGetStatementData** - Fetching statement data by statement ID (with optional viewId and runId)
120
120
  - **useGetViewsBySheetId** - Fetching all views for a statement sheet
@@ -196,7 +196,7 @@ This template comes with [Tailwind CSS v4](https://tailwindcss.com/) configured
196
196
  - CSS variables for theming
197
197
  - Dark mode support with next-themes
198
198
  - shadcn/ui design system
199
- - Custom BlueCopa color palette
199
+ - Custom Bluecopa color palette
200
200
  - Responsive design utilities
201
201
 
202
202
  ## Key Technologies
@@ -123,7 +123,7 @@ export default function StatementsPage() {
123
123
  <div>
124
124
  <h1 className="text-3xl font-bold tracking-tight">Statement Viewer</h1>
125
125
  <p className="text-muted-foreground">
126
- View and manage statement data using BlueCopa statement hooks
126
+ View and manage statement data using Bluecopa statement hooks
127
127
  </p>
128
128
  </div>
129
129
  <div className="flex gap-2">
@@ -1,7 +1,12 @@
1
- import React from "react";
1
+ import React, { useEffect } from "react";
2
2
  import { createRoot, type Root } from "react-dom/client";
3
3
  import singleSpaReact from "single-spa-react";
4
- import { MemoryRouter, BrowserRouter } from "react-router-dom";
4
+ import {
5
+ MemoryRouter,
6
+ BrowserRouter,
7
+ useNavigate,
8
+ useLocation,
9
+ } from "react-router-dom";
5
10
  import App from "./app";
6
11
  import type { AppProps } from "single-spa";
7
12
 
@@ -18,6 +23,93 @@ interface LifecycleProps {
18
23
 
19
24
  let root: Root | null = null;
20
25
 
26
+ // Helper function to extract path from browser URL
27
+ function getInitialPath(basename?: string): string {
28
+ const currentPath = window.location.pathname;
29
+ const search = window.location.search;
30
+ const hash = window.location.hash;
31
+
32
+ // If basename is provided, extract the path after basename
33
+ let pathAfterBasename = currentPath;
34
+ if (basename && currentPath.startsWith(basename)) {
35
+ pathAfterBasename = currentPath.slice(basename.length) || "/";
36
+ }
37
+
38
+ // Combine path, search params, and hash
39
+ return pathAfterBasename + search + hash;
40
+ }
41
+
42
+ // Component to sync MemoryRouter navigation with browser URL
43
+ const RouterSync: React.FC<{ basename?: string }> = ({ basename }) => {
44
+ const location = useLocation();
45
+ const navigate = useNavigate();
46
+
47
+ useEffect(() => {
48
+ // Get the current path from MemoryRouter
49
+ const mainAppPath = window.location.pathname;
50
+ if (mainAppPath.includes("/apps/ext/")) {
51
+ const currentPath = location.pathname;
52
+ const search = location.search || "";
53
+ const hash = location.hash || "";
54
+
55
+ // Calculate the full URL path
56
+ const basenamePath = basename || "";
57
+ const fullPath = basenamePath + currentPath + search + hash;
58
+
59
+ // Update browser URL without reloading the page
60
+ const currentBrowserPath =
61
+ window.location.pathname +
62
+ window.location.search +
63
+ window.location.hash;
64
+ if (currentBrowserPath !== fullPath) {
65
+ // Use pushState to maintain browser history for back/forward buttons
66
+ window.history.pushState(
67
+ { ...window.history.state, path: fullPath },
68
+ "",
69
+ fullPath
70
+ );
71
+ }
72
+ }
73
+ }, [location.pathname, location.search, location.hash, basename]);
74
+
75
+ // Listen for browser navigation (back/forward buttons)
76
+ useEffect(() => {
77
+ const handlePopState = () => {
78
+ const mainAppPath = window.location.pathname;
79
+ // If current path does not contain /apps/ext/, clean up all /apps/ext/ references
80
+ if (mainAppPath.includes("/apps/ext/")) {
81
+ const currentPath = window.location.pathname;
82
+ const search = window.location.search || "";
83
+ const hash = window.location.hash || "";
84
+ const basenamePath = basename || "";
85
+
86
+ // Extract the path after basename
87
+ let pathToNavigate = currentPath;
88
+ if (basenamePath && currentPath.startsWith(basenamePath)) {
89
+ pathToNavigate = currentPath.slice(basenamePath.length) || "/";
90
+ }
91
+
92
+ // Combine with search and hash
93
+ const fullPathToNavigate = pathToNavigate + search + hash;
94
+ const currentRouterPath =
95
+ location.pathname + (location.search || "") + (location.hash || "");
96
+
97
+ // Navigate MemoryRouter to match browser URL
98
+ if (currentRouterPath !== fullPathToNavigate) {
99
+ navigate(fullPathToNavigate, { replace: true });
100
+ }
101
+ } else {
102
+ window.removeEventListener("popstate", handlePopState);
103
+ }
104
+ };
105
+
106
+ window.addEventListener("popstate", handlePopState);
107
+ return () => window.removeEventListener("popstate", handlePopState);
108
+ }, [navigate, location.pathname, location.search, location.hash, basename]);
109
+
110
+ return null;
111
+ };
112
+
21
113
  // Root component wrapper that handles routing
22
114
  const MicrofrontendRoot: React.FC<{
23
115
  isMicroFrontend: boolean;
@@ -26,10 +118,17 @@ const MicrofrontendRoot: React.FC<{
26
118
  // Use MemoryRouter for micro-frontend to avoid conflicts with host routing
27
119
  // Use BrowserRouter for standalone mode
28
120
  const Router = isMicroFrontend ? MemoryRouter : BrowserRouter;
29
- const routerProps = isMicroFrontend ? {} : { basename: props?.basename };
121
+
122
+ // Get initial path from browser URL for MemoryRouter
123
+ const initialPath = isMicroFrontend ? getInitialPath(props?.basename) : "/";
124
+
125
+ const routerProps = isMicroFrontend
126
+ ? { initialEntries: [initialPath], initialIndex: 0 }
127
+ : { basename: props?.basename };
30
128
 
31
129
  return (
32
130
  <Router {...routerProps}>
131
+ {isMicroFrontend && <RouterSync basename={props?.basename} />}
33
132
  <App {...props} />
34
133
  </Router>
35
134
  );
@@ -1,6 +1,6 @@
1
- System.register(['./__federation_fn_import-CzfA7kmP.js', './client-CkHcT_xc.js'], (function (exports, module) {
1
+ System.register(['./__federation_fn_import-CzfA7kmP.js', './client-Dms8K6Dw.js'], (function (exports, module) {
2
2
  'use strict';
3
- var importShared, clientExports, jsxRuntimeExports, MemoryRouter, BrowserRouter, App;
3
+ var importShared, clientExports, jsxRuntimeExports, MemoryRouter, BrowserRouter, App, useLocation, useNavigate;
4
4
  return {
5
5
  setters: [module => {
6
6
  importShared = module.importShared;
@@ -10,17 +10,81 @@ System.register(['./__federation_fn_import-CzfA7kmP.js', './client-CkHcT_xc.js']
10
10
  MemoryRouter = module.M;
11
11
  BrowserRouter = module.B;
12
12
  App = module.A;
13
+ useLocation = module.u;
14
+ useNavigate = module.a;
13
15
  }],
14
16
  execute: (async function () {
15
17
 
16
18
  function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o);}return n}function t(t){for(var n=1;n<arguments.length;n++){var r=null!=arguments[n]?arguments[n]:{};n%2?e(Object(r),true).forEach((function(e){o(t,e,r[e]);})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):e(Object(r)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e));}));}return t}function n(e){return (n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:true,configurable:true,writable:true}):e[t]=n,e}function r(e){return (r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function a(e,t){var n;if("function"!=typeof(n=t.domElement?function(){return t.domElement}:t.domElementGetter?t.domElementGetter:e.domElementGetter?e.domElementGetter:function(e){var t=e.appName||e.name;if(!t)throw Error("single-spa's dom-element-getter-helpers was not given an application name as a prop, so it can't make a unique dom element container for the react application");var n="single-spa-application:".concat(t);return function(){var e=document.getElementById(n);return e||((e=document.createElement("div")).id=n,document.body.appendChild(e)),e}}(t)))throw Error("single-spa's dom-element-getter-helpers was given an invalid domElementGetter for application or parcel '".concat(t.name,"'. Expected a function, received ").concat(r(n)));return function(){var e=n(t);if(!(e instanceof HTMLElement))throw Error("single-spa's dom-element-getter-helpers: domElementGetter returned an invalid dom element for application or parcel '".concat(t.name,"'. Expected HTMLElement, received ").concat(r(e)));return e}}var c=null;try{c=require("react").createContext();}catch(e){}var u={React:null,ReactDOM:null,ReactDOMClient:null,rootComponent:null,loadRootComponent:null,errorBoundary:null,errorBoundaryClass:null,domElementGetter:null,parcelCanUpdate:true,suppressComponentDidCatchWarning:false,domElements:{},renderResults:{},updateResolves:{},unmountResolves:{}};function i(e){if("object"!==n(e))throw new Error("single-spa-react requires a configuration object");var o,r=t(t({},u),e);if(!r.React)throw new Error("single-spa-react must be passed opts.React");if(!r.ReactDOM&&!r.ReactDOMClient)throw new Error("single-spa-react must be passed opts.ReactDOM or opts.ReactDOMClient");r.renderType||(null!==(o=r.ReactDOMClient)&&void 0!==o&&o.createRoot?r.renderType="createRoot":r.renderType="render");if(!r.rootComponent&&!r.loadRootComponent)throw new Error("single-spa-react must be passed opts.rootComponent or opts.loadRootComponent");if(r.errorBoundary&&"function"!=typeof r.errorBoundary)throw Error("The errorBoundary opt for single-spa-react must either be omitted or be a function that returns React elements");!c&&r.React.createContext&&(c=r.React.createContext()),r.SingleSpaRoot=function(e){function t(e){t.displayName="SingleSpaRoot(".concat(e.name,")");}return t.prototype=Object.create(e.React.Component.prototype),t.prototype.componentDidMount=function(){setTimeout(this.props.mountFinished);},t.prototype.componentWillUnmount=function(){setTimeout(this.props.unmountFinished);},t.prototype.render=function(){return setTimeout(this.props.updateFinished),this.props.children},t}(r);var a={bootstrap:s.bind(null,r),mount:p.bind(null,r),unmount:l.bind(null,r)};return r.parcelCanUpdate&&(a.update=m.bind(null,r)),a}function s(e,t){return e.rootComponent?Promise.resolve():e.loadRootComponent(t).then((function(t){e.rootComponent=t;}))}function p(e,t){return new Promise((function(n,o){e.suppressComponentDidCatchWarning||!function(e){if(!(e&&"string"==typeof e.version&&e.version.indexOf(".")>=0))return false;var t=e.version.slice(0,e.version.indexOf("."));try{return Number(t)>=16}catch(e){return false}}(e.React)||e.errorBoundary||e.errorBoundaryClass||(e.rootComponent.prototype?e.rootComponent.prototype.componentDidCatch||console.warn("single-spa-react: ".concat(t.name||t.appName||t.childAppName,"'s rootComponent should implement componentDidCatch to avoid accidentally unmounting the entire single-spa application.")):console.warn("single-spa-react: ".concat(t.name||t.appName||t.childAppName,"'s rootComponent does not implement an error boundary. If using a functional component, consider providing an opts.errorBoundary to singleSpaReact(opts).")));var r=y(e,t,(function(){n(this);})),c=a(e,t)(),u=function(e){var t=e.reactDom,n=e.renderType,o=e.elementToRender,r=e.domElement,a=t[n];if("function"!=typeof a)throw new Error('renderType "'.concat(n,'" did not return a function.'));switch(n){case "createRoot":case "unstable_createRoot":case "createBlockingRoot":case "unstable_createBlockingRoot":var c=a(r);return c.render(o),c;case "hydrateRoot":return a(r,o);case "hydrate":default:return a(o,r),null}}({elementToRender:r,domElement:c,reactDom:d(e),renderType:f(e)});e.domElements[t.name]=c,e.renderResults[t.name]=u;}))}function l(e,t){return new Promise((function(n){e.unmountResolves[t.name]=n;var o=e.renderResults[t.name];o&&o.unmount?o.unmount():d(e).unmountComponentAtNode(e.domElements[t.name]),delete e.domElements[t.name],delete e.renderResults[t.name];}))}function m(e,t){return new Promise((function(n){e.updateResolves[t.name]||(e.updateResolves[t.name]=[]),e.updateResolves[t.name].push(n);var o=y(e,t,null),r=e.renderResults[t.name];if(r&&r.render)r.render(o);else {var c=a(e,t)();d(e).render(o,c);}}))}function d(e){return e.ReactDOMClient||e.ReactDOM}function f(e){return "function"==typeof e.renderType?e.renderType():e.renderType}function y(e,n,o){var r=e.React.createElement(e.rootComponent,n),a=c?e.React.createElement(c.Provider,{value:n},r):r;return (e.errorBoundary||n.errorBoundary||e.errorBoundaryClass||n.errorBoundaryClass)&&(e.errorBoundaryClass=e.errorBoundaryClass||n.errorBoundaryClass||function(e,t){function n(t){e.React.Component.apply(this,arguments),this.state={caughtError:null,caughtErrorInfo:null},n.displayName="SingleSpaReactErrorBoundary(".concat(t.name,")");}return n.prototype=Object.create(e.React.Component.prototype),n.prototype.render=function(){return this.state.caughtError?(e.errorBoundary||t.errorBoundary)(this.state.caughtError,this.state.caughtErrorInfo,this.props):this.props.children},n.prototype.componentDidCatch=function(e,t){this.setState({caughtError:e,caughtErrorInfo:t});},n}(e,n),a=e.React.createElement(e.errorBoundaryClass,n,a)),a=e.React.createElement(e.SingleSpaRoot,t(t({},n),{},{mountFinished:o,updateFinished:function(){e.updateResolves[n.name]&&(e.updateResolves[n.name].forEach((function(e){return e()})),delete e.updateResolves[n.name]);},unmountFinished:function(){e.unmountResolves[n.name]&&(e.unmountResolves[n.name](),delete e.unmountResolves[n.name]);}}),a)}
17
19
 
18
20
  const React = await importShared('react');
21
+ const {useEffect} = React;
19
22
  let root = null;
23
+ function getInitialPath(basename) {
24
+ const currentPath = window.location.pathname;
25
+ const search = window.location.search;
26
+ const hash = window.location.hash;
27
+ let pathAfterBasename = currentPath;
28
+ if (basename && currentPath.startsWith(basename)) {
29
+ pathAfterBasename = currentPath.slice(basename.length) || "/";
30
+ }
31
+ return pathAfterBasename + search + hash;
32
+ }
33
+ const RouterSync = ({ basename }) => {
34
+ const location = useLocation();
35
+ const navigate = useNavigate();
36
+ useEffect(() => {
37
+ const mainAppPath = window.location.pathname;
38
+ if (mainAppPath.includes("/apps/ext/")) {
39
+ const currentPath = location.pathname;
40
+ const search = location.search || "";
41
+ const hash = location.hash || "";
42
+ const basenamePath = basename || "";
43
+ const fullPath = basenamePath + currentPath + search + hash;
44
+ const currentBrowserPath = window.location.pathname + window.location.search + window.location.hash;
45
+ if (currentBrowserPath !== fullPath) {
46
+ window.history.pushState(
47
+ { ...window.history.state, path: fullPath },
48
+ "",
49
+ fullPath
50
+ );
51
+ }
52
+ }
53
+ }, [location.pathname, location.search, location.hash, basename]);
54
+ useEffect(() => {
55
+ const handlePopState = () => {
56
+ const mainAppPath = window.location.pathname;
57
+ if (mainAppPath.includes("/apps/ext/")) {
58
+ const currentPath = window.location.pathname;
59
+ const search = window.location.search || "";
60
+ const hash = window.location.hash || "";
61
+ const basenamePath = basename || "";
62
+ let pathToNavigate = currentPath;
63
+ if (basenamePath && currentPath.startsWith(basenamePath)) {
64
+ pathToNavigate = currentPath.slice(basenamePath.length) || "/";
65
+ }
66
+ const fullPathToNavigate = pathToNavigate + search + hash;
67
+ const currentRouterPath = location.pathname + (location.search || "") + (location.hash || "");
68
+ if (currentRouterPath !== fullPathToNavigate) {
69
+ navigate(fullPathToNavigate, { replace: true });
70
+ }
71
+ } else {
72
+ window.removeEventListener("popstate", handlePopState);
73
+ }
74
+ };
75
+ window.addEventListener("popstate", handlePopState);
76
+ return () => window.removeEventListener("popstate", handlePopState);
77
+ }, [navigate, location.pathname, location.search, location.hash, basename]);
78
+ return null;
79
+ };
20
80
  const MicrofrontendRoot = ({ isMicroFrontend, props }) => {
21
81
  const Router = isMicroFrontend ? MemoryRouter : BrowserRouter;
22
- const routerProps = isMicroFrontend ? {} : { basename: props?.basename };
23
- return /* @__PURE__ */ jsxRuntimeExports.jsx(Router, { ...routerProps, children: /* @__PURE__ */ jsxRuntimeExports.jsx(App, { ...props }) });
82
+ const initialPath = isMicroFrontend ? getInitialPath(props?.basename) : "/";
83
+ const routerProps = isMicroFrontend ? { initialEntries: [initialPath], initialIndex: 0 } : { basename: props?.basename };
84
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(Router, { ...routerProps, children: [
85
+ isMicroFrontend && /* @__PURE__ */ jsxRuntimeExports.jsx(RouterSync, { basename: props?.basename }),
86
+ /* @__PURE__ */ jsxRuntimeExports.jsx(App, { ...props })
87
+ ] });
24
88
  };
25
89
  const lifecycles = i({
26
90
  React,