xladmin 0.3.5 → 0.3.7

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.
@@ -5,6 +5,7 @@ type ShellContextValue = {
5
5
  pendingPath: string | null;
6
6
  pendingView: 'overview' | 'model' | 'generic' | null;
7
7
  startPendingNavigation: (path: string, view?: 'overview' | 'model' | 'generic') => void;
8
+ finishPendingNavigation: (path?: string) => void;
8
9
  };
9
10
  export declare function ShellContextProvider({ value, children, }: {
10
11
  value: ShellContextValue;
package/dist/index.js CHANGED
@@ -1180,8 +1180,9 @@ function AdminMessageBubble({
1180
1180
  borderRadius: "11px",
1181
1181
  px: 1.5,
1182
1182
  py: 1.125,
1183
- border: `1px solid ${appearance.borderColor}`,
1184
1183
  backgroundColor: appearance.backgroundColor,
1184
+ backdropFilter: "blur(14px)",
1185
+ WebkitBackdropFilter: "blur(14px)",
1185
1186
  boxShadow: `0 14px 32px ${alpha("#000000", 0.22)}`,
1186
1187
  transform: item.leaving ? "translateX(24px) scale(0.98)" : "translateX(0) scale(1)",
1187
1188
  opacity: item.leaving ? 0 : 1,
@@ -1223,7 +1224,7 @@ function AdminMessageBubble({
1223
1224
  fontSize: 14,
1224
1225
  lineHeight: 1.35,
1225
1226
  fontWeight: 500,
1226
- color: "text.primary",
1227
+ color: appearance.textColor,
1227
1228
  wordBreak: "break-word",
1228
1229
  flex: 1,
1229
1230
  display: "flex",
@@ -1241,27 +1242,27 @@ function getBubbleAppearance(theme, kind) {
1241
1242
  if (kind === "success") {
1242
1243
  return {
1243
1244
  icon: CheckCircleOutlineIcon,
1244
- borderColor: alpha(theme.palette.success.main, 0.62),
1245
- backgroundColor: alpha(theme.palette.success.main, 0.26),
1246
- iconColor: theme.palette.success.main,
1247
- iconBackgroundColor: alpha(theme.palette.success.main, 0.3)
1245
+ backgroundColor: alpha(theme.palette.success.main, 0.6),
1246
+ iconColor: theme.palette.common.white,
1247
+ iconBackgroundColor: alpha(theme.palette.common.white, 0.14),
1248
+ textColor: theme.palette.common.white
1248
1249
  };
1249
1250
  }
1250
1251
  if (kind === "error") {
1251
1252
  return {
1252
1253
  icon: ErrorOutlineIcon,
1253
- borderColor: alpha(theme.palette.error.main, 0.42),
1254
- backgroundColor: alpha(theme.palette.error.main, 0.14),
1255
- iconColor: theme.palette.error.main,
1256
- iconBackgroundColor: alpha(theme.palette.error.main, 0.18)
1254
+ backgroundColor: alpha(theme.palette.error.main, 0.6),
1255
+ iconColor: theme.palette.common.white,
1256
+ iconBackgroundColor: alpha(theme.palette.common.white, 0.14),
1257
+ textColor: theme.palette.common.white
1257
1258
  };
1258
1259
  }
1259
1260
  return {
1260
1261
  icon: InfoOutlinedIcon,
1261
- borderColor: alpha(theme.palette.info.main, 0.42),
1262
- backgroundColor: alpha(theme.palette.info.main, 0.14),
1263
- iconColor: theme.palette.info.main,
1264
- iconBackgroundColor: alpha(theme.palette.info.main, 0.18)
1262
+ backgroundColor: alpha(theme.palette.info.main, 0.6),
1263
+ iconColor: theme.palette.common.white,
1264
+ iconBackgroundColor: alpha(theme.palette.common.white, 0.14),
1265
+ textColor: theme.palette.common.white
1265
1266
  };
1266
1267
  }
1267
1268
 
@@ -1371,7 +1372,7 @@ function FormDialog({
1371
1372
  }
1372
1373
 
1373
1374
  // src/components/OverviewPage.tsx
1374
- import { useEffect as useEffect7, useMemo as useMemo7, useState as useState7 } from "react";
1375
+ import { useEffect as useEffect7, useLayoutEffect, useMemo as useMemo7, useState as useState7 } from "react";
1375
1376
  import { Alert as Alert3, Box as Box6, Grid, Paper as Paper4, Skeleton as Skeleton2, Stack as Stack6 } from "@mui/material";
1376
1377
 
1377
1378
  // src/hooks/useAdminDocumentTitle.ts
@@ -1402,6 +1403,31 @@ function useAdminData() {
1402
1403
  return useContext4(AdminDataContext);
1403
1404
  }
1404
1405
 
1406
+ // src/components/layout/ShellContext.tsx
1407
+ import { createContext as createContext5, useContext as useContext5 } from "react";
1408
+ import { jsx as jsx7 } from "react/jsx-runtime";
1409
+ var defaultShellContextValue = {
1410
+ isMobile: false,
1411
+ openMobileSidebar: () => {
1412
+ },
1413
+ pendingPath: null,
1414
+ pendingView: null,
1415
+ startPendingNavigation: () => {
1416
+ },
1417
+ finishPendingNavigation: () => {
1418
+ }
1419
+ };
1420
+ var ShellContext = createContext5(defaultShellContextValue);
1421
+ function ShellContextProvider({
1422
+ value,
1423
+ children
1424
+ }) {
1425
+ return /* @__PURE__ */ jsx7(ShellContext.Provider, { value, children });
1426
+ }
1427
+ function useShellContext() {
1428
+ return useContext5(ShellContext);
1429
+ }
1430
+
1405
1431
  // src/components/ModelsBlocks.tsx
1406
1432
  import { memo as memo2, useMemo as useMemo6 } from "react";
1407
1433
  import { Box as Box4, Stack as Stack4, useMediaQuery, useTheme as useTheme2 } from "@mui/material";
@@ -1420,10 +1446,10 @@ import {
1420
1446
 
1421
1447
  // src/components/models-blocks/BlockTitle.tsx
1422
1448
  import { Stack as Stack2, Typography as Typography2 } from "@mui/material";
1423
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
1449
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
1424
1450
  function BlockTitle({ block, compact = false }) {
1425
1451
  return /* @__PURE__ */ jsxs4(Stack2, { spacing: 0.25, children: [
1426
- /* @__PURE__ */ jsx7(
1452
+ /* @__PURE__ */ jsx8(
1427
1453
  Typography2,
1428
1454
  {
1429
1455
  variant: compact ? "subtitle1" : "h6",
@@ -1435,7 +1461,7 @@ function BlockTitle({ block, compact = false }) {
1435
1461
  children: block.title
1436
1462
  }
1437
1463
  ),
1438
- block.description && !compact ? /* @__PURE__ */ jsx7(Typography2, { color: "text.secondary", sx: { fontSize: compact ? 12 : 14, lineHeight: 1.3 }, children: block.description }) : null
1464
+ block.description && !compact ? /* @__PURE__ */ jsx8(Typography2, { color: "text.secondary", sx: { fontSize: compact ? 12 : 14, lineHeight: 1.3 }, children: block.description }) : null
1439
1465
  ] });
1440
1466
  }
1441
1467
 
@@ -1494,10 +1520,10 @@ function getStorageKey(blockSlug) {
1494
1520
  }
1495
1521
 
1496
1522
  // src/components/NavLink.tsx
1497
- import { jsx as jsx8 } from "react/jsx-runtime";
1523
+ import { jsx as jsx9 } from "react/jsx-runtime";
1498
1524
  function NavLink({ href, children, style, title, onClick, router }) {
1499
1525
  const resolvedRouter = useAdminRouter(router);
1500
- return /* @__PURE__ */ jsx8(
1526
+ return /* @__PURE__ */ jsx9(
1501
1527
  "a",
1502
1528
  {
1503
1529
  href,
@@ -1513,7 +1539,7 @@ function NavLink({ href, children, style, title, onClick, router }) {
1513
1539
  }
1514
1540
 
1515
1541
  // src/components/models-blocks/DashboardModelsBlock.tsx
1516
- import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
1542
+ import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
1517
1543
  function DashboardModelsBlock({ block, basePath }) {
1518
1544
  const [isExpanded, setIsExpanded] = useBlockExpandedState(block.slug, block.default_expanded);
1519
1545
  return /* @__PURE__ */ jsxs5(
@@ -1532,10 +1558,10 @@ function DashboardModelsBlock({ block, basePath }) {
1532
1558
  }
1533
1559
  },
1534
1560
  children: [
1535
- /* @__PURE__ */ jsx9(
1561
+ /* @__PURE__ */ jsx10(
1536
1562
  AccordionSummary,
1537
1563
  {
1538
- expandIcon: block.collapsible ? /* @__PURE__ */ jsx9(ExpandMoreIcon, { fontSize: "small" }) : void 0,
1564
+ expandIcon: block.collapsible ? /* @__PURE__ */ jsx10(ExpandMoreIcon, { fontSize: "small" }) : void 0,
1539
1565
  sx: {
1540
1566
  minHeight: "48px",
1541
1567
  pr: 1.75,
@@ -1557,15 +1583,15 @@ function DashboardModelsBlock({ block, basePath }) {
1557
1583
  mb: 1.05
1558
1584
  }
1559
1585
  },
1560
- children: /* @__PURE__ */ jsx9(BlockTitle, { block })
1586
+ children: /* @__PURE__ */ jsx10(BlockTitle, { block })
1561
1587
  }
1562
1588
  ),
1563
- /* @__PURE__ */ jsx9(AccordionDetails, { sx: { px: 1.35, pb: 1.35, pt: 0 }, children: /* @__PURE__ */ jsx9(Stack3, { spacing: 0.5, sx: { px: 0.4 }, children: block.models.map((model) => /* @__PURE__ */ jsx9(
1589
+ /* @__PURE__ */ jsx10(AccordionDetails, { sx: { px: 1.35, pb: 1.35, pt: 0 }, children: /* @__PURE__ */ jsx10(Stack3, { spacing: 0.5, sx: { px: 0.4 }, children: block.models.map((model) => /* @__PURE__ */ jsx10(
1564
1590
  NavLink,
1565
1591
  {
1566
1592
  href: `${basePath}/${model.slug}`,
1567
1593
  style: { textDecoration: "none", display: "block" },
1568
- children: /* @__PURE__ */ jsx9(
1594
+ children: /* @__PURE__ */ jsx10(
1569
1595
  ButtonBase,
1570
1596
  {
1571
1597
  sx: {
@@ -1575,7 +1601,7 @@ function DashboardModelsBlock({ block, basePath }) {
1575
1601
  borderRadius: "8px",
1576
1602
  overflow: "hidden"
1577
1603
  },
1578
- children: /* @__PURE__ */ jsx9(
1604
+ children: /* @__PURE__ */ jsx10(
1579
1605
  ListItemButton,
1580
1606
  {
1581
1607
  sx: {
@@ -1584,7 +1610,7 @@ function DashboardModelsBlock({ block, basePath }) {
1584
1610
  px: 1.25,
1585
1611
  py: 0.4
1586
1612
  },
1587
- children: /* @__PURE__ */ jsx9(ListItemText, { primary: model.title })
1613
+ children: /* @__PURE__ */ jsx10(ListItemText, { primary: model.title })
1588
1614
  }
1589
1615
  )
1590
1616
  }
@@ -1609,7 +1635,7 @@ import {
1609
1635
  ListItemText as ListItemText2,
1610
1636
  Paper as Paper2
1611
1637
  } from "@mui/material";
1612
- import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1638
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
1613
1639
  function SidebarModelsBlock({ block, basePath, activeModelSlug, onModelNavigate }) {
1614
1640
  const [isExpanded, setIsExpanded] = useBlockExpandedState(block.slug, block.default_expanded);
1615
1641
  if (block.collapsible) {
@@ -1629,10 +1655,10 @@ function SidebarModelsBlock({ block, basePath, activeModelSlug, onModelNavigate
1629
1655
  }
1630
1656
  },
1631
1657
  children: [
1632
- /* @__PURE__ */ jsx10(
1658
+ /* @__PURE__ */ jsx11(
1633
1659
  AccordionSummary2,
1634
1660
  {
1635
- expandIcon: /* @__PURE__ */ jsx10(ExpandMoreIcon2, { fontSize: "small" }),
1661
+ expandIcon: /* @__PURE__ */ jsx11(ExpandMoreIcon2, { fontSize: "small" }),
1636
1662
  sx: {
1637
1663
  minHeight: "42px",
1638
1664
  pr: 1.25,
@@ -1648,10 +1674,10 @@ function SidebarModelsBlock({ block, basePath, activeModelSlug, onModelNavigate
1648
1674
  my: 0
1649
1675
  }
1650
1676
  },
1651
- children: /* @__PURE__ */ jsx10(BlockTitle, { block, compact: true })
1677
+ children: /* @__PURE__ */ jsx11(BlockTitle, { block, compact: true })
1652
1678
  }
1653
1679
  ),
1654
- /* @__PURE__ */ jsx10(AccordionDetails2, { sx: { p: 0 }, children: /* @__PURE__ */ jsx10(
1680
+ /* @__PURE__ */ jsx11(AccordionDetails2, { sx: { p: 0 }, children: /* @__PURE__ */ jsx11(
1655
1681
  SidebarModelsList,
1656
1682
  {
1657
1683
  models: block.models,
@@ -1673,8 +1699,8 @@ function SidebarModelsBlock({ block, basePath, activeModelSlug, onModelNavigate
1673
1699
  overflow: "hidden"
1674
1700
  },
1675
1701
  children: [
1676
- /* @__PURE__ */ jsx10(Box3, { sx: { px: 1.25, py: 1 }, children: /* @__PURE__ */ jsx10(BlockTitle, { block, compact: true }) }),
1677
- /* @__PURE__ */ jsx10(
1702
+ /* @__PURE__ */ jsx11(Box3, { sx: { px: 1.25, py: 1 }, children: /* @__PURE__ */ jsx11(BlockTitle, { block, compact: true }) }),
1703
+ /* @__PURE__ */ jsx11(
1678
1704
  SidebarModelsList,
1679
1705
  {
1680
1706
  models: block.models,
@@ -1688,16 +1714,16 @@ function SidebarModelsBlock({ block, basePath, activeModelSlug, onModelNavigate
1688
1714
  );
1689
1715
  }
1690
1716
  function SidebarModelsList({ models, basePath, activeModelSlug, onModelNavigate }) {
1691
- return /* @__PURE__ */ jsx10(List, { dense: true, disablePadding: true, sx: { display: "flex", flexDirection: "column", gap: 0.5, p: 1.35 }, children: models.map((model) => {
1717
+ return /* @__PURE__ */ jsx11(List, { dense: true, disablePadding: true, sx: { display: "flex", flexDirection: "column", gap: 0.5, p: 1.35 }, children: models.map((model) => {
1692
1718
  const href = `${basePath}/${model.slug}`;
1693
1719
  const isActive = activeModelSlug === model.slug;
1694
- return /* @__PURE__ */ jsx10(
1720
+ return /* @__PURE__ */ jsx11(
1695
1721
  NavLink,
1696
1722
  {
1697
1723
  href,
1698
1724
  style: { textDecoration: "none", display: "block" },
1699
1725
  onClick: () => onModelNavigate == null ? void 0 : onModelNavigate(href),
1700
- children: /* @__PURE__ */ jsx10(
1726
+ children: /* @__PURE__ */ jsx11(
1701
1727
  ListItemButton2,
1702
1728
  {
1703
1729
  selected: isActive,
@@ -1716,7 +1742,7 @@ function SidebarModelsList({ models, basePath, activeModelSlug, onModelNavigate
1716
1742
  backgroundColor: "rgba(255, 255, 255, 0.2)"
1717
1743
  }
1718
1744
  },
1719
- children: /* @__PURE__ */ jsx10(ListItemText2, { primary: model.title })
1745
+ children: /* @__PURE__ */ jsx11(ListItemText2, { primary: model.title })
1720
1746
  }
1721
1747
  )
1722
1748
  },
@@ -1726,7 +1752,7 @@ function SidebarModelsList({ models, basePath, activeModelSlug, onModelNavigate
1726
1752
  }
1727
1753
 
1728
1754
  // src/components/ModelsBlocks.tsx
1729
- import { jsx as jsx11 } from "react/jsx-runtime";
1755
+ import { jsx as jsx12 } from "react/jsx-runtime";
1730
1756
  var ModelsBlocks = memo2(function ModelsBlocks2({
1731
1757
  basePath,
1732
1758
  models,
@@ -1757,7 +1783,7 @@ var ModelsBlocks = memo2(function ModelsBlocks2({
1757
1783
  return distributeBlocksByHeight(normalizedBlocks, columnCount);
1758
1784
  }, [isMdUp, isXlUp, normalizedBlocks]);
1759
1785
  if (variant === "sidebar") {
1760
- return /* @__PURE__ */ jsx11(Stack4, { spacing: 1, children: normalizedBlocks.map((block) => /* @__PURE__ */ jsx11(
1786
+ return /* @__PURE__ */ jsx12(Stack4, { spacing: 1, children: normalizedBlocks.map((block) => /* @__PURE__ */ jsx12(
1761
1787
  SidebarModelsBlock,
1762
1788
  {
1763
1789
  block,
@@ -1768,7 +1794,7 @@ var ModelsBlocks = memo2(function ModelsBlocks2({
1768
1794
  block.slug
1769
1795
  )) });
1770
1796
  }
1771
- return /* @__PURE__ */ jsx11(Box4, { sx: { display: "flex", gap: 2, alignItems: "flex-start" }, children: dashboardColumns.map((column, columnIndex) => /* @__PURE__ */ jsx11(Box4, { sx: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx11(Stack4, { spacing: 2, children: column.map((block) => /* @__PURE__ */ jsx11(DashboardModelsBlock, { block, basePath }, block.slug)) }) }, columnIndex)) });
1797
+ return /* @__PURE__ */ jsx12(Box4, { sx: { display: "flex", gap: 2, alignItems: "flex-start" }, children: dashboardColumns.map((column, columnIndex) => /* @__PURE__ */ jsx12(Box4, { sx: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx12(Stack4, { spacing: 2, children: column.map((block) => /* @__PURE__ */ jsx12(DashboardModelsBlock, { block, basePath }, block.slug)) }) }, columnIndex)) });
1772
1798
  });
1773
1799
  function distributeBlocksByHeight(blocks, columnCount) {
1774
1800
  const columns = Array.from({ length: columnCount }, () => []);
@@ -1795,31 +1821,6 @@ import MenuIcon from "@mui/icons-material/Menu";
1795
1821
  import { Box as Box5 } from "@mui/material";
1796
1822
  import ExpandMoreIcon3 from "@mui/icons-material/ExpandMore";
1797
1823
  import { Alert as Alert2, Collapse, IconButton, Paper as Paper3, Skeleton, Stack as Stack5, Typography as Typography3 } from "@mui/material";
1798
-
1799
- // src/components/layout/ShellContext.tsx
1800
- import { createContext as createContext5, useContext as useContext5 } from "react";
1801
- import { jsx as jsx12 } from "react/jsx-runtime";
1802
- var defaultShellContextValue = {
1803
- isMobile: false,
1804
- openMobileSidebar: () => {
1805
- },
1806
- pendingPath: null,
1807
- pendingView: null,
1808
- startPendingNavigation: () => {
1809
- }
1810
- };
1811
- var ShellContext = createContext5(defaultShellContextValue);
1812
- function ShellContextProvider({
1813
- value,
1814
- children
1815
- }) {
1816
- return /* @__PURE__ */ jsx12(ShellContext.Provider, { value, children });
1817
- }
1818
- function useShellContext() {
1819
- return useContext5(ShellContext);
1820
- }
1821
-
1822
- // src/components/layout/MainHeader.tsx
1823
1824
  import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1824
1825
  var MAIN_HEADER_PADDING_X = 2.5;
1825
1826
  var MAIN_HEADER_PADDING_T = 1.35;
@@ -1979,6 +1980,7 @@ var inFlightModelsRequest = null;
1979
1980
  function OverviewPage({ client, basePath }) {
1980
1981
  const t = useAdminTranslation();
1981
1982
  useAdminDocumentTitle(t("admin_title"), t("overview_title"));
1983
+ const { pendingPath, finishPendingNavigation } = useShellContext();
1982
1984
  const adminData = useAdminData();
1983
1985
  const shellModelsResponse = useMemo7(() => {
1984
1986
  if (adminData.models.length === 0 && adminData.blocks.length === 0) {
@@ -2032,6 +2034,18 @@ function OverviewPage({ client, basePath }) {
2032
2034
  isMounted = false;
2033
2035
  };
2034
2036
  }, [client, shellModelsResponse, t]);
2037
+ useLayoutEffect(() => {
2038
+ if (pendingPath === null) {
2039
+ return;
2040
+ }
2041
+ if (isLoading) {
2042
+ return;
2043
+ }
2044
+ if (!data && !error) {
2045
+ return;
2046
+ }
2047
+ finishPendingNavigation();
2048
+ }, [data, error, finishPendingNavigation, isLoading, pendingPath]);
2035
2049
  if (isLoading && !data) {
2036
2050
  return /* @__PURE__ */ jsx14(OverviewPageSkeleton, {});
2037
2051
  }
@@ -2094,6 +2108,7 @@ function OverviewPageSkeleton() {
2094
2108
  }
2095
2109
 
2096
2110
  // src/components/ModelPage.tsx
2111
+ import { useLayoutEffect as useLayoutEffect3 } from "react";
2097
2112
  import AddIcon from "@mui/icons-material/Add";
2098
2113
  import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
2099
2114
  import ChevronRightIcon from "@mui/icons-material/ChevronRight";
@@ -2713,7 +2728,7 @@ var SearchField = memo5(function SearchField2({
2713
2728
  });
2714
2729
 
2715
2730
  // src/components/model-page/useModelPageController.ts
2716
- import { useCallback as useCallback5, useEffect as useEffect10, useMemo as useMemo9, useRef as useRef4, useState as useState10 } from "react";
2731
+ import { useCallback as useCallback5, useEffect as useEffect10, useLayoutEffect as useLayoutEffect2, useMemo as useMemo9, useRef as useRef4, useState as useState10 } from "react";
2717
2732
 
2718
2733
  // src/cache.ts
2719
2734
  var MAX_CACHE_ENTRIES = 100;
@@ -2899,7 +2914,7 @@ function useModelPageController({
2899
2914
  useEffect10(() => {
2900
2915
  setPageInput(String(currentPage));
2901
2916
  }, [currentPage]);
2902
- useEffect10(() => {
2917
+ useLayoutEffect2(() => {
2903
2918
  var _a2, _b2, _c2, _d2;
2904
2919
  if (previousSlugRef.current === slug) {
2905
2920
  return;
@@ -2939,7 +2954,7 @@ function useModelPageController({
2939
2954
  setPendingDeleteScope(null);
2940
2955
  setPendingDeleteMode("single");
2941
2956
  }, [client, locationSearch, slug]);
2942
- useEffect10(() => {
2957
+ useLayoutEffect2(() => {
2943
2958
  var _a2, _b2;
2944
2959
  const nextSearchParams = new URLSearchParams(locationSearch);
2945
2960
  const nextQuery = (_a2 = nextSearchParams.get("q")) != null ? _a2 : "";
@@ -3393,6 +3408,7 @@ function ModelPage({ client, basePath, slug, router, renderBeforePagination }) {
3393
3408
  const location = useAdminLocation(resolvedRouter);
3394
3409
  const theme = useTheme3();
3395
3410
  const isMobile = useMediaQuery2(theme.breakpoints.down("md"));
3411
+ const { pendingPath, finishPendingNavigation } = useShellContext();
3396
3412
  const controller = useModelPageController({
3397
3413
  client,
3398
3414
  slug,
@@ -3401,6 +3417,21 @@ function ModelPage({ client, basePath, slug, router, renderBeforePagination }) {
3401
3417
  router: resolvedRouter,
3402
3418
  t
3403
3419
  });
3420
+ useLayoutEffect3(() => {
3421
+ if (pendingPath === null) {
3422
+ return;
3423
+ }
3424
+ if (controller.isLoading) {
3425
+ return;
3426
+ }
3427
+ if (!controller.meta && !controller.error) {
3428
+ return;
3429
+ }
3430
+ if (controller.meta && controller.meta.slug !== slug) {
3431
+ return;
3432
+ }
3433
+ finishPendingNavigation(location.pathname);
3434
+ }, [controller.error, controller.isLoading, controller.meta, finishPendingNavigation, location.pathname, pendingPath, slug]);
3404
3435
  useAdminDocumentTitle(t("admin_title"), (_b = (_a = controller.meta) == null ? void 0 : _a.title) != null ? _b : slug);
3405
3436
  if (!controller.isLoading && controller.error && !controller.data) {
3406
3437
  return /* @__PURE__ */ jsx20(Alert5, { severity: "error", children: controller.error });
@@ -3825,6 +3856,7 @@ function resolveFieldSortable(field) {
3825
3856
  }
3826
3857
 
3827
3858
  // src/components/ObjectPage.tsx
3859
+ import { useLayoutEffect as useLayoutEffect5 } from "react";
3828
3860
  import ArrowBackIcon from "@mui/icons-material/ArrowBack";
3829
3861
  import MoreVertIcon2 from "@mui/icons-material/MoreVert";
3830
3862
  import { Alert as Alert6, Box as Box13, Button as Button5, IconButton as IconButton4, Menu as Menu2, MenuItem as MenuItem3, Paper as Paper9, Stack as Stack13, Typography as Typography7, useMediaQuery as useMediaQuery3 } from "@mui/material";
@@ -3942,7 +3974,7 @@ var ReadonlyObjectField = memo7(function ReadonlyObjectField2({
3942
3974
  });
3943
3975
 
3944
3976
  // src/components/object-page/useObjectPageController.ts
3945
- import { useCallback as useCallback7, useEffect as useEffect11, useMemo as useMemo10, useState as useState11 } from "react";
3977
+ import { useCallback as useCallback7, useLayoutEffect as useLayoutEffect4, useMemo as useMemo10, useState as useState11 } from "react";
3946
3978
 
3947
3979
  // src/utils/isDeepEqual.ts
3948
3980
  function isDeepEqual(left, right) {
@@ -4006,7 +4038,7 @@ function useObjectPageController({
4006
4038
  const [isDeletePreviewLoading, setIsDeletePreviewLoading] = useState11(false);
4007
4039
  const [deletePreviewError, setDeletePreviewError] = useState11(null);
4008
4040
  const [actionsAnchorEl, setActionsAnchorEl] = useState11(null);
4009
- useEffect11(() => {
4041
+ useLayoutEffect4(() => {
4010
4042
  var _a2;
4011
4043
  let isMounted = true;
4012
4044
  const bucket = getClientCacheBucket(client);
@@ -4223,6 +4255,7 @@ function ObjectPage({ client, slug, id, router }) {
4223
4255
  const pathname = location.pathname;
4224
4256
  const theme = useTheme4();
4225
4257
  const isPhone = useMediaQuery3(theme.breakpoints.down("sm"));
4258
+ const { pendingPath, finishPendingNavigation } = useShellContext();
4226
4259
  const listPath = pathname.split("/").slice(0, -1).join("/");
4227
4260
  const controller = useObjectPageController({
4228
4261
  client,
@@ -4232,6 +4265,21 @@ function ObjectPage({ client, slug, id, router }) {
4232
4265
  router: resolvedRouter,
4233
4266
  t
4234
4267
  });
4268
+ useLayoutEffect5(() => {
4269
+ if (pendingPath === null) {
4270
+ return;
4271
+ }
4272
+ if (controller.isLoading) {
4273
+ return;
4274
+ }
4275
+ if (!controller.meta && !controller.error) {
4276
+ return;
4277
+ }
4278
+ if (controller.meta && controller.meta.slug !== slug) {
4279
+ return;
4280
+ }
4281
+ finishPendingNavigation(pathname);
4282
+ }, [controller.error, controller.isLoading, controller.meta, finishPendingNavigation, pathname, pendingPath, slug]);
4235
4283
  useAdminDocumentTitle(t("admin_title"), (_b = (_a = controller.meta) == null ? void 0 : _a.title) != null ? _b : slug, controller.objectTitle);
4236
4284
  if (controller.isLoading && !controller.data) {
4237
4285
  return /* @__PURE__ */ jsx24(ObjectPageSkeleton, {});
@@ -4449,7 +4497,7 @@ function ObjectPage({ client, slug, id, router }) {
4449
4497
  }
4450
4498
 
4451
4499
  // src/components/Shell.tsx
4452
- import { useEffect as useEffect12, useMemo as useMemo11, useState as useState12 } from "react";
4500
+ import { useEffect as useEffect11, useMemo as useMemo11, useState as useState12 } from "react";
4453
4501
  import { Box as Box16, CssBaseline, Drawer, GlobalStyles, Stack as Stack14, useMediaQuery as useMediaQuery4 } from "@mui/material";
4454
4502
  import { ThemeProvider } from "@mui/material/styles";
4455
4503
 
@@ -4584,13 +4632,9 @@ var defaultAdminTheme = createTheme({
4584
4632
  import { Box as Box14 } from "@mui/material";
4585
4633
  import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
4586
4634
  function Main({ children }) {
4587
- const { pathname } = useAdminLocation();
4635
+ useAdminLocation();
4588
4636
  const { pendingPath, pendingView } = useShellContext();
4589
- const normalizeAdminPath2 = (path) => {
4590
- const normalizedPath = path.endsWith("/") && path !== "/" ? path.slice(0, -1) : path;
4591
- return normalizedPath.replace(/^\/(ru|en)(?=\/|$)/, "") || "/";
4592
- };
4593
- const isPendingNavigation = pendingPath !== null && normalizeAdminPath2(pathname) !== normalizeAdminPath2(pendingPath);
4637
+ const isPendingNavigation = pendingPath !== null;
4594
4638
  return /* @__PURE__ */ jsxs17(
4595
4639
  Box14,
4596
4640
  {
@@ -4707,23 +4751,14 @@ function Shell({ client, models, blocks, basePath, locale, children, theme, rout
4707
4751
  const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState12(false);
4708
4752
  const [pendingPath, setPendingPath] = useState12(null);
4709
4753
  const [pendingView, setPendingView] = useState12(null);
4710
- useEffect12(() => {
4754
+ useEffect11(() => {
4711
4755
  if (isDesktopSidebar) {
4712
4756
  setIsMobileSidebarOpen(false);
4713
4757
  }
4714
4758
  }, [isDesktopSidebar]);
4715
- useEffect12(() => {
4759
+ useEffect11(() => {
4716
4760
  setIsMobileSidebarOpen(false);
4717
4761
  }, [pathname]);
4718
- useEffect12(() => {
4719
- if (pendingPath === null) {
4720
- return;
4721
- }
4722
- if (normalizeAdminPath(pathname) === normalizeAdminPath(pendingPath)) {
4723
- setPendingPath(null);
4724
- setPendingView(null);
4725
- }
4726
- }, [pathname, pendingPath]);
4727
4762
  const shellContextValue = useMemo11(() => ({
4728
4763
  isMobile: !isDesktopSidebar,
4729
4764
  openMobileSidebar: () => setIsMobileSidebarOpen(true),
@@ -4735,6 +4770,16 @@ function Shell({ client, models, blocks, basePath, locale, children, theme, rout
4735
4770
  }
4736
4771
  setPendingPath(path);
4737
4772
  setPendingView(view);
4773
+ },
4774
+ finishPendingNavigation: (path) => {
4775
+ if (pendingPath === null) {
4776
+ return;
4777
+ }
4778
+ if (path && normalizeAdminPath(path) !== normalizeAdminPath(pendingPath)) {
4779
+ return;
4780
+ }
4781
+ setPendingPath(null);
4782
+ setPendingView(null);
4738
4783
  }
4739
4784
  }), [isDesktopSidebar, pathname, pendingPath, pendingView]);
4740
4785
  return /* @__PURE__ */ jsx27(AdminRouterProvider, { router: resolvedRouter, children: /* @__PURE__ */ jsx27(ThemeProvider, { theme: activeTheme, children: /* @__PURE__ */ jsx27(AdminLocaleProvider, { locale, children: /* @__PURE__ */ jsx27(AdminDataProvider, { value: { locale: locale === "en" ? "en" : "ru", models, blocks }, children: /* @__PURE__ */ jsx27(ShellContextProvider, { value: shellContextValue, children: /* @__PURE__ */ jsxs19(AdminMessageProvider, { children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xladmin",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "Framework-agnostic React + MUI admin frontend for xladmin.",
5
5
  "license": "MIT",
6
6
  "type": "module",