@carlonicora/nextjs-jsonapi 6.27.0 → 6.28.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 (37) hide show
  1. package/dist/{BlockNoteEditor-D2DXVXTJ.mjs → BlockNoteEditor-2LO34HXR.mjs} +2 -2
  2. package/dist/{BlockNoteEditor-NQB75M47.js → BlockNoteEditor-SWDRMNLT.js} +9 -9
  3. package/dist/{BlockNoteEditor-NQB75M47.js.map → BlockNoteEditor-SWDRMNLT.js.map} +1 -1
  4. package/dist/billing/index.js +378 -378
  5. package/dist/billing/index.mjs +1 -1
  6. package/dist/{chunk-YGV27OAW.js → chunk-6RWEYSYE.js} +27 -5
  7. package/dist/chunk-6RWEYSYE.js.map +1 -0
  8. package/dist/{chunk-HU3AGUFI.mjs → chunk-NV3NNNS6.mjs} +27 -5
  9. package/dist/chunk-NV3NNNS6.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 +3 -1
  13. package/dist/components/containers/RoundPageContainer.d.ts.map +1 -1
  14. package/dist/components/index.js +2 -2
  15. package/dist/components/index.mjs +1 -1
  16. package/dist/components/typography/DetailField.d.ts +3 -1
  17. package/dist/components/typography/DetailField.d.ts.map +1 -1
  18. package/dist/contexts/index.js +2 -2
  19. package/dist/contexts/index.mjs +1 -1
  20. package/dist/email-automations/index.js +78 -78
  21. package/dist/email-automations/index.mjs +1 -1
  22. package/dist/features/analytics/index.js +107 -107
  23. package/dist/features/analytics/index.mjs +1 -1
  24. package/dist/features/blog/index.js +93 -93
  25. package/dist/features/blog/index.mjs +1 -1
  26. package/dist/features/help/index.js +31 -31
  27. package/dist/features/help/index.mjs +1 -1
  28. package/dist/features/tokenusage/index.js +102 -102
  29. package/dist/features/tokenusage/index.mjs +1 -1
  30. package/package.json +1 -1
  31. package/src/components/containers/RoundPageContainer.tsx +21 -2
  32. package/src/components/containers/__tests__/RoundPageContainer.detailsSurface.spec.tsx +82 -0
  33. package/src/components/typography/DetailField.tsx +4 -1
  34. package/src/components/typography/__tests__/DetailField.spec.tsx +13 -0
  35. package/dist/chunk-HU3AGUFI.mjs.map +0 -1
  36. package/dist/chunk-YGV27OAW.js.map +0 -1
  37. /package/dist/{BlockNoteEditor-D2DXVXTJ.mjs.map → BlockNoteEditor-2LO34HXR.mjs.map} +0 -0
@@ -119,6 +119,8 @@ type RoundPageContainerProps = {
119
119
  * navigation — an "info" icon actively misdescribes a conversation list.
120
120
  */
121
121
  detailsIcon?: ReactNode;
122
+ /** Paints the details panel on the recessed surface so cards inside it read as cards. Default "default" (unchanged). */
123
+ detailsSurface?: "default" | "muted";
122
124
  /**
123
125
  * Which element scrolls the page.
124
126
  * - `"document"` (default) — the shell's height only FLOORS at the viewport
@@ -187,6 +189,7 @@ export function RoundPageContainer({
187
189
  defaultDetailsOpen = false,
188
190
  detailsTitle,
189
191
  detailsIcon,
192
+ detailsSurface = "default",
190
193
  scroll = "fixed",
191
194
  }: RoundPageContainerProps) {
192
195
  const t = useTranslations();
@@ -702,7 +705,15 @@ export function RoundPageContainer({
702
705
  <SheetHeader>
703
706
  <SheetTitle>{detailsTitle ?? t("ui.labels.details")}</SheetTitle>
704
707
  </SheetHeader>
705
- <div className="overflow-y-auto p-6 pt-0">{details}</div>
708
+ <div
709
+ data-slot="details-body"
710
+ className={cn(
711
+ "overflow-y-auto",
712
+ detailsSurface === "muted" ? "bg-muted dark:bg-background p-3" : "p-6 pt-0",
713
+ )}
714
+ >
715
+ {details}
716
+ </div>
706
717
  </SheetContent>
707
718
  </Sheet>
708
719
  ) : (
@@ -739,7 +750,15 @@ export function RoundPageContainer({
739
750
  </div>
740
751
  </div>
741
752
  )}
742
- <div className="min-h-0 flex-1 overflow-y-auto p-4">{details}</div>
753
+ <div
754
+ data-slot="details-body"
755
+ className={cn(
756
+ "min-h-0 flex-1 overflow-y-auto",
757
+ detailsSurface === "muted" ? "bg-muted dark:bg-background p-3" : "p-4",
758
+ )}
759
+ >
760
+ {details}
761
+ </div>
743
762
  </div>
744
763
  ))}
745
764
  </div>
@@ -0,0 +1,82 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import { beforeAll, describe, expect, it, vi } from "vitest";
3
+ import { SharedProvider } from "../../../contexts/SharedContext";
4
+ import { configureI18n } from "../../../i18n";
5
+ import { RoundPageContainer } from "../../containers/RoundPageContainer";
6
+
7
+ vi.mock("next/navigation", () => ({
8
+ usePathname: () => "/",
9
+ useRouter: () => ({
10
+ push: vi.fn(),
11
+ replace: vi.fn(),
12
+ prefetch: vi.fn(),
13
+ back: vi.fn(),
14
+ forward: vi.fn(),
15
+ refresh: vi.fn(),
16
+ }),
17
+ useSearchParams: () => new URLSearchParams(),
18
+ useParams: () => ({}),
19
+ redirect: vi.fn(),
20
+ notFound: vi.fn(),
21
+ }));
22
+
23
+ beforeAll(() => {
24
+ configureI18n({
25
+ useRouter: () => ({
26
+ push: vi.fn(),
27
+ replace: vi.fn(),
28
+ back: vi.fn(),
29
+ forward: vi.fn(),
30
+ refresh: vi.fn(),
31
+ prefetch: vi.fn(),
32
+ }),
33
+ useTranslations: () => (key: string) => key,
34
+ usePathname: () => "/",
35
+ Link: ({ href, children, ...rest }: { href: string; children: React.ReactNode; [key: string]: any }) => (
36
+ <a href={href} {...rest}>
37
+ {children}
38
+ </a>
39
+ ),
40
+ });
41
+ });
42
+
43
+ function withShared(node: React.ReactNode) {
44
+ return <SharedProvider value={{ breadcrumbs: [], title: { type: "" } }}>{node}</SharedProvider>;
45
+ }
46
+
47
+ async function detailsBody(): Promise<HTMLElement> {
48
+ const content = await screen.findByText("d");
49
+ const body = content.closest<HTMLElement>('[data-slot="details-body"]');
50
+ if (!body) throw new Error("details body not found");
51
+ return body;
52
+ }
53
+
54
+ describe("RoundPageContainer details surface", () => {
55
+ it("default surface keeps the details body unpainted with p-4", async () => {
56
+ render(
57
+ withShared(
58
+ <RoundPageContainer testId="shell" details={<div>d</div>} defaultDetailsOpen>
59
+ content
60
+ </RoundPageContainer>,
61
+ ),
62
+ );
63
+ const body = await detailsBody();
64
+ expect(body.classList.contains("p-4")).toBe(true);
65
+ expect(body.classList.contains("bg-muted")).toBe(false);
66
+ });
67
+
68
+ it("muted surface paints the details body", async () => {
69
+ render(
70
+ withShared(
71
+ <RoundPageContainer testId="shell" details={<div>d</div>} defaultDetailsOpen detailsSurface="muted">
72
+ content
73
+ </RoundPageContainer>,
74
+ ),
75
+ );
76
+ const body = await detailsBody();
77
+ expect(body.classList.contains("bg-muted")).toBe(true);
78
+ expect(body.classList.contains("dark:bg-background")).toBe(true);
79
+ expect(body.classList.contains("p-3")).toBe(true);
80
+ expect(body.classList.contains("p-4")).toBe(false);
81
+ });
82
+ });
@@ -6,6 +6,8 @@ type DetailFieldProps = React.ComponentProps<"div"> & {
6
6
  value?: React.ReactNode;
7
7
  horizontal?: boolean;
8
8
  labelWidth?: string;
9
+ /** Extra classes for the value element (e.g. "min-w-0 flex-1 break-words" so long values wrap in a horizontal row). */
10
+ valueClassName?: string;
9
11
  };
10
12
 
11
13
  function DetailField({
@@ -13,6 +15,7 @@ function DetailField({
13
15
  value,
14
16
  horizontal = false,
15
17
  labelWidth,
18
+ valueClassName,
16
19
  className,
17
20
  children,
18
21
  ...props
@@ -26,7 +29,7 @@ function DetailField({
26
29
  <span className={cn("text-muted-foreground text-xs", horizontal && labelWidth && cn("shrink-0", labelWidth))}>
27
30
  {label}
28
31
  </span>
29
- <div className="text-sm">{value ?? children}</div>
32
+ <div className={cn("text-sm", valueClassName)}>{value ?? children}</div>
30
33
  </div>
31
34
  );
32
35
  }
@@ -0,0 +1,13 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import { describe, expect, it } from "vitest";
3
+ import { DetailField } from "../DetailField";
4
+
5
+ describe("DetailField", () => {
6
+ it("valueClassName lands on the value element", () => {
7
+ render(<DetailField horizontal label="L" value="V" valueClassName="min-w-0 flex-1" />);
8
+ const value = screen.getByText("V");
9
+ expect(value.classList.contains("text-sm")).toBe(true);
10
+ expect(value.classList.contains("min-w-0")).toBe(true);
11
+ expect(value.classList.contains("flex-1")).toBe(true);
12
+ });
13
+ });