diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 1bee34c3..93c9211d 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -7,9 +7,10 @@ import "@malloy-publisher/sdk/styles.css"; import "@malloydata/malloy-explorer/styles.css"; import { CssBaseline } from "@mui/material"; import { ThemeProvider } from "@mui/material/styles"; -import * as React from "react"; +import { lazy, Suspense, useMemo } from "react"; import { createBrowserRouter, RouterProvider } from "react-router-dom"; -import { HeaderProps } from "./components/Header"; +import { Loading } from "./components/common/Loading"; +import { HeaderProps } from "./components/layout/Header/Header"; import theme from "./theme"; /** @@ -17,13 +18,21 @@ import theme from "./theme"; * React.lazy and dynamic import() statements for lazy loading React * components. */ -const HomePage = React.lazy(() => import("./components/HomePage")); -const MainPage = React.lazy(() => import("./components/MainPage")); -const ModelPage = React.lazy(() => import("./components/ModelPage")); -const PackagePage = React.lazy(() => import("./components/PackagePage")); -const ProjectPage = React.lazy(() => import("./components/ProjectPage")); -const RouteError = React.lazy(() => import("./components/RouteError")); -const WorkbookPage = React.lazy(() => import("./components/WorkbookPage")); +const HomePage = lazy(() => import("./components/pages/HomePage/HomePage")); +const MainPage = lazy(() => import("./components/layout/MainPage/MainPage")); +const ModelPage = lazy(() => import("./components/pages/ModelPage/ModelPage")); +const PackagePage = lazy( + () => import("./components/pages/PackagePage/PackagePage"), +); +const ProjectPage = lazy( + () => import("./components/pages/ProjectPage/ProjectPage"), +); +const RouteError = lazy( + () => import("./components/common/RouteError/RouteError"), +); +const WorkbookPage = lazy( + () => import("./components/pages/WorkbookPage/WorkbookPage"), +); // Create router configuration function export const createMalloyRouter = ( @@ -39,7 +48,9 @@ export const createMalloyRouter = ( - + }> + + @@ -47,24 +58,44 @@ export const createMalloyRouter = ( errorElement: , children: [ { - path: "", - element: , + index: true, + element: ( + }> + + + ), }, { path: ":projectName", - element: , + element: ( + }> + + + ), }, { path: ":projectName/:packageName", - element: , + element: ( + }> + + + ), }, { path: ":projectName/:packageName/*", - element: , + element: ( + }> + + + ), }, { path: ":projectName/:packageName/workbook/:workspace/:workbookPath", - element: , + element: ( + }> + + + ), }, ], }, @@ -77,11 +108,15 @@ export interface MalloyPublisherAppProps { workbookStorage: WorkbookStorage; } -export const MalloyPublisherApp: React.FC = ({ - workbookStorage, +export const MalloyPublisherApp = ({ basePath = "/", + workbookStorage, headerProps, -}) => { - const router = createMalloyRouter(basePath, workbookStorage, headerProps); +}: MalloyPublisherAppProps) => { + const router = useMemo( + () => createMalloyRouter(basePath, workbookStorage, headerProps), + [basePath, workbookStorage, headerProps], + ); + return ; }; diff --git a/packages/app/src/components/common/Loading/Loading.tsx b/packages/app/src/components/common/Loading/Loading.tsx new file mode 100644 index 00000000..c78269ed --- /dev/null +++ b/packages/app/src/components/common/Loading/Loading.tsx @@ -0,0 +1,102 @@ +import Box from "@mui/material/Box"; +import CircularProgress from "@mui/material/CircularProgress"; +import Typography from "@mui/material/Typography"; + +export interface LoadingProps { + text?: string; + /** + * The size of the CircularProgress component + * @default 20 + */ + size?: number | string; + /** + * The color of the CircularProgress component + * @default "primary" + */ + color?: + | "primary" + | "secondary" + | "error" + | "info" + | "success" + | "warning" + | "inherit"; + /** + * The thickness of the circular progress + * @default 3.6 + */ + thickness?: number; + /** + * Whether to center the component + * @default true + */ + centered?: boolean; + /** + * Custom spacing between spinner and text + * @default 2 + */ + spacing?: number; + /** + * Typography variant for the text + * @default "body1" + */ + textVariant?: + | "h1" + | "h2" + | "h3" + | "h4" + | "h5" + | "h6" + | "subtitle1" + | "subtitle2" + | "body1" + | "body2" + | "caption" + | "overline"; +} + +export function Loading({ + text, + size = 20, + color = "primary", + thickness = 3.6, + centered = true, + spacing = 2, + textVariant = "body2", +}: LoadingProps) { + const content = ( + + + {text && ( + + {text} + + )} + + ); + + if (centered) { + return ( + + {content} + + ); + } + + return content; +} diff --git a/packages/app/src/components/common/Loading/index.ts b/packages/app/src/components/common/Loading/index.ts new file mode 100644 index 00000000..a9f097d8 --- /dev/null +++ b/packages/app/src/components/common/Loading/index.ts @@ -0,0 +1,2 @@ +export { Loading } from "./Loading"; +export type { LoadingProps } from "./Loading"; diff --git a/packages/app/src/components/RouteError.tsx b/packages/app/src/components/common/RouteError/RouteError.tsx similarity index 100% rename from packages/app/src/components/RouteError.tsx rename to packages/app/src/components/common/RouteError/RouteError.tsx diff --git a/packages/app/src/components/common/index.ts b/packages/app/src/components/common/index.ts new file mode 100644 index 00000000..d7318b3c --- /dev/null +++ b/packages/app/src/components/common/index.ts @@ -0,0 +1,2 @@ +export * from "./RouteError/RouteError"; +export * from "./Loading"; diff --git a/packages/app/src/components/BreadcrumbNav.tsx b/packages/app/src/components/layout/BreadcrumNav/BreadcrumbNav.tsx similarity index 97% rename from packages/app/src/components/BreadcrumbNav.tsx rename to packages/app/src/components/layout/BreadcrumNav/BreadcrumbNav.tsx index 3a5e0564..749b5356 100644 --- a/packages/app/src/components/BreadcrumbNav.tsx +++ b/packages/app/src/components/layout/BreadcrumNav/BreadcrumbNav.tsx @@ -1,6 +1,7 @@ import { useRouterClickHandler } from "@malloy-publisher/sdk"; import { ChevronRight } from "@mui/icons-material"; -import { Box, Chip } from "@mui/material"; +import Box from "@mui/material/Box"; +import Chip from "@mui/material/Chip"; import Breadcrumbs from "@mui/material/Breadcrumbs"; import { useParams } from "react-router-dom"; diff --git a/packages/app/src/components/Header.tsx b/packages/app/src/components/layout/Header/Header.tsx similarity index 88% rename from packages/app/src/components/Header.tsx rename to packages/app/src/components/layout/Header/Header.tsx index 2d1e758c..2dbd14be 100644 --- a/packages/app/src/components/Header.tsx +++ b/packages/app/src/components/layout/Header/Header.tsx @@ -1,20 +1,18 @@ import MenuIcon from "@mui/icons-material/Menu"; -import { - AppBar, - Box, - Button, - IconButton, - Menu, - MenuItem, - Stack, - Toolbar, - Typography, - useMediaQuery, - useTheme, -} from "@mui/material"; +import AppBar from "@mui/material/AppBar"; +import MenuItem from "@mui/material/MenuItem"; +import Box from "@mui/material/Box"; +import Button from "@mui/material/Button"; +import IconButton from "@mui/material/IconButton"; +import Menu from "@mui/material/Menu"; +import Stack from "@mui/material/Stack"; +import Toolbar from "@mui/material/Toolbar"; +import Typography from "@mui/material/Typography"; +import useMediaQuery from "@mui/material/useMediaQuery"; +import { useTheme } from "@mui/material/styles"; import { useState } from "react"; import { useNavigate } from "react-router-dom"; -import BreadcrumbNav from "./BreadcrumbNav"; +import BreadcrumbNav from "../BreadcrumNav/BreadcrumbNav"; export interface HeaderProps { logoHeader?: React.ReactElement; diff --git a/packages/app/src/components/index.ts b/packages/app/src/components/layout/Header/index.ts similarity index 100% rename from packages/app/src/components/index.ts rename to packages/app/src/components/layout/Header/index.ts diff --git a/packages/app/src/components/MainPage.tsx b/packages/app/src/components/layout/MainPage/MainPage.tsx similarity index 93% rename from packages/app/src/components/MainPage.tsx rename to packages/app/src/components/layout/MainPage/MainPage.tsx index 83433b73..97a0008a 100644 --- a/packages/app/src/components/MainPage.tsx +++ b/packages/app/src/components/layout/MainPage/MainPage.tsx @@ -1,7 +1,7 @@ import { Box } from "@mui/material"; import Container from "@mui/material/Container"; import { Outlet } from "react-router-dom"; -import Header, { HeaderProps } from "./Header"; +import Header, { HeaderProps } from "../Header/Header"; interface PublisherConfigProps { headerProps?: HeaderProps; diff --git a/packages/app/src/components/layout/index.ts b/packages/app/src/components/layout/index.ts new file mode 100644 index 00000000..dbb58c49 --- /dev/null +++ b/packages/app/src/components/layout/index.ts @@ -0,0 +1,4 @@ +export * from "./Header"; +export type { HeaderProps } from "./Header"; +export { default as MainPage } from "./MainPage/MainPage"; +export { default as BreadcrumbNav } from "./BreadcrumNav/BreadcrumbNav"; diff --git a/packages/app/src/components/HomePage.tsx b/packages/app/src/components/pages/HomePage/HomePage.tsx similarity index 100% rename from packages/app/src/components/HomePage.tsx rename to packages/app/src/components/pages/HomePage/HomePage.tsx diff --git a/packages/app/src/components/ModelPage.tsx b/packages/app/src/components/pages/ModelPage/ModelPage.tsx similarity index 100% rename from packages/app/src/components/ModelPage.tsx rename to packages/app/src/components/pages/ModelPage/ModelPage.tsx diff --git a/packages/app/src/components/PackagePage.tsx b/packages/app/src/components/pages/PackagePage/PackagePage.tsx similarity index 100% rename from packages/app/src/components/PackagePage.tsx rename to packages/app/src/components/pages/PackagePage/PackagePage.tsx diff --git a/packages/app/src/components/ProjectPage.tsx b/packages/app/src/components/pages/ProjectPage/ProjectPage.tsx similarity index 100% rename from packages/app/src/components/ProjectPage.tsx rename to packages/app/src/components/pages/ProjectPage/ProjectPage.tsx diff --git a/packages/app/src/components/WorkbookPage.tsx b/packages/app/src/components/pages/WorkbookPage/WorkbookPage.tsx similarity index 100% rename from packages/app/src/components/WorkbookPage.tsx rename to packages/app/src/components/pages/WorkbookPage/WorkbookPage.tsx diff --git a/packages/app/src/components/pages/index.ts b/packages/app/src/components/pages/index.ts new file mode 100644 index 00000000..b7a7fe27 --- /dev/null +++ b/packages/app/src/components/pages/index.ts @@ -0,0 +1,5 @@ +export { default as HomePage } from "./HomePage/HomePage"; +export { default as ProjectPage } from "./ProjectPage/ProjectPage"; +export { default as PackagePage } from "./PackagePage/PackagePage"; +export { default as ModelPage } from "./ModelPage/ModelPage"; +export { default as WorkbookPage } from "./WorkbookPage/WorkbookPage"; diff --git a/packages/app/src/components/ToggleColorMode.tsx b/packages/app/src/components/theme/ToggleColorMode/ToggleColorMode.tsx similarity index 100% rename from packages/app/src/components/ToggleColorMode.tsx rename to packages/app/src/components/theme/ToggleColorMode/ToggleColorMode.tsx diff --git a/packages/app/src/index.ts b/packages/app/src/index.ts index c8b5fdec..8dbdc9d7 100644 --- a/packages/app/src/index.ts +++ b/packages/app/src/index.ts @@ -1,10 +1,10 @@ // Main App exports -export { MalloyPublisherApp, createMalloyRouter } from "./App"; +export { createMalloyRouter, MalloyPublisherApp } from "./App"; export type { MalloyPublisherAppProps } from "./App"; // Theme exports +export * from "./components/layout/Header"; export { default as theme } from "./theme"; -export * from "./components"; // Additional component exports for advanced usage -export { default as BreadcrumbNav } from "./components/BreadcrumbNav"; -export { default as ToggleColorMode } from "./components/ToggleColorMode"; +export { default as BreadcrumbNav } from "./components/layout/BreadcrumNav/BreadcrumbNav"; +export { default as ToggleColorMode } from "./components/theme/ToggleColorMode/ToggleColorMode";