@ciscode/ui-authentication-kit 1.0.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/LICENSE +20 -0
- package/README.md +44 -0
- package/dist/components/InlineError.d.ts +8 -0
- package/dist/components/InlineError.d.ts.map +1 -0
- package/dist/components/InlineError.js +31 -0
- package/dist/components/InlineError.js.map +1 -0
- package/dist/components/ProfilePage.d.ts +3 -0
- package/dist/components/ProfilePage.d.ts.map +1 -0
- package/dist/components/ProfilePage.js +151 -0
- package/dist/components/ProfilePage.js.map +1 -0
- package/dist/components/RequirePermissions.d.ts +15 -0
- package/dist/components/RequirePermissions.d.ts.map +1 -0
- package/dist/components/RequirePermissions.js +20 -0
- package/dist/components/RequirePermissions.js.map +1 -0
- package/dist/components/SessionExpiredModal.d.ts +7 -0
- package/dist/components/SessionExpiredModal.d.ts.map +1 -0
- package/dist/components/SessionExpiredModal.js +26 -0
- package/dist/components/SessionExpiredModal.js.map +1 -0
- package/dist/components/actions/InputField.d.ts +10 -0
- package/dist/components/actions/InputField.d.ts.map +1 -0
- package/dist/components/actions/InputField.js +22 -0
- package/dist/components/actions/InputField.js.map +1 -0
- package/dist/components/actions/SocialButton.d.ts +4 -0
- package/dist/components/actions/SocialButton.d.ts.map +1 -0
- package/dist/components/actions/SocialButton.js +10 -0
- package/dist/components/actions/SocialButton.js.map +1 -0
- package/dist/context/AuthConfigContext.d.ts +12 -0
- package/dist/context/AuthConfigContext.d.ts.map +1 -0
- package/dist/context/AuthConfigContext.js +18 -0
- package/dist/context/AuthConfigContext.js.map +1 -0
- package/dist/context/AuthStateContext.d.ts +17 -0
- package/dist/context/AuthStateContext.d.ts.map +1 -0
- package/dist/context/AuthStateContext.js +9 -0
- package/dist/context/AuthStateContext.js.map +1 -0
- package/dist/context/RbacContext.d.ts +12 -0
- package/dist/context/RbacContext.d.ts.map +1 -0
- package/dist/context/RbacContext.js +21 -0
- package/dist/context/RbacContext.js.map +1 -0
- package/dist/hooks/useAbility.d.ts +8 -0
- package/dist/hooks/useAbility.d.ts.map +1 -0
- package/dist/hooks/useAbility.js +24 -0
- package/dist/hooks/useAbility.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2596 -0
- package/dist/index.umd.js +49 -0
- package/dist/main/app.d.ts +6 -0
- package/dist/main/app.d.ts.map +1 -0
- package/dist/main/app.js +7 -0
- package/dist/main/app.js.map +1 -0
- package/dist/models/AuthConfig.d.ts +17 -0
- package/dist/models/AuthConfig.d.ts.map +1 -0
- package/dist/models/AuthConfig.js +2 -0
- package/dist/models/AuthConfig.js.map +1 -0
- package/dist/models/ColorTheme.d.ts +8 -0
- package/dist/models/ColorTheme.d.ts.map +1 -0
- package/dist/models/ColorTheme.js +2 -0
- package/dist/models/ColorTheme.js.map +1 -0
- package/dist/models/Type.d.ts +13 -0
- package/dist/models/Type.d.ts.map +1 -0
- package/dist/models/Type.js +2 -0
- package/dist/models/Type.js.map +1 -0
- package/dist/models/User.d.ts +15 -0
- package/dist/models/User.d.ts.map +1 -0
- package/dist/models/User.js +2 -0
- package/dist/models/User.js.map +1 -0
- package/dist/pages/auth/GoogleCallbackPage.d.ts +3 -0
- package/dist/pages/auth/GoogleCallbackPage.d.ts.map +1 -0
- package/dist/pages/auth/GoogleCallbackPage.js +20 -0
- package/dist/pages/auth/GoogleCallbackPage.js.map +1 -0
- package/dist/pages/auth/SignInPage.d.ts +4 -0
- package/dist/pages/auth/SignInPage.d.ts.map +1 -0
- package/dist/pages/auth/SignInPage.js +152 -0
- package/dist/pages/auth/SignInPage.js.map +1 -0
- package/dist/pages/auth/SignUpPage.d.ts +3 -0
- package/dist/pages/auth/SignUpPage.d.ts.map +1 -0
- package/dist/pages/auth/SignUpPage.js +177 -0
- package/dist/pages/auth/SignUpPage.js.map +1 -0
- package/dist/providers/AuthProvider.d.ts +9 -0
- package/dist/providers/AuthProvider.d.ts.map +1 -0
- package/dist/providers/AuthProvider.js +160 -0
- package/dist/providers/AuthProvider.js.map +1 -0
- package/dist/utils/attachAuthInterceptor.d.ts +12 -0
- package/dist/utils/attachAuthInterceptor.d.ts.map +1 -0
- package/dist/utils/attachAuthInterceptor.js +73 -0
- package/dist/utils/attachAuthInterceptor.js.map +1 -0
- package/dist/utils/colorHelpers.d.ts +32 -0
- package/dist/utils/colorHelpers.d.ts.map +1 -0
- package/dist/utils/colorHelpers.js +44 -0
- package/dist/utils/colorHelpers.js.map +1 -0
- package/dist/utils/jwtHelpers.d.ts +3 -0
- package/dist/utils/jwtHelpers.d.ts.map +1 -0
- package/dist/utils/jwtHelpers.js +14 -0
- package/dist/utils/jwtHelpers.js.map +1 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ciscode
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# React TypeScript DeveloperKit (Template)
|
|
2
|
+
|
|
3
|
+
Template repository for building reusable React TypeScript **npm libraries**
|
|
4
|
+
(components + hooks + utilities).
|
|
5
|
+
|
|
6
|
+
## What you get
|
|
7
|
+
|
|
8
|
+
- ESM + CJS + Types build (tsup)
|
|
9
|
+
- Vitest testing
|
|
10
|
+
- ESLint + Prettier (flat config)
|
|
11
|
+
- Changesets (manual release flow, no automation PR)
|
|
12
|
+
- Husky (pre-commit + pre-push)
|
|
13
|
+
- Enforced public API via `src/index.ts`
|
|
14
|
+
- Dependency-free styling (Tailwind-compatible by convention only)
|
|
15
|
+
- `react` and `react-dom` as peerDependencies
|
|
16
|
+
|
|
17
|
+
## Package structure
|
|
18
|
+
|
|
19
|
+
- `src/components` – reusable UI components
|
|
20
|
+
- `src/hooks` – reusable React hooks
|
|
21
|
+
- `src/utils` – framework-agnostic utilities
|
|
22
|
+
- `src/index.ts` – **only public API** (no deep imports allowed)
|
|
23
|
+
|
|
24
|
+
Anything not exported from `src/index.ts` is considered private.
|
|
25
|
+
|
|
26
|
+
## Scripts
|
|
27
|
+
|
|
28
|
+
- `npm run build` – build to `dist/` (tsup)
|
|
29
|
+
- `npm test` – run tests (vitest)
|
|
30
|
+
- `npm run typecheck` – TypeScript typecheck
|
|
31
|
+
- `npm run lint` – ESLint
|
|
32
|
+
- `npm run format` / `npm run format:write` – Prettier
|
|
33
|
+
- `npx changeset` – create a changeset
|
|
34
|
+
|
|
35
|
+
## Release flow (summary)
|
|
36
|
+
|
|
37
|
+
- Work on a `feature` branch from `develop`
|
|
38
|
+
- Merge to `develop`
|
|
39
|
+
- Add a changeset for user-facing changes: `npx changeset`
|
|
40
|
+
- Promote `develop` → `master`
|
|
41
|
+
- Tag `vX.Y.Z` to publish (npm OIDC)
|
|
42
|
+
|
|
43
|
+
This repository is a **template**. Teams should clone it and focus only on
|
|
44
|
+
library logic, not tooling or release mechanics.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InlineError.d.ts","sourceRoot":"","sources":["../../src/components/InlineError.tsx"],"names":[],"mappings":"AACA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAInD,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAuDvC,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/components/actions/InlineError.tsx
|
|
2
|
+
import React, { useEffect, useState } from "react";
|
|
3
|
+
import { AlertTriangle, X } from "lucide-react";
|
|
4
|
+
import { useT } from "@ciscode/ui-translate-core";
|
|
5
|
+
export const InlineError = ({ message, dismissAfterMs = 4000, }) => {
|
|
6
|
+
const t = useT("authLib"); // or whichever namespace you use for common strings
|
|
7
|
+
const [show, setShow] = useState(false);
|
|
8
|
+
/* show on message change */
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
setShow(Boolean(message));
|
|
11
|
+
if (message && dismissAfterMs > 0) {
|
|
12
|
+
const id = window.setTimeout(() => setShow(false), dismissAfterMs);
|
|
13
|
+
return () => window.clearTimeout(id);
|
|
14
|
+
}
|
|
15
|
+
}, [message, dismissAfterMs]);
|
|
16
|
+
if (!show || !message)
|
|
17
|
+
return null;
|
|
18
|
+
return (React.createElement("div", { role: "alert", "aria-live": "assertive", className: `
|
|
19
|
+
relative isolate flex w-full max-w-md items-start gap-2 overflow-hidden
|
|
20
|
+
rounded-lg border border-red-300 bg-red-50/80 p-4 pr-6 text-sm text-red-800
|
|
21
|
+
shadow-lg backdrop-blur
|
|
22
|
+
transition-all duration-300 ease-out
|
|
23
|
+
${show ? "translate-y-0 opacity-100" : "-translate-y-2 opacity-0"}
|
|
24
|
+
` },
|
|
25
|
+
React.createElement("span", { className: "absolute ltr:left-0 rtl:right-0 top-0 h-full w-1 bg-gradient-to-b from-red-500 to-red-400" }),
|
|
26
|
+
React.createElement(AlertTriangle, { className: "mt-0.5 h-5 w-5 flex-none" }),
|
|
27
|
+
React.createElement("span", { className: "grow leading-5 ltr:text-left rtl:text-right" }, message),
|
|
28
|
+
React.createElement("button", { onClick: () => setShow(false), "aria-label": t("inlineError.dismiss"), className: "\n absolute ltr:right-2 rtl:left-2 top-2 rounded p-1 text-red-600/70\n hover:bg-red-100 hover:text-red-700 focus:outline-none\n focus-visible:ring focus-visible:ring-red-500/50\n " },
|
|
29
|
+
React.createElement(X, { className: "h-4 w-4" }))));
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=InlineError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InlineError.js","sourceRoot":"","sources":["../../src/components/InlineError.tsx"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAOlD,MAAM,CAAC,MAAM,WAAW,GAAoB,CAAC,EAC3C,OAAO,EACP,cAAc,GAAG,IAAI,GACtB,EAAE,EAAE;IACH,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,oDAAoD;IAC/E,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExC,4BAA4B;IAC5B,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1B,IAAI,OAAO,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC,CAAC;YACnE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;IAE9B,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAEnC,OAAO,CACL,6BACE,IAAI,EAAC,OAAO,eACF,WAAW,EACrB,SAAS,EAAE;;;;;UAKP,IAAI,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,0BAA0B;OAClE;QAGD,8BAAM,SAAS,EAAC,2FAA2F,GAAG;QAG9G,oBAAC,aAAa,IAAC,SAAS,EAAC,0BAA0B,GAAG;QAGtD,8BAAM,SAAS,EAAC,6CAA6C,IAC1D,OAAO,CACH;QAGP,gCACE,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,gBACjB,CAAC,CAAC,qBAAqB,CAAC,EACpC,SAAS,EAAC,uNAIT;YAED,oBAAC,CAAC,IAAC,SAAS,EAAC,SAAS,GAAG,CAClB,CACL,CACP,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfilePage.d.ts","sourceRoot":"","sources":["../../src/components/ProfilePage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAK5D,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAiW/B,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import React, { useEffect, useMemo, useState } from 'react';
|
|
11
|
+
import { useAuthState } from '../context/AuthStateContext';
|
|
12
|
+
export const ProfilePage = () => {
|
|
13
|
+
var _a, _b;
|
|
14
|
+
const { user, api, setUser } = useAuthState();
|
|
15
|
+
const [name, setName] = useState((_a = user === null || user === void 0 ? void 0 : user.name) !== null && _a !== void 0 ? _a : '');
|
|
16
|
+
const [email, setEmail] = useState((_b = user === null || user === void 0 ? void 0 : user.email) !== null && _b !== void 0 ? _b : '');
|
|
17
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
18
|
+
const [saving, setSaving] = useState(false);
|
|
19
|
+
const [toast, setToast] = useState({
|
|
20
|
+
open: false,
|
|
21
|
+
type: 'success',
|
|
22
|
+
title: '',
|
|
23
|
+
message: '',
|
|
24
|
+
});
|
|
25
|
+
const phone = '+971 50 827 8229';
|
|
26
|
+
// Auto-hide toast after 3s
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!toast.open)
|
|
29
|
+
return;
|
|
30
|
+
const id = window.setTimeout(() => setToast((t) => (Object.assign(Object.assign({}, t), { open: false }))), 3000);
|
|
31
|
+
return () => window.clearTimeout(id);
|
|
32
|
+
}, [toast.open]);
|
|
33
|
+
// Load profile
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
let cancelled = false;
|
|
36
|
+
function loadProfile() {
|
|
37
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
38
|
+
var _a, _b;
|
|
39
|
+
try {
|
|
40
|
+
const { data } = yield api.get('/auth/client/me');
|
|
41
|
+
if (cancelled)
|
|
42
|
+
return;
|
|
43
|
+
setUser(data);
|
|
44
|
+
setName((_a = data === null || data === void 0 ? void 0 : data.name) !== null && _a !== void 0 ? _a : '');
|
|
45
|
+
setEmail((_b = data === null || data === void 0 ? void 0 : data.email) !== null && _b !== void 0 ? _b : '');
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
console.error('Failed to load profile details:', err);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
loadProfile();
|
|
53
|
+
return () => {
|
|
54
|
+
cancelled = true;
|
|
55
|
+
};
|
|
56
|
+
}, [api, setUser]);
|
|
57
|
+
const displayName = useMemo(() => {
|
|
58
|
+
return (name || (user === null || user === void 0 ? void 0 : user.name) || (user === null || user === void 0 ? void 0 : user.email) || '').trim();
|
|
59
|
+
}, [name, user === null || user === void 0 ? void 0 : user.name, user === null || user === void 0 ? void 0 : user.email]);
|
|
60
|
+
const avatarInitial = useMemo(() => {
|
|
61
|
+
return displayName.charAt(0).toUpperCase() || '?';
|
|
62
|
+
}, [displayName]);
|
|
63
|
+
function handleSave() {
|
|
64
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
+
if (!user)
|
|
66
|
+
return;
|
|
67
|
+
setSaving(true);
|
|
68
|
+
try {
|
|
69
|
+
yield api.patch('/auth/client/me', { name });
|
|
70
|
+
setUser(Object.assign(Object.assign({}, user), { name }));
|
|
71
|
+
setIsEditing(false);
|
|
72
|
+
setToast({
|
|
73
|
+
open: true,
|
|
74
|
+
type: 'success',
|
|
75
|
+
title: 'Changes saved',
|
|
76
|
+
message: 'Your profile was updated successfully.',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
console.error('Failed to update profile:', err);
|
|
81
|
+
setToast({
|
|
82
|
+
open: true,
|
|
83
|
+
type: 'error',
|
|
84
|
+
title: 'Save failed',
|
|
85
|
+
message: 'Failed to save changes. Please try again.',
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
setSaving(false);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (!user) {
|
|
94
|
+
return React.createElement("p", { className: "text-sm text-gray-500" }, "No user data available.");
|
|
95
|
+
}
|
|
96
|
+
const isSuccess = toast.type === 'success';
|
|
97
|
+
return (React.createElement("div", { className: "max-w-3xl mx-auto" },
|
|
98
|
+
toast.open && (React.createElement("div", { className: "fixed top-6 right-6 z-[999999] flex items-center gap-3 rounded-xl border bg-white px-4 py-3 shadow-lg", role: "status", "aria-live": "polite", style: {
|
|
99
|
+
borderColor: isSuccess ? '#BBF7D0' : '#FECACA',
|
|
100
|
+
} },
|
|
101
|
+
React.createElement("div", { className: "flex h-9 w-9 items-center justify-center rounded-full", style: {
|
|
102
|
+
backgroundColor: isSuccess ? '#ECFDF5' : '#FEF2F2',
|
|
103
|
+
} }, isSuccess ? (React.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: "text-green-600" },
|
|
104
|
+
React.createElement("path", { d: "M20 6L9 17L4 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }))) : (React.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", className: "text-red-600" },
|
|
105
|
+
React.createElement("path", { d: "M12 9V13", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
106
|
+
React.createElement("path", { d: "M12 17H12.01", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
107
|
+
React.createElement("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" })))),
|
|
108
|
+
React.createElement("div", { className: "flex flex-col" },
|
|
109
|
+
React.createElement("span", { className: "text-sm font-semibold", style: { color: isSuccess ? '#15803D' : '#B91C1C' } }, toast.title),
|
|
110
|
+
toast.message && (React.createElement("span", { className: "text-xs text-gray-500" }, toast.message))),
|
|
111
|
+
React.createElement("button", { type: "button", onClick: () => setToast((t) => (Object.assign(Object.assign({}, t), { open: false }))), className: "ml-2 rounded-md px-2 py-1 text-gray-500 hover:bg-gray-100", "aria-label": "Close", title: "Close" },
|
|
112
|
+
React.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
|
|
113
|
+
React.createElement("path", { d: "M18 6L6 18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
114
|
+
React.createElement("path", { d: "M6 6L18 18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }))))),
|
|
115
|
+
React.createElement("div", { className: "rounded-2xl border border-gray-200 bg-white shadow-sm" },
|
|
116
|
+
React.createElement("div", { className: "px-6 pt-6 pb-4" },
|
|
117
|
+
React.createElement("div", { className: "flex items-center justify-between" },
|
|
118
|
+
React.createElement("div", { className: "flex items-center gap-4" },
|
|
119
|
+
React.createElement("div", { className: "relative" },
|
|
120
|
+
React.createElement("div", { className: "h-16 w-16 rounded-full bg-blue-600 flex items-center justify-center text-white text-2xl font-semibold" }, avatarInitial),
|
|
121
|
+
React.createElement("button", { type: "button", className: "absolute -bottom-1 -right-1 h-8 w-8 rounded-full border border-gray-200 bg-white shadow-sm flex items-center justify-center hover:bg-gray-50", title: "Change avatar" },
|
|
122
|
+
React.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
|
|
123
|
+
React.createElement("path", { d: "M12 20H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
124
|
+
React.createElement("path", { d: "M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5Z", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" })))),
|
|
125
|
+
React.createElement("div", null,
|
|
126
|
+
React.createElement("h1", { className: "text-2xl font-semibold" }, "My Profile"),
|
|
127
|
+
React.createElement("p", { className: "text-sm text-gray-500" }, "Personal details"))),
|
|
128
|
+
!isEditing ? (React.createElement("button", { type: "button", onClick: () => setIsEditing(true), title: "Edit profile", className: "h-9 w-9 rounded-full border border-gray-200 bg-white shadow-sm flex items-center justify-center hover:bg-gray-50" },
|
|
129
|
+
React.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" },
|
|
130
|
+
React.createElement("path", { d: "M12 20H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
|
|
131
|
+
React.createElement("path", { d: "M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5Z", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" })))) : (React.createElement("button", { type: "button", onClick: handleSave, disabled: saving, className: "rounded-full border border-blue-200 bg-blue-50 px-4 py-2 text-sm font-medium text-blue-700 hover:bg-blue-100 disabled:opacity-60" }, saving ? 'Saving…' : 'Save changes')))),
|
|
132
|
+
React.createElement("div", { className: "px-6 pb-6 border-t border-gray-100 pt-6" },
|
|
133
|
+
React.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-5" },
|
|
134
|
+
React.createElement("div", null,
|
|
135
|
+
React.createElement("label", { className: "block text-xs font-medium text-gray-500 mb-2" }, "Username"),
|
|
136
|
+
React.createElement("input", { type: "text", value: name, disabled: !isEditing || saving, onChange: (e) => setName(e.target.value), className: `w-full rounded-lg border px-3 py-2 text-sm outline-none ${isEditing
|
|
137
|
+
? 'border-gray-300 bg-white focus:border-blue-500 focus:ring-2 focus:ring-blue-100'
|
|
138
|
+
: 'border-gray-200 bg-gray-50 text-gray-700'}` })),
|
|
139
|
+
React.createElement("div", null,
|
|
140
|
+
React.createElement("label", { className: "block text-xs font-medium text-gray-500 mb-2" }, "Email ID"),
|
|
141
|
+
React.createElement("input", { type: "email", value: email, disabled: true, className: "w-full rounded-lg border border-gray-200 bg-gray-50 px-3 py-2 text-sm text-gray-700 cursor-not-allowed" })),
|
|
142
|
+
React.createElement("div", null,
|
|
143
|
+
React.createElement("label", { className: "block text-xs font-medium text-gray-500 mb-2" }, "Mobile number"),
|
|
144
|
+
React.createElement("input", { type: "text", value: phone, disabled: true, className: "w-full rounded-lg border border-gray-200 bg-gray-50 px-3 py-2 text-sm text-gray-700 cursor-not-allowed" }))),
|
|
145
|
+
isEditing && (React.createElement("button", { type: "button", disabled: saving, onClick: () => {
|
|
146
|
+
var _a;
|
|
147
|
+
setIsEditing(false);
|
|
148
|
+
setName((_a = user === null || user === void 0 ? void 0 : user.name) !== null && _a !== void 0 ? _a : '');
|
|
149
|
+
}, className: "mt-6 text-sm font-medium text-gray-600 hover:text-gray-900" }, "Cancel"))))));
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=ProfilePage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfilePage.js","sourceRoot":"","sources":["../../src/components/ProfilePage.tsx"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAI3D,MAAM,CAAC,MAAM,WAAW,GAAa,GAAG,EAAE;;IACxC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,YAAY,EAAE,CAAC;IAE9C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,mCAAI,EAAE,CAAC,CAAC;IACnD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,KAAK,mCAAI,EAAE,CAAC,CAAC;IACtD,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAK/B;QACD,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,EAAE;QACT,OAAO,EAAE,EAAE;KACZ,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,kBAAkB,CAAC;IAEjC,2BAA2B;IAC3B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,KAAK,CAAC,IAAI;YAAE,OAAO;QACxB,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iCAAM,CAAC,KAAE,IAAI,EAAE,KAAK,IAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QACnF,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAEjB,eAAe;IACf,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,SAAe,WAAW;;;gBACxB,IAAI,CAAC;oBACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;oBAClD,IAAI,SAAS;wBAAE,OAAO;oBAEtB,OAAO,CAAC,IAAI,CAAC,CAAC;oBACd,OAAO,CAAC,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,mCAAI,EAAE,CAAC,CAAC;oBAC1B,QAAQ,CAAC,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,KAAK,mCAAI,EAAE,CAAC,CAAC;gBAC9B,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAC;gBACxD,CAAC;YACH,CAAC;SAAA;QAED,WAAW,EAAE,CAAC;QACd,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAEnB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE;QAC/B,OAAO,CAAC,IAAI,KAAI,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,CAAA,KAAI,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,KAAK,CAAA,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1D,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,EAAE,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,KAAK,CAAC,CAAC,CAAC;IAEpC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE;QACjC,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,GAAG,CAAC;IACpD,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IAElB,SAAe,UAAU;;YACvB,IAAI,CAAC,IAAI;gBAAE,OAAO;YAElB,SAAS,CAAC,IAAI,CAAC,CAAC;YAEhB,IAAI,CAAC;gBACH,MAAM,GAAG,CAAC,KAAK,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC7C,OAAO,iCAAM,IAAI,KAAE,IAAI,IAAG,CAAC;gBAC3B,YAAY,CAAC,KAAK,CAAC,CAAC;gBAEpB,QAAQ,CAAC;oBACP,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,SAAS;oBACf,KAAK,EAAE,eAAe;oBACtB,OAAO,EAAE,wCAAwC;iBAClD,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;gBAEhD,QAAQ,CAAC;oBACP,IAAI,EAAE,IAAI;oBACV,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,aAAa;oBACpB,OAAO,EAAE,2CAA2C;iBACrD,CAAC,CAAC;YACL,CAAC;oBAAS,CAAC;gBACT,SAAS,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;KAAA;IAED,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,2BAAG,SAAS,EAAC,uBAAuB,8BAA4B,CAAC;IAC1E,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;IAE3C,OAAO,CACL,6BAAK,SAAS,EAAC,mBAAmB;QAE/B,KAAK,CAAC,IAAI,IAAI,CACb,6BACE,SAAS,EAAC,uGAAuG,EACjH,IAAI,EAAC,QAAQ,eACH,QAAQ,EAClB,KAAK,EAAE;gBACL,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;aAC/C;YAED,6BACE,SAAS,EAAC,uDAAuD,EACjE,KAAK,EAAE;oBACL,eAAe,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;iBACnD,IAEA,SAAS,CAAC,CAAC,CAAC,CACX,6BACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,4BAA4B,EAClC,SAAS,EAAC,gBAAgB;gBAE1B,8BACE,CAAC,EAAC,iBAAiB,EACnB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,GACtB,CACE,CACP,CAAC,CAAC,CAAC,CACF,6BACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,4BAA4B,EAClC,SAAS,EAAC,cAAc;gBAExB,8BACE,CAAC,EAAC,UAAU,EACZ,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB;gBACF,8BACE,CAAC,EAAC,cAAc,EAChB,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB;gBACF,8BACE,CAAC,EAAC,0FAA0F,EAC5F,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,cAAc,EAAC,OAAO,GACtB,CACE,CACP,CACG;YAEN,6BAAK,SAAS,EAAC,eAAe;gBAC5B,8BACE,SAAS,EAAC,uBAAuB,EACjC,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,IAElD,KAAK,CAAC,KAAK,CACP;gBACN,KAAK,CAAC,OAAO,IAAI,CAChB,8BAAM,SAAS,EAAC,uBAAuB,IAAE,KAAK,CAAC,OAAO,CAAQ,CAC/D,CACG;YAEN,gCACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iCAAM,CAAC,KAAE,IAAI,EAAE,KAAK,IAAG,CAAC,EACvD,SAAS,EAAC,2DAA2D,gBAC1D,OAAO,EAClB,KAAK,EAAC,OAAO;gBAEb,6BACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,4BAA4B;oBAElC,8BACE,CAAC,EAAC,YAAY,EACd,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB;oBACF,8BACE,CAAC,EAAC,YAAY,EACd,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB,CACE,CACC,CACL,CACP;QAED,6BAAK,SAAS,EAAC,uDAAuD;YAEpE,6BAAK,SAAS,EAAC,gBAAgB;gBAC7B,6BAAK,SAAS,EAAC,mCAAmC;oBAChD,6BAAK,SAAS,EAAC,yBAAyB;wBACtC,6BAAK,SAAS,EAAC,UAAU;4BACvB,6BAAK,SAAS,EAAC,uGAAuG,IACnH,aAAa,CACV;4BAGN,gCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,8IAA8I,EACxJ,KAAK,EAAC,eAAe;gCAErB,6BACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,4BAA4B;oCAElC,8BACE,CAAC,EAAC,WAAW,EACb,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB;oCACF,8BACE,CAAC,EAAC,sDAAsD,EACxD,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,cAAc,EAAC,OAAO,GACtB,CACE,CACC,CACL;wBAEN;4BACE,4BAAI,SAAS,EAAC,wBAAwB,iBAAgB;4BACtD,2BAAG,SAAS,EAAC,uBAAuB,uBAAqB,CACrD,CACF;oBAEL,CAAC,SAAS,CAAC,CAAC,CAAC,CACZ,gCACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,EACjC,KAAK,EAAC,cAAc,EACpB,SAAS,EAAC,kHAAkH;wBAE5H,6BACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,4BAA4B;4BAElC,8BACE,CAAC,EAAC,WAAW,EACb,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,GACrB;4BACF,8BACE,CAAC,EAAC,sDAAsD,EACxD,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,cAAc,EAAC,OAAO,GACtB,CACE,CACC,CACV,CAAC,CAAC,CAAC,CACF,gCACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAC,kIAAkI,IAE3I,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAC7B,CACV,CACG,CACF;YAGN,6BAAK,SAAS,EAAC,yCAAyC;gBACtD,6BAAK,SAAS,EAAC,uCAAuC;oBACpD;wBACE,+BAAO,SAAS,EAAC,8CAA8C,eAEvD;wBACR,+BACE,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,CAAC,SAAS,IAAI,MAAM,EAC9B,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACxC,SAAS,EAAE,2DACT,SAAS;gCACP,CAAC,CAAC,iFAAiF;gCACnF,CAAC,CAAC,0CACN,EAAE,GACF,CACE;oBAEN;wBACE,+BAAO,SAAS,EAAC,8CAA8C,eAEvD;wBACR,+BACE,IAAI,EAAC,OAAO,EACZ,KAAK,EAAE,KAAK,EACZ,QAAQ,QACR,SAAS,EAAC,wGAAwG,GAClH,CACE;oBAEN;wBACE,+BAAO,SAAS,EAAC,8CAA8C,oBAEvD;wBACR,+BACE,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,QAAQ,QACR,SAAS,EAAC,wGAAwG,GAClH,CACE,CACF;gBAEL,SAAS,IAAI,CACZ,gCACE,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,GAAG,EAAE;;wBACZ,YAAY,CAAC,KAAK,CAAC,CAAC;wBACpB,OAAO,CAAC,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,mCAAI,EAAE,CAAC,CAAC;oBAC5B,CAAC,EACD,SAAS,EAAC,4DAA4D,aAG/D,CACV,CACG,CACF,CACF,CACP,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** list of permissions; *every* one must be present */
|
|
4
|
+
fallbackpermessions?: string[];
|
|
5
|
+
/** at least one of these must be present (optional) */
|
|
6
|
+
anyPermessions?: string[];
|
|
7
|
+
/** role(s) that always bypass the check (optional) */
|
|
8
|
+
fallbackRoles: string[];
|
|
9
|
+
/** where to redirect ("/dashboard" by default) */
|
|
10
|
+
redirectTo?: string;
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
export declare const RequirePermissions: React.FC<Props>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=RequirePermissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequirePermissions.d.ts","sourceRoot":"","sources":["../../src/components/RequirePermissions.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,KAAK;IACX,wDAAwD;IACxD,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,wDAAwD;IACxD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,wDAAwD;IACxD,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAwB9C,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/components/auth/RequirePermissions.tsx
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Navigate } from 'react-router'; // or useNavigate()
|
|
4
|
+
import { useCan, useHasRole } from '../hooks/useAbility'; // your hooks
|
|
5
|
+
export const RequirePermissions = ({ children, fallbackpermessions = [], anyPermessions = [], fallbackRoles = ['super-admin'], redirectTo = '/dashboard', }) => {
|
|
6
|
+
/* 1. super‑admin bypass */
|
|
7
|
+
const hasBypass = fallbackRoles.some(r => useHasRole(r));
|
|
8
|
+
if (hasBypass)
|
|
9
|
+
return React.createElement(React.Fragment, null, children);
|
|
10
|
+
/* 2. must have *all* */
|
|
11
|
+
const hasAll = fallbackpermessions.length === 0 || fallbackpermessions.every(p => useCan(p));
|
|
12
|
+
/* 3. must have *any* */
|
|
13
|
+
const hasSome = anyPermessions.length === 0 || anyPermessions.some(p => useCan(p));
|
|
14
|
+
if (hasAll && hasSome) {
|
|
15
|
+
return React.createElement(React.Fragment, null, children);
|
|
16
|
+
}
|
|
17
|
+
/* 4. no access => either redirect or render a 403 page */
|
|
18
|
+
return React.createElement(Navigate, { to: redirectTo, replace: true });
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=RequirePermissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequirePermissions.js","sourceRoot":"","sources":["../../src/components/RequirePermissions.tsx"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC,CAAY,mBAAmB;AACvE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC,CAAC,aAAa;AAcvE,MAAM,CAAC,MAAM,kBAAkB,GAAoB,CAAC,EAChD,QAAQ,EACR,mBAAmB,GAAG,EAAE,EACxB,cAAc,GAAG,EAAE,EACnB,aAAa,GAAG,CAAC,aAAa,CAAC,EAC/B,UAAU,GAAG,YAAY,GAC5B,EAAE,EAAE;IAED,2BAA2B;IAC3B,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,IAAI,SAAS;QAAE,OAAO,0CAAG,QAAQ,CAAI,CAAC;IAEtC,yBAAyB;IACzB,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,KAAK,CAAC,IAAI,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7F,yBAAyB;IACzB,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,KAAK,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnF,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;QACpB,OAAO,0CAAG,QAAQ,CAAI,CAAC;IAC3B,CAAC;IAED,2DAA2D;IAC3D,OAAO,oBAAC,QAAQ,IAAC,EAAE,EAAE,UAAU,EAAE,OAAO,SAAG,CAAC;AAChD,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionExpiredModal.d.ts","sourceRoot":"","sources":["../../src/components/SessionExpiredModal.tsx"],"names":[],"mappings":"AACA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAIzC,UAAU,KAAK;IACX,SAAS,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CA6C/C,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// src/components/auth/SessionExpiredModal.tsx
|
|
2
|
+
import React, { useEffect } from 'react';
|
|
3
|
+
import ReactDOM from 'react-dom';
|
|
4
|
+
import { useT } from '@ciscode/ui-translate-core';
|
|
5
|
+
export const SessionExpiredModal = ({ onConfirm }) => {
|
|
6
|
+
const t = useT('authLib'); // assuming translations under "auth" namespace
|
|
7
|
+
/* disable scroll & clicks behind the modal */
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const { body } = document;
|
|
10
|
+
const prevOverflow = body.style.overflow;
|
|
11
|
+
const prevPointer = body.style.pointerEvents;
|
|
12
|
+
body.style.overflow = 'hidden';
|
|
13
|
+
body.style.pointerEvents = 'none';
|
|
14
|
+
return () => {
|
|
15
|
+
body.style.overflow = prevOverflow;
|
|
16
|
+
body.style.pointerEvents = prevPointer;
|
|
17
|
+
};
|
|
18
|
+
}, []);
|
|
19
|
+
return ReactDOM.createPortal(React.createElement("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center bg-black/40 backdrop-blur-sm" },
|
|
20
|
+
React.createElement("div", { className: "pointer-events-auto w-full max-w-sm rounded-xl bg-white p-6 shadow-xl" },
|
|
21
|
+
React.createElement("h2", { className: "mb-4 text-xl font-semibold text-gray-800 ltr:text-left rtl:text-center" }, t('sessionExpired.title')),
|
|
22
|
+
React.createElement("p", { className: "mb-8 text-sm text-gray-600 ltr:text-left rtl:text-center" }, t('sessionExpired.message')),
|
|
23
|
+
React.createElement("div", { className: "flex justify-end" },
|
|
24
|
+
React.createElement("button", { onClick: onConfirm, className: "\n rounded-lg bg-red-600 px-4 py-2 text-sm font-medium text-white\n hover:bg-red-700 focus-visible:outline focus-visible:outline-2\n focus-visible:outline-offset-2 focus-visible:outline-red-600\n " }, t('sessionExpired.button'))))), document.body);
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=SessionExpiredModal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionExpiredModal.js","sourceRoot":"","sources":["../../src/components/SessionExpiredModal.tsx"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACzC,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAMlD,MAAM,CAAC,MAAM,mBAAmB,GAAoB,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE;IAClE,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,+CAA+C;IAE1E,8CAA8C;IAC9C,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;QAC1B,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;QACzC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC;QAE7C,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;QAElC,OAAO,GAAG,EAAE;YACR,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,YAAY,CAAC;YACnC,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,WAAW,CAAC;QAC3C,CAAC,CAAC;IACN,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,QAAQ,CAAC,YAAY,CACxB,6BAAK,SAAS,EAAC,sFAAsF;QACjG,6BAAK,SAAS,EAAC,uEAAuE;YAClF,4BAAI,SAAS,EAAC,wEAAwE,IACjF,CAAC,CAAC,sBAAsB,CAAC,CACzB;YAEL,2BAAG,SAAS,EAAC,0DAA0D,IAClE,CAAC,CAAC,wBAAwB,CAAC,CAC5B;YAEJ,6BAAK,SAAS,EAAC,kBAAkB;gBAC7B,gCACI,OAAO,EAAE,SAAS,EAClB,SAAS,EAAC,wPAIrB,IAEY,CAAC,CAAC,uBAAuB,CAAC,CACtB,CACP,CACJ,CACJ,EACN,QAAQ,CAAC,IAAI,CAChB,CAAC;AACN,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { InputFieldProps } from "../../models/Type";
|
|
3
|
+
/**
|
|
4
|
+
* InputField:
|
|
5
|
+
* - Renders a label + input combination
|
|
6
|
+
* - Uses translation keys for both `label` and `placeholder`
|
|
7
|
+
* - Automatically flips text alignment in RTL
|
|
8
|
+
*/
|
|
9
|
+
export declare const InputField: React.FC<InputFieldProps>;
|
|
10
|
+
//# sourceMappingURL=InputField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InputField.d.ts","sourceRoot":"","sources":["../../../src/components/actions/InputField.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAkChD,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// src/components/actions/InputField.tsx
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { useT } from "@ciscode/ui-translate-core";
|
|
4
|
+
/**
|
|
5
|
+
* InputField:
|
|
6
|
+
* - Renders a label + input combination
|
|
7
|
+
* - Uses translation keys for both `label` and `placeholder`
|
|
8
|
+
* - Automatically flips text alignment in RTL
|
|
9
|
+
*/
|
|
10
|
+
export const InputField = ({ label, // translation key for the label
|
|
11
|
+
type = "text", placeholder, // translation key for the placeholder
|
|
12
|
+
color = "", value, onChange, }) => {
|
|
13
|
+
const t = useT("authLib"); // assumes your translations live under the "auth" namespace
|
|
14
|
+
return (React.createElement("div", { className: "mt-8 flex flex-col" },
|
|
15
|
+
label && (React.createElement("label", { htmlFor: `input-${label}`, className: "self-start text-base text-black dark:text-white block ltr:text-left rtl:text-right" }, t(label))),
|
|
16
|
+
React.createElement("input", { id: `input-${label}`, type: type, placeholder: placeholder ? t(placeholder) : undefined, value: value, onChange: (e) => onChange === null || onChange === void 0 ? void 0 : onChange(e.target.value), className: `
|
|
17
|
+
px-4 py-4 mt-3.5 text-sm font-light rounded-lg border border-solid w-full
|
|
18
|
+
ltr:text-left rtl:text-right
|
|
19
|
+
${color}
|
|
20
|
+
` })));
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=InputField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InputField.js","sourceRoot":"","sources":["../../../src/components/actions/InputField.tsx"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAGlD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAA8B,CAAC,EACpD,KAAK,EAAW,gCAAgC;AAChD,IAAI,GAAG,MAAM,EACb,WAAW,EAAK,sCAAsC;AACtD,KAAK,GAAG,EAAE,EACV,KAAK,EACL,QAAQ,GACT,EAAE,EAAE;IACH,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAE,4DAA4D;IAExF,OAAO,CACL,6BAAK,SAAS,EAAC,oBAAoB;QAChC,KAAK,IAAI,CACR,+BACE,OAAO,EAAE,SAAS,KAAK,EAAE,EACzB,SAAS,EAAC,oFAAoF,IAE7F,CAAC,CAAC,KAAK,CAAC,CACH,CACT;QACD,+BACE,EAAE,EAAE,SAAS,KAAK,EAAE,EACpB,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,EACrD,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAC3C,SAAS,EAAE;;;YAGP,KAAK;SACR,GACD,CACE,CACP,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SocialButton.d.ts","sourceRoot":"","sources":["../../../src/components/actions/SocialButton.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAkBpD,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// src/components/actions/SocialButton.tsx
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { useT } from "@ciscode/ui-translate-core";
|
|
4
|
+
export const SocialButton = ({ icon, label }) => {
|
|
5
|
+
const t = useT("authLib"); // assuming "auth" namespace for these labels
|
|
6
|
+
return (React.createElement("div", { className: "flex gap-5 px-8 py-3 items-center bg-indigo-50 rounded-lg max-md:px-5" },
|
|
7
|
+
React.createElement("img", { loading: "lazy", src: icon, alt: label ? t(label) : "", className: "object-contain shrink-0 aspect-square w-[26px]" }),
|
|
8
|
+
label && (React.createElement("div", { className: "basis-auto text-sm hidden md:block ltr:text-left rtl:text-right" }, t(label)))));
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=SocialButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SocialButton.js","sourceRoot":"","sources":["../../../src/components/actions/SocialButton.tsx"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAGlD,MAAM,CAAC,MAAM,YAAY,GAAgC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;IAC3E,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,6CAA6C;IAExE,OAAO,CACL,6BAAK,SAAS,EAAC,uEAAuE;QACpF,6BACE,OAAO,EAAC,MAAM,EACd,GAAG,EAAE,IAAI,EACT,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,EAC1B,SAAS,EAAC,gDAAgD,GAC1D;QACD,KAAK,IAAI,CACR,6BAAK,SAAS,EAAC,iEAAiE,IAC7E,CAAC,CAAC,KAAK,CAAC,CACL,CACP,CACG,CACP,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { AuthConfigProps } from "../models/AuthConfig";
|
|
3
|
+
/**
|
|
4
|
+
* The shape of your config context. We'll store the entire AuthConfig
|
|
5
|
+
* so that anywhere in your library can read it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const AuthConfigContext: React.Context<AuthConfigProps | null>;
|
|
8
|
+
/**
|
|
9
|
+
* A small helper to let components easily consume the AuthConfigContext
|
|
10
|
+
*/
|
|
11
|
+
export declare function useAuthConfig(): AuthConfigProps;
|
|
12
|
+
//# sourceMappingURL=AuthConfigContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthConfigContext.d.ts","sourceRoot":"","sources":["../../src/context/AuthConfigContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,uCAAoD,CAAC;AAEnF;;GAEG;AACH,wBAAgB,aAAa,IAAI,eAAe,CAM/C"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//src/contexts/AuthConfigContext.ts
|
|
2
|
+
import React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* The shape of your config context. We'll store the entire AuthConfig
|
|
5
|
+
* so that anywhere in your library can read it.
|
|
6
|
+
*/
|
|
7
|
+
export const AuthConfigContext = React.createContext(null);
|
|
8
|
+
/**
|
|
9
|
+
* A small helper to let components easily consume the AuthConfigContext
|
|
10
|
+
*/
|
|
11
|
+
export function useAuthConfig() {
|
|
12
|
+
const config = React.useContext(AuthConfigContext);
|
|
13
|
+
if (!config) {
|
|
14
|
+
throw new Error("useAuthConfig must be used within an AuthConfigProvider");
|
|
15
|
+
}
|
|
16
|
+
return config;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=AuthConfigContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthConfigContext.js","sourceRoot":"","sources":["../../src/context/AuthConfigContext.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC,aAAa,CAAyB,IAAI,CAAC,CAAC;AAEnF;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { UserProfile } from '../models/User';
|
|
2
|
+
import { AxiosInstance } from 'axios';
|
|
3
|
+
export interface AuthCtx {
|
|
4
|
+
isAuthenticated: boolean;
|
|
5
|
+
user: UserProfile | null;
|
|
6
|
+
accessToken: string | null;
|
|
7
|
+
api: AxiosInstance;
|
|
8
|
+
login(credentials: {
|
|
9
|
+
email: string;
|
|
10
|
+
password: string;
|
|
11
|
+
}): Promise<void>;
|
|
12
|
+
logout(): void;
|
|
13
|
+
setUser(user: UserProfile | null): void;
|
|
14
|
+
}
|
|
15
|
+
export declare const AuthStateCtx: import("react").Context<AuthCtx | null>;
|
|
16
|
+
export declare function useAuthState(): AuthCtx;
|
|
17
|
+
//# sourceMappingURL=AuthStateContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthStateContext.d.ts","sourceRoot":"","sources":["../../src/context/AuthStateContext.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEtC,MAAM,WAAW,OAAO;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,GAAG,EAAE,aAAa,CAAC;IACnB,KAAK,CAAC,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;CACzC;AAED,eAAO,MAAM,YAAY,yCAAsC,CAAC;AAEhE,wBAAgB,YAAY,IAAI,OAAO,CAItC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
export const AuthStateCtx = createContext(null);
|
|
3
|
+
export function useAuthState() {
|
|
4
|
+
const ctx = useContext(AuthStateCtx);
|
|
5
|
+
if (!ctx)
|
|
6
|
+
throw new Error('useAuthState must be inside <AuthProvider>');
|
|
7
|
+
return ctx;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=AuthStateContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthStateContext.js","sourceRoot":"","sources":["../../src/context/AuthStateContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAclD,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAiB,IAAI,CAAC,CAAC;AAEhE,MAAM,UAAU,YAAY;IAC1B,MAAM,GAAG,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IACrC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IACxE,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/** A single rule */
|
|
3
|
+
export interface RbacRule {
|
|
4
|
+
perms?: string[];
|
|
5
|
+
fallbackRoles?: string[];
|
|
6
|
+
}
|
|
7
|
+
/** Arbitrary nesting: feature‑key ➜ action ➜ rule */
|
|
8
|
+
export type RbacTable = Record<string, Record<string, RbacRule>>;
|
|
9
|
+
export declare const RbacContext: React.Context<RbacTable>;
|
|
10
|
+
export declare const RbacProvider: React.Provider<RbacTable>;
|
|
11
|
+
export declare function useGrant(feature: string, action: string): boolean;
|
|
12
|
+
//# sourceMappingURL=RbacContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RbacContext.d.ts","sourceRoot":"","sources":["../../src/context/RbacContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,oBAAoB;AACpB,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,qDAAqD;AACrD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;AAGjE,eAAO,MAAM,WAAW,0BAAqC,CAAC;AAG9D,eAAO,MAAM,YAAY,2BAAuB,CAAC;AAGjD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,WAQvD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/context/RbacContext.ts
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useCan, useHasRole } from '../hooks/useAbility';
|
|
4
|
+
/* empty default so the library still renders in Storybook / tests */
|
|
5
|
+
export const RbacContext = React.createContext({});
|
|
6
|
+
/* provider re‑export – host app supplies the actual table */
|
|
7
|
+
export const RbacProvider = RbacContext.Provider;
|
|
8
|
+
/* helper hook that libraries call */
|
|
9
|
+
export function useGrant(feature, action) {
|
|
10
|
+
var _a, _b, _c;
|
|
11
|
+
const table = React.useContext(RbacContext);
|
|
12
|
+
const rule = (_a = table[feature]) === null || _a === void 0 ? void 0 : _a[action];
|
|
13
|
+
if (!rule)
|
|
14
|
+
return false; // no rule = no access
|
|
15
|
+
if ((_b = rule.perms) === null || _b === void 0 ? void 0 : _b.some(p => useCan(p)))
|
|
16
|
+
return true;
|
|
17
|
+
if ((_c = rule.fallbackRoles) === null || _c === void 0 ? void 0 : _c.some(r => useHasRole(r)))
|
|
18
|
+
return true;
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=RbacContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RbacContext.js","sourceRoot":"","sources":["../../src/context/RbacContext.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAWzD,qEAAqE;AACrE,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,aAAa,CAAY,EAAE,CAAC,CAAC;AAE9D,6DAA6D;AAC7D,MAAM,CAAC,MAAM,YAAY,GAAG,WAAW,CAAC,QAAQ,CAAC;AAEjD,qCAAqC;AACrC,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,MAAc;;IACtD,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAI,MAAA,KAAK,CAAC,OAAO,CAAC,0CAAG,MAAM,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC,CAAoB,sBAAsB;IAElE,IAAI,MAAA,IAAI,CAAC,KAAK,0CAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAAY,OAAO,IAAI,CAAC;IAC5D,IAAI,MAAA,IAAI,CAAC,aAAa,0CAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9D,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function useHasRole(...roles: string[]): boolean;
|
|
2
|
+
export declare function useHasModule(moduleName: string): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Generic permission checker. Accepts one or many permissions.
|
|
5
|
+
* Returns true if *every* permission is present.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useCan(...needed: string[]): boolean;
|
|
8
|
+
//# sourceMappingURL=useAbility.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAbility.d.ts","sourceRoot":"","sources":["../../src/hooks/useAbility.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,WAI5C;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,WAG9C;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,WAIzC"}
|