ebig-library 0.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/README.md +964 -0
- package/dist/component/audio/audio.d.ts +22 -0
- package/dist/component/audio/audio.d.ts.map +1 -0
- package/dist/component/button/button.d.ts +32 -0
- package/dist/component/button/button.d.ts.map +1 -0
- package/dist/component/calendar/calendar.d.ts +27 -0
- package/dist/component/calendar/calendar.d.ts.map +1 -0
- package/dist/component/carousel/carousel.d.ts +32 -0
- package/dist/component/carousel/carousel.d.ts.map +1 -0
- package/dist/component/checkbox/checkbox.d.ts +18 -0
- package/dist/component/checkbox/checkbox.d.ts.map +1 -0
- package/dist/component/ck-editor/ckeditor.d.ts +66 -0
- package/dist/component/ck-editor/ckeditor.d.ts.map +1 -0
- package/dist/component/color-picker/color-picker.d.ts +22 -0
- package/dist/component/color-picker/color-picker.d.ts.map +1 -0
- package/dist/component/component-form.d.ts +211 -0
- package/dist/component/component-form.d.ts.map +1 -0
- package/dist/component/component-status.d.ts +8 -0
- package/dist/component/component-status.d.ts.map +1 -0
- package/dist/component/date-time-picker/date-time-picker.d.ts +42 -0
- package/dist/component/date-time-picker/date-time-picker.d.ts.map +1 -0
- package/dist/component/dialog/dialog.d.ts +19 -0
- package/dist/component/dialog/dialog.d.ts.map +1 -0
- package/dist/component/dropdown/select-dropdown.d.ts +70 -0
- package/dist/component/dropdown/select-dropdown.d.ts.map +1 -0
- package/dist/component/ebig-editor/ebig-editor.d.ts +41 -0
- package/dist/component/ebig-editor/ebig-editor.d.ts.map +1 -0
- package/dist/component/empty-page.d.ts +13 -0
- package/dist/component/empty-page.d.ts.map +1 -0
- package/dist/component/icon/ebig-icon.d.ts +35 -0
- package/dist/component/icon/ebig-icon.d.ts.map +1 -0
- package/dist/component/icon-picker/icon-picker.d.ts +22 -0
- package/dist/component/icon-picker/icon-picker.d.ts.map +1 -0
- package/dist/component/icon-picker/iconLibrary.d.ts +12 -0
- package/dist/component/icon-picker/iconLibrary.d.ts.map +1 -0
- package/dist/component/iframe/iframe.d.ts +23 -0
- package/dist/component/iframe/iframe.d.ts.map +1 -0
- package/dist/component/import-file/import-file.d.ts +33 -0
- package/dist/component/import-file/import-file.d.ts.map +1 -0
- package/dist/component/import-file/upload.d.ts +46 -0
- package/dist/component/import-file/upload.d.ts.map +1 -0
- package/dist/component/infinite-scroll/infinite-scroll.d.ts +16 -0
- package/dist/component/infinite-scroll/infinite-scroll.d.ts.map +1 -0
- package/dist/component/input-otp/input-otp.d.ts +23 -0
- package/dist/component/input-otp/input-otp.d.ts.map +1 -0
- package/dist/component/number-picker/number-picker.d.ts +26 -0
- package/dist/component/number-picker/number-picker.d.ts.map +1 -0
- package/dist/component/pagination/pagination.d.ts +19 -0
- package/dist/component/pagination/pagination.d.ts.map +1 -0
- package/dist/component/popup/popup.d.ts +40 -0
- package/dist/component/popup/popup.d.ts.map +1 -0
- package/dist/component/progress-bar/progress-bar.d.ts +19 -0
- package/dist/component/progress-bar/progress-bar.d.ts.map +1 -0
- package/dist/component/progress-circle/progress-circle.d.ts +18 -0
- package/dist/component/progress-circle/progress-circle.d.ts.map +1 -0
- package/dist/component/radio-button/radio-button.d.ts +17 -0
- package/dist/component/radio-button/radio-button.d.ts.map +1 -0
- package/dist/component/rating/rating.d.ts +17 -0
- package/dist/component/rating/rating.d.ts.map +1 -0
- package/dist/component/slider/slider.d.ts +42 -0
- package/dist/component/slider/slider.d.ts.map +1 -0
- package/dist/component/switch/switch.d.ts +18 -0
- package/dist/component/switch/switch.d.ts.map +1 -0
- package/dist/component/tag/tag.d.ts +23 -0
- package/dist/component/tag/tag.d.ts.map +1 -0
- package/dist/component/text/text.d.ts +14 -0
- package/dist/component/text/text.d.ts.map +1 -0
- package/dist/component/text-area/text-area.d.ts +31 -0
- package/dist/component/text-area/text-area.d.ts.map +1 -0
- package/dist/component/text-field/text-field.d.ts +39 -0
- package/dist/component/text-field/text-field.d.ts.map +1 -0
- package/dist/component/toast-noti/toast-noti.d.ts +9 -0
- package/dist/component/toast-noti/toast-noti.d.ts.map +1 -0
- package/dist/component/video/video.d.ts +24 -0
- package/dist/component/video/video.d.ts.map +1 -0
- package/dist/controller/config.d.ts +58 -0
- package/dist/controller/config.d.ts.map +1 -0
- package/dist/controller/data.d.ts +124 -0
- package/dist/controller/data.d.ts.map +1 -0
- package/dist/controller/setting.d.ts +56 -0
- package/dist/controller/setting.d.ts.map +1 -0
- package/dist/controller/utils.d.ts +70 -0
- package/dist/controller/utils.d.ts.map +1 -0
- package/dist/index.cjs.js +290 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.es.js +110091 -0
- package/dist/index.es.js.map +1 -0
- package/dist/language/i18n.d.ts +4 -0
- package/dist/language/i18n.d.ts.map +1 -0
- package/dist/module/EbigProvider.d.ts +47 -0
- package/dist/module/EbigProvider.d.ts.map +1 -0
- package/dist/module/card/cardById.d.ts +133 -0
- package/dist/module/card/cardById.d.ts.map +1 -0
- package/dist/module/card/config.d.ts +5 -0
- package/dist/module/card/config.d.ts.map +1 -0
- package/dist/module/chart/chartById.d.ts +26 -0
- package/dist/module/chart/chartById.d.ts.map +1 -0
- package/dist/module/chart/chartByType.d.ts +48 -0
- package/dist/module/chart/chartByType.d.ts.map +1 -0
- package/dist/module/da.d.ts +147 -0
- package/dist/module/da.d.ts.map +1 -0
- package/dist/module/form/config.d.ts +19 -0
- package/dist/module/form/config.d.ts.map +1 -0
- package/dist/module/form/formById.d.ts +72 -0
- package/dist/module/form/formById.d.ts.map +1 -0
- package/dist/module/page/component-form.d.ts +235 -0
- package/dist/module/page/component-form.d.ts.map +1 -0
- package/dist/module/page/config.d.ts +15 -0
- package/dist/module/page/config.d.ts.map +1 -0
- package/dist/module/page/pageById.d.ts +227 -0
- package/dist/module/page/pageById.d.ts.map +1 -0
- package/dist/module/table/addEditElement.d.ts +40 -0
- package/dist/module/table/addEditElement.d.ts.map +1 -0
- package/dist/module/table/config.d.ts +42 -0
- package/dist/module/table/config.d.ts.map +1 -0
- package/dist/module/table/exportXlsx.d.ts +22 -0
- package/dist/module/table/exportXlsx.d.ts.map +1 -0
- package/dist/module/table/featureElement.d.ts +51 -0
- package/dist/module/table/featureElement.d.ts.map +1 -0
- package/dist/module/table/tableById.d.ts +187 -0
- package/dist/module/table/tableById.d.ts.map +1 -0
- package/dist/module/table/tableElement.d.ts +100 -0
- package/dist/module/table/tableElement.d.ts.map +1 -0
- package/dist/module/view/viewById.d.ts +58 -0
- package/dist/module/view/viewById.d.ts.map +1 -0
- package/package.json +81 -0
package/README.md
ADDED
|
@@ -0,0 +1,964 @@
|
|
|
1
|
+
# ebig-library
|
|
2
|
+
|
|
3
|
+
A modern, lightweight React + TypeScript UI component library by **eBig** — 35+ ready-to-use components, a responsive layout system, design-token theming, built-in i18n (en/vi), and optional eBig backend integration for dynamic form/table/page rendering.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/ebig-library)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Table of Contents
|
|
11
|
+
|
|
12
|
+
- [Installation](#installation)
|
|
13
|
+
- [Setup: EbigProvider](#setup-ebigprovider)
|
|
14
|
+
- [Global Context](#global-context)
|
|
15
|
+
- [Layout System](#layout-system)
|
|
16
|
+
- [Skin / CSS](#skin--css)
|
|
17
|
+
- [Components](#components)
|
|
18
|
+
- [Button & SimpleButton](#button--simplebutton)
|
|
19
|
+
- [Ebigicon](#ebigicon)
|
|
20
|
+
- [TextField](#textfield)
|
|
21
|
+
- [TextArea](#textarea)
|
|
22
|
+
- [SelectDropdown](#selectdropdown)
|
|
23
|
+
- [Checkbox](#checkbox)
|
|
24
|
+
- [Switch](#switch)
|
|
25
|
+
- [RadioButton](#radiobutton)
|
|
26
|
+
- [DateTimePicker](#datetimepicker)
|
|
27
|
+
- [NumberPicker](#numberpicker)
|
|
28
|
+
- [Slider](#slider)
|
|
29
|
+
- [Rating](#rating)
|
|
30
|
+
- [InputOtp](#inputotp)
|
|
31
|
+
- [ColorPicker](#colorpicker)
|
|
32
|
+
- [Tag](#tag)
|
|
33
|
+
- [Pagination](#pagination)
|
|
34
|
+
- [InfiniteScroll](#infinitescroll)
|
|
35
|
+
- [Dialog](#dialog)
|
|
36
|
+
- [Popup](#popup)
|
|
37
|
+
- [ToastMessage](#toastmessage)
|
|
38
|
+
- [ProgressBar](#progressbar)
|
|
39
|
+
- [ProgressCircle](#progresscircle)
|
|
40
|
+
- [Calendar](#calendar)
|
|
41
|
+
- [Carousel](#carousel)
|
|
42
|
+
- [VideoPlayer / AudioPlayer / IframePlayer](#videoplayer--audioplayer--iframeplayer)
|
|
43
|
+
- [ImportFile / UploadFiles](#importfile--uploadfiles)
|
|
44
|
+
- [CustomCkEditor5](#customckeditor5)
|
|
45
|
+
- [EbigEditor](#ebigeditor)
|
|
46
|
+
- [IconPicker](#iconpicker)
|
|
47
|
+
- [EmptyPage](#emptypage)
|
|
48
|
+
- [Text](#text)
|
|
49
|
+
- [ComponentStatus](#componentstatus)
|
|
50
|
+
- [Form Components (react-hook-form)](#form-components-react-hook-form)
|
|
51
|
+
- [Utility Class (Util)](#utility-class-util)
|
|
52
|
+
- [Controllers](#controllers)
|
|
53
|
+
- [DataController](#datacontroller)
|
|
54
|
+
- [SettingDataController](#settingdatacontroller)
|
|
55
|
+
- [AccountController](#accountcontroller)
|
|
56
|
+
- [EbigController](#ebigcontroller)
|
|
57
|
+
- [TableController](#tablecontroller)
|
|
58
|
+
- [IntegrationController](#integrationcontroller)
|
|
59
|
+
- [BaseDA](#baseda)
|
|
60
|
+
- [Backend-Driven Modules](#backend-driven-modules)
|
|
61
|
+
- [Design Tokens & Theming](#design-tokens--theming)
|
|
62
|
+
- [Responsive Grid Classes](#responsive-grid-classes)
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Installation
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npm install ebig-library
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Import the CSS skin files (required for layout and typography utilities):
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<!-- In your index.html or root CSS -->
|
|
76
|
+
<link rel="stylesheet" href="https://cdn.ebig.co/ebig-library/src/skin/root.min.css" />
|
|
77
|
+
<link rel="stylesheet" href="https://cdn.ebig.co/ebig-library/src/skin/layout.min.css" />
|
|
78
|
+
<link rel="stylesheet" href="https://cdn.ebig.co/ebig-library/src/skin/typography.min.css" />
|
|
79
|
+
<link rel="stylesheet" href="https://cdn.ebig.co/ebig-library/src/skin/toast-noti.min.css" />
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> These are loaded automatically if you use `EbigProvider` with `loadResources={true}` (default).
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Setup: EbigProvider
|
|
87
|
+
|
|
88
|
+
Wrap your app's root with `EbigProvider`. It sets up routing (`BrowserRouter` internally), toast notifications, dialogs, token refresh, and optional design token + i18n loading from the eBig backend.
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
// main.tsx
|
|
92
|
+
import ReactDOM from 'react-dom/client'
|
|
93
|
+
import EbigProvider, { Route } from 'ebig-library'
|
|
94
|
+
|
|
95
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
96
|
+
<EbigProvider
|
|
97
|
+
pid="your-project-id"
|
|
98
|
+
url="https://your-ebig-api.com/"
|
|
99
|
+
fileUrl="https://your-file-server.com/"
|
|
100
|
+
imgUrlId="https://your-cdn.com/"
|
|
101
|
+
theme="light" // "light" | "dark"
|
|
102
|
+
loadResources={true} // false → skip backend token/i18n loading
|
|
103
|
+
>
|
|
104
|
+
<Route path="/" element={<HomePage />} />
|
|
105
|
+
<Route path="/about" element={<AboutPage />} />
|
|
106
|
+
</EbigProvider>
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
> **Important:** `EbigProvider` wraps `BrowserRouter` internally. Do **not** add another `BrowserRouter` in your app.
|
|
111
|
+
|
|
112
|
+
### Props
|
|
113
|
+
|
|
114
|
+
| Prop | Type | Required | Description |
|
|
115
|
+
|---|---|---|---|
|
|
116
|
+
| `pid` | `string` | ✅ | eBig project ID (32-char) |
|
|
117
|
+
| `url` | `string` | ✅ | eBig API base URL |
|
|
118
|
+
| `fileUrl` | `string` | ✅ | File server URL |
|
|
119
|
+
| `imgUrlId` | `string` | ✅ | CDN/image URL prefix |
|
|
120
|
+
| `theme` | `"light" \| "dark"` | — | Default `"light"` |
|
|
121
|
+
| `loadResources` | `boolean` | — | Default `true`. Set to `false` to skip backend loading |
|
|
122
|
+
| `onInvalidToken` | `() => void` | — | Called on 401 — override to redirect to login |
|
|
123
|
+
| `children` | `ReactNode` | — | `<Route>` elements |
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Global Context
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import { useEbigContext } from 'ebig-library'
|
|
131
|
+
|
|
132
|
+
function MyComponent() {
|
|
133
|
+
const {
|
|
134
|
+
theme, // "light" | "dark"
|
|
135
|
+
setTheme,
|
|
136
|
+
userData, // current user object (set by you)
|
|
137
|
+
setUserData,
|
|
138
|
+
globalData, // any global state bag
|
|
139
|
+
setGlobalData,
|
|
140
|
+
i18n, // i18next instance
|
|
141
|
+
} = useEbigContext()
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
|
|
145
|
+
Toggle theme
|
|
146
|
+
</button>
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Layout System
|
|
154
|
+
|
|
155
|
+
Use `row` and `col` CSS classes for flex layouts. Add `remain` to let a child fill remaining space.
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
// Horizontal (flex-direction: row, align-items: center)
|
|
159
|
+
<div className="row" style={{ gap: 12 }}>
|
|
160
|
+
<span>Left</span>
|
|
161
|
+
<span className="remain">Stretches to fill space</span>
|
|
162
|
+
<span>Right</span>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
// Vertical (flex-direction: column)
|
|
166
|
+
<div className="col" style={{ gap: 8 }}>
|
|
167
|
+
<span>Top</span>
|
|
168
|
+
<span>Bottom</span>
|
|
169
|
+
</div>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Skin / CSS
|
|
175
|
+
|
|
176
|
+
| Resource | URL |
|
|
177
|
+
|---|---|
|
|
178
|
+
| Design tokens (CSS variables) | `https://cdn.ebig.co/ebig-library/src/skin/root.min.css` |
|
|
179
|
+
| Layout utilities (`row`, `col`, grids) | `https://cdn.ebig.co/ebig-library/src/skin/layout.min.css` |
|
|
180
|
+
| Typography (`heading-1`…`heading-8`, `body-1`…`body-3`) | `https://cdn.ebig.co/ebig-library/src/skin/typography.min.css` |
|
|
181
|
+
| Toast styles | `https://cdn.ebig.co/ebig-library/src/skin/toast-noti.min.css` |
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Components
|
|
186
|
+
|
|
187
|
+
### Button & SimpleButton
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
import { Button, SimpleButton, Ebigicon } from 'ebig-library'
|
|
191
|
+
|
|
192
|
+
// Basic
|
|
193
|
+
<Button label="Click me" onClick={() => alert('clicked!')} />
|
|
194
|
+
|
|
195
|
+
// Size + color variant
|
|
196
|
+
<Button label="Save" className="size40 button-primary" onClick={handleSave} />
|
|
197
|
+
|
|
198
|
+
// With prefix icon
|
|
199
|
+
<Button
|
|
200
|
+
label="Upload"
|
|
201
|
+
prefix={<Ebigicon src="outline/arrows/cloud-upload" size={16} />}
|
|
202
|
+
className="size40 button-neutral"
|
|
203
|
+
onClick={handleUpload}
|
|
204
|
+
/>
|
|
205
|
+
|
|
206
|
+
// As a link
|
|
207
|
+
<Button label="Docs" linkTo="https://ebig.co" target="_blank" className="size40 button-grey" />
|
|
208
|
+
|
|
209
|
+
// With tooltip
|
|
210
|
+
<Button label="Info" tooltip={{ message: 'More details', position: 'top' }} />
|
|
211
|
+
|
|
212
|
+
// Submit — also triggers on Enter key
|
|
213
|
+
<Button label="Submit" type="submit" className="size40 button-primary" onClick={handleSubmit} />
|
|
214
|
+
|
|
215
|
+
// SimpleButton — auto-disables itself during async onClick to prevent double-clicks
|
|
216
|
+
<SimpleButton label="Save" className="size40 button-primary" onClick={async () => { await save() }} />
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Size classes:** `size24` · `size32` *(default)* · `size40` · `size48` · `size56` · `size64`
|
|
220
|
+
|
|
221
|
+
**Color classes:** `button-primary` · `button-grey` · `button-neutral` · `button-black` · `button-white` · `button-infor` · `button-warning` · `button-error` · `button-success` · `button-infor-main` · `button-warning-main` · `button-error-main` · `button-success-main`
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### Ebigicon
|
|
226
|
+
|
|
227
|
+
SVG icon component. Icons are fetched from `https://cdn.ebig.co/icon-library/` and cached in the browser via the Cache API after first load.
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
import { Ebigicon } from 'ebig-library'
|
|
231
|
+
|
|
232
|
+
<Ebigicon src="outline/user/user" size={24} />
|
|
233
|
+
<Ebigicon src="fill/actions/trash" size={20} color="#E14337" onClick={handleDelete} className="icon-button" />
|
|
234
|
+
|
|
235
|
+
// With tooltip
|
|
236
|
+
<Ebigicon src="outline/essential/info-circle" size={20} tooltip={{ message: 'Help', position: 'bottom' }} />
|
|
237
|
+
|
|
238
|
+
// From a custom link
|
|
239
|
+
<Ebigicon link="https://your-cdn.com/custom-icon.svg" size={24} />
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Style classes:** `icon-button` (adds hover/active styles) · `icon-button light` · `border` · `dashed`
|
|
243
|
+
|
|
244
|
+
**Size classes:** `size24` · `size32` · `size40` · `size48` · `size56` · `size64`
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### TextField
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
import { TextField, Ebigicon } from 'ebig-library'
|
|
252
|
+
|
|
253
|
+
<TextField placeholder="Enter name" onChange={(e) => setName(e.target.value)} />
|
|
254
|
+
|
|
255
|
+
// With prefix icon and helper text (shown in red below)
|
|
256
|
+
<TextField
|
|
257
|
+
prefix={<Ebigicon src="outline/user/user" size={16} />}
|
|
258
|
+
placeholder="Email"
|
|
259
|
+
type="email"
|
|
260
|
+
helperText="Invalid email"
|
|
261
|
+
className="size40 body-3"
|
|
262
|
+
/>
|
|
263
|
+
|
|
264
|
+
// With react-hook-form
|
|
265
|
+
const { register } = useForm()
|
|
266
|
+
<TextField placeholder="Username" register={register('username', { required: true })} />
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Size classes:** `size24` · `size32` · `size40` *(default)* · `size48`
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
### TextArea
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
import { TextArea } from 'ebig-library'
|
|
277
|
+
|
|
278
|
+
<TextArea placeholder="Write something..." onChange={(e) => setText(e.target.value)} />
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
### SelectDropdown
|
|
284
|
+
|
|
285
|
+
Single-value dropdown. Supports static options, async lazy-loading, hierarchical (parent/child) options, and `react-hook-form`.
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
import { SelectDropdown } from 'ebig-library'
|
|
289
|
+
|
|
290
|
+
const options = [
|
|
291
|
+
{ id: '1', name: 'Option A' },
|
|
292
|
+
{ id: '2', name: 'Option B' },
|
|
293
|
+
{ id: '3', name: 'Option C', disabled: true },
|
|
294
|
+
]
|
|
295
|
+
|
|
296
|
+
// Static
|
|
297
|
+
<SelectDropdown
|
|
298
|
+
value={selected}
|
|
299
|
+
options={options}
|
|
300
|
+
placeholder="Choose one"
|
|
301
|
+
onChange={(item) => setSelected(item?.id)}
|
|
302
|
+
/>
|
|
303
|
+
|
|
304
|
+
// Async (loads on open / search)
|
|
305
|
+
<SelectDropdown
|
|
306
|
+
options={[]}
|
|
307
|
+
getOptions={async ({ length, search }) => {
|
|
308
|
+
const res = await fetchItems({ page: Math.floor(length / 10) + 1, search })
|
|
309
|
+
return { data: res.items, totalCount: res.total }
|
|
310
|
+
}}
|
|
311
|
+
onChange={(item) => setSelected(item?.id)}
|
|
312
|
+
/>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
### Checkbox
|
|
318
|
+
|
|
319
|
+
```tsx
|
|
320
|
+
import { Checkbox } from 'ebig-library'
|
|
321
|
+
|
|
322
|
+
<Checkbox value={isChecked} onChange={(val) => setIsChecked(val)} />
|
|
323
|
+
<Checkbox value={null} /> {/* null = indeterminate */}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
### Switch
|
|
329
|
+
|
|
330
|
+
```tsx
|
|
331
|
+
import { Switch } from 'ebig-library'
|
|
332
|
+
|
|
333
|
+
<Switch value={isOn} onChange={(val) => setIsOn(val)} />
|
|
334
|
+
<Switch value={isOn} size="2.4rem" onBackground="#287CF0" onChange={setIsOn} />
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
### RadioButton
|
|
340
|
+
|
|
341
|
+
```tsx
|
|
342
|
+
import { RadioButton } from 'ebig-library'
|
|
343
|
+
|
|
344
|
+
<RadioButton value={selected === 'a'} onChange={() => setSelected('a')} label="Option A" />
|
|
345
|
+
<RadioButton value={selected === 'b'} onChange={() => setSelected('b')} label="Option B" />
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
### DateTimePicker
|
|
351
|
+
|
|
352
|
+
```tsx
|
|
353
|
+
import { DateTimePicker } from 'ebig-library'
|
|
354
|
+
|
|
355
|
+
<DateTimePicker value={date} onChange={(val) => setDate(val)} placeholder="Pick a date" />
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
### NumberPicker
|
|
361
|
+
|
|
362
|
+
```tsx
|
|
363
|
+
import { NumberPicker } from 'ebig-library'
|
|
364
|
+
|
|
365
|
+
<NumberPicker value={count} onChange={(val) => setCount(val)} min={0} max={100} />
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
### Slider
|
|
371
|
+
|
|
372
|
+
```tsx
|
|
373
|
+
import { Slider } from 'ebig-library'
|
|
374
|
+
|
|
375
|
+
<Slider value={volume} min={0} max={100} onChange={(val) => setVolume(val)} />
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
### Rating
|
|
381
|
+
|
|
382
|
+
```tsx
|
|
383
|
+
import { Rating } from 'ebig-library'
|
|
384
|
+
|
|
385
|
+
<Rating value={3} onChange={(val) => setRating(val)} />
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
### InputOtp
|
|
391
|
+
|
|
392
|
+
```tsx
|
|
393
|
+
import { InputOtp } from 'ebig-library'
|
|
394
|
+
|
|
395
|
+
<InputOtp length={6} onComplete={(code) => verifyOtp(code)} />
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
### ColorPicker
|
|
401
|
+
|
|
402
|
+
```tsx
|
|
403
|
+
import { ColorPicker } from 'ebig-library'
|
|
404
|
+
|
|
405
|
+
<ColorPicker value={color} onChange={(hex) => setColor(hex)} />
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
### Tag
|
|
411
|
+
|
|
412
|
+
```tsx
|
|
413
|
+
import { Tag } from 'ebig-library'
|
|
414
|
+
|
|
415
|
+
<Tag label="Active" color="#287CF0" />
|
|
416
|
+
<Tag label="Error" color="#E14337" onRemove={() => handleRemove()} />
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
### Pagination
|
|
422
|
+
|
|
423
|
+
```tsx
|
|
424
|
+
import { Pagination } from 'ebig-library'
|
|
425
|
+
|
|
426
|
+
<Pagination
|
|
427
|
+
pageIndex={page}
|
|
428
|
+
totalCount={total}
|
|
429
|
+
pageSize={10}
|
|
430
|
+
onChange={(newPage) => setPage(newPage)}
|
|
431
|
+
/>
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
### InfiniteScroll
|
|
437
|
+
|
|
438
|
+
```tsx
|
|
439
|
+
import { InfiniteScroll } from 'ebig-library'
|
|
440
|
+
|
|
441
|
+
<InfiniteScroll
|
|
442
|
+
data={items}
|
|
443
|
+
render={(item) => <div key={item.id}>{item.name}</div>}
|
|
444
|
+
totalCount={total}
|
|
445
|
+
onLoadMore={() => loadNextPage()}
|
|
446
|
+
/>
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
### Dialog
|
|
452
|
+
|
|
453
|
+
```tsx
|
|
454
|
+
import { showDialog, DialogAlignment } from 'ebig-library'
|
|
455
|
+
|
|
456
|
+
showDialog({
|
|
457
|
+
title: 'Confirm delete',
|
|
458
|
+
content: 'Are you sure?',
|
|
459
|
+
alignment: DialogAlignment.center,
|
|
460
|
+
onConfirm: () => handleDelete(),
|
|
461
|
+
})
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
### Popup
|
|
467
|
+
|
|
468
|
+
```tsx
|
|
469
|
+
import { Popup, showPopup, closePopup } from 'ebig-library'
|
|
470
|
+
import { useRef } from 'react'
|
|
471
|
+
|
|
472
|
+
const ref = useRef()
|
|
473
|
+
|
|
474
|
+
<button onClick={(ev) => showPopup({ ref, id: 'my-popup', clickTarget: ev.currentTarget, content: () => <div>Content</div> })}>
|
|
475
|
+
Open popup
|
|
476
|
+
</button>
|
|
477
|
+
<Popup ref={ref} />
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
### ToastMessage
|
|
483
|
+
|
|
484
|
+
```tsx
|
|
485
|
+
import { ToastMessage } from 'ebig-library'
|
|
486
|
+
|
|
487
|
+
ToastMessage.success('Saved successfully')
|
|
488
|
+
ToastMessage.errors('Something went wrong')
|
|
489
|
+
ToastMessage.warning('Check your input')
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
### ProgressBar
|
|
495
|
+
|
|
496
|
+
```tsx
|
|
497
|
+
import { ProgressBar } from 'ebig-library'
|
|
498
|
+
|
|
499
|
+
<ProgressBar percent={75} label="Uploading..." />
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
### ProgressCircle
|
|
505
|
+
|
|
506
|
+
```tsx
|
|
507
|
+
import { ProgressCircle } from 'ebig-library'
|
|
508
|
+
|
|
509
|
+
<ProgressCircle percent={60} size={80} />
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
### Calendar
|
|
515
|
+
|
|
516
|
+
```tsx
|
|
517
|
+
import { Calendar } from 'ebig-library'
|
|
518
|
+
|
|
519
|
+
<Calendar value={date} onChange={(val) => setDate(val)} />
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
### Carousel
|
|
525
|
+
|
|
526
|
+
```tsx
|
|
527
|
+
import { Carousel } from 'ebig-library'
|
|
528
|
+
|
|
529
|
+
<Carousel>
|
|
530
|
+
<img src="/slide1.jpg" alt="Slide 1" />
|
|
531
|
+
<img src="/slide2.jpg" alt="Slide 2" />
|
|
532
|
+
</Carousel>
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
### VideoPlayer / AudioPlayer / IframePlayer
|
|
538
|
+
|
|
539
|
+
```tsx
|
|
540
|
+
import { VideoPlayer, AudioPlayer, IframePlayer } from 'ebig-library'
|
|
541
|
+
|
|
542
|
+
<VideoPlayer src="https://example.com/video.mp4" />
|
|
543
|
+
<AudioPlayer src="https://example.com/audio.mp3" />
|
|
544
|
+
<IframePlayer src="https://www.youtube.com/embed/xxxxx" />
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
---
|
|
548
|
+
|
|
549
|
+
### ImportFile / UploadFiles
|
|
550
|
+
|
|
551
|
+
```tsx
|
|
552
|
+
import { ImportFile, UploadFiles } from 'ebig-library'
|
|
553
|
+
|
|
554
|
+
// File input with preview
|
|
555
|
+
<ImportFile
|
|
556
|
+
value={files}
|
|
557
|
+
onChange={(fileList) => setFiles(fileList)}
|
|
558
|
+
maxSize={5 * 1024 * 1024} // 5 MB
|
|
559
|
+
accept={['.png', '.jpg', '.pdf']}
|
|
560
|
+
/>
|
|
561
|
+
|
|
562
|
+
// Full upload flow with progress and CDN upload
|
|
563
|
+
<UploadFiles
|
|
564
|
+
value={uploadedFiles}
|
|
565
|
+
onChange={(files) => setUploadedFiles(files)}
|
|
566
|
+
/>
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
### CustomCkEditor5
|
|
572
|
+
|
|
573
|
+
Rich-text editor powered by CKEditor 5. Requires `ckeditor5` and `@ckeditor/ckeditor5-react` to be installed by the consumer.
|
|
574
|
+
|
|
575
|
+
```tsx
|
|
576
|
+
import { CustomCkEditor5, CkEditorUploadAdapter } from 'ebig-library'
|
|
577
|
+
|
|
578
|
+
<CustomCkEditor5
|
|
579
|
+
value={html}
|
|
580
|
+
onChange={(val) => setHtml(val)}
|
|
581
|
+
uploadAdapter={CkEditorUploadAdapter}
|
|
582
|
+
/>
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
### EbigEditor
|
|
588
|
+
|
|
589
|
+
Lightweight rich-text editor (no CKEditor dependency). Supports emoji, bold, italic, underline, hyperlinks, and `@mention`-style suggestion hooks.
|
|
590
|
+
|
|
591
|
+
```tsx
|
|
592
|
+
import { EbigEditor } from 'ebig-library'
|
|
593
|
+
|
|
594
|
+
<EbigEditor
|
|
595
|
+
placeholder="Write a comment..."
|
|
596
|
+
onChange={(value, el) => setContent(value)}
|
|
597
|
+
onBlur={(value, el) => handleBlur(value)}
|
|
598
|
+
/>
|
|
599
|
+
|
|
600
|
+
// Custom toolbar subset
|
|
601
|
+
<EbigEditor
|
|
602
|
+
customToolbar={['bold', 'italic', 'emoji']}
|
|
603
|
+
onChange={(val) => setContent(val)}
|
|
604
|
+
/>
|
|
605
|
+
|
|
606
|
+
// Mention suggestions
|
|
607
|
+
<EbigEditor
|
|
608
|
+
onSuggest={[{
|
|
609
|
+
triggerPattern: '@',
|
|
610
|
+
render: (offset, match, select) => (
|
|
611
|
+
<MentionList offset={offset} query={match} onSelect={select} />
|
|
612
|
+
)
|
|
613
|
+
}]}
|
|
614
|
+
onChange={(val) => setContent(val)}
|
|
615
|
+
/>
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
---
|
|
619
|
+
|
|
620
|
+
### IconPicker
|
|
621
|
+
|
|
622
|
+
```tsx
|
|
623
|
+
import { IconPicker } from 'ebig-library'
|
|
624
|
+
|
|
625
|
+
<IconPicker value={iconName} onChange={(name) => setIconName(name)} />
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
---
|
|
629
|
+
|
|
630
|
+
### EmptyPage
|
|
631
|
+
|
|
632
|
+
```tsx
|
|
633
|
+
import { EmptyPage } from 'ebig-library'
|
|
634
|
+
|
|
635
|
+
<EmptyPage
|
|
636
|
+
title="No data found"
|
|
637
|
+
subtitle="Try adjusting your filters"
|
|
638
|
+
button={<Button label="Reset" onClick={reset} />}
|
|
639
|
+
/>
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
---
|
|
643
|
+
|
|
644
|
+
### Text
|
|
645
|
+
|
|
646
|
+
Typography component that renders semantic HTML elements with typography class helpers.
|
|
647
|
+
|
|
648
|
+
```tsx
|
|
649
|
+
import { Text } from 'ebig-library'
|
|
650
|
+
|
|
651
|
+
<Text className="heading-3">Page title</Text>
|
|
652
|
+
<Text className="body-2" maxLine={2}>Truncated body text that wraps at two lines...</Text>
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
---
|
|
656
|
+
|
|
657
|
+
### ComponentStatus
|
|
658
|
+
|
|
659
|
+
```tsx
|
|
660
|
+
import { ComponentStatus, getStatusIcon } from 'ebig-library'
|
|
661
|
+
|
|
662
|
+
<ComponentStatus status="success" label="Completed" />
|
|
663
|
+
const icon = getStatusIcon('warning')
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
---
|
|
667
|
+
|
|
668
|
+
## Form Components (react-hook-form)
|
|
669
|
+
|
|
670
|
+
Pre-built form field wrappers integrating `react-hook-form`. All accept `methods` (from `useForm()`), `name`, `label`, `required`, `disabled`, `placeholder`, and `className`.
|
|
671
|
+
|
|
672
|
+
```tsx
|
|
673
|
+
import { useForm } from 'react-hook-form'
|
|
674
|
+
import {
|
|
675
|
+
TextFieldForm,
|
|
676
|
+
TextAreaForm,
|
|
677
|
+
Select1Form,
|
|
678
|
+
SelectMultipleForm,
|
|
679
|
+
CheckboxForm,
|
|
680
|
+
SwitchForm,
|
|
681
|
+
DateTimePickerForm,
|
|
682
|
+
NumberPickerForm, // NumberPicker
|
|
683
|
+
RateForm, // Rating
|
|
684
|
+
ColorPickerForm,
|
|
685
|
+
GroupCheckboxForm,
|
|
686
|
+
GroupRadioButtonForm,
|
|
687
|
+
RangeForm, // Slider
|
|
688
|
+
CKEditorForm,
|
|
689
|
+
EbigEditorForm,
|
|
690
|
+
InputPasswordForm,
|
|
691
|
+
IconPickerForm,
|
|
692
|
+
UploadMultipleFileTypeForm,
|
|
693
|
+
} from 'ebig-library'
|
|
694
|
+
|
|
695
|
+
const methods = useForm()
|
|
696
|
+
|
|
697
|
+
<form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
698
|
+
<TextFieldForm methods={methods} name="username" label="Username" required />
|
|
699
|
+
<TextFieldForm methods={methods} name="price" label="Price" type="money" />
|
|
700
|
+
<Select1Form
|
|
701
|
+
methods={methods}
|
|
702
|
+
name="category"
|
|
703
|
+
label="Category"
|
|
704
|
+
options={[{ id: '1', name: 'Tech' }, { id: '2', name: 'Finance' }]}
|
|
705
|
+
/>
|
|
706
|
+
<DateTimePickerForm methods={methods} name="dueDate" label="Due date" />
|
|
707
|
+
<EbigEditorForm methods={methods} name="description" label="Description" />
|
|
708
|
+
<Button label="Submit" type="submit" className="size40 button-primary" />
|
|
709
|
+
</form>
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
---
|
|
713
|
+
|
|
714
|
+
## Utility Class (Util)
|
|
715
|
+
|
|
716
|
+
```tsx
|
|
717
|
+
import { Util } from 'ebig-library'
|
|
718
|
+
|
|
719
|
+
// Date & Time
|
|
720
|
+
Util.dateTime_stringToDecimal('2026-04-08T10:00:00Z') // → Unix seconds
|
|
721
|
+
Util.stringToDate('08/04/2026', 'dd/mm/yyyy') // → Date
|
|
722
|
+
Util.calculateAge('01/01/2000') // → number
|
|
723
|
+
|
|
724
|
+
// Number & Currency
|
|
725
|
+
Util.formatCurrency(1500000, 'VND') // → "1,500,000.00 ₫"
|
|
726
|
+
Util.formatCurrency(99.9, 'USD') // → "$99.90"
|
|
727
|
+
Util.convertCurrency(100, 'USD', 'VND') // → 2450000
|
|
728
|
+
|
|
729
|
+
// Color
|
|
730
|
+
Util.hexToRgb('#287CF0') // → { r: 40, g: 124, b: 240 }
|
|
731
|
+
Util.rgbToHex(40, 124, 240) // → "#287cf0"
|
|
732
|
+
|
|
733
|
+
// String
|
|
734
|
+
Util.toSlug('Hello World!') // → "hello-world"
|
|
735
|
+
Util.randomGID() // → 32-char random hex ID
|
|
736
|
+
|
|
737
|
+
// Cookie
|
|
738
|
+
Util.getCookie('accessToken')
|
|
739
|
+
Util.setCookie('accessToken', token)
|
|
740
|
+
Util.clearCookie()
|
|
741
|
+
|
|
742
|
+
// File
|
|
743
|
+
Util.formatFileSize(1048576) // → "1 MB"
|
|
744
|
+
Util.stringToFile('content', 'file.txt')
|
|
745
|
+
|
|
746
|
+
// Auth
|
|
747
|
+
Util.encodeBase64('string')
|
|
748
|
+
Util.decodeBase64('encoded')
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
---
|
|
752
|
+
|
|
753
|
+
## Controllers
|
|
754
|
+
|
|
755
|
+
All controllers require `ConfigData.url` and `ConfigData.pid` to be set (done automatically by `EbigProvider`).
|
|
756
|
+
|
|
757
|
+
### DataController
|
|
758
|
+
|
|
759
|
+
Generic CRUD for any project data module.
|
|
760
|
+
|
|
761
|
+
```tsx
|
|
762
|
+
import { DataController } from 'ebig-library'
|
|
763
|
+
|
|
764
|
+
const ctrl = new DataController('Product')
|
|
765
|
+
|
|
766
|
+
// Fetch list (RediSearch query syntax)
|
|
767
|
+
const res = await ctrl.getListSimple({ page: 1, size: 20, query: '@Category:{Electronics}' })
|
|
768
|
+
|
|
769
|
+
// Get by ID
|
|
770
|
+
const item = await ctrl.getById('abc123')
|
|
771
|
+
|
|
772
|
+
// Add
|
|
773
|
+
await ctrl.add([{ Name: 'Product A', Price: 100 }])
|
|
774
|
+
|
|
775
|
+
// Edit
|
|
776
|
+
await ctrl.edit([{ Id: 'abc123', Price: 120 }])
|
|
777
|
+
|
|
778
|
+
// Delete
|
|
779
|
+
await ctrl.delete(['abc123', 'def456'])
|
|
780
|
+
|
|
781
|
+
// Aggregate / group
|
|
782
|
+
await ctrl.aggregateList({ filter: '@Price:[100 200]', sortby: [{ prop: 'Price', direction: 'ASC' }] })
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
### SettingDataController
|
|
786
|
+
|
|
787
|
+
For system-level setting entities (`report`, `chart`, `form`, `card`, `view`).
|
|
788
|
+
|
|
789
|
+
```tsx
|
|
790
|
+
import { SettingDataController } from 'ebig-library'
|
|
791
|
+
|
|
792
|
+
const ctrl = new SettingDataController('form')
|
|
793
|
+
await ctrl.getListSimple({ page: 1, size: 10 })
|
|
794
|
+
await ctrl.action('add', { data: [{ Name: 'My Form' }] })
|
|
795
|
+
await ctrl.getByIds(['id1', 'id2'])
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
### AccountController
|
|
799
|
+
|
|
800
|
+
Login, get user info, and password utilities.
|
|
801
|
+
|
|
802
|
+
```tsx
|
|
803
|
+
import { AccountController } from 'ebig-library'
|
|
804
|
+
|
|
805
|
+
const acc = new AccountController('Customer') // or 'User'
|
|
806
|
+
|
|
807
|
+
// Login with account/password
|
|
808
|
+
const res = await acc.login({ type: 'account', username: 'admin', password: 'pass' })
|
|
809
|
+
|
|
810
|
+
// Login with Google OAuth token
|
|
811
|
+
await acc.login({ type: 'google', token: googleToken })
|
|
812
|
+
|
|
813
|
+
// Get current user info
|
|
814
|
+
const info = await acc.getInfor()
|
|
815
|
+
|
|
816
|
+
// Hash a password
|
|
817
|
+
const hashed = await acc.hashPassword('mypassword')
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
### EbigController
|
|
821
|
+
|
|
822
|
+
Project-level queries (fetches eBig project metadata). **Do not change the internal API paths.**
|
|
823
|
+
|
|
824
|
+
```tsx
|
|
825
|
+
import { EbigController } from 'ebig-library'
|
|
826
|
+
|
|
827
|
+
const ctrl = new EbigController('Project')
|
|
828
|
+
const project = await ctrl.getById('your-project-id')
|
|
829
|
+
const results = await ctrl.getListSimple({ query: '@Domain:{ebig.co}', size: 1 })
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
### TableController
|
|
833
|
+
|
|
834
|
+
CRUD for schema-level settings (`table`, `column`, `rel`, `menu`, `page`, `layout`, `designtoken`, `workflow`, `process`, `step`).
|
|
835
|
+
|
|
836
|
+
```tsx
|
|
837
|
+
import { TableController } from 'ebig-library'
|
|
838
|
+
|
|
839
|
+
const ctrl = new TableController('table')
|
|
840
|
+
const tables = await ctrl.getAll()
|
|
841
|
+
await ctrl.add([{ Name: 'Orders' }])
|
|
842
|
+
await ctrl.edit([{ Id: 'xxx', Name: 'OrdersV2' }])
|
|
843
|
+
await ctrl.delete(['xxx'])
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
### IntegrationController
|
|
847
|
+
|
|
848
|
+
```tsx
|
|
849
|
+
import { IntegrationController } from 'ebig-library'
|
|
850
|
+
|
|
851
|
+
const integration = new IntegrationController()
|
|
852
|
+
await integration.sendEmail({
|
|
853
|
+
templateId: 'welcome-email',
|
|
854
|
+
templateParams: { to: 'user@example.com', name: 'Alice' }
|
|
855
|
+
})
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
### BaseDA
|
|
859
|
+
|
|
860
|
+
Low-level HTTP helpers used by all controllers. Use directly only when you need calls outside the standard controller pattern.
|
|
861
|
+
|
|
862
|
+
```tsx
|
|
863
|
+
import { BaseDA, ConfigData } from 'ebig-library'
|
|
864
|
+
|
|
865
|
+
// GET (auto-injects auth headers for ConfigData.url requests)
|
|
866
|
+
const data = await BaseDA.get(`${ConfigData.url}data/custom-endpoint`, {
|
|
867
|
+
headers: { pid: ConfigData.pid }
|
|
868
|
+
})
|
|
869
|
+
|
|
870
|
+
// POST
|
|
871
|
+
await BaseDA.post(`${ConfigData.url}data/action?action=add`, {
|
|
872
|
+
headers: { pid: ConfigData.pid, module: 'Product' },
|
|
873
|
+
body: { data: [{ Name: 'Item' }] }
|
|
874
|
+
})
|
|
875
|
+
|
|
876
|
+
// Upload files (auto-batches: max 12 files / 200 MB per batch)
|
|
877
|
+
const uploaded = await BaseDA.uploadFiles(fileList)
|
|
878
|
+
// uploaded → [{ Id, Url, Name, ... }]
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
---
|
|
882
|
+
|
|
883
|
+
## Backend-Driven Modules
|
|
884
|
+
|
|
885
|
+
Render entire UI sections driven by eBig backend configuration. Requires a valid `pid`/`url` in `EbigProvider`.
|
|
886
|
+
|
|
887
|
+
```tsx
|
|
888
|
+
import { PageById, PageByUrl, FormById, CardById, ViewById, ChartById, ChartByType } from 'ebig-library'
|
|
889
|
+
|
|
890
|
+
// Render a full page by its backend ID
|
|
891
|
+
<PageById id="page-id" />
|
|
892
|
+
|
|
893
|
+
// Render a page by URL path (matches current URL)
|
|
894
|
+
<PageByUrl url="location.pathname" />
|
|
895
|
+
|
|
896
|
+
// Render a form by ID
|
|
897
|
+
<FormById id="form-id" onSuccess={(data) => console.log(data)} />
|
|
898
|
+
|
|
899
|
+
// Render a card layout by ID
|
|
900
|
+
<CardById id="card-id" />
|
|
901
|
+
|
|
902
|
+
// Render a data view by ID
|
|
903
|
+
<ViewById id="view-id" />
|
|
904
|
+
|
|
905
|
+
// Chart by backend config ID
|
|
906
|
+
<ChartById id="chart-id" />
|
|
907
|
+
|
|
908
|
+
// Chart by type with your own data
|
|
909
|
+
<ChartByType type="bar" data={chartData} />
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
---
|
|
913
|
+
|
|
914
|
+
## Design Tokens & Theming
|
|
915
|
+
|
|
916
|
+
Design tokens are loaded from the eBig backend at runtime and injected as CSS custom properties into `<head>`. Toggle dark mode via `setTheme`:
|
|
917
|
+
|
|
918
|
+
```tsx
|
|
919
|
+
const { theme, setTheme } = useEbigContext()
|
|
920
|
+
setTheme('dark') // adds class="dark" to <html>
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
Tokens follow the pattern:
|
|
924
|
+
|
|
925
|
+
```css
|
|
926
|
+
/* Light mode */
|
|
927
|
+
--primary-main-color: #287CF0;
|
|
928
|
+
--neutral-text-title-color: #18181B;
|
|
929
|
+
|
|
930
|
+
/* Dark mode (html.dark) */
|
|
931
|
+
--primary-main-color: #4A90E2;
|
|
932
|
+
--neutral-text-title-color: #EAEAEC;
|
|
933
|
+
```
|
|
934
|
+
|
|
935
|
+
---
|
|
936
|
+
|
|
937
|
+
## Responsive Grid Classes
|
|
938
|
+
|
|
939
|
+
The layout system uses a **24-column grid**. Add these classes to children inside a `row`.
|
|
940
|
+
|
|
941
|
+
| Class | Columns | Notes |
|
|
942
|
+
|---|---|---|
|
|
943
|
+
| `col1` – `col24` | 1/24 – 24/24 | Always applied |
|
|
944
|
+
| `remain` | fills rest | `flex: 1` |
|
|
945
|
+
| `col1-min` – `col24-min` | at **< 576px** | phones |
|
|
946
|
+
| `col1-sm` – `col24-sm` | at **≥ 576px** | small devices |
|
|
947
|
+
| `col1-md` – `col24-md` | at **≥ 768px** | tablets |
|
|
948
|
+
| `col1-lg` – `col24-lg` | at **≥ 992px** | laptops |
|
|
949
|
+
| `col1-xl` – `col24-xl` | at **≥ 1200px** | desktops |
|
|
950
|
+
| `col1-xxl` – `col24-xxl` | at **> 1200px** | wide screens |
|
|
951
|
+
|
|
952
|
+
```tsx
|
|
953
|
+
// 2-column on desktop, stacks on mobile
|
|
954
|
+
<div className="row" style={{ gap: 16 }}>
|
|
955
|
+
<div className="col24 col12-lg" style={{ "--gutter": "16px" }}>Left panel</div>
|
|
956
|
+
<div className="col24 col12-lg" style={{ "--gutter": "16px" }}>Right panel</div>
|
|
957
|
+
</div>
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
---
|
|
961
|
+
|
|
962
|
+
## License
|
|
963
|
+
|
|
964
|
+
MIT © [eBig / FDITECH](https://github.com/FDITECH)
|