@kirill.konshin/mui 0.0.4 → 0.0.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
@@ -2,6 +2,12 @@
2
2
 
3
3
  MUI utilities (main entry) and Toolpad admin components (`/admin` entry).
4
4
 
5
+ # Peer versions
6
+
7
+ `@mui/material` is pinned to `^7` on purpose, even though MUI itself is already on v9: `@toolpad/core` (0.16, latest) still peers on `^7`, so v7 is the correct — and only working — choice today. Bump both together once Toolpad ships v9 support.
8
+
9
+ `@kirill.konshin/auth` is an OPTIONAL peer and is only referenced in types: the `/admin` entry has no runtime dependency on it, so `AdminAppProvider` and `AdminDashboardLayout` work in apps with no auth at all. Install `@kirill.konshin/auth` only when you use `AdminSignInPage`.
10
+
5
11
  # Admin — `@kirill.konshin/mui/admin`
6
12
 
7
13
  Preconfigured [`@toolpad/core`](https://mui.com/toolpad/core/introduction/) building blocks for password-protected admin apps, wired to [`@kirill.konshin/auth`](https://github.com/kirill-konshin/utils/tree/main/packages/auth):
@@ -78,6 +84,8 @@ export function AdminSignIn({
78
84
 
79
85
  Root layout still needs `AppRouterCacheProvider` from `@mui/material-nextjs/v15-appRouter` (with `options={{ enableCssLayer: true }}`) and your theme.
80
86
 
87
+ Wrap `AdminAppProvider` in `<Suspense>`: Toolpad's `NextAppProvider` calls `useSearchParams()`, and `cacheComponents` (set by `defineNextConfig`, see `@kirill.konshin/next`) fails the prerender of any client hook reading URL data outside a boundary.
88
+
81
89
  # Utilities (main entry)
82
90
 
83
91
  `AppBarOffset`, `FormControlFieldset`, `FormLabelLegend`, `GenericControl`, `ReadOnly` — see stories.
@@ -1 +1 @@
1
- {"version":3,"file":"dashboardLayout.js","names":[],"sources":["../../src/admin/dashboardLayout.tsx"],"sourcesContent":["'use client';\n\nimport React, { type ComponentProps, type FC, memo } from 'react';\n\nimport { DashboardLayout } from '@toolpad/core/DashboardLayout';\nimport { PageContainer } from '@toolpad/core/PageContainer';\n\nexport type AdminDashboardLayoutProps = ComponentProps<typeof DashboardLayout> & {\n /** Wrap children in Toolpad `PageContainer`, default true */\n pageContainer?: boolean;\n};\n\n// Client wrapper is mandatory: @toolpad/core ships some DashboardLayout modules without\n// 'use client' banners (AppTitle, DashboardHeader — verified still missing in 0.16), which crash\n// when evaluated in the server graph. Re-check on Toolpad upgrades.\nexport const AdminDashboardLayout: FC<AdminDashboardLayoutProps> = memo(function AdminDashboardLayout({\n children,\n pageContainer = true,\n ...props\n}) {\n return (\n <DashboardLayout defaultSidebarCollapsed {...props}>\n {pageContainer ? <PageContainer>{children}</PageContainer> : children}\n </DashboardLayout>\n );\n});\n"],"mappings":";;;;;;AAeA,IAAa,uBAAsD,KAAK,SAAS,qBAAqB,EAClG,UACA,gBAAgB,MAChB,GAAG,SACJ;CACC,OACI,oBAAC,iBAAD;EAAiB,yBAAA;EAAwB,GAAI;YACxC,gBAAgB,oBAAC,eAAD,EAAgB,SAAwB,CAAA,IAAI;CAChD,CAAA;AAEzB,CAAC"}
1
+ {"version":3,"file":"dashboardLayout.js","names":[],"sources":["../../src/admin/dashboardLayout.tsx"],"sourcesContent":["'use client';\n\nimport React, { type ComponentProps, type FC, memo } from 'react';\n\nimport { DashboardLayout } from '@toolpad/core/DashboardLayout';\nimport { PageContainer } from '@toolpad/core/PageContainer';\n\nexport type AdminDashboardLayoutProps = ComponentProps<typeof DashboardLayout> & {\n /** Wrap children in Toolpad `PageContainer`, default true */\n pageContainer?: boolean;\n};\n\n// Client wrapper is mandatory: @toolpad/core ships some DashboardLayout modules without\n// 'use client' banners (AppTitle, DashboardHeader — verified still missing in 0.16), which crash\n// when evaluated in the server graph. Re-check on Toolpad upgrades.\nexport const AdminDashboardLayout: FC<AdminDashboardLayoutProps> = memo(function AdminDashboardLayout({\n children,\n pageContainer = true,\n ...props\n}) {\n return (\n <DashboardLayout defaultSidebarCollapsed {...props}>\n {pageContainer ? <PageContainer>{children}</PageContainer> : children}\n </DashboardLayout>\n );\n});\n"],"mappings":";;;;;;AAeA,IAAa,uBAAsD,KAAK,SAAS,qBAAqB,EAClG,UACA,gBAAgB,MAChB,GAAG,SACJ;CACC,OACI,oBAAC,iBAAD;EAAiB,yBAAA;EAAwB,GAAI;EACxC,UAAA,gBAAgB,oBAAC,eAAD,EAAgB,SAAwB,CAAA,IAAI;CAChD,CAAA;AAEzB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"signInPage.d.ts","sourceRoot":"","sources":["../../src/admin/signInPage.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAE,KAAK,cAAc,EAAE,KAAK,EAAE,EAAqB,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,KAAK,eAAe,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,CAAC;AAEzD,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,GAAG;IACjE,iGAAiG;IACjG,WAAW,EAAE,YAAY,CAAC,iBAAiB,CAAC,CAAC;IAC7C,gGAAgG;IAChG,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yCAAyC;IACzC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,oBAAoB,CA2DnD,CAAC"}
1
+ {"version":3,"file":"signInPage.d.ts","sourceRoot":"","sources":["../../src/admin/signInPage.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAE,KAAK,cAAc,EAAE,KAAK,EAAE,EAAqB,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,KAAK,eAAe,GAAG,cAAc,CAAC,OAAO,UAAU,CAAC,CAAC;AAEzD,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,GAAG;IACjE,iGAAiG;IACjG,WAAW,EAAE,YAAY,CAAC,iBAAiB,CAAC,CAAC;IAC7C,gGAAgG;IAChG,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yCAAyC;IACzC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAcF;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,oBAAoB,CA2DnD,CAAC"}
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import { memo, useCallback } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
- import { STATE_PARAM } from "@kirill.konshin/auth/client";
5
4
  import { formLabelClasses } from "@mui/material/FormLabel";
6
5
  import { SignInPage } from "@toolpad/core/SignInPage";
7
6
  //#region src/admin/signInPage.tsx
7
+ var STATE_PARAM = "state";
8
8
  var DEFAULT_PROVIDERS = [{
9
9
  id: "credentials",
10
10
  name: "password"
@@ -16,13 +16,14 @@ var NOT_CONFIGURED_SUBTITLE = "Set ADMIN_PASSWORD and a SESSION_SECRET of at lea
16
16
  * `loginAction` redirects (handled by Next.js), on failure its message is shown.
17
17
  */
18
18
  var AdminSignInPage = memo(function AdminSignInPage({ loginAction, isConfigured = true, notConfiguredSubtitle = NOT_CONFIGURED_SUBTITLE, providers = DEFAULT_PROVIDERS, state, localeText, slots, slotProps, ...props }) {
19
+ const signIn = useCallback(async (_provider, formData) => {
20
+ if (!(formData instanceof FormData)) return { error: "Password is required" };
21
+ if (state) formData.set(STATE_PARAM, state);
22
+ const error = await loginAction(null, formData);
23
+ return error ? { error } : {};
24
+ }, [loginAction, state]);
19
25
  return /* @__PURE__ */ jsx(SignInPage, {
20
- signIn: useCallback(async (_provider, formData) => {
21
- if (!(formData instanceof FormData)) return { error: "Password is required" };
22
- if (state) formData.set(STATE_PARAM, state);
23
- const error = await loginAction(null, formData);
24
- return error ? { error } : {};
25
- }, [loginAction, state]),
26
+ signIn,
26
27
  providers: isConfigured ? providers : [],
27
28
  localeText: isConfigured ? localeText : {
28
29
  signInTitle: "Authentication needs configuration",
@@ -1 +1 @@
1
- {"version":3,"file":"signInPage.js","names":[],"sources":["../../src/admin/signInPage.tsx"],"sourcesContent":["'use client';\n\nimport React, { type ComponentProps, type FC, memo, useCallback } from 'react';\n\nimport { type PasswordAuth } from '@kirill.konshin/auth';\nimport { STATE_PARAM } from '@kirill.konshin/auth/client';\nimport { formLabelClasses } from '@mui/material/FormLabel';\nimport { SignInPage } from '@toolpad/core/SignInPage';\n\ntype SignInPageProps = ComponentProps<typeof SignInPage>;\n\nexport type AdminSignInPageProps = Omit<SignInPageProps, 'signIn'> & {\n /** `auth.loginFormAction` from `@kirill.konshin/auth`, re-exported from a `'use server'` file */\n loginAction: PasswordAuth['loginFormAction'];\n /** Pass `auth.isConfigured()` to render setup instructions instead of the form, default true */\n isConfigured?: boolean;\n /** Subtitle shown when not configured */\n notConfiguredSubtitle?: string;\n /** Sanitized return URL (`auth.getState(await searchParams)`), threaded into the login form */\n state?: string;\n};\n\nconst DEFAULT_PROVIDERS: SignInPageProps['providers'] = [{ id: 'credentials', name: 'password' }];\n\nconst NOT_CONFIGURED_SUBTITLE = 'Set ADMIN_PASSWORD and a SESSION_SECRET of at least 32 characters, then restart.';\n\n/**\n * Toolpad `SignInPage` preconfigured for the password-only login of `@kirill.konshin/auth`: single\n * credentials provider, no email/rememberMe fields, errors surfaced through the form. On success\n * `loginAction` redirects (handled by Next.js), on failure its message is shown.\n */\nexport const AdminSignInPage: FC<AdminSignInPageProps> = memo(function AdminSignInPage({\n loginAction,\n isConfigured = true,\n notConfiguredSubtitle = NOT_CONFIGURED_SUBTITLE,\n providers = DEFAULT_PROVIDERS,\n state,\n localeText,\n slots,\n slotProps,\n ...props\n}) {\n const signIn = useCallback<NonNullable<SignInPageProps['signIn']>>(\n async (_provider, formData) => {\n if (!(formData instanceof FormData)) return { error: 'Password is required' };\n // thread the return URL through the form only — never store it in the session,\n // multiple tabs logging in concurrently would clash\n if (state) formData.set(STATE_PARAM, state);\n const error = await loginAction(null, formData);\n return error ? { error } : {};\n },\n [loginAction, state],\n );\n\n return (\n <SignInPage\n signIn={signIn}\n providers={isConfigured ? providers : []}\n localeText={\n isConfigured\n ? localeText\n : {\n signInTitle: 'Authentication needs configuration',\n signInSubtitle: notConfiguredSubtitle,\n ...localeText,\n }\n }\n slots={{\n emailField: () => null,\n rememberMe: () => null,\n subtitle: () => null,\n ...slots,\n }}\n slotProps={{\n ...slotProps,\n // FIXME https://github.com/mui/toolpad/issues/4572 — still relevant in 0.16:\n // browser validation popups fight the server-side errors (noValidate is settable\n // declaratively through the form slot) and the password label renders misaligned;\n // re-check on Toolpad upgrades\n form: { noValidate: true, ...slotProps?.form },\n passwordField: {\n autoFocus: true,\n sx: { [`& .${formLabelClasses.root}`]: { top: '-2px' } },\n ...slotProps?.passwordField,\n },\n submitButton: { variant: 'contained', ...slotProps?.submitButton },\n }}\n {...props}\n />\n );\n});\n"],"mappings":";;;;;;;AAsBA,IAAM,oBAAkD,CAAC;CAAE,IAAI;CAAe,MAAM;AAAW,CAAC;AAEhG,IAAM,0BAA0B;;;;;;AAOhC,IAAa,kBAA4C,KAAK,SAAS,gBAAgB,EACnF,aACA,eAAe,MACf,wBAAwB,yBACxB,YAAY,mBACZ,OACA,YACA,OACA,WACA,GAAG,SACJ;CAaC,OACI,oBAAC,YAAD;EACY,QAdD,YACX,OAAO,WAAW,aAAa;GAC3B,IAAI,EAAE,oBAAoB,WAAW,OAAO,EAAE,OAAO,uBAAuB;GAG5E,IAAI,OAAO,SAAS,IAAI,aAAa,KAAK;GAC1C,MAAM,QAAQ,MAAM,YAAY,MAAM,QAAQ;GAC9C,OAAO,QAAQ,EAAE,MAAM,IAAI,CAAC;EAChC,GACA,CAAC,aAAa,KAAK,CAKP;EACR,WAAW,eAAe,YAAY,CAAC;EACvC,YACI,eACM,aACA;GACI,aAAa;GACb,gBAAgB;GAChB,GAAG;EACP;EAEV,OAAO;GACH,kBAAkB;GAClB,kBAAkB;GAClB,gBAAgB;GAChB,GAAG;EACP;EACA,WAAW;GACP,GAAG;GAKH,MAAM;IAAE,YAAY;IAAM,GAAG,WAAW;GAAK;GAC7C,eAAe;IACX,WAAW;IACX,IAAI,GAAG,MAAM,iBAAiB,SAAS,EAAE,KAAK,OAAO,EAAE;IACvD,GAAG,WAAW;GAClB;GACA,cAAc;IAAE,SAAS;IAAa,GAAG,WAAW;GAAa;EACrE;EACA,GAAI;CACP,CAAA;AAET,CAAC"}
1
+ {"version":3,"file":"signInPage.js","names":[],"sources":["../../src/admin/signInPage.tsx"],"sourcesContent":["'use client';\n\nimport React, { type ComponentProps, type FC, memo, useCallback } from 'react';\n\nimport { type PasswordAuth } from '@kirill.konshin/auth';\nimport type { STATE_PARAM as StateParam } from '@kirill.konshin/auth/client';\nimport { formLabelClasses } from '@mui/material/FormLabel';\nimport { SignInPage } from '@toolpad/core/SignInPage';\n\ntype SignInPageProps = ComponentProps<typeof SignInPage>;\n\nexport type AdminSignInPageProps = Omit<SignInPageProps, 'signIn'> & {\n /** `auth.loginFormAction` from `@kirill.konshin/auth`, re-exported from a `'use server'` file */\n loginAction: PasswordAuth['loginFormAction'];\n /** Pass `auth.isConfigured()` to render setup instructions instead of the form, default true */\n isConfigured?: boolean;\n /** Subtitle shown when not configured */\n notConfiguredSubtitle?: string;\n /** Sanitized return URL (`auth.getState(await searchParams)`), threaded into the login form */\n state?: string;\n};\n\n/*\n * Inlined, NOT imported at runtime: `@kirill.konshin/auth` is an OPTIONAL peer, so importing\n * `@kirill.konshin/auth/client` here would make the whole `/admin` entry unresolvable in apps that\n * only use `AdminAppProvider`/`AdminDashboardLayout` (the barrel re-exports this module). The\n * annotation is a compile-time guard: it stops resolving the day auth renames the param.\n */\nconst STATE_PARAM: typeof StateParam = 'state';\n\nconst DEFAULT_PROVIDERS: SignInPageProps['providers'] = [{ id: 'credentials', name: 'password' }];\n\nconst NOT_CONFIGURED_SUBTITLE = 'Set ADMIN_PASSWORD and a SESSION_SECRET of at least 32 characters, then restart.';\n\n/**\n * Toolpad `SignInPage` preconfigured for the password-only login of `@kirill.konshin/auth`: single\n * credentials provider, no email/rememberMe fields, errors surfaced through the form. On success\n * `loginAction` redirects (handled by Next.js), on failure its message is shown.\n */\nexport const AdminSignInPage: FC<AdminSignInPageProps> = memo(function AdminSignInPage({\n loginAction,\n isConfigured = true,\n notConfiguredSubtitle = NOT_CONFIGURED_SUBTITLE,\n providers = DEFAULT_PROVIDERS,\n state,\n localeText,\n slots,\n slotProps,\n ...props\n}) {\n const signIn = useCallback<NonNullable<SignInPageProps['signIn']>>(\n async (_provider, formData) => {\n if (!(formData instanceof FormData)) return { error: 'Password is required' };\n // thread the return URL through the form only — never store it in the session,\n // multiple tabs logging in concurrently would clash\n if (state) formData.set(STATE_PARAM, state);\n const error = await loginAction(null, formData);\n return error ? { error } : {};\n },\n [loginAction, state],\n );\n\n return (\n <SignInPage\n signIn={signIn}\n providers={isConfigured ? providers : []}\n localeText={\n isConfigured\n ? localeText\n : {\n signInTitle: 'Authentication needs configuration',\n signInSubtitle: notConfiguredSubtitle,\n ...localeText,\n }\n }\n slots={{\n emailField: () => null,\n rememberMe: () => null,\n subtitle: () => null,\n ...slots,\n }}\n slotProps={{\n ...slotProps,\n // FIXME https://github.com/mui/toolpad/issues/4572 — still relevant in 0.16:\n // browser validation popups fight the server-side errors (noValidate is settable\n // declaratively through the form slot) and the password label renders misaligned;\n // re-check on Toolpad upgrades\n form: { noValidate: true, ...slotProps?.form },\n passwordField: {\n autoFocus: true,\n sx: { [`& .${formLabelClasses.root}`]: { top: '-2px' } },\n ...slotProps?.passwordField,\n },\n submitButton: { variant: 'contained', ...slotProps?.submitButton },\n }}\n {...props}\n />\n );\n});\n"],"mappings":";;;;;;AA4BA,IAAM,cAAiC;AAEvC,IAAM,oBAAkD,CAAC;CAAE,IAAI;CAAe,MAAM;AAAW,CAAC;AAEhG,IAAM,0BAA0B;;;;;;AAOhC,IAAa,kBAA4C,KAAK,SAAS,gBAAgB,EACnF,aACA,eAAe,MACf,wBAAwB,yBACxB,YAAY,mBACZ,OACA,YACA,OACA,WACA,GAAG,SACJ;CACC,MAAM,SAAS,YACX,OAAO,WAAW,aAAa;EAC3B,IAAI,EAAE,oBAAoB,WAAW,OAAO,EAAE,OAAO,uBAAuB;EAG5E,IAAI,OAAO,SAAS,IAAI,aAAa,KAAK;EAC1C,MAAM,QAAQ,MAAM,YAAY,MAAM,QAAQ;EAC9C,OAAO,QAAQ,EAAE,MAAM,IAAI,CAAC;CAChC,GACA,CAAC,aAAa,KAAK,CACvB;CAEA,OACI,oBAAC,YAAD;EACY;EACR,WAAW,eAAe,YAAY,CAAC;EACvC,YACI,eACM,aACA;GACI,aAAa;GACb,gBAAgB;GAChB,GAAG;EACP;EAEV,OAAO;GACH,kBAAkB;GAClB,kBAAkB;GAClB,gBAAgB;GAChB,GAAG;EACP;EACA,WAAW;GACP,GAAG;GAKH,MAAM;IAAE,YAAY;IAAM,GAAG,WAAW;GAAK;GAC7C,eAAe;IACX,WAAW;IACX,IAAI,GAAG,MAAM,iBAAiB,SAAS,EAAE,KAAK,OAAO,EAAE;IACvD,GAAG,WAAW;GAClB;GACA,cAAc;IAAE,SAAS;IAAa,GAAG,WAAW;GAAa;EACrE;EACA,GAAI;CACP,CAAA;AAET,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kirill.konshin/mui",
3
3
  "description": "Utilities",
4
- "version": "0.0.4",
4
+ "version": "0.0.5",
5
5
  "type": "module",
6
6
  "hasStorybook": true,
7
7
  "scripts": {
@@ -19,17 +19,17 @@
19
19
  },
20
20
  "devDependencies": {
21
21
  "@emotion/react": "^11.14.0",
22
- "@emotion/styled": "^11.14.0",
22
+ "@emotion/styled": "^11.14.1",
23
23
  "@kirill.konshin/auth": "*",
24
24
  "@kirill.konshin/utils-private": "*",
25
- "@mui/material": "^7.3.0",
25
+ "@mui/material": "^9.3.1",
26
26
  "@toolpad/core": "^0.16.0",
27
- "next": "^16.2.12",
28
- "react": "^19.1.1"
27
+ "next": "^16.3.0",
28
+ "react": "^19.2.8"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@kirill.konshin/auth": "*",
32
- "@mui/material": "^7",
32
+ "@mui/material": "^9",
33
33
  "@toolpad/core": "^0.16",
34
34
  "next": "^16",
35
35
  "react": "^19"
@@ -57,17 +57,15 @@
57
57
  "author": "Kirill Konshin <kirill@konshin.org> (https://konshin.org)",
58
58
  "license": "MIT",
59
59
  "exports": {
60
- "./admin": {
61
- "import": {
62
- "import": "./dist/admin/index.js",
63
- "types": "./dist/admin/index.d.ts"
64
- }
65
- },
66
60
  ".": {
67
- "import": {
68
- "import": "./dist/index.js",
69
- "types": "./dist/index.d.ts"
70
- }
61
+ "types": "./dist/index.d.ts",
62
+ "import": "./dist/index.js",
63
+ "default": "./dist/index.js"
64
+ },
65
+ "./admin": {
66
+ "types": "./dist/admin/index.d.ts",
67
+ "import": "./dist/admin/index.js",
68
+ "default": "./dist/admin/index.js"
71
69
  }
72
70
  },
73
71
  "main": "./dist/index.js",