habarico 7.3.0-beta.3 → 7.3.0-beta.5

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
@@ -11,7 +11,7 @@ or 19.
11
11
  ## Installation
12
12
 
13
13
  ```bash
14
- pnpm add habarico
14
+ npm install habarico
15
15
  ```
16
16
 
17
17
  Peer dependencies (React, React Admin, MUI) are not bundled — install them in the project at the
@@ -21,28 +21,6 @@ same versions the library declares.
21
21
  > data router. Let `SchemaAdmin` create one itself, or wrap it in `createBrowserRouter` — a legacy
22
22
  > `<BrowserRouter>` silently disables the guard.
23
23
 
24
- ## Local development against a checkout
25
-
26
- To run a project against your working copy instead of the published package, link it from the
27
- project directory — the free library first, the paid one second:
28
-
29
- ```bash
30
- pydev link-library <path-to-libs>/habarico-base/node <path-to-libs>/habarico-enterprise/node-enterprise
31
- ```
32
-
33
- `<path-to-libs>` is the directory holding your library checkouts — the same placeholder the Ruby services use in their compose files. Relative or absolute, both work.
34
-
35
- Link only what you develop; either package works on its own. When you link both, the order matters —
36
- `habarico-enterprise` resolves its own `habarico` through the project, so the free library
37
- has to be linked first or both end up with their own copy of React.
38
-
39
- ```bash
40
- pnpm watch # in the library you edit
41
- pydev unlink-library <same paths>
42
- ```
43
-
44
- See [Installation](https://docs.habarico.com/node/installation) for the details.
45
-
46
24
  ## Quick start
47
25
 
48
26
  ```tsx
@@ -77,7 +55,7 @@ is only a quick start.
77
55
 
78
56
  | Section | What it covers |
79
57
  | --- | --- |
80
- | [Installation](https://docs.habarico.com/node/installation) | Packages, the router requirement, local development against a checkout |
58
+ | [Installation](https://docs.habarico.com/node/installation) | Peer dependencies and the router requirement |
81
59
  | [Base components](https://docs.habarico.com/node/base-components/) | `SchemaAdmin` and `SchemaResource` — every prop |
82
60
  | [View components](https://docs.habarico.com/node/view-components/) | List, show, create, edit and action views |
83
61
  | [Providers](https://docs.habarico.com/node/providers/) | Auth, data and schema providers, and the customisation registries |
@@ -91,10 +69,6 @@ The backends serving those schemas are documented at
91
69
  [docs.habarico.com/ruby/intro](https://docs.habarico.com/ruby/intro); the contract between them is the
92
70
  [API reference](https://docs.habarico.com/api).
93
71
 
94
- The architecture of the library itself — its four layers and what belongs where — is documented in
95
- `src/foundation/README.md`, `src/design/README.md`, `src/admin/README.md` and
96
- `src/schema/README.md`, next to the code they describe.
97
-
98
72
  ## License
99
73
 
100
74
  [MIT](LICENSE)
package/lib/index.cjs CHANGED
@@ -55441,6 +55441,7 @@ const MenuItem = ({
55441
55441
  highlighted,
55442
55442
  sub,
55443
55443
  dropdown,
55444
+ expanded,
55444
55445
  tooltip,
55445
55446
  onMouseEnter,
55446
55447
  onMouseLeave,
@@ -55450,12 +55451,13 @@ const MenuItem = ({
55450
55451
  const isLight = theme.palette.mode === "light";
55451
55452
  const activeText = isLight ? theme.palette.primary.dark : theme.palette.primary.light;
55452
55453
  const activeIcon = isLight ? theme.palette.primary.main : theme.palette.primary.lighter;
55454
+ const isGroup = !!item.items?.length;
55455
+ const linkProps = isGroup ? { "aria-expanded": !!expanded } : { component: RouterLink, href: item.href };
55453
55456
  return /* @__PURE__ */ jsxRuntime.jsx(material.Tooltip, { title: tooltip, placement: "right", children: /* @__PURE__ */ jsxRuntime.jsxs(
55454
55457
  material.ListItemButton,
55455
55458
  {
55456
55459
  disableGutters: true,
55457
- component: RouterLink,
55458
- href: item.href,
55460
+ ...linkProps,
55459
55461
  onMouseEnter,
55460
55462
  onMouseLeave,
55461
55463
  onClick,
@@ -55504,6 +55506,7 @@ const MenuItemWithPopper = ({ children, onClick, ...rest }) => {
55504
55506
  const isOverSubMenuRef = React.useRef(false);
55505
55507
  const openTimeoutRef = React.useRef(void 0);
55506
55508
  const closeTimeoutRef = React.useRef(void 0);
55509
+ const openedByClickRef = React.useRef(false);
55507
55510
  const closeIfNotOver = React.useCallback(() => {
55508
55511
  clearTimeout(closeTimeoutRef.current);
55509
55512
  closeTimeoutRef.current = setTimeout(() => {
@@ -55517,9 +55520,22 @@ const MenuItemWithPopper = ({ children, onClick, ...rest }) => {
55517
55520
  isOverMenuRef.current = true;
55518
55521
  const target = e.currentTarget;
55519
55522
  openTimeoutRef.current = setTimeout(() => {
55523
+ openedByClickRef.current = false;
55520
55524
  setAnchorEl(target);
55521
55525
  }, POPOVER_OPEN_DEBOUNCE);
55522
55526
  }, []);
55527
+ const togglePopper = React.useCallback(
55528
+ (e) => {
55529
+ clearTimeout(openTimeoutRef.current);
55530
+ clearTimeout(closeTimeoutRef.current);
55531
+ const target = e.currentTarget;
55532
+ const close = Boolean(anchorEl) && openedByClickRef.current;
55533
+ openedByClickRef.current = !close;
55534
+ setAnchorEl(close ? null : target);
55535
+ onClick?.(e);
55536
+ },
55537
+ [anchorEl, onClick]
55538
+ );
55523
55539
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
55524
55540
  /* @__PURE__ */ jsxRuntime.jsx(
55525
55541
  MenuItem,
@@ -55531,7 +55547,8 @@ const MenuItemWithPopper = ({ children, onClick, ...rest }) => {
55531
55547
  isOverMenuRef.current = false;
55532
55548
  closeIfNotOver();
55533
55549
  },
55534
- onClick
55550
+ onClick: togglePopper,
55551
+ expanded: Boolean(anchorEl)
55535
55552
  }
55536
55553
  ),
55537
55554
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -55629,8 +55646,39 @@ const MenuListCollapsed = ({ items, level, onItemClick }) => {
55629
55646
  const SUB_INDENT = 40;
55630
55647
  const ELBOW_WIDTH = 16;
55631
55648
  const ELBOW_RADIUS = 10;
55632
- const MenuListFull = ({ items, level, onItemClick }) => {
55649
+ const MenuListFullItem = ({ item, level, onItemClick }) => {
55633
55650
  const { isActive, isExpanded } = useActiveExpanded();
55651
+ const pathname = usePathname();
55652
+ const routeExpanded = isExpanded(item);
55653
+ const [open, setOpen] = React.useState(routeExpanded);
55654
+ const [syncedPathname, setSyncedPathname] = React.useState(pathname);
55655
+ if (syncedPathname !== pathname) {
55656
+ setSyncedPathname(pathname);
55657
+ if (routeExpanded) setOpen(true);
55658
+ }
55659
+ const active = isActive(item);
55660
+ const isGroup = !!item.items?.length;
55661
+ const highlighted = !active && isGroup && open;
55662
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
55663
+ /* @__PURE__ */ jsxRuntime.jsx(
55664
+ MenuItem,
55665
+ {
55666
+ item,
55667
+ active,
55668
+ highlighted,
55669
+ expanded: isGroup ? open : void 0,
55670
+ sub: level >= 1,
55671
+ collapsed: false,
55672
+ onClick: () => {
55673
+ if (isGroup) setOpen((value) => !value);
55674
+ onItemClick?.(item);
55675
+ }
55676
+ }
55677
+ ),
55678
+ isGroup && /* @__PURE__ */ jsxRuntime.jsx(material.Collapse, { in: open, children: /* @__PURE__ */ jsxRuntime.jsx(MenuListFull, { items: item.items, onItemClick, level: level + 1 }) })
55679
+ ] });
55680
+ };
55681
+ const MenuListFull = ({ items, level, onItemClick }) => {
55634
55682
  const theme = material.useTheme();
55635
55683
  const isSub = level >= 1;
55636
55684
  const lineColor = varAlpha(theme.palette.grey["500Channel"], 0.32);
@@ -55651,9 +55699,7 @@ const MenuListFull = ({ items, level, onItemClick }) => {
55651
55699
  position: isSub ? "relative" : void 0
55652
55700
  },
55653
55701
  children: items.map((item, index) => {
55654
- const active = isActive(item);
55655
- const highlighted = !active && !!item.items?.length && isExpanded(item);
55656
- return /* @__PURE__ */ jsxRuntime.jsxs(
55702
+ return /* @__PURE__ */ jsxRuntime.jsx(
55657
55703
  material.ListItem,
55658
55704
  {
55659
55705
  disableGutters: true,
@@ -55684,22 +55730,7 @@ const MenuListFull = ({ items, level, onItemClick }) => {
55684
55730
  }
55685
55731
  }
55686
55732
  },
55687
- children: [
55688
- /* @__PURE__ */ jsxRuntime.jsx(
55689
- MenuItem,
55690
- {
55691
- item,
55692
- active,
55693
- highlighted,
55694
- sub: isSub,
55695
- collapsed: false,
55696
- onClick: () => {
55697
- onItemClick?.(item);
55698
- }
55699
- }
55700
- ),
55701
- item.items && /* @__PURE__ */ jsxRuntime.jsx(material.Collapse, { in: isExpanded(item), children: /* @__PURE__ */ jsxRuntime.jsx(MenuListFull, { items: item.items, onItemClick, level: level + 1 }) })
55702
- ]
55733
+ children: /* @__PURE__ */ jsxRuntime.jsx(MenuListFullItem, { item, level, onItemClick })
55703
55734
  },
55704
55735
  index
55705
55736
  );