995 lines
24 KiB
Markdown
995 lines
24 KiB
Markdown
# 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 |
|
||
| `uikit/layout` | Header, Sidebar | Chakra + React |
|
||
| `uikit/core` | API، BiProvider، Keycloak، Permission | Chakra + React Query + Axios + Keycloak + Query Params |
|
||
| `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 @emotion/react@11
|
||
yarn add @emotion/styled@11
|
||
yarn add chakra-react-select@5
|
||
yarn add react-select@5
|
||
yarn add framer-motion@10
|
||
```
|
||
|
||
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@2
|
||
yarn add @emotion/react@11
|
||
yarn add @emotion/styled@11
|
||
yarn add framer-motion@10
|
||
```
|
||
|
||
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>
|
||
);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
# Sidebar
|
||
|
||
required dependencies:
|
||
|
||
```bash
|
||
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion
|
||
yarn add @tanstack/react-query axios keycloak-js
|
||
yarn add next-query-params@^5.1.0 use-query-params@^2.2.2
|
||
```
|
||
|
||
`Sidebar` همان UI ناوبری سامانه را برای دسکتاپ و موبایل ارائه میدهد. در دسکتاپ به صورت نوار آیکون کناری و در موبایل به صورت bottom navigation + drawer «بیشتر» نمایش داده میشود.
|
||
|
||
آیتمها به صورت config به کامپوننت داده میشوند:
|
||
|
||
```jsx
|
||
import { SlUserFollowing } from "react-icons/sl";
|
||
|
||
const navigationItems = [
|
||
{
|
||
title: "آنالیز شبکه متعارف - فالوور/فالووینگ",
|
||
mobileTitle: "ارتباط کاربران",
|
||
icon: SlUserFollowing,
|
||
path: "/user-connections/analyze",
|
||
perm: ["analyze"],
|
||
},
|
||
];
|
||
```
|
||
|
||
نمونه استفاده در Next.js Pages Router:
|
||
|
||
```jsx
|
||
import NextLink from "next/link";
|
||
import { useRouter } from "next/router";
|
||
import { Sidebar } from "uikit/layout";
|
||
|
||
function AppSidebar() {
|
||
const router = useRouter();
|
||
|
||
return (
|
||
<Sidebar
|
||
items={navigationItems}
|
||
currentPath={router.asPath}
|
||
linkComponent={NextLink}
|
||
/>
|
||
);
|
||
}
|
||
```
|
||
|
||
`Sidebar` باید داخل `BiProvider` استفاده شود. Permission هر آیتم از `perm` توسط خود UI Kit بررسی میشود و خروج با Keycloak توسط خود UI Kit انجام میشود. سامانه مقصد نیازی به `usePermission` یا `logoutKeycloak` برای Sidebar ندارد.
|
||
|
||
کنترل دسترسی کلی `panel_access` عمداً داخل Sidebar انجام نمیشود تا navigation هنگام render باعث redirect و لغو route در Next.js نشود. اگر سامانه به این guard نیاز دارد، از `PanelAccessGuard` موجود در `uikit/core` در سطح Layout/App استفاده کنید.
|
||
|
||
`aliases` نیز پشتیبانی میشود و برای تشخیص آیتم active استفاده میشود:
|
||
|
||
```jsx
|
||
{
|
||
title: "آنالیز شبکه های اجتماعی خارجی",
|
||
mobileTitle: "شبکه خارجی",
|
||
icon: TbAnalyze,
|
||
path: "/posts/final_analyze",
|
||
aliases: ["/posts/analyze"],
|
||
perm: ["analyze"],
|
||
}
|
||
```
|
||
|
||
اگر `perm` آرایه باشد، همه permissionهای داخل آرایه برای فعال بودن آیتم لازم هستند. آیتم بدون `perm` محدودیت permission ندارد.
|
||
|
||
---
|
||
|
||
# Core
|
||
|
||
required dependencies:
|
||
|
||
```bash
|
||
yarn add @chakra-ui/react@^2
|
||
yarn add @emotion/react@^11
|
||
yarn add @emotion/styled@^11
|
||
yarn add framer-motion@^12
|
||
yarn add @tanstack/react-query@^5
|
||
yarn add axios@^1
|
||
yarn add keycloak-js
|
||
yarn add next-query-params@^5.1.0
|
||
yarn add use-query-params@^2.2.2
|
||
```
|
||
|
||
---
|
||
|
||
## 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 @tanstack/react-table
|
||
```
|
||
|
||
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>
|
||
);
|
||
}
|
||
```
|
||
|
||
|
||
## Sidebar.Exit
|
||
|
||
`Sidebar` بهصورت پیشفرض گزینه خروج را نمایش نمیدهد. برای فعالکردن خروج Keycloak داخلی UI Kit، آن را بهصورت compound component اضافه کنید:
|
||
|
||
```jsx
|
||
<Sidebar
|
||
items={items}
|
||
currentPath={router.asPath}
|
||
linkComponent={NextLink}
|
||
>
|
||
<Sidebar.Exit />
|
||
</Sidebar>
|
||
```
|
||
|
||
عنوان و آیکون خروج قابل تغییر هستند:
|
||
|
||
```jsx
|
||
<Sidebar.Exit title="خروج از سامانه" icon={MyExitIcon} />
|
||
```
|
||
|
||
`Sidebar.Exit` از `logoutKeycloak` داخلی UI Kit استفاده میکند و callback خروج از سامانه مقصد نیاز ندارد.
|
||
|
||
### Sidebar active route notes
|
||
|
||
`Sidebar` compares `currentPath` with each item's `path` and `aliases`, ignoring query strings, hashes, and trailing slashes. Use the actual application route as `path`; use `aliases` only for alternate routes that should keep the same item active.
|
||
|
||
Active sidebar items are rendered as non-links to avoid redundant same-route navigations. This is especially useful on pages that synchronize URL query params.
|
||
|
||
---
|
||
|
||
# Remote AppHeader (self-contained)
|
||
|
||
`AppHeader` یک remote مستقل است و برای فایل remote خودش از `setupUikitRemoteDeps` یا
|
||
`window.__UIKIT_REMOTE_DEPS__` استفاده نمیکند.
|
||
|
||
```jsx
|
||
import { AppHeader } from "uikit/remote/ui";
|
||
|
||
function ExampleAppHeader() {
|
||
return (
|
||
<AppHeader bg="#314E89">
|
||
<AppHeader.BrandSection>
|
||
<AppHeader.Logo src="/logo.png" />
|
||
|
||
<AppHeader.Brand>
|
||
<AppHeader.Title>عنوان سامانه</AppHeader.Title>
|
||
<AppHeader.Description>توضیحات سامانه</AppHeader.Description>
|
||
</AppHeader.Brand>
|
||
</AppHeader.BrandSection>
|
||
|
||
<AppHeader.Extra
|
||
src="/secondary-logo.png"
|
||
text="متن دلخواه"
|
||
/>
|
||
<AppHeader.Bi />
|
||
</AppHeader>
|
||
);
|
||
}
|
||
```
|
||
|
||
`AppHeader` در flow عادی صفحه باقی میماند و عرض کامل میگیرد؛ بنابراین اگر داخل `VStack`/`Stack` قرار بگیرد، محتوای بعدی زیر Header قرار نمیگیرد.
|
||
|
||
`bg` اختیاری است و رنگ پسزمینه پیشفرض Header را override میکند. `AppHeader.Extra` نیز اختیاری است و لوگو + متن دلخواه میگیرد. `AppHeader.Extra` و `AppHeader.Bi` مستقل از هم هستند و میتوان هرکدام را حذف کرد. اگر هر دو وجود داشته باشند، در انتهای Header ترتیب نمایشی `Extra` سپس `Bi` است.
|
||
|
||
فایل remote از این آدرس بارگذاری میشود:
|
||
|
||
```text
|
||
https://uikit.d.aiengines.ir/AppHeader.js
|
||
```
|
||
|
||
برای `AppHeader.js` هیچ dependency از host تزریق نمیشود. خود remote به صورت Web Component
|
||
ایزوله با Shadow DOM اجرا میشود. تنها `font-family` از سامانه مقصد inherit میشود تا AppHeader
|
||
از همان فونت برنامه استفاده کند؛ سایر استایلها همچنان ایزوله هستند. مسیر React wrapper فقط
|
||
`react` خود برنامه را برای mount کردن custom element استفاده میکند و هیچ وابستگی به Chakra ندارد.
|
||
|
||
|
||
## AppHeader local preview
|
||
|
||
برای دیدن `remote/ui/AppHeader` قبل از انتشار:
|
||
|
||
```bash
|
||
yarn install
|
||
yarn dev
|
||
```
|
||
|
||
سپس آدرس Vite که در ترمینال نمایش داده میشود (معمولاً `http://localhost:5173`) را باز کنید. در حالت dev، همان سورس `src/remote/ui/AppHeader/AppHeader.remote.jsx` بهصورت remote لوکال لود میشود.
|
||
|
||
|
||
## Remote AppSidebar
|
||
|
||
`AppSidebar` is an isolated desktop sidebar. Its visual layer lives inside Shadow DOM and does not depend on Chakra, Tailwind, router, permission or authentication packages from the host. The host supplies the menu data and application logic.
|
||
|
||
Prefer the dedicated entry so projects that only need `AppSidebar` do not load the Chakra-oriented remote setup used by older components:
|
||
|
||
```jsx
|
||
import { AppSidebar } from "uikit/remote/ui/AppSidebar";
|
||
|
||
<AppSidebar
|
||
items={[
|
||
{
|
||
id: "home",
|
||
title: "عنوان آیتم",
|
||
mobileTitle: "عنوان کوتاه",
|
||
icon: <YourSvgIcon />,
|
||
active: true,
|
||
onClick: () => navigate("/home"),
|
||
},
|
||
]}
|
||
>
|
||
<AppSidebar.Exit onClick={logout} />
|
||
</AppSidebar>
|
||
```
|
||
|
||
Permission and routing decisions belong to the host. Filter inaccessible items before passing them, or pass `disabled: true` when the disabled state should remain visible.
|
||
|
||
متن `AppSidebar.Exit` داخل خود UI Kit ثابت و همیشه «خروج» است؛ Host فقط callback و در صورت نیاز `disabled` را پاس میدهد.
|
||
|
||
### AppSidebar responsive behavior
|
||
|
||
On widths below the desktop breakpoint (`62em`), `AppSidebar` renders a fixed bottom navigation bar:
|
||
|
||
- Up to 4 visible items: all items are shown directly; when `AppSidebar.Exit` is enabled, exit is the final direct item and there is no **More** button.
|
||
- More than 4 visible items: the first 4 items stay in the bottom bar; **More** is added as the fifth slot; item 5 onward plus `AppSidebar.Exit` are rendered in the bottom drawer.
|
||
- `hidden` items are excluded before this count is calculated.
|
||
|
||
The host remains responsible for route, permission and logout logic.
|
||
|
||
|
||
## Pagination
|
||
|
||
`remote/ui/Pagination` چهار حالت نمایشی دارد و قرارداد props در همه آنها یکسان است:
|
||
|
||
```txt
|
||
full
|
||
compact
|
||
simple
|
||
minimal
|
||
```
|
||
|
||
حالت `minimal` فقط نحوه نمایش را سادهتر میکند. همه variantها API یکسان دارند و `loading` نیز یک prop اختیاری است:
|
||
|
||
```jsx
|
||
import { Pagination } from "uikit/remote/ui";
|
||
|
||
<Pagination
|
||
level="minimal"
|
||
currentPage={page}
|
||
totalPages={totalPages}
|
||
totalCount={totalCount}
|
||
pageSize={10}
|
||
loading={isLoading}
|
||
onPageChange={setPage}
|
||
/>
|
||
```
|
||
|
||
اگر `loading` پاس داده نشود، رفتار Pagination مانند قبل است.
|
||
|
||
- `loading=true` و `totalPages`/`totalCount` هنوز در دسترس نیستند: صفحه جاری `1` است و جای مقادیر نامشخص loader نمایش داده میشود.
|
||
- `loading=true` و totals قبلاً موجودند: totals ثابت میمانند و فقط صفحه جاری تا رسیدن پاسخ جدید loader نمایش میدهد.
|
||
- در جابهجایی بین صفحات، اگر loader داخل دکمه صفحه جاری نمایش داده شود، spinner سفید است تا روی پسزمینه active خوانا بماند.
|
||
|
||
|
||
## Deployed remote demo
|
||
|
||
The production build now also creates a static preview at `dist/remote/index.html`.
|
||
Because the Docker server already serves `dist/remote` as its document root, opening
|
||
`https://uikit.d.aiengines.ir/` shows the UI Kit preview instead of a directory listing.
|
||
The remote module URLs stay unchanged, for example `/AppHeader.js`, `/AppSidebar.js`,
|
||
`/Pagination.js`, and `/GBadge.js`.
|
||
|
||
|
||
### AppHeader.Extra بدون متن
|
||
اگر `text` پاس داده نشود، فقط لوگو نمایش داده میشود و تصویر تمام ارتفاع قابلاستفادهی `AppHeader.Extra` را میگیرد.
|