@carlonicora/nextjs-jsonapi 6.20.6 → 6.21.0

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.
Files changed (36) hide show
  1. package/dist/{BlockNoteEditor-H5QBL25M.mjs → BlockNoteEditor-66ZACETR.mjs} +2 -2
  2. package/dist/{BlockNoteEditor-IRMQQGPS.js → BlockNoteEditor-NXCRWS2O.js} +9 -9
  3. package/dist/{BlockNoteEditor-IRMQQGPS.js.map → BlockNoteEditor-NXCRWS2O.js.map} +1 -1
  4. package/dist/billing/index.js +378 -378
  5. package/dist/billing/index.mjs +1 -1
  6. package/dist/{chunk-EGTC75OW.js → chunk-3CGU6WXY.js} +8 -4
  7. package/dist/chunk-3CGU6WXY.js.map +1 -0
  8. package/dist/{chunk-RF2PR5G3.mjs → chunk-OHHA5BBX.mjs} +8 -4
  9. package/dist/chunk-OHHA5BBX.mjs.map +1 -0
  10. package/dist/client/index.js +2 -2
  11. package/dist/client/index.mjs +1 -1
  12. package/dist/components/containers/RoundPageContainer.d.ts.map +1 -1
  13. package/dist/components/index.js +2 -2
  14. package/dist/components/index.mjs +1 -1
  15. package/dist/contexts/index.js +2 -2
  16. package/dist/contexts/index.mjs +1 -1
  17. package/dist/email-automations/index.js +78 -78
  18. package/dist/email-automations/index.mjs +1 -1
  19. package/dist/features/analytics/index.js +107 -107
  20. package/dist/features/analytics/index.mjs +1 -1
  21. package/dist/features/blog/index.js +93 -93
  22. package/dist/features/blog/index.mjs +1 -1
  23. package/dist/features/help/index.js +31 -31
  24. package/dist/features/help/index.mjs +1 -1
  25. package/dist/features/tokenusage/index.js +102 -102
  26. package/dist/features/tokenusage/index.mjs +1 -1
  27. package/dist/shadcnui/ui/popover.d.ts +1 -1
  28. package/dist/shadcnui/ui/popover.d.ts.map +1 -1
  29. package/package.json +1 -1
  30. package/src/components/containers/RoundPageContainer.tsx +11 -2
  31. package/src/components/containers/__tests__/RoundPageContainer.padding.spec.tsx +21 -0
  32. package/src/shadcnui/ui/__tests__/popover.container.spec.tsx +22 -0
  33. package/src/shadcnui/ui/popover.tsx +7 -2
  34. package/dist/chunk-EGTC75OW.js.map +0 -1
  35. package/dist/chunk-RF2PR5G3.mjs.map +0 -1
  36. /package/dist/{BlockNoteEditor-H5QBL25M.mjs.map → BlockNoteEditor-66ZACETR.mjs.map} +0 -0
@@ -244,9 +244,16 @@ export function RoundPageContainer({
244
244
  // demo bar, a credit warning). Unset, it is 0 and the height is unchanged; an
245
245
  // app that renders such a banner publishes its live height on <html>, or the
246
246
  // banner pushes the page past the viewport and the document scrolls it away.
247
+ // `--app-footer-h` is the same for a panel fixed to the bottom of the viewport
248
+ // (a drawer over the page): published while it is shown, it keeps the bottom
249
+ // of a full-height page above the panel instead of under it.
247
250
  const shellHeight = isFixed
248
- ? `h-[calc(100svh-var(--app-header-h,3rem)-var(--app-banner-h,0px))]`
249
- : `min-h-[calc(100svh-var(--app-header-h,3rem)-var(--app-banner-h,0px))]`;
251
+ ? `h-[calc(100svh-var(--app-header-h,3rem)-var(--app-banner-h,0px)-var(--app-footer-h,0px))]`
252
+ : `min-h-[calc(100svh-var(--app-header-h,3rem)-var(--app-banner-h,0px)-var(--app-footer-h,0px))]`;
253
+ // A page that grows with its content scrolls the document instead, so it gets the
254
+ // panel's height as bottom margin: its last lines can scroll above the panel. A
255
+ // full-height page already subtracts it from its height above, so it gets none.
256
+ const footerSpace = isFixed ? `` : `mb-[var(--app-footer-h,0px)]`;
250
257
  const clip = isFixed ? `overflow-hidden` : ``;
251
258
  const scrollY = isFixed ? `overflow-y-auto` : ``;
252
259
  // The bar is an in-flow sibling of the content (see MobileNavigationBar's own
@@ -364,6 +371,7 @@ export function RoundPageContainer({
364
371
  className={cn(
365
372
  "flex w-full flex-col",
366
373
  shellHeight,
374
+ footerSpace,
367
375
  // Deliberately NO bottom safe-area inset, here or in
368
376
  // MobileNavigationBar. iOS still reports 34px of bottom inset
369
377
  // (measured in an installed PWA), but nothing is drawn in that strip
@@ -409,6 +417,7 @@ export function RoundPageContainer({
409
417
  className={cn(
410
418
  `flex w-full flex-col`,
411
419
  shellHeight,
420
+ footerSpace,
412
421
  // Deliberately NO bottom safe-area inset, here or in
413
422
  // MobileNavigationBar. iOS still reports 34px of bottom inset
414
423
  // (measured in an installed PWA), but nothing is drawn in that strip
@@ -61,4 +61,25 @@ describe("RoundPageContainer shell padding", () => {
61
61
  expect(shell.classList.contains("p-2")).toBe(true);
62
62
  expect(shell.classList.contains("ps-0")).toBe(false);
63
63
  });
64
+
65
+ it("keeps the page above a bottom panel: the height also subtracts --app-footer-h", async () => {
66
+ render(withShared(<RoundPageContainer testId="shell">content</RoundPageContainer>));
67
+ const shell = await screen.findByTestId("shell");
68
+ expect(shell.className).toContain("-var(--app-footer-h,0px))]");
69
+ });
70
+
71
+ it("a page that grows with its content gets the bottom panel's height as margin; a full-height one does not", async () => {
72
+ const { unmount } = render(
73
+ withShared(
74
+ <RoundPageContainer testId="doc" scroll="document">
75
+ content
76
+ </RoundPageContainer>,
77
+ ),
78
+ );
79
+ expect((await screen.findByTestId("doc")).classList.contains("mb-[var(--app-footer-h,0px)]")).toBe(true);
80
+ unmount();
81
+
82
+ render(withShared(<RoundPageContainer testId="fixed">content</RoundPageContainer>));
83
+ expect((await screen.findByTestId("fixed")).classList.contains("mb-[var(--app-footer-h,0px)]")).toBe(false);
84
+ });
64
85
  });
@@ -0,0 +1,22 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import { describe, expect, it } from "vitest";
3
+ import { Popover, PopoverContent, PopoverTrigger } from "../popover";
4
+
5
+ describe("PopoverContent container", () => {
6
+ it("portals the popup into the given container instead of <body>", async () => {
7
+ const container = document.createElement("div");
8
+ container.setAttribute("data-testid", "trap");
9
+ document.body.appendChild(container);
10
+
11
+ render(
12
+ <Popover defaultOpen>
13
+ <PopoverTrigger>open</PopoverTrigger>
14
+ <PopoverContent container={container}>inside</PopoverContent>
15
+ </Popover>,
16
+ );
17
+
18
+ const popup = await screen.findByText("inside");
19
+ expect(container.contains(popup)).toBe(true);
20
+ container.remove();
21
+ });
22
+ });
@@ -20,15 +20,20 @@ function PopoverContent({
20
20
  side = "bottom",
21
21
  sideOffset = 4,
22
22
  anchor,
23
+ container,
23
24
  ...props
24
25
  }: PopoverPrimitive.Popup.Props &
25
- Pick<PopoverPrimitive.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset" | "anchor">) {
26
+ Pick<PopoverPrimitive.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset" | "anchor"> &
27
+ // Where the popup is portalled (default: <body>). A popover opened from inside a
28
+ // focus-trapping surface (a modal dialog or drawer) passes that surface here, or
29
+ // the trap pulls focus back out of the popup and its inputs cannot be typed in.
30
+ Pick<PopoverPrimitive.Portal.Props, "container">) {
26
31
  // Pickers size themselves to their field (`w-(--anchor-width)`). In a narrow
27
32
  // field on a phone that leaves a ~100px list where every name wraps, so on a
28
33
  // phone they get a usable minimum width (capped to the screen).
29
34
  const matchesAnchorWidth = typeof className === "string" && className.includes("--anchor-width");
30
35
  return (
31
- <PopoverPrimitive.Portal>
36
+ <PopoverPrimitive.Portal container={container}>
32
37
  <PopoverPrimitive.Positioner
33
38
  align={align}
34
39
  alignOffset={alignOffset}