@multiplatform.one/core 7.34.4 → 7.35.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplatform.one/core",
3
- "version": "7.34.4",
3
+ "version": "7.35.0",
4
4
  "description": "Core framework shell, provider composition, and layout factories for multiplatform.one",
5
5
  "keywords": [
6
6
  "app",
@@ -41,11 +41,11 @@
41
41
  "access": "public"
42
42
  },
43
43
  "dependencies": {
44
- "@multiplatform.one/i18n": "^7.34.4",
45
- "@multiplatform.one/logger": "^7.34.4",
46
- "@multiplatform.one/platform": "^7.34.4",
47
- "@multiplatform.one/store": "^7.34.4",
48
- "@multiplatform.one/theme": "^7.34.4",
44
+ "@multiplatform.one/i18n": "^7.35.0",
45
+ "@multiplatform.one/logger": "^7.35.0",
46
+ "@multiplatform.one/platform": "^7.35.0",
47
+ "@multiplatform.one/store": "^7.35.0",
48
+ "@multiplatform.one/theme": "^7.35.0",
49
49
  "@tanstack/devtools-utils": "^0.4.0",
50
50
  "@tanstack/pacer-devtools": "1.6.0",
51
51
  "@tanstack/react-devtools": "0.10.13",
@@ -53,8 +53,8 @@
53
53
  "react-cookie": "^8.1.2"
54
54
  },
55
55
  "devDependencies": {
56
- "@multiplatform.one/frappe": "7.34.4",
57
- "@multiplatform.one/web3": "7.34.4",
56
+ "@multiplatform.one/frappe": "7.35.0",
57
+ "@multiplatform.one/web3": "7.35.0",
58
58
  "@sentry/react": "^10.51.0",
59
59
  "@tanstack/react-query": "^5.104.3",
60
60
  "@tanstack/react-query-devtools": "^5.104.3",
@@ -72,10 +72,10 @@
72
72
  "vitest": "^4.1.5"
73
73
  },
74
74
  "peerDependencies": {
75
- "@multiplatform.one/frappe": "^7.34.4",
76
- "@multiplatform.one/frappe-ui": "^7.34.4",
77
- "@multiplatform.one/keycloak": "^7.34.4",
78
- "@multiplatform.one/web3": "^7.34.4",
75
+ "@multiplatform.one/frappe": "^7.35.0",
76
+ "@multiplatform.one/frappe-ui": "^7.35.0",
77
+ "@multiplatform.one/keycloak": "^7.35.0",
78
+ "@multiplatform.one/web3": "^7.35.0",
79
79
  "@sentry/react": "^9.0.0 || ^10.0.0",
80
80
  "@tanstack/react-query": "^5.0.0",
81
81
  "@tanstack/react-query-devtools": "^5.0.0",
@@ -0,0 +1,79 @@
1
+ // @vitest-environment happy-dom
2
+ import { act, cleanup, render, screen } from "@testing-library/react";
3
+ import type { ComponentType, PropsWithChildren } from "react";
4
+ import { afterEach, describe, expect, it, vi } from "vitest";
5
+ import { createApp } from "./CreateApp";
6
+
7
+ const { env, platform, provided } = vi.hoisted(() => ({
8
+ env: {} as Record<string, string>,
9
+ platform: { isWeb: true },
10
+ provided: {
11
+ current: {} as {
12
+ baseUrl?: string;
13
+ betterAuthBaseUrl?: string;
14
+ loadingComponent?: ComponentType;
15
+ },
16
+ },
17
+ }));
18
+ vi.mock("@multiplatform.one/platform", () => ({
19
+ config: { get: (key: string) => env[key] },
20
+ isDev: false,
21
+ get isWeb() {
22
+ return platform.isWeb;
23
+ },
24
+ }));
25
+ vi.mock("@multiplatform.one/theme", () => ({
26
+ ThemeProvider: ({ children }: PropsWithChildren) => children,
27
+ }));
28
+ vi.mock("@multiplatform.one/frappe-ui", () => ({
29
+ FrappeProvider: ({ children }: PropsWithChildren) => children,
30
+ }));
31
+ vi.mock("./TanstackProvider", () => ({ createTanstackProvider: vi.fn() }));
32
+ vi.mock("./loadWalletProvider", () => ({ default: () => null }));
33
+ vi.mock("one", () => ({ usePathname: () => "/", useRouter: () => ({ push: vi.fn() }) }));
34
+ vi.mock("@multiplatform.one/keycloak", () => ({
35
+ KeycloakProvider: ({ children, ...props }: PropsWithChildren<typeof provided.current>) => {
36
+ provided.current = props;
37
+ const Slot = props.loadingComponent;
38
+ return (
39
+ <>
40
+ <span>keycloak loaded</span>
41
+ {children}
42
+ {Slot && <Slot />}
43
+ </>
44
+ );
45
+ },
46
+ }));
47
+ afterEach(() => {
48
+ cleanup();
49
+ for (const key of Object.keys(env)) delete env[key];
50
+ });
51
+
52
+ describe.each([true, false])("createApp keycloak (isWeb=%s)", (isWeb) => {
53
+ it.each([
54
+ ["https://explicit.test/auth", "https://public.test/auth", "https://explicit.test/auth"],
55
+ [undefined, "https://public.test/auth", "https://public.test/auth"],
56
+ [undefined, undefined, "https://app.test/auth"],
57
+ ])("uses explicit, public, then fallback URL (%s, %s)", async (baseUrl, publicUrl, expected) => {
58
+ platform.isWeb = isWeb;
59
+ env.BASE_URL = "https://app.test";
60
+ if (publicUrl) env.KEYCLOAK_BASE_URL = publicUrl;
61
+ env.BETTER_AUTH_BASE_URL = "https://app.test/backend/prefix";
62
+ const Slot = () => <div>custom auth loading</div>;
63
+ const { AppProvider } = createApp({
64
+ keycloak: { enabled: true, baseUrl, loadingComponent: Slot },
65
+ });
66
+ await act(async () => {
67
+ render(
68
+ <AppProvider>
69
+ <span>app child</span>
70
+ </AppProvider>,
71
+ );
72
+ });
73
+ expect(screen.queryByText("keycloak loaded")).not.toBeNull();
74
+ expect(provided.current.baseUrl).toBe(expected);
75
+ expect(provided.current.betterAuthBaseUrl).toBe("https://app.test/backend/prefix");
76
+ expect(provided.current.loadingComponent).toBe(Slot);
77
+ expect(screen.queryByText("custom auth loading")).not.toBeNull();
78
+ });
79
+ });
@@ -138,6 +138,7 @@ export interface TanstackConfig {
138
138
  }
139
139
 
140
140
  export interface KeycloakConfig {
141
+ loadingComponent?: ComponentType;
141
142
  /** Force-enable or disable. When omitted, reads KEYCLOAK_ENABLED from env config. */
142
143
  enabled?: boolean;
143
144
  baseUrl?: string;
@@ -346,6 +347,7 @@ export function createApp(appConfig: CreateAppConfig) {
346
347
  messageHandlerKeys?: string[];
347
348
  betterAuthBaseUrl?: string;
348
349
  expoScheme?: string;
350
+ loadingComponent?: ComponentType;
349
351
  }>
350
352
  >,
351
353
  };
@@ -360,7 +362,11 @@ export function createApp(appConfig: CreateAppConfig) {
360
362
  <LazyKeycloakProvider
361
363
  disabled={false}
362
364
  debug={cfg.debug ?? config.get("DEBUG") === "1"}
363
- baseUrl={cfg.baseUrl || `${config.get("BASE_URL") || ""}/auth`}
365
+ baseUrl={
366
+ cfg.baseUrl ||
367
+ config.get("KEYCLOAK_BASE_URL") ||
368
+ `${config.get("BASE_URL") || ""}/auth`
369
+ }
364
370
  clientId={cfg.clientId || config.get("KEYCLOAK_CLIENT_ID")}
365
371
  publicClientId={cfg.publicClientId || config.get("KEYCLOAK_PUBLIC_CLIENT_ID")}
366
372
  realm={cfg.realm || config.get("KEYCLOAK_REALM") || ""}
@@ -374,6 +380,7 @@ export function createApp(appConfig: CreateAppConfig) {
374
380
  undefined
375
381
  }
376
382
  expoScheme={cfg.expoScheme}
383
+ loadingComponent={cfg.loadingComponent}
377
384
  >
378
385
  {children}
379
386
  </LazyKeycloakProvider>
@@ -0,0 +1,56 @@
1
+ import { renderToStaticMarkup } from "react-dom/server";
2
+ import { afterEach, describe, expect, it, vi } from "vitest";
3
+ import type { ReactNode } from "react";
4
+ import { createRootLayout } from "./CreateRootLayout.web";
5
+
6
+ vi.mock("one", () => ({
7
+ LoadProgressBar: () => null,
8
+ Slot: () => null,
9
+ useMatches: vi.fn(() => []),
10
+ SchemeProvider: ({ children }: { children: ReactNode }) => children,
11
+ setUserScheme: vi.fn(),
12
+ useUserScheme: () => ({ value: "light" }),
13
+ }));
14
+ vi.mock("i18next", () => ({
15
+ default: {
16
+ use: () => ({ init: () => Promise.resolve() }),
17
+ changeLanguage: vi.fn(),
18
+ language: "en",
19
+ },
20
+ }));
21
+ vi.mock("react-i18next", () => ({ initReactI18next: {} }));
22
+ vi.mock("@multiplatform.one/platform", () => ({
23
+ config: { get: (_key: string, fallback?: string) => fallback },
24
+ isDev: false,
25
+ platform: { isServer: false },
26
+ }));
27
+ vi.mock("@multiplatform.one/i18n", () => ({ createI18nConfig: () => ({}) }));
28
+ vi.mock("@multiplatform.one/logger", () => ({ logger: { error: vi.fn() } }));
29
+ vi.mock("@multiplatform.one/store", () => ({ storage: {} }));
30
+ vi.mock("./RuntimePublicConfigScript", () => ({ RuntimePublicConfigScript: () => null }));
31
+
32
+ function renderClientRoot() {
33
+ const Wrapper = ({ children }: { children?: ReactNode }) => children;
34
+ const Layout = createRootLayout({
35
+ AppProvider: Wrapper,
36
+ RootLayout: Wrapper,
37
+ i18n: { defaultLanguage: "en" },
38
+ } as Parameters<typeof createRootLayout>[0]);
39
+ return renderToStaticMarkup(<Layout />);
40
+ }
41
+
42
+ afterEach(() => {
43
+ vi.unstubAllGlobals();
44
+ });
45
+
46
+ describe("web root preset scale on a client render (SPA route)", () => {
47
+ it("names the cookie's preset on <html>, since the SPA shell has no head script", () => {
48
+ vi.stubGlobal("document", { cookie: "a=1; mp.preset=dense" });
49
+ expect(renderClientRoot()).toMatch(/<html[^>]*data-mp-scale="dense"/);
50
+ });
51
+
52
+ it("leaves the attribute off without a preset cookie", () => {
53
+ vi.stubGlobal("document", { cookie: "a=1" });
54
+ expect(renderClientRoot()).not.toMatch(/<html[^>]*data-mp-scale=/);
55
+ });
56
+ });
@@ -6,7 +6,7 @@ import { createRootLayout } from "./CreateRootLayout.web";
6
6
  vi.mock("one", () => ({
7
7
  LoadProgressBar: () => null,
8
8
  Slot: () => null,
9
- useMatches: () => [],
9
+ useMatches: vi.fn(() => []),
10
10
  SchemeProvider: ({ children }: { children: ReactNode }) => children,
11
11
  setUserScheme: vi.fn(),
12
12
  useUserScheme: () => ({ value: "light" }),
@@ -64,3 +64,65 @@ describe("web root title (MPO-325)", () => {
64
64
  expect(renderRoot({ favicon: "/custom.svg" })).not.toContain("<title>");
65
65
  });
66
66
  });
67
+
68
+ describe("web root preset scale (FZ-7158 WP-a2)", () => {
69
+ it("runs the scale attribute script in the head before any body content", () => {
70
+ const html = renderRoot();
71
+ const head = html.slice(html.indexOf("<head>"), html.indexOf("</head>"));
72
+ expect(head).toContain("data-mp-scale");
73
+ expect(head).toContain("mp\\.preset=");
74
+ expect(html.indexOf("mp\\.preset=")).toBeLessThan(html.indexOf("<body"));
75
+ });
76
+
77
+ it("renders <html data-mp-scale> from the request's mp.preset cookie", async () => {
78
+ const one = await import("one");
79
+ vi.mocked(one.useMatches).mockReturnValueOnce([
80
+ { loaderData: { cookieHeader: "a=1; mp.preset=dense" } },
81
+ ] as unknown as ReturnType<typeof one.useMatches>);
82
+ const html = renderRoot();
83
+ expect(html).toMatch(/<html[^>]*data-mp-scale="dense"/);
84
+ });
85
+
86
+ it("leaves the attribute off without a preset cookie", () => {
87
+ const html = renderRoot();
88
+ expect(html).not.toMatch(/<html[^>]*data-mp-scale=/);
89
+ });
90
+ });
91
+
92
+ describe("web root Inter faces (FZ-7158 WP-b3)", () => {
93
+ it("declares five faces and preloads only the four first-screen weights", () => {
94
+ const html = renderRoot({ interFonts: true });
95
+ const faces = [...html.matchAll(/@font-face\{([^}]+)\}/g)].map((match) => match[1]);
96
+ expect(faces).toHaveLength(5);
97
+ for (const weight of [400, 500, 600, 700, 800]) {
98
+ expect(faces.filter((face) => face.includes(`font-weight:${weight};`))).toEqual([
99
+ expect.stringContaining(`src:url("/fonts/inter-${weight}.woff2")`),
100
+ ]);
101
+ expect(faces.find((face) => face.includes(`font-weight:${weight};`))).toContain(
102
+ 'font-family:"Inter";font-style:normal;',
103
+ );
104
+ expect(faces.find((face) => face.includes(`font-weight:${weight};`))).toContain(
105
+ "font-display:optional;",
106
+ );
107
+ }
108
+ const preloads = (html.match(/<link\b[^>]*>/g) ?? []).filter(
109
+ (link) => link.includes('rel="preload"') && link.includes('as="font"'),
110
+ );
111
+ expect(preloads.map((link) => link.match(/href="([^"]+)"/)?.[1])).toEqual(
112
+ [400, 600, 700, 800].map((weight) => `/fonts/inter-${weight}.woff2`),
113
+ );
114
+ for (const link of preloads) {
115
+ expect(link).toContain('type="font/woff2"');
116
+ expect(link).toContain('crossorigin=""');
117
+ }
118
+ });
119
+
120
+ it("renders no Inter declarations or preloads when disabled", () => {
121
+ const html = renderRoot({ interFonts: false });
122
+ expect(html).not.toContain("@font-face");
123
+ expect(html).not.toContain("__font_inter");
124
+ for (const weight of [400, 500, 600, 700, 800]) {
125
+ expect(html).not.toContain(`/fonts/inter-${weight}.woff2`);
126
+ }
127
+ });
128
+ });
@@ -11,13 +11,18 @@ import {
11
11
  useMatches,
12
12
  useUserScheme,
13
13
  } from "one";
14
- import type { ComponentType, ReactNode } from "react";
14
+ import { type ComponentType, type ReactNode, useState } from "react";
15
15
  import { CookiesProvider, Cookies } from "react-cookie";
16
16
  import { initReactI18next } from "react-i18next";
17
17
  import { config, isDev, platform } from "@multiplatform.one/platform";
18
18
  import { createI18nConfig } from "@multiplatform.one/i18n";
19
19
  import { logger } from "@multiplatform.one/logger";
20
20
  import { storage } from "@multiplatform.one/store";
21
+ import {
22
+ cookiePreset,
23
+ scaleAttributeFromCookie,
24
+ scaleAttributeScript,
25
+ } from "@multiplatform.one/theme/scale-attribute";
21
26
  import { RuntimePublicConfigScript } from "./RuntimePublicConfigScript";
22
27
  import type { CreateRootLayoutConfig, RootLoaderData } from "./rootLayoutShared";
23
28
 
@@ -116,6 +121,17 @@ export function createRootLayout(cfg: CreateRootLayoutConfig): ComponentType {
116
121
  platform.isServer && rootLoaderData?.cookieHeader
117
122
  ? new Cookies(rootLoaderData.cookieHeader)
118
123
  : undefined;
124
+ // The preset scale's <html> attribute: server-rendered from the request
125
+ // cookie, and set by the blocking head script on cached documents. An SPA
126
+ // route's shell has no such script and its client render re-creates
127
+ // <html> with only the attributes named here, so the client reads the
128
+ // cookie once too; later switches are ThemeProvider's.
129
+ const [clientScale] = useState(() =>
130
+ platform.isServer ? undefined : scaleAttributeFromCookie(new Cookies().get(cookiePreset)),
131
+ );
132
+ const presetScale = ssrCookies
133
+ ? scaleAttributeFromCookie(ssrCookies.get(cookiePreset))
134
+ : clientScale;
119
135
 
120
136
  // Use SSR-detected language (from loader) or fall back to i18next's current language
121
137
  const htmlLang =
@@ -141,13 +157,20 @@ export function createRootLayout(cfg: CreateRootLayoutConfig): ComponentType {
141
157
  const interFonts = cfg.head?.interFonts !== false;
142
158
  const interFontCss = [
143
159
  '@font-face{font-family:"Inter";font-style:normal;font-weight:400;font-display:optional;src:url("/fonts/inter-400.woff2") format("woff2")}',
160
+ '@font-face{font-family:"Inter";font-style:normal;font-weight:500;font-display:optional;src:url("/fonts/inter-500.woff2") format("woff2")}',
161
+ '@font-face{font-family:"Inter";font-style:normal;font-weight:600;font-display:optional;src:url("/fonts/inter-600.woff2") format("woff2")}',
144
162
  '@font-face{font-family:"Inter";font-style:normal;font-weight:700;font-display:optional;src:url("/fonts/inter-700.woff2") format("woff2")}',
163
+ '@font-face{font-family:"Inter";font-style:normal;font-weight:800;font-display:optional;src:url("/fonts/inter-800.woff2") format("woff2")}',
145
164
  ].join("");
146
165
 
147
166
  return (
148
- <html lang={htmlLang} suppressHydrationWarning>
167
+ <html lang={htmlLang} data-mp-scale={presetScale} suppressHydrationWarning>
149
168
  <head>
150
169
  <meta charSet="utf-8" />
170
+ <script
171
+ dangerouslySetInnerHTML={{ __html: scaleAttributeScript }}
172
+ suppressHydrationWarning
173
+ />
151
174
  {/* RUNTIME public config, first thing after charset so it is parsed
152
175
  and executed before the deferred app bundle constructs Config.
153
176
  Without it the browser has NO path to config at all: Config's env
@@ -165,6 +188,13 @@ export function createRootLayout(cfg: CreateRootLayoutConfig): ComponentType {
165
188
  type="font/woff2"
166
189
  crossOrigin=""
167
190
  />
191
+ <link
192
+ rel="preload"
193
+ href="/fonts/inter-600.woff2"
194
+ as="font"
195
+ type="font/woff2"
196
+ crossOrigin=""
197
+ />
168
198
  <link
169
199
  rel="preload"
170
200
  href="/fonts/inter-700.woff2"
@@ -172,6 +202,13 @@ export function createRootLayout(cfg: CreateRootLayoutConfig): ComponentType {
172
202
  type="font/woff2"
173
203
  crossOrigin=""
174
204
  />
205
+ <link
206
+ rel="preload"
207
+ href="/fonts/inter-800.woff2"
208
+ as="font"
209
+ type="font/woff2"
210
+ crossOrigin=""
211
+ />
175
212
  <style precedence="reset" href="__font_inter">
176
213
  {interFontCss}
177
214
  </style>
@@ -189,7 +226,6 @@ export function createRootLayout(cfg: CreateRootLayoutConfig): ComponentType {
189
226
  "a{color:inherit;text-decoration:none}",
190
227
  "h1,h2,h3,h4,h5,h6{margin:0;padding:0}",
191
228
  "p,input,textarea,button,ul,ol,li,pre,dialog{all:unset;box-sizing:border-box}",
192
- "@keyframes skeleton-pulse{0%{opacity:1}50%{opacity:0.4}100%{opacity:1}}",
193
229
  ].join("")}
194
230
  </style>
195
231
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5" />
@@ -83,6 +83,7 @@ export interface TanstackConfig {
83
83
  onThemeColorChange?: (color: string) => void;
84
84
  }
85
85
  export interface KeycloakConfig {
86
+ loadingComponent?: ComponentType;
86
87
  /** Force-enable or disable. When omitted, reads KEYCLOAK_ENABLED from env config. */
87
88
  enabled?: boolean;
88
89
  baseUrl?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"CreateApp.d.ts","sourceRoot":"","sources":["../../src/app/CreateApp.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CreateApp.d.ts","sourceRoot":"","sources":["../../src/app/CreateApp.tsx"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { ComponentType } from "react";
1
+ import { type ComponentType } from "react";
2
2
  import type { CreateRootLayoutConfig } from "./rootLayoutShared";
3
3
  export type { CreateRootLayoutConfig, HeadConfig, RootLayoutProps, RootLoaderData, SentryConfig, } from "./rootLayoutShared";
4
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"CreateRootLayout.web.d.ts","sourceRoot":"","sources":["../../src/app/CreateRootLayout.web.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAa,MAAM,OAAO,CAAC;AAQtD,OAAO,KAAK,EAAE,sBAAsB,EAAkB,MAAM,oBAAoB,CAAC;AAEjF,YAAY,EACV,sBAAsB,EACtB,UAAU,EACV,eAAe,EACf,cAAc,EACd,YAAY,GACb,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,sBAAsB,GAAG,aAAa,CAqL3E"}
1
+ {"version":3,"file":"CreateRootLayout.web.d.ts","sourceRoot":"","sources":["../../src/app/CreateRootLayout.web.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,KAAK,aAAa,EAA4B,MAAM,OAAO,CAAC;AAarE,OAAO,KAAK,EAAE,sBAAsB,EAAkB,MAAM,oBAAoB,CAAC;AAEjF,YAAY,EACV,sBAAsB,EACtB,UAAU,EACV,eAAe,EACf,cAAc,EACd,YAAY,GACb,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,sBAAsB,GAAG,aAAa,CAoN3E"}