@chemmangat/msal-next 4.2.2 → 5.0.1
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/CHANGELOG.md +85 -0
- package/README.md +27 -1
- package/dist/index.d.mts +42 -2
- package/dist/index.d.ts +42 -2
- package/dist/index.js +39 -35
- package/dist/index.mjs +39 -35
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,91 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [5.0.0] - 2026-03-16
|
|
6
|
+
|
|
7
|
+
### ⚠️ Breaking Changes
|
|
8
|
+
|
|
9
|
+
- **Node.js 18+ required** — The CLI and codemod tools require Node.js 18 or higher.
|
|
10
|
+
- **CLI package renamed** — `@chemmangat/msal-next-cli` is now the canonical CLI package, invokable via `npx @chemmangat/msal-next init`.
|
|
11
|
+
- **Codemod is a breaking addition** — Running `npx @chemmangat/msal-next migrate` will rewrite popup API calls in your project. Review changes with `git diff` before committing.
|
|
12
|
+
|
|
13
|
+
### ✨ New Features
|
|
14
|
+
|
|
15
|
+
#### 1. Interactive CLI — `npx @chemmangat/msal-next init`
|
|
16
|
+
The `init` command now interactively collects all required configuration:
|
|
17
|
+
- Azure AD **Client ID** and **Tenant ID**
|
|
18
|
+
- **Authority type** (`common`, `organizations`, `consumers`, `tenant`)
|
|
19
|
+
- **Cache location** (`sessionStorage`, `localStorage`, `memoryStorage`)
|
|
20
|
+
|
|
21
|
+
After collecting answers it automatically:
|
|
22
|
+
- Creates `.env.local` with all environment variables
|
|
23
|
+
- Updates (or creates) `app/layout.tsx` with `MSALProvider` wired up
|
|
24
|
+
- Creates a starter `app/auth/page.tsx` using `useMsalAuth` and `MicrosoftSignInButton`
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npx @chemmangat/msal-next init
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### 2. UI Component Slots — `renderAccount` prop
|
|
31
|
+
Both `AccountSwitcher` and `AccountList` now accept a `renderAccount` render prop that lets consumers fully customize how each account row is displayed.
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<AccountSwitcher
|
|
35
|
+
renderAccount={(account, isActive) => (
|
|
36
|
+
<div style={{ fontWeight: isActive ? 'bold' : 'normal' }}>
|
|
37
|
+
{account.name} — {account.username}
|
|
38
|
+
</div>
|
|
39
|
+
)}
|
|
40
|
+
/>
|
|
41
|
+
|
|
42
|
+
<AccountList
|
|
43
|
+
renderAccount={(account, isActive) => (
|
|
44
|
+
<span>{account.name} {isActive ? '✓' : ''}</span>
|
|
45
|
+
)}
|
|
46
|
+
/>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### 3. Comprehensive Test Coverage (80%+)
|
|
50
|
+
Full Vitest + `@testing-library/react` test suite covering:
|
|
51
|
+
- All hooks: `useMsalAuth`, `useUserProfile`, `useRoles`, `useTokenRefresh`, `useMultiAccount`, `useGraphApi`
|
|
52
|
+
- All components: `MicrosoftSignInButton`, `SignOutButton`, `UserAvatar`, `AuthStatus`, `AuthGuard`, `AccountSwitcher`, `AccountList`
|
|
53
|
+
|
|
54
|
+
Run tests:
|
|
55
|
+
```bash
|
|
56
|
+
npm test # single run
|
|
57
|
+
npm run test:coverage # with coverage report
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### 4. Codemod — `npx @chemmangat/msal-next migrate`
|
|
61
|
+
Scans your project and replaces deprecated popup API calls with their redirect equivalents:
|
|
62
|
+
|
|
63
|
+
| Before | After |
|
|
64
|
+
|--------|-------|
|
|
65
|
+
| `loginPopup()` | `loginRedirect()` |
|
|
66
|
+
| `logoutPopup()` | `logoutRedirect()` |
|
|
67
|
+
| `acquireTokenPopup()` | `acquireTokenRedirect()` |
|
|
68
|
+
| `useRedirect={false}` | *(removed)* |
|
|
69
|
+
|
|
70
|
+
Prints a summary of all files modified and occurrences replaced.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npx @chemmangat/msal-next migrate
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 🔄 Migration from v4.x
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm install @chemmangat/msal-next@5.0.0
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
If you have any popup API usage, run the codemod:
|
|
83
|
+
```bash
|
|
84
|
+
npx @chemmangat/msal-next migrate
|
|
85
|
+
git diff # review changes
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
5
90
|
## [4.2.0] - 2026-03-08
|
|
6
91
|
|
|
7
92
|
### 🎉 Major Feature Release - Multi-Account Management
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Microsoft/Azure AD authentication for Next.js App Router. Minimal setup, full Ty
|
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](./SECURITY.md)
|
|
8
8
|
|
|
9
|
-
**Current version:
|
|
9
|
+
**Current version: 5.0.0**
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -16,6 +16,20 @@ Microsoft/Azure AD authentication for Next.js App Router. Minimal setup, full Ty
|
|
|
16
16
|
npm install @chemmangat/msal-next @azure/msal-browser @azure/msal-react
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
Or scaffold everything automatically with the CLI (Node.js 18+ required):
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @chemmangat/msal-next-cli init
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The `init` command interactively asks for your client ID, tenant ID, authority type, and cache location, then creates `.env.local`, updates `app/layout.tsx` with `MSALProvider`, and generates a starter `app/auth/page.tsx`.
|
|
26
|
+
|
|
27
|
+
To migrate an existing project from popup-based auth to redirect:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx @chemmangat/msal-next-cli migrate
|
|
31
|
+
```
|
|
32
|
+
|
|
19
33
|
---
|
|
20
34
|
|
|
21
35
|
## Quick Start
|
|
@@ -179,6 +193,12 @@ Protects content and redirects unauthenticated users to login.
|
|
|
179
193
|
onSwitch={(account) => {}}
|
|
180
194
|
onAdd={() => {}}
|
|
181
195
|
onRemove={(account) => {}}
|
|
196
|
+
// v5.0.0 — custom account row rendering
|
|
197
|
+
renderAccount={(account, isActive) => (
|
|
198
|
+
<div style={{ fontWeight: isActive ? 'bold' : 'normal' }}>
|
|
199
|
+
{account.name} ({account.username})
|
|
200
|
+
</div>
|
|
201
|
+
)}
|
|
182
202
|
/>
|
|
183
203
|
```
|
|
184
204
|
|
|
@@ -192,6 +212,12 @@ Protects content and redirects unauthenticated users to login.
|
|
|
192
212
|
clickToSwitch
|
|
193
213
|
orientation="vertical" // 'vertical' | 'horizontal'
|
|
194
214
|
onAccountClick={(account) => {}}
|
|
215
|
+
// v5.0.0 — custom account row rendering
|
|
216
|
+
renderAccount={(account, isActive) => (
|
|
217
|
+
<div style={{ color: isActive ? 'blue' : 'black' }}>
|
|
218
|
+
{account.name} — {account.username}
|
|
219
|
+
</div>
|
|
220
|
+
)}
|
|
195
221
|
/>
|
|
196
222
|
```
|
|
197
223
|
|
package/dist/index.d.mts
CHANGED
|
@@ -741,6 +741,26 @@ interface AccountSwitcherProps {
|
|
|
741
741
|
* @defaultValue true
|
|
742
742
|
*/
|
|
743
743
|
showRemoveButton?: boolean;
|
|
744
|
+
/**
|
|
745
|
+
* Custom render function for each account item in the dropdown.
|
|
746
|
+
* When provided, replaces the default account row rendering.
|
|
747
|
+
*
|
|
748
|
+
* @param account - The AccountInfo for this row
|
|
749
|
+
* @param isActive - Whether this account is the currently active account
|
|
750
|
+
* @returns ReactNode to render in place of the default row
|
|
751
|
+
*
|
|
752
|
+
* @example
|
|
753
|
+
* ```tsx
|
|
754
|
+
* <AccountSwitcher
|
|
755
|
+
* renderAccount={(account, isActive) => (
|
|
756
|
+
* <div style={{ fontWeight: isActive ? 'bold' : 'normal' }}>
|
|
757
|
+
* {account.name} ({account.username})
|
|
758
|
+
* </div>
|
|
759
|
+
* )}
|
|
760
|
+
* />
|
|
761
|
+
* ```
|
|
762
|
+
*/
|
|
763
|
+
renderAccount?: (account: AccountInfo, isActive: boolean) => ReactNode;
|
|
744
764
|
}
|
|
745
765
|
/**
|
|
746
766
|
* Account Switcher Component
|
|
@@ -769,7 +789,7 @@ interface AccountSwitcherProps {
|
|
|
769
789
|
* }
|
|
770
790
|
* ```
|
|
771
791
|
*/
|
|
772
|
-
declare function AccountSwitcher({ showAvatars, maxAccounts, onSwitch, onAdd, onRemove, className, style, variant, showAddButton, showRemoveButton, }: AccountSwitcherProps): react_jsx_runtime.JSX.Element | null;
|
|
792
|
+
declare function AccountSwitcher({ showAvatars, maxAccounts, onSwitch, onAdd, onRemove, className, style, variant, showAddButton, showRemoveButton, renderAccount, }: AccountSwitcherProps): react_jsx_runtime.JSX.Element | null;
|
|
773
793
|
|
|
774
794
|
interface AccountListProps {
|
|
775
795
|
/**
|
|
@@ -809,6 +829,26 @@ interface AccountListProps {
|
|
|
809
829
|
* @defaultValue 'vertical'
|
|
810
830
|
*/
|
|
811
831
|
orientation?: 'vertical' | 'horizontal';
|
|
832
|
+
/**
|
|
833
|
+
* Custom render function for each account item.
|
|
834
|
+
* When provided, replaces the default account row rendering.
|
|
835
|
+
*
|
|
836
|
+
* @param account - The AccountInfo for this row
|
|
837
|
+
* @param isActive - Whether this account is the currently active account
|
|
838
|
+
* @returns ReactNode to render in place of the default row content
|
|
839
|
+
*
|
|
840
|
+
* @example
|
|
841
|
+
* ```tsx
|
|
842
|
+
* <AccountList
|
|
843
|
+
* renderAccount={(account, isActive) => (
|
|
844
|
+
* <div style={{ color: isActive ? 'blue' : 'black' }}>
|
|
845
|
+
* {account.name} — {account.username}
|
|
846
|
+
* </div>
|
|
847
|
+
* )}
|
|
848
|
+
* />
|
|
849
|
+
* ```
|
|
850
|
+
*/
|
|
851
|
+
renderAccount?: (account: AccountInfo, isActive: boolean) => ReactNode;
|
|
812
852
|
}
|
|
813
853
|
/**
|
|
814
854
|
* Account List Component
|
|
@@ -838,7 +878,7 @@ interface AccountListProps {
|
|
|
838
878
|
* }
|
|
839
879
|
* ```
|
|
840
880
|
*/
|
|
841
|
-
declare function AccountList({ showAvatars, showDetails, showActiveIndicator, clickToSwitch, onAccountClick, className, style, orientation, }: AccountListProps): react_jsx_runtime.JSX.Element;
|
|
881
|
+
declare function AccountList({ showAvatars, showDetails, showActiveIndicator, clickToSwitch, onAccountClick, className, style, orientation, renderAccount, }: AccountListProps): react_jsx_runtime.JSX.Element;
|
|
842
882
|
|
|
843
883
|
interface UseMsalAuthReturn {
|
|
844
884
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -741,6 +741,26 @@ interface AccountSwitcherProps {
|
|
|
741
741
|
* @defaultValue true
|
|
742
742
|
*/
|
|
743
743
|
showRemoveButton?: boolean;
|
|
744
|
+
/**
|
|
745
|
+
* Custom render function for each account item in the dropdown.
|
|
746
|
+
* When provided, replaces the default account row rendering.
|
|
747
|
+
*
|
|
748
|
+
* @param account - The AccountInfo for this row
|
|
749
|
+
* @param isActive - Whether this account is the currently active account
|
|
750
|
+
* @returns ReactNode to render in place of the default row
|
|
751
|
+
*
|
|
752
|
+
* @example
|
|
753
|
+
* ```tsx
|
|
754
|
+
* <AccountSwitcher
|
|
755
|
+
* renderAccount={(account, isActive) => (
|
|
756
|
+
* <div style={{ fontWeight: isActive ? 'bold' : 'normal' }}>
|
|
757
|
+
* {account.name} ({account.username})
|
|
758
|
+
* </div>
|
|
759
|
+
* )}
|
|
760
|
+
* />
|
|
761
|
+
* ```
|
|
762
|
+
*/
|
|
763
|
+
renderAccount?: (account: AccountInfo, isActive: boolean) => ReactNode;
|
|
744
764
|
}
|
|
745
765
|
/**
|
|
746
766
|
* Account Switcher Component
|
|
@@ -769,7 +789,7 @@ interface AccountSwitcherProps {
|
|
|
769
789
|
* }
|
|
770
790
|
* ```
|
|
771
791
|
*/
|
|
772
|
-
declare function AccountSwitcher({ showAvatars, maxAccounts, onSwitch, onAdd, onRemove, className, style, variant, showAddButton, showRemoveButton, }: AccountSwitcherProps): react_jsx_runtime.JSX.Element | null;
|
|
792
|
+
declare function AccountSwitcher({ showAvatars, maxAccounts, onSwitch, onAdd, onRemove, className, style, variant, showAddButton, showRemoveButton, renderAccount, }: AccountSwitcherProps): react_jsx_runtime.JSX.Element | null;
|
|
773
793
|
|
|
774
794
|
interface AccountListProps {
|
|
775
795
|
/**
|
|
@@ -809,6 +829,26 @@ interface AccountListProps {
|
|
|
809
829
|
* @defaultValue 'vertical'
|
|
810
830
|
*/
|
|
811
831
|
orientation?: 'vertical' | 'horizontal';
|
|
832
|
+
/**
|
|
833
|
+
* Custom render function for each account item.
|
|
834
|
+
* When provided, replaces the default account row rendering.
|
|
835
|
+
*
|
|
836
|
+
* @param account - The AccountInfo for this row
|
|
837
|
+
* @param isActive - Whether this account is the currently active account
|
|
838
|
+
* @returns ReactNode to render in place of the default row content
|
|
839
|
+
*
|
|
840
|
+
* @example
|
|
841
|
+
* ```tsx
|
|
842
|
+
* <AccountList
|
|
843
|
+
* renderAccount={(account, isActive) => (
|
|
844
|
+
* <div style={{ color: isActive ? 'blue' : 'black' }}>
|
|
845
|
+
* {account.name} — {account.username}
|
|
846
|
+
* </div>
|
|
847
|
+
* )}
|
|
848
|
+
* />
|
|
849
|
+
* ```
|
|
850
|
+
*/
|
|
851
|
+
renderAccount?: (account: AccountInfo, isActive: boolean) => ReactNode;
|
|
812
852
|
}
|
|
813
853
|
/**
|
|
814
854
|
* Account List Component
|
|
@@ -838,7 +878,7 @@ interface AccountListProps {
|
|
|
838
878
|
* }
|
|
839
879
|
* ```
|
|
840
880
|
*/
|
|
841
|
-
declare function AccountList({ showAvatars, showDetails, showActiveIndicator, clickToSwitch, onAccountClick, className, style, orientation, }: AccountListProps): react_jsx_runtime.JSX.Element;
|
|
881
|
+
declare function AccountList({ showAvatars, showDetails, showActiveIndicator, clickToSwitch, onAccountClick, className, style, orientation, renderAccount, }: AccountListProps): react_jsx_runtime.JSX.Element;
|
|
842
882
|
|
|
843
883
|
interface UseMsalAuthReturn {
|
|
844
884
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1918,7 +1918,8 @@ function AccountSwitcher({
|
|
|
1918
1918
|
style,
|
|
1919
1919
|
variant = "default",
|
|
1920
1920
|
showAddButton = true,
|
|
1921
|
-
showRemoveButton = true
|
|
1921
|
+
showRemoveButton = true,
|
|
1922
|
+
renderAccount
|
|
1922
1923
|
}) {
|
|
1923
1924
|
const {
|
|
1924
1925
|
accounts,
|
|
@@ -2101,40 +2102,42 @@ function AccountSwitcher({
|
|
|
2101
2102
|
}
|
|
2102
2103
|
},
|
|
2103
2104
|
children: [
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.
|
|
2107
|
-
|
|
2108
|
-
|
|
2105
|
+
renderAccount ? renderAccount(account, isActiveAccount(account)) : /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
2106
|
+
showAvatars && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: avatarStyle, children: getInitials(account.name) }),
|
|
2107
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
2108
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: { fontWeight: "500", fontSize: "14px" }, children: account.name || account.username }),
|
|
2109
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2110
|
+
"div",
|
|
2111
|
+
{
|
|
2112
|
+
style: {
|
|
2113
|
+
fontSize: "12px",
|
|
2114
|
+
color: "#6b7280",
|
|
2115
|
+
overflow: "hidden",
|
|
2116
|
+
textOverflow: "ellipsis",
|
|
2117
|
+
whiteSpace: "nowrap"
|
|
2118
|
+
},
|
|
2119
|
+
children: account.username
|
|
2120
|
+
}
|
|
2121
|
+
)
|
|
2122
|
+
] }),
|
|
2123
|
+
isActiveAccount(account) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2124
|
+
"svg",
|
|
2109
2125
|
{
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2126
|
+
width: "20",
|
|
2127
|
+
height: "20",
|
|
2128
|
+
viewBox: "0 0 20 20",
|
|
2129
|
+
fill: "none",
|
|
2130
|
+
style: { flexShrink: 0 },
|
|
2131
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2132
|
+
"path",
|
|
2133
|
+
{
|
|
2134
|
+
d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z",
|
|
2135
|
+
fill: "#3b82f6"
|
|
2136
|
+
}
|
|
2137
|
+
)
|
|
2118
2138
|
}
|
|
2119
2139
|
)
|
|
2120
2140
|
] }),
|
|
2121
|
-
isActiveAccount(account) && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2122
|
-
"svg",
|
|
2123
|
-
{
|
|
2124
|
-
width: "20",
|
|
2125
|
-
height: "20",
|
|
2126
|
-
viewBox: "0 0 20 20",
|
|
2127
|
-
fill: "none",
|
|
2128
|
-
style: { flexShrink: 0 },
|
|
2129
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2130
|
-
"path",
|
|
2131
|
-
{
|
|
2132
|
-
d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z",
|
|
2133
|
-
fill: "#3b82f6"
|
|
2134
|
-
}
|
|
2135
|
-
)
|
|
2136
|
-
}
|
|
2137
|
-
),
|
|
2138
2141
|
showRemoveButton && accounts.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
2139
2142
|
"button",
|
|
2140
2143
|
{
|
|
@@ -2243,7 +2246,8 @@ function AccountList({
|
|
|
2243
2246
|
onAccountClick,
|
|
2244
2247
|
className = "",
|
|
2245
2248
|
style,
|
|
2246
|
-
orientation = "vertical"
|
|
2249
|
+
orientation = "vertical",
|
|
2250
|
+
renderAccount
|
|
2247
2251
|
}) {
|
|
2248
2252
|
const { accounts, switchAccount, isActiveAccount } = useMultiAccount();
|
|
2249
2253
|
const handleAccountClick = (account) => {
|
|
@@ -2310,7 +2314,7 @@ function AccountList({
|
|
|
2310
2314
|
}
|
|
2311
2315
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className, style: containerStyle, children: accounts.map((account) => {
|
|
2312
2316
|
const isActive = isActiveAccount(account);
|
|
2313
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.
|
|
2317
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2314
2318
|
"div",
|
|
2315
2319
|
{
|
|
2316
2320
|
onClick: () => handleAccountClick(account),
|
|
@@ -2332,7 +2336,7 @@ function AccountList({
|
|
|
2332
2336
|
e.currentTarget.style.borderColor = "#e5e7eb";
|
|
2333
2337
|
}
|
|
2334
2338
|
},
|
|
2335
|
-
children: [
|
|
2339
|
+
children: renderAccount ? renderAccount(account, isActive) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
2336
2340
|
showAvatars && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: avatarStyle, children: getInitials(account.name) }),
|
|
2337
2341
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
2338
2342
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
@@ -2408,7 +2412,7 @@ function AccountList({
|
|
|
2408
2412
|
]
|
|
2409
2413
|
}
|
|
2410
2414
|
)
|
|
2411
|
-
]
|
|
2415
|
+
] })
|
|
2412
2416
|
},
|
|
2413
2417
|
account.homeAccountId
|
|
2414
2418
|
);
|
package/dist/index.mjs
CHANGED
|
@@ -1854,7 +1854,8 @@ function AccountSwitcher({
|
|
|
1854
1854
|
style,
|
|
1855
1855
|
variant = "default",
|
|
1856
1856
|
showAddButton = true,
|
|
1857
|
-
showRemoveButton = true
|
|
1857
|
+
showRemoveButton = true,
|
|
1858
|
+
renderAccount
|
|
1858
1859
|
}) {
|
|
1859
1860
|
const {
|
|
1860
1861
|
accounts,
|
|
@@ -2037,40 +2038,42 @@ function AccountSwitcher({
|
|
|
2037
2038
|
}
|
|
2038
2039
|
},
|
|
2039
2040
|
children: [
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
/* @__PURE__ */
|
|
2043
|
-
|
|
2044
|
-
|
|
2041
|
+
renderAccount ? renderAccount(account, isActiveAccount(account)) : /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
2042
|
+
showAvatars && /* @__PURE__ */ jsx9("div", { style: avatarStyle, children: getInitials(account.name) }),
|
|
2043
|
+
/* @__PURE__ */ jsxs6("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
2044
|
+
/* @__PURE__ */ jsx9("div", { style: { fontWeight: "500", fontSize: "14px" }, children: account.name || account.username }),
|
|
2045
|
+
/* @__PURE__ */ jsx9(
|
|
2046
|
+
"div",
|
|
2047
|
+
{
|
|
2048
|
+
style: {
|
|
2049
|
+
fontSize: "12px",
|
|
2050
|
+
color: "#6b7280",
|
|
2051
|
+
overflow: "hidden",
|
|
2052
|
+
textOverflow: "ellipsis",
|
|
2053
|
+
whiteSpace: "nowrap"
|
|
2054
|
+
},
|
|
2055
|
+
children: account.username
|
|
2056
|
+
}
|
|
2057
|
+
)
|
|
2058
|
+
] }),
|
|
2059
|
+
isActiveAccount(account) && /* @__PURE__ */ jsx9(
|
|
2060
|
+
"svg",
|
|
2045
2061
|
{
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2062
|
+
width: "20",
|
|
2063
|
+
height: "20",
|
|
2064
|
+
viewBox: "0 0 20 20",
|
|
2065
|
+
fill: "none",
|
|
2066
|
+
style: { flexShrink: 0 },
|
|
2067
|
+
children: /* @__PURE__ */ jsx9(
|
|
2068
|
+
"path",
|
|
2069
|
+
{
|
|
2070
|
+
d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z",
|
|
2071
|
+
fill: "#3b82f6"
|
|
2072
|
+
}
|
|
2073
|
+
)
|
|
2054
2074
|
}
|
|
2055
2075
|
)
|
|
2056
2076
|
] }),
|
|
2057
|
-
isActiveAccount(account) && /* @__PURE__ */ jsx9(
|
|
2058
|
-
"svg",
|
|
2059
|
-
{
|
|
2060
|
-
width: "20",
|
|
2061
|
-
height: "20",
|
|
2062
|
-
viewBox: "0 0 20 20",
|
|
2063
|
-
fill: "none",
|
|
2064
|
-
style: { flexShrink: 0 },
|
|
2065
|
-
children: /* @__PURE__ */ jsx9(
|
|
2066
|
-
"path",
|
|
2067
|
-
{
|
|
2068
|
-
d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z",
|
|
2069
|
-
fill: "#3b82f6"
|
|
2070
|
-
}
|
|
2071
|
-
)
|
|
2072
|
-
}
|
|
2073
|
-
),
|
|
2074
2077
|
showRemoveButton && accounts.length > 1 && /* @__PURE__ */ jsx9(
|
|
2075
2078
|
"button",
|
|
2076
2079
|
{
|
|
@@ -2179,7 +2182,8 @@ function AccountList({
|
|
|
2179
2182
|
onAccountClick,
|
|
2180
2183
|
className = "",
|
|
2181
2184
|
style,
|
|
2182
|
-
orientation = "vertical"
|
|
2185
|
+
orientation = "vertical",
|
|
2186
|
+
renderAccount
|
|
2183
2187
|
}) {
|
|
2184
2188
|
const { accounts, switchAccount, isActiveAccount } = useMultiAccount();
|
|
2185
2189
|
const handleAccountClick = (account) => {
|
|
@@ -2246,7 +2250,7 @@ function AccountList({
|
|
|
2246
2250
|
}
|
|
2247
2251
|
return /* @__PURE__ */ jsx10("div", { className, style: containerStyle, children: accounts.map((account) => {
|
|
2248
2252
|
const isActive = isActiveAccount(account);
|
|
2249
|
-
return /* @__PURE__ */
|
|
2253
|
+
return /* @__PURE__ */ jsx10(
|
|
2250
2254
|
"div",
|
|
2251
2255
|
{
|
|
2252
2256
|
onClick: () => handleAccountClick(account),
|
|
@@ -2268,7 +2272,7 @@ function AccountList({
|
|
|
2268
2272
|
e.currentTarget.style.borderColor = "#e5e7eb";
|
|
2269
2273
|
}
|
|
2270
2274
|
},
|
|
2271
|
-
children: [
|
|
2275
|
+
children: renderAccount ? renderAccount(account, isActive) : /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
2272
2276
|
showAvatars && /* @__PURE__ */ jsx10("div", { style: avatarStyle, children: getInitials(account.name) }),
|
|
2273
2277
|
/* @__PURE__ */ jsxs7("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
2274
2278
|
/* @__PURE__ */ jsx10(
|
|
@@ -2344,7 +2348,7 @@ function AccountList({
|
|
|
2344
2348
|
]
|
|
2345
2349
|
}
|
|
2346
2350
|
)
|
|
2347
|
-
]
|
|
2351
|
+
] })
|
|
2348
2352
|
},
|
|
2349
2353
|
account.homeAccountId
|
|
2350
2354
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chemmangat/msal-next",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"description": "Production-ready Microsoft/Azure AD authentication for Next.js App Router. Zero-config setup, TypeScript-first, multi-account support, auto token refresh. The easiest way to add Microsoft login to your Next.js app.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"@azure/msal-browser": "^3.11.1",
|
|
92
92
|
"@azure/msal-react": "^2.0.15",
|
|
93
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
93
94
|
"@testing-library/react": "^14.0.0",
|
|
94
95
|
"@testing-library/react-hooks": "^8.0.1",
|
|
95
96
|
"@types/react": "^18.2.0",
|