uikit/README.md
Mohamad Zade 2ae702a8b3
Some checks failed
Build and Deploy Next.js + Nginx Docker Image / build-and-deploy (push) Failing after 59s
Build and Deploy Next.js + Nginx Docker Image / deploy (push) Has been skipped
Update README.md
2026-07-13 09:44:27 +00:00

742 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# uikit
Shared library for BI next.js projects.
---
## Install
```bash
yarn add git+https://git.d.aiengines.ir/bi/uikit.git
```
---
## Update
```bash
yarn upgrade uikit
```
or
```bash
rm -rf .next
rm -rf node_modules/.vite
rm -rf node_modules/.cache
rm -rf node_modules/uikit
yarn upgrade uikit
```
---
# imports
| مسیر | کاربرد | dependency اضافی |
| ------------------ | ------------------------------------- | --------------------------------------- |
| `uikit` | utility functions | - |
| `uikit/utils` | utility functions | - |
| `uikit/pagination` | pagination | Chakra + React + react-icons |
| `uikit/layout` | Header | Chakra + React |
| `uikit/core` | API، BiProvider، Keycloak، Permission | Chakra + React Query + Axios + Keycloak |
| `uikit/table` | DataTable | Chakra + TanStack Table + Pagination |
| `uikit/remote/ui` | Remote UI components مثل `GBadge` | Chakra + React + remote static file |
---
# utils
```js
import { toFaDigits, toEnDigits, toFaNumber } from "uikit/utils";
toFaDigits(123456);
toEnDigits("۱۲۳۴۵۶");
toFaNumber(123456);
```
or
```js
import { toFaDigits } from "uikit";
```
---
# pagination
required dependencies
```bash
yarn add @chakra-ui/react@2
yarn add @chakra-ui/icons@2
yarn add @emotion/react@11
yarn add @emotion/styled@11
yarn add chakra-react-select@5
yarn add react-select@5
yarn add framer-motion@10
yarn add react-icons
```
using
```jsx
import { Pagination, LightPagination, SimplePagination } from "uikit/pagination";
function Page() {
return (
<Pagination
currentPage={1}
totalCount={100}
totalPages={5}
onPageChange={(page) => console.log(page)}
/>
);
}
```
---
# Header
required dependencies:
```bash
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion
```
using:
```jsx
import { Header } from "uikit/layout";
function AppHeader() {
return (
<Header>
<Header.BrandSection>
<Header.Logo src="/logo.png" />
<Header.Brand>
<Header.Title>عنوان سامانه</Header.Title>
<Header.Description>توضیح کوتاه سامانه</Header.Description>
</Header.Brand>
</Header.BrandSection>
<Header.Bi />
</Header>
);
}
```
---
# Core
required dependencies:
```bash
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion @tanstack/react-query axios keycloak-js
```
---
## BiProvider
```jsx
import { BiProvider } from "uikit/core";
export default function App() {
return (
<BiProvider
apiBaseUrl="https://api.example.com"
keycloakClientId="front-client"
permissionClientId="permission-client"
>
<YourApp />
</BiProvider>
);
}
```
---
## BiProvider props
| Prop |
| ----------------------------- |
| `apiBaseUrl` |
| `keycloakClientId` |
| `permissionClientId` |
| `loading` |
| `updateChecker` |
| `updateCheckerProps` |
| `keycloakUrl` |
| `keycloakRealm` |
| `permissionUrl` |
| `keycloakEnabled` |
| `permissionEnabled` |
| `remoteUiEnabled` |
| `remoteUiUrl` |
| `remoteUiChakraProviderProps` |
---
## BiProvider defaults
```js
keycloakUrl = "https://auth.ibagher.ir";
keycloakRealm = "bi";
permissionUrl = "https://api.d.aiengines.ir/user_api/v1/permissions/list";
updateChecker = false;
remoteUiEnabled = true;
remoteUiUrl = "https://uikit.d.aiengines.ir/GBadge.js";
```
---
## BiProvider with Remote UI
`BiProvider` به صورت خودکار dependencyهای لازم برای کامپوننت‌های `remote/ui` را setup می‌کند.
پس اگر سامانه مقصد از `BiProvider` استفاده می‌کند، برای استفاده از `GBadge` کار اضافه‌ای لازم نیست.
```jsx
import { BiProvider } from "uikit/core";
import { GBadge } from "uikit/remote/ui";
export default function App() {
return (
<BiProvider
apiBaseUrl="https://api.example.com"
keycloakClientId="front-client"
permissionClientId="permission-client"
>
<GBadge colorScheme="blue" py={1} px={2} borderRadius="full">
فعال
</GBadge>
</BiProvider>
);
}
```
در این حالت `GBadge` همچنان از Chakra استفاده می‌کند، ولی فایل remote آن، یعنی `GBadge.js`، خودش Chakra و React و font را داخل bundle نمی‌آورد.
dependencyهای لازم از خود سامانه مقصد گرفته می‌شوند.
---
## Change Remote UI URL
اگر فایل remote روی آدرس دیگری deploy شده باشد:
```jsx
import { BiProvider } from "uikit/core";
export default function App() {
return (
<BiProvider
apiBaseUrl="https://api.example.com"
keycloakClientId="front-client"
permissionClientId="permission-client"
remoteUiUrl="https://static.example.com/uikit/GBadge.js"
>
<YourApp />
</BiProvider>
);
}
```
---
## Disable Remote UI setup in BiProvider
اگر نمی‌خواهید `BiProvider` به صورت خودکار remote ui را setup کند:
```jsx
import { BiProvider } from "uikit/core";
export default function App() {
return (
<BiProvider
apiBaseUrl="https://api.example.com"
keycloakClientId="front-client"
permissionClientId="permission-client"
remoteUiEnabled={false}
>
<YourApp />
</BiProvider>
);
}
```
---
To enable `updateChecker` you should have a script `write-version.js` in the root of the project and in the `package.json` of the target project, run before the build:
```json
{
"scripts": {
"prebuild": "node write-version.js",
"build": "next build"
}
}
```
---
# API
```js
import { api, fetcher, configureApi, getApi } from "uikit/core";
```
```js
import { api } from "uikit/core";
const response = await api.get("/users");
```
or
```js
import { fetcher } from "uikit/core";
const data = await fetcher("/users");
```
---
# createApi
```js
import { createApi } from "uikit/core";
export const sampleApi = createApi({
key: "sample",
url: "/...",
actions: {
create: {
method: "post",
url: "/...",
},
update: {
method: "patch",
url: (id) => `/.../${id}`,
},
delete: {
method: "delete",
url: (id) => `/.../${id}`,
},
confirm: {
method: "post",
url: "/...",
},
updateImage: {
method: "post",
url: (id) => `/.../${id}/image`,
body: ({ formData }) => formData,
},
},
});
```
---
# Keycloak
```js
import {
getKeycloakToken,
loginKeycloak,
logoutKeycloak,
} from "uikit/core";
const token = getKeycloakToken();
loginKeycloak();
logoutKeycloak({
redirectUri: window.location.origin,
});
```
---
# Permission
```jsx
import { Can, usePermission } from "uikit/core";
function Page() {
const { can, cannot, permissions } = usePermission();
return (
<>
{can("users:list") && <div>لیست کاربران</div>}
<Can perm="users:create" fallback={null}>
<button>ایجاد کاربر</button>
</Can>
</>
);
}
```
---
# Remote UI
`remote/ui` برای کامپوننت‌هایی است که باید بدون build مجدد سامانه مقصد، از طریق فایل remote به‌روزرسانی شوند.
مثلاً `GBadge` از این مسیر استفاده می‌شود:
```jsx
import { GBadge } from "uikit/remote/ui";
function Page() {
return (
<GBadge colorScheme="blue" py={1} px={2} borderRadius="full">
فعال
</GBadge>
);
}
```
---
## GBadge
required dependencies:
```bash
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion
```
using:
```jsx
import { GBadge } from "uikit/remote/ui";
function Page({ item }) {
return (
<GBadge colorScheme="blue" py={1} px={2} borderRadius="full">
{item}
</GBadge>
);
}
```
`GBadge` از Chakra `Badge` استفاده می‌کند.
اما برای کم شدن حجم فایل remote، این موارد داخل `GBadge.js` bundle نمی‌شوند:
```txt
React
ReactDOM
Chakra
Emotion
theme
Fonts
font files
```
این موارد باید در سامانه مقصد وجود داشته باشند.
---
## GBadge with BiProvider
اگر سامانه مقصد از `BiProvider` استفاده می‌کند، نیازی به setup دستی نیست:
```jsx
import { BiProvider } from "uikit/core";
import { GBadge } from "uikit/remote/ui";
function App() {
return (
<BiProvider
apiBaseUrl="https://api.example.com"
keycloakClientId="front-client"
permissionClientId="permission-client"
>
<GBadge colorScheme="blue" py={1} px={2} borderRadius="full">
فعال
</GBadge>
</BiProvider>
);
}
```
---
## GBadge without BiProvider
اگر سامانه مقصد از `BiProvider` استفاده نمی‌کند، دو حالت وجود دارد.
### حالت ساده
اگر theme خاصی ندارید، فقط استفاده از `GBadge` کافی است:
```jsx
import { GBadge } from "uikit/remote/ui";
function Page() {
return (
<GBadge colorScheme="blue" py={1} px={2} borderRadius="full">
فعال
</GBadge>
);
}
```
در این حالت wrapper مربوط به `GBadge` خودش dependencyهای لازم را setup می‌کند.
---
### حالت با theme اختصاصی
اگر سامانه مقصد theme اختصاصی Chakra دارد، بهتر است در entry اصلی پروژه یک بار setup انجام شود.
مثلاً در `main.jsx`، `App.jsx` یا `_app.jsx`:
```jsx
import React from "react";
import { createRoot } from "react-dom/client";
import { ChakraProvider } from "@chakra-ui/react";
import { setupUikitRemoteDeps } from "uikit/remote/ui";
import { theme } from "./theme";
import App from "./App";
setupUikitRemoteDeps({
theme,
});
createRoot(document.getElementById("root")).render(
<ChakraProvider theme={theme}>
<App />
</ChakraProvider>,
);
```
برای Next.js:
```jsx
import { ChakraProvider } from "@chakra-ui/react";
import { setupUikitRemoteDeps } from "uikit/remote/ui";
import { theme } from "@/theme";
setupUikitRemoteDeps({
theme,
});
export default function App({ Component, pageProps }) {
return (
<ChakraProvider theme={theme}>
<Component {...pageProps} />
</ChakraProvider>
);
}
```
---
## Remote URL without BiProvider
اگر سامانه مقصد از `BiProvider` استفاده نمی‌کند و آدرس فایل remote متفاوت است:
```jsx
import { setupUikitRemoteDeps } from "uikit/remote/ui";
import { theme } from "./theme";
setupUikitRemoteDeps({
theme,
remoteUrl: "https://static.example.com/uikit/GBadge.js",
});
```
یا مستقیم روی خود کامپوننت:
```jsx
import { GBadge } from "uikit/remote/ui";
function Page() {
return (
<GBadge
remoteUrl="https://static.example.com/uikit/GBadge.js"
colorScheme="blue"
py={1}
px={2}
borderRadius="full"
>
فعال
</GBadge>
);
}
```
---
## Font
فونت داخل فایل remote باندل نمی‌شود.
اگر سامانه مقصد از `BiProvider` استفاده می‌کند، فونت و theme اصلی از همان `BiProvider` می‌آید.
اگر سامانه مقصد `BiProvider` ندارد، فونت را در خود سامانه مقصد ست کنید:
```css
@font-face {
font-family: Estedad;
src: url("/fonts/estedad.woff2") format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
:root {
--uikit-font-family: Estedad, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
body {
font-family: var(--uikit-font-family);
}
```
`GBadge` از این مقدار استفاده می‌کند:
```css
var(--uikit-font-family, inherit)
```
---
## Build Remote UI
برای ساخت فایل remote:
```bash
yarn build:remote
```
خروجی remote:
```txt
dist/remote/GBadge.js
```
این فایل باید روی static server یا CDN داخلی deploy شود.
مثلاً:
```txt
https://uikit.d.aiengines.ir/GBadge.js
```
---
## Deploy Remote UI
بعد از تغییر در `GBadge.remote.jsx` یا کامپوننت‌های remote:
```bash
yarn build:remote
```
سپس فایل زیر را deploy کنید:
```txt
dist/remote/GBadge.js
```
سامانه‌های مقصد بعد از reload صفحه، نسخه جدید remote را دریافت می‌کنند.
اگر cache سمت browser یا CDN فعال است، باید cache فایل remote کنترل شود.
---
## Important Notes
اگر از مسیر زیر استفاده شود:
```js
import { GBadge } from "uikit/remote/ui";
```
خود کامپوننت از فایل remote استفاده می‌کند.
اما اگر کامپوننتی از مسیر معمولی package import شود، مثل:
```js
import { SomeComponent } from "uikit";
```
یا:
```js
import { SomeComponent } from "uikit/table";
```
آن کامپوننت داخل build سامانه مقصد bundle می‌شود و برای آپدیت شدن نیاز به rebuild یا `yarn upgrade` دارد.
پس:
```txt
uikit/remote/ui => update by remote file
uikit/table => update by package upgrade
uikit/core => update by package upgrade
uikit/layout => update by package upgrade
```
---
# DataTable
required dependencies:
```bash
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion @tanstack/react-table react-icons
```
using:
```jsx
import { DataTable } from "uikit/table";
function UsersTable({ data, columns }) {
return (
<DataTable
data={data}
columns={columns}
page={1}
size={20}
pagination={{
totalCount: 100,
totalPages: 5,
}}
onPageChange={(page) => console.log(page)}
getRowId={(row) => String(row.id)}
enableSelection
showIndex
>
<DataTable.Topbar>
<DataTable.Title>لیست کاربران</DataTable.Title>
<DataTable.Spacer />
<DataTable.Actions>
<DataTable.SelectAll />
</DataTable.Actions>
</DataTable.Topbar>
<DataTable.Content>
<DataTable.Table />
<DataTable.Pagination />
</DataTable.Content>
</DataTable>
);
}
```