jb-grid 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.
Files changed (53) hide show
  1. package/README.md +7 -0
  2. package/index.js +1 -0
  3. package/package.json +32 -0
  4. package/react/README.md +195 -0
  5. package/react/dist/JBGrid.cjs.js +17989 -0
  6. package/react/dist/JBGrid.cjs.js.map +1 -0
  7. package/react/dist/JBGrid.js +17983 -0
  8. package/react/dist/JBGrid.js.map +1 -0
  9. package/react/dist/JBGrid.umd.js +17989 -0
  10. package/react/dist/JBGrid.umd.js.map +1 -0
  11. package/react/dist/common/hooks/use-event.d.ts +3 -0
  12. package/react/dist/common/hooks/useLazyRef.d.ts +4 -0
  13. package/react/dist/common/hooks/useMobx.d.ts +4 -0
  14. package/react/dist/common/scripts/device-detection.d.ts +1 -0
  15. package/react/dist/common/scripts/persian-helper.d.ts +3 -0
  16. package/react/dist/web-component/jb-grid/react/lib/Components/Cell.d.ts +10 -0
  17. package/react/dist/web-component/jb-grid/react/lib/Components/ExpandRow.d.ts +11 -0
  18. package/react/dist/web-component/jb-grid/react/lib/Components/JBLoading.d.ts +6 -0
  19. package/react/dist/web-component/jb-grid/react/lib/Components/Row.d.ts +5 -0
  20. package/react/dist/web-component/jb-grid/react/lib/Components/content-error/ContentError.d.ts +10 -0
  21. package/react/dist/web-component/jb-grid/react/lib/Content.d.ts +16 -0
  22. package/react/dist/web-component/jb-grid/react/lib/Footer.d.ts +9 -0
  23. package/react/dist/web-component/jb-grid/react/lib/Header.d.ts +22 -0
  24. package/react/dist/web-component/jb-grid/react/lib/JBGrid.d.ts +24 -0
  25. package/react/dist/web-component/jb-grid/react/lib/JBGridData.d.ts +16 -0
  26. package/react/dist/web-component/jb-grid/react/lib/JBGridViewModel.d.ts +71 -0
  27. package/react/dist/web-component/jb-grid/react/lib/Types.d.ts +124 -0
  28. package/react/dist/web-component/jb-grid/react/lib/i18n.d.ts +2 -0
  29. package/react/dist/web-component/jb-searchbar/types.d.ts +1 -0
  30. package/react/index.js +1 -0
  31. package/react/lib/Components/Cell.scss +63 -0
  32. package/react/lib/Components/Cell.tsx +19 -0
  33. package/react/lib/Components/ExpandRow.scss +37 -0
  34. package/react/lib/Components/ExpandRow.tsx +19 -0
  35. package/react/lib/Components/JBLoading.scss +140 -0
  36. package/react/lib/Components/JBLoading.tsx +30 -0
  37. package/react/lib/Components/Row.scss +25 -0
  38. package/react/lib/Components/Row.tsx +18 -0
  39. package/react/lib/Components/content-error/ContentError.tsx +20 -0
  40. package/react/lib/Components/content-error/content-error.scss +26 -0
  41. package/react/lib/Content.tsx +76 -0
  42. package/react/lib/Footer.tsx +95 -0
  43. package/react/lib/Header.tsx +70 -0
  44. package/react/lib/JBGrid.scss +350 -0
  45. package/react/lib/JBGrid.tsx +62 -0
  46. package/react/lib/JBGridBridgeExample.js +90 -0
  47. package/react/lib/JBGridData.ts +51 -0
  48. package/react/lib/JBGridViewModel.ts +476 -0
  49. package/react/lib/Types.ts +142 -0
  50. package/react/lib/_constants.scss +7 -0
  51. package/react/lib/i18n.ts +15 -0
  52. package/react/package.json +42 -0
  53. package/react/tsconfig.json +18 -0
@@ -0,0 +1,476 @@
1
+ import React, { createContext, useContext } from 'react';
2
+ import { observable, extendObservable, makeObservable, action, computed } from 'mobx';
3
+ import { ActionDispatchers, AnyObject, JBGridBridgeClassInterface, JBGridBridgeInterface, JBGridCallbacks, JBGridColumnDef, JBGridConfig, JBGridConfigInterface, JBGridFilter, JBGridI18nConfig, JBGridResponseData, JBGridRowData, JBGridRowDetail, JBGridStyles, SearchbarConfig } from './Types.js';
4
+ import { JBSearchbarWebComponent } from 'jb-searchbar';
5
+ import { defaultI18n } from './i18n.js';
6
+ import { JBSearchbarValue } from 'jb-searchbar/types.js';
7
+ import { assign } from 'lodash';
8
+ class JBGridViewModel<T extends AnyObject> {
9
+ //we write computed style of grid here
10
+ styles: JBGridStyles = {
11
+ table: {
12
+ generalCols: {
13
+ gridTemplateColumns: "auto",
14
+
15
+ },
16
+ fullWidthCol: {
17
+ gridColumn: '1 / end'
18
+ },
19
+ scrollIndent: {
20
+ width: 'calc(100% - 17px)'
21
+ },
22
+ mainRowStyle: {
23
+ gridTemplateColumns: "auto",
24
+ }
25
+ },
26
+ searchBar: {
27
+ },
28
+ contentWrapper: {
29
+ }
30
+ }
31
+ elements = {
32
+ refreshIcon: React.createRef<SVGElement>(),
33
+ searchbar: React.createRef<JBSearchbarWebComponent>()
34
+ }
35
+ //the whole component DOM store(referenced) in this variable
36
+ JBGridComponentDom: HTMLDivElement | null = null;
37
+ //keep wrapper DOM element for some pupose like wrapper changing in full screen functionality
38
+ gridWrapperElement: HTMLElement | null = null;
39
+ //when we start fetch new data from server it get true until load data is finished
40
+ isLoading = false;
41
+ //define bridge to convert grid data to server compatible data and convert server data to grid understandable format
42
+ dataBridge: JBGridBridgeInterface;
43
+ //add debounce feature to grid gotoPage function
44
+ paginationDebounce;
45
+ //keep grid searchbar height so on height
46
+ isErrorOccurred = false;
47
+ filter: JBGridFilter = {
48
+ config: null,
49
+ value: []
50
+ }
51
+ callBacks: JBGridCallbacks = {
52
+ onFullscreenChange: () => { console.error('you must set onFullscreenChange callback to jb-grid component if you want it to work'); }
53
+ }
54
+ config: JBGridConfig<T>;
55
+ i18n: JBGridI18nConfig;
56
+ constructor(onFullscreenChange: (isFullScreen: boolean) => void, config: JBGridConfigInterface<T>, bridge: JBGridBridgeClassInterface) {
57
+ makeObservable(this, {
58
+ styles: observable,
59
+ isLoading: observable,
60
+ isErrorOccurred: observable,
61
+ filter: observable,
62
+ exitFullScreenGrid: action,
63
+ fullScreenGrid: action,
64
+ goToLastPage: action,
65
+ fetchGridData: action,
66
+ initFilter: action.bound,
67
+ InitSize: action.bound,
68
+ onFetchSuccess: action.bound,
69
+ mergeObject: action,
70
+ sendFirstRequest: action,
71
+ refreshBtnClick: action.bound,
72
+ setSortColumn: action.bound,
73
+ goToPage: action.bound,
74
+ openMainHeaderSection: action.bound,
75
+ openSearchHeaderSection: action.bound,
76
+ onPageSizeChange: action.bound,
77
+ InitGrid: action.bound,
78
+ refreshData: action.bound,
79
+ showErrorPanel: action.bound,
80
+ hideErrorPanel: action.bound,
81
+ paginationDisplayNumbers: computed
82
+ });
83
+ if (config == undefined || config == null) {
84
+ //when user dont pass config prop
85
+ console.error("JBGrid need you to pass config as a prop to it \n and currently its null or undefined");
86
+ }
87
+ const observableConfig = observable(config);
88
+ this.setI18n({});
89
+ this.paginationDebounce = this.debounce(this.refreshData, 300);
90
+
91
+ //TODO:add trigger function so user can call grid functions outside of grid js file
92
+ const actionDispatchers: ActionDispatchers = Object.freeze({
93
+ refreshData: () => this.refreshData(),
94
+ fullScreenGrid: () => this.fullScreenGrid(),
95
+ exitFullScreenGrid: () => this.exitFullScreenGrid()
96
+ });
97
+ this.config = observableConfig;
98
+ this.config.actionDispatchers = actionDispatchers;
99
+ if (typeof bridge != 'function') {
100
+ //no bridge provided
101
+ }
102
+ this.dataBridge = new bridge();
103
+ if (typeof onFullscreenChange == "function") {
104
+ this.callBacks.onFullscreenChange = onFullscreenChange;
105
+ }
106
+ this.InitGrid();
107
+ }
108
+ setI18n(newValue: JBGridI18nConfig) {
109
+ //loadash assign work from left to right so newValue has top priority
110
+ this.i18n = assign({}, defaultI18n, newValue);
111
+ }
112
+ InitGrid() {
113
+ //init grid config on load or change
114
+ this.InitSize();
115
+
116
+ }
117
+ onComponentDidMount(searchbarConfig: SearchbarConfig | null) {
118
+ this.sendFirstRequest();
119
+ this.initFilter(searchbarConfig);
120
+ }
121
+ mergeObject(inputConfig: JBGridConfig<any>, defaultConfig: JBGridConfig<any>) {
122
+ const addedProperty = {};
123
+ for (const prop in defaultConfig) {
124
+ if (inputConfig[prop] == undefined || inputConfig[prop] == null) {
125
+ addedProperty[prop] = defaultConfig[prop];
126
+ }
127
+ }
128
+ extendObservable(inputConfig, addedProperty);
129
+ return inputConfig;
130
+ }
131
+ sendFirstRequest() {
132
+ this.isLoading = true;
133
+ this.fetchGridData().then(action(() => {
134
+ this.isLoading = false;
135
+ this.hideErrorPanel();
136
+ })).catch(action((e: any) => {
137
+ this.isLoading = false;
138
+ this.showErrorPanel();
139
+ }));
140
+ }
141
+ initFilter(searchbarConfig: SearchbarConfig | null) {
142
+ if (searchbarConfig && this.elements.searchbar.current) {
143
+ this.elements.searchbar.current.columnList = searchbarConfig.columnList;
144
+ this.elements.searchbar.current.searchOnChange = searchbarConfig.searchOnChange === true ? searchbarConfig.searchOnChange : false;
145
+ this.elements.searchbar.current.addEventListener('search', (e) => {
146
+ this.elements.searchbar.current!.isLoading = true;
147
+ const target = e.target as JBSearchbarWebComponent;
148
+ this.onSearch(target.value).finally(() => {
149
+ this.elements.searchbar.current!.isLoading = false;
150
+ });
151
+ });
152
+ //this.elements.searchbar.current.addEventListener('');
153
+ this.filter.config = searchbarConfig;
154
+
155
+ }
156
+ }
157
+ InitSize() {
158
+ //init table width column
159
+ const scrollWidth = this.getScrollbarWidth();
160
+ this.styles.table.scrollIndent.width = 'calc(100% - ' + scrollWidth + 'px)';
161
+ //config css grid for table layout
162
+ let gridTemplateColumns = "";
163
+ this.config.table.columns.map((item) => {
164
+ if (item.width != null || item.width != undefined) {
165
+ if (typeof (item.width) == "number") {
166
+ gridTemplateColumns += ' ' + item.width + 'px';
167
+ } else {
168
+ gridTemplateColumns += ' ' + item.width;
169
+ }
170
+
171
+ } else {
172
+ gridTemplateColumns += " 1fr";
173
+ }
174
+ });
175
+ this.styles.table.generalCols.gridTemplateColumns = gridTemplateColumns;
176
+ this.styles.table.fullWidthCol.gridColumn = "1 / " + (this.config.table.columns.length + 1);
177
+ }
178
+ getScrollbarWidth() {
179
+ const outer = document.createElement("div");
180
+ outer.style.visibility = "hidden";
181
+ outer.style.width = "100px";
182
+ document.body.appendChild(outer);
183
+
184
+ const widthNoScroll = outer.offsetWidth;
185
+ // force scrollbars
186
+ outer.style.overflow = "scroll";
187
+
188
+ // add inner div
189
+ const inner = document.createElement("div");
190
+ inner.style.width = "100%";
191
+ outer.appendChild(inner);
192
+
193
+ const widthWithScroll = inner.offsetWidth;
194
+
195
+ // remove div's
196
+ outer.parentNode?.removeChild(outer);
197
+
198
+ return widthNoScroll - widthWithScroll;
199
+ }
200
+ fetchGridData() {
201
+ const fetchGridDataPromise = new Promise((resolve, reject) => {
202
+ const requestBody = this.CreateRequestBody();
203
+ this.dataBridge.getData(this.config.data.requestParams, requestBody).then(action((data) => {
204
+ const bridgeData = this.dataBridge.mapServerResponseDataToGridData(data);
205
+ if (bridgeData.pageIndex == this.config.page.index) {
206
+ this.config.data.data = [];
207
+ //check user don't change page during loading time if he do we wait for latest response
208
+ this.standardData(bridgeData.content).then((content: JBGridRowData<T>[]) => {
209
+ const data = { ...bridgeData, content };
210
+ this.onFetchSuccess(data);
211
+ resolve(null);
212
+ });
213
+ } else {
214
+ console.error('jb-grid requested page index is different from response page index it maybe a bridge problem or server data problem');
215
+ }
216
+ })).catch((err) => {
217
+ reject(err);
218
+ });
219
+ });
220
+ return fetchGridDataPromise;
221
+ }
222
+ onFetchSuccess(data: JBGridResponseData<T>) {
223
+ this.config.data.data = data.content;
224
+ this.config.data.metaData.startItemIndex = data.startItemIndex;
225
+ this.config.data.metaData.endItemIndex = data.endItemIndex;
226
+ this.config.data.metaData.totalItemsCount = data.totalItemsCount;
227
+ this.config.page.totalPages = data.totalPages;
228
+ }
229
+ standardData(data: AnyObject[]) {
230
+ return new Promise<JBGridRowData<T>[]>((resolve) => {
231
+ const items: JBGridRowData<AnyObject>[] = data.map((item) => {
232
+ const detail: JBGridRowDetail = {
233
+ jbGridDetail: {
234
+ isDeleting: false,
235
+ isDeleted: false,
236
+ isRecovering: false,
237
+ isExpanded: false
238
+ }
239
+ };
240
+ const row: JBGridRowData<AnyObject> = Object.assign({}, item, detail);
241
+ return row;
242
+ });
243
+ //in case of user want to modify or add custom field to our observable array
244
+ if (typeof this.config.callbacks.onDataStandardizing == "function") {
245
+ const response = this.config.callbacks.onDataStandardizing<T>(items);
246
+ if (response instanceof Promise) {
247
+ response.then((content) => {
248
+ resolve(content);
249
+ });
250
+ } else {
251
+ resolve(response);
252
+ }
253
+ //end of callback block
254
+ } else {
255
+ resolve(items as JBGridRowData<T>[]);
256
+ }
257
+
258
+
259
+
260
+ });
261
+
262
+ }
263
+ CreateRequestBody() {
264
+ const sortColumn = this.config.table.columns.find(x => x.sort) || null;
265
+ const requestBody = this.dataBridge.createRequestBody(this.config.page, this.filter.value, sortColumn, this.config.data);
266
+ return requestBody;
267
+ }
268
+
269
+ goToNextPage() {
270
+ const currentPage = this.config.page.index;
271
+ if (currentPage < this.config.page.totalPages) {
272
+ this.goToPage(currentPage + 1);
273
+ }
274
+
275
+ }
276
+ goToPrevPage() {
277
+ const currentPage = this.config.page.index;
278
+ if (currentPage > 1) {
279
+ this.goToPage(currentPage - 1);
280
+ }
281
+
282
+ }
283
+ goToLastPage() {
284
+ const currentPage = this.config.page.index;
285
+ if (currentPage != this.config.page.totalPages) {
286
+ this.goToPage(this.config.page.totalPages);
287
+ }
288
+
289
+ }
290
+ goToFirstPage() {
291
+ const currentPage = this.config.page.index;
292
+ if (currentPage != 1) {
293
+ this.goToPage(1);
294
+ }
295
+
296
+ }
297
+ refreshBtnClick() {
298
+ const anime = this.playRefreshBtnAnimation();
299
+ this.refreshData().then(() => {
300
+ this.stopRefreshBtnAnimation(anime);
301
+ }).catch((e) => {
302
+ console.error('Error while refreshing data', e);
303
+ this.stopRefreshBtnAnimation(anime);
304
+ });
305
+ }
306
+ playRefreshBtnAnimation() {
307
+ const anime = this.elements.refreshIcon.current!.animate([{ transform: "rotate(0deg)" }, { transform: "rotate(360deg)" }], { id: 'rotate', duration: 400, direction: "reverse", iterations: Infinity });
308
+ return anime;
309
+ }
310
+ stopRefreshBtnAnimation(anime: Animation) {
311
+ anime.cancel();
312
+ }
313
+ goToPage(destinationPageIndex: number) {
314
+ return new Promise((resolve, reject) => {
315
+ //for navigate in pages you must call this function and every other way is forbidden
316
+ this.config.page.index = destinationPageIndex;
317
+ this.paginationDebounce()
318
+ .then(() => {
319
+ resolve(null);
320
+ if (this.config.callbacks.onPageIndexChange) {
321
+ this.config.callbacks.onPageIndexChange(destinationPageIndex);
322
+ }
323
+ }).catch((e: any) => {
324
+ reject(e);
325
+ });
326
+ });
327
+ }
328
+ debounce(func: (...args: any[]) => any, delay: number) {
329
+ //create a waiting time for serial function call and execute last function execute request
330
+ let inDebounce: ReturnType<typeof setTimeout>;
331
+ const debounceInstance = (...inputs: any[]) => {
332
+ return new Promise((resolve, reject) => {
333
+ const self: JBGridViewModel<T> = this;
334
+ const args = inputs;
335
+ clearTimeout(inDebounce);
336
+ inDebounce = setTimeout(
337
+ () => func.apply(self, args)
338
+ .then((args: any) => {
339
+ resolve(args);
340
+ }).catch((e: Error) => { reject(e); })
341
+ , delay);
342
+ });
343
+ };
344
+ return debounceInstance;
345
+ }
346
+ refreshData(): Promise<void> {
347
+ const refreshDataPromise = new Promise<void>((resolve, reject) => {
348
+ this.isLoading = true;
349
+ this.fetchGridData().then(action(() => {
350
+ this.isLoading = false;
351
+ this.hideErrorPanel();
352
+ resolve();
353
+ })).catch(action((e) => {
354
+ this.isLoading = false;
355
+ this.showErrorPanel();
356
+ reject(e);
357
+ }));
358
+ });
359
+ //every time we need to change showing data we must call this func
360
+ return refreshDataPromise;
361
+ }
362
+ onSearch(filterList: JBSearchbarValue) {
363
+ this.filter.value = filterList;
364
+ const onSearchPromise = new Promise((resolve, reject) => {
365
+ //reset pagination when filter change
366
+ this.goToPage(1).then(() => {
367
+ resolve(null);
368
+ }).catch((e) => {
369
+ reject(e);
370
+ });
371
+ });
372
+ return onSearchPromise;
373
+ }
374
+ onPageSizeChange(e) {
375
+ this.config.page.size = parseInt(e.target.value);
376
+ this.goToPage(1);
377
+ }
378
+ onFullScreenBtnClicked(currentValue: boolean) {
379
+ const newValue = !currentValue;
380
+ this.callBacks.onFullscreenChange(newValue);
381
+ }
382
+ onFullscreenChanged(newValue: boolean) {
383
+ if (newValue == true) {
384
+ this.fullScreenGrid();
385
+ } else {
386
+ this.exitFullScreenGrid();
387
+ }
388
+ }
389
+ fullScreenGrid() {
390
+ //TODO: handle if another grid is open before new request come up
391
+ const container = document.createElement('div');
392
+ container.classList.add('jb-grid-full-screen-container');
393
+ document.body.append(container);
394
+ this.JBGridComponentDom;
395
+ const child = document.createElement('div');
396
+ child.innerHTML = "";
397
+ this.gridWrapperElement = this.JBGridComponentDom!.parentElement!;
398
+ container.append(this.JBGridComponentDom as Node);
399
+ //TODO:call on full screen call back
400
+ }
401
+ exitFullScreenGrid() {
402
+ const container = document.querySelector('.jb-grid-full-screen-container') as HTMLDivElement;
403
+ if (this.gridWrapperElement) {
404
+ //put grid element back to their orginal place
405
+ this.gridWrapperElement.append(this.JBGridComponentDom as Node);
406
+ //remove added temp fullscreen container
407
+ }
408
+ container[0].remove();
409
+ }
410
+ setSortColumn(column: JBGridColumnDef) {
411
+ if (column.sortable) {
412
+ if (column.sort) {
413
+ //if we just change sort order
414
+ column.sort = column.sort.toUpperCase() == "ASC" ? "DESC" : "ASC";
415
+ } else {
416
+ //we user chnge sort column
417
+ const prevColumnSort = this.config.table.columns.find(x => x.sort);
418
+ if (prevColumnSort) {
419
+ prevColumnSort.sort = undefined;
420
+ }
421
+ column.sort = "ASC";
422
+ }
423
+ this.refreshData();
424
+ }
425
+ }
426
+ changePageNumberToInput() {
427
+ //when user click on page number
428
+ //TODO: change page Input method to text input
429
+ const pageNumber: string | null = prompt(this.i18n.messages.EnterPageNumberMessage, this.config.page.totalPages.toString());
430
+ if (pageNumber && parseInt(pageNumber) > 0 && parseInt(pageNumber) < this.config.page.totalPages) {
431
+ this.goToPage(parseInt(pageNumber));
432
+ }
433
+ }
434
+ openSearchHeaderSection() {
435
+ this.elements.searchbar.current?.focus();
436
+ this.config.states.headerSection = "SEARCH";
437
+ }
438
+ openMainHeaderSection() {
439
+ this.config.states.headerSection = "MAIN";
440
+ }
441
+ showErrorPanel() {
442
+ //when we couldn't connect to server or get error from server for our request we show error panel to user
443
+ this.isErrorOccurred = true;
444
+ }
445
+ hideErrorPanel() {
446
+ this.isErrorOccurred = false;
447
+ }
448
+ get paginationDisplayNumbers() {
449
+ return {
450
+ currentPage: this.toPersianNumber(this.config.page.index),
451
+ nextPage: this.config.page.index + 1 <= this.config.page.totalPages ? this.toPersianNumber(this.config.page.index + 1) : "",
452
+ next2Page: this.config.page.index + 2 <= this.config.page.totalPages ? this.toPersianNumber(this.config.page.index + 2) : "",
453
+ prevPage: this.config.page.index - 1 > 0 ? this.toPersianNumber(this.config.page.index - 1) : "",
454
+ prev2Page: this.config.page.index - 2 > 0 ? this.toPersianNumber(this.config.page.index - 2) : "",
455
+ totalItemsCount: this.toPersianNumber(this.config.data.metaData.totalItemsCount),
456
+ startItemIndex:this.toPersianNumber(this.config.data.metaData.startItemIndex),
457
+ endItemIndex:this.toPersianNumber(this.config.data.metaData.endItemIndex),
458
+ pageSizes:[this.toPersianNumber(20),this.toPersianNumber(30),this.toPersianNumber(50),this.toPersianNumber(100)]
459
+ };
460
+ }
461
+ toPersianNumber(input: string | number) {
462
+ if (this.i18n.showPersianNumber) {
463
+ const inputString = input.toString();
464
+ const correctedString = inputString.replace(/[0-9]/g, function (word) {
465
+ return String.fromCharCode(1776 + parseInt(word));
466
+ });
467
+ return correctedString;
468
+ }
469
+ return input;
470
+ }
471
+
472
+ }
473
+
474
+ export default JBGridViewModel;
475
+ export const JBGridContext = createContext<JBGridViewModel<AnyObject> | null>(null);
476
+ export const useJBGridVM = () => useContext(JBGridContext);
@@ -0,0 +1,142 @@
1
+ import { FilterColumn, JBSearchbarValue } from "jb-searchbar/types.js";
2
+
3
+
4
+ // export type JBGridRowData = {
5
+ // [key: keyof T]: any,
6
+ // jbGridDetail: {
7
+ // isDeleting: boolean,
8
+ // isDeleted: boolean,
9
+ // isRecovering: boolean,
10
+ // isExpanded: boolean
11
+ // }
12
+ // }
13
+ export type JBGridRowDataDetail = {
14
+ isDeleting: boolean,
15
+ isDeleted: boolean,
16
+ isRecovering: boolean,
17
+ isExpanded: boolean
18
+ }
19
+ export type JBGridRowDetail = { jbGridDetail: JBGridRowDataDetail };
20
+ export type AnyObject = {
21
+ [key: string]: any;
22
+ }
23
+ export type JBGridStyles = {
24
+ table: {
25
+ generalCols: {
26
+ gridTemplateColumns: string,
27
+
28
+ },
29
+ fullWidthCol: {
30
+ gridColumn: string
31
+ },
32
+ scrollIndent: {
33
+ width: string
34
+ },
35
+ mainRowStyle: {
36
+ gridTemplateColumns: string,
37
+ }
38
+ },
39
+ searchBar: any,
40
+ contentWrapper: any
41
+ }
42
+ export type JBGridRowData<T extends AnyObject> = T & JBGridRowDetail;
43
+
44
+ export type JBGridResponseData<T extends AnyObject> = {
45
+ pageIndex: number,
46
+ startItemIndex: number,
47
+ endItemIndex: number,
48
+ totalItemsCount: number,
49
+ totalPages: number,
50
+ content: JBGridRowData<T>[],
51
+ }
52
+ export type JBGridFilter = {
53
+ config: SearchbarConfig | null,
54
+ value: JBSearchbarValue
55
+ }
56
+ export type SearchbarConfig = {
57
+ columnList: FilterColumn[],
58
+ searchOnChange: boolean
59
+ }
60
+ export interface JBGridBridgeInterface {
61
+ mapServerResponseDataToGridData: (data: any) => JBGridResponseData<any>,
62
+ getData: (data: JBGridConfigRequestParams, requestBody: any) => Promise<any>,
63
+ createRequestBody: (page: JBGridDataPage, filter?: JBSearchbarValue, sortColumn?: JBGridColumnDef | null, requestConfig?: JBGridConfigRequestParams) => any
64
+ }
65
+ // export interface JBGridBridgeClassInterface {
66
+ // new(): JBGridBridgeInterface
67
+ // }
68
+ type ClassBuilder<I, Args extends any[] = any[]> = new (...args: Args) => I;
69
+
70
+ export type JBGridBridgeClassInterface = ClassBuilder<JBGridBridgeInterface, []>;
71
+ //
72
+ export type JBGridDataPage = {
73
+ index: number,
74
+ size: number,
75
+ totalPages: number,
76
+ }
77
+ export type JBGridColumnDef = {
78
+ width?: string | number,
79
+ sort?: "ASC" | "DESC" | undefined,
80
+ sortable?: boolean,
81
+ id: number,
82
+ title: string,
83
+ name: string
84
+ }
85
+ export type JBGridConfigRequestParams = {
86
+ method?: "POST" | "GET",
87
+ url?: string,
88
+ //user can add any parameter needed to create request in his app
89
+ [key: string]: any
90
+ }
91
+ export type JBGridDataConfig<T extends AnyObject> = {
92
+ data: JBGridRowData<T>[],
93
+ //TODO: make it as a Generic type so user can standard it in whole app
94
+ requestParams: JBGridConfigRequestParams,
95
+ metaData: {
96
+ startItemIndex: number,
97
+ endItemIndex: number,
98
+ totalItemsCount: number
99
+ }
100
+ };
101
+ export type JBGridTableConfig = {
102
+ columns: JBGridColumnDef[]
103
+ }
104
+ export type JBGridConfigStates = {
105
+ headerSection: 'MAIN' | "SEARCH",
106
+ isFullScreen: boolean
107
+ }
108
+ export type JBGridCallbackConfig<T extends AnyObject> = {
109
+ onDataStandardizing: ((data: JBGridRowData<AnyObject>[]) => JBGridRowData<T>[]) | (<T extends AnyObject>(data: JBGridRowData<AnyObject>[]) => Promise<JBGridRowData<T>[]>) | null | undefined,
110
+ onPageIndexChange: ((newPageIndex: number) => unknown) | null | undefined
111
+ }
112
+ export type JBGridI18nMessage = {
113
+ serverErrorText?: string,
114
+ serverErrorTitle?: string,
115
+ serverErrorRefreshButtonTitle?: string,
116
+ EnterPageNumberMessage?: string,
117
+ currentAvailableItem?: string,
118
+ pageItemCount?:string,
119
+ from?:string
120
+ }
121
+ export type JBGridI18nConfig = {
122
+ messages?: JBGridI18nMessage,
123
+ showPersianNumber?: boolean
124
+ }
125
+ export type ActionDispatchers = Readonly<{
126
+ refreshData: () => Promise<void>,
127
+ fullScreenGrid: () => void,
128
+ exitFullScreenGrid: () => void
129
+ }>
130
+ export interface JBGridConfigInterface<T extends AnyObject> {
131
+
132
+ table: JBGridTableConfig
133
+ data: JBGridDataConfig<T>,
134
+ page: JBGridDataPage,
135
+ callbacks: JBGridCallbackConfig<T>,
136
+ actionDispatchers?: ActionDispatchers,
137
+ states: JBGridConfigStates,
138
+ }
139
+ export type JBGridConfig<T extends AnyObject> = JBGridConfigInterface<T>;
140
+ export type JBGridCallbacks = {
141
+ onFullscreenChange: (isFullscreen: boolean) => void
142
+ }
@@ -0,0 +1,7 @@
1
+ $tablet-width: 768px;
2
+ @mixin tablet {
3
+ @media (max-width: #{$tablet-width}) {
4
+ @content;
5
+ }
6
+ }
7
+ $BaseGridRowColor: #f9f9f9;
@@ -0,0 +1,15 @@
1
+ import { JBGridI18nConfig, JBGridI18nMessage } from "./Types.js";
2
+
3
+ const i18nMessages:JBGridI18nMessage = {
4
+ EnterPageNumberMessage:"شماره صفحه ای که میخواهید وارد آن شوید را وارد کنید",
5
+ serverErrorText:"متاسفانه در هنگام بارگذاری اطلاعات خطایی رخ داده است",
6
+ serverErrorTitle:"すみません",
7
+ serverErrorRefreshButtonTitle:"تلاش مجدد",
8
+ currentAvailableItem:"تعداد کل ایتم های موجود",
9
+ pageItemCount:"تعداد آیتم در هر صفحه",
10
+ from:"از",
11
+ };
12
+ export const defaultI18n:JBGridI18nConfig = {
13
+ messages: i18nMessages,
14
+ showPersianNumber:false
15
+ };
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "jb-grid-react",
3
+ "description": "react mobx jb grid table",
4
+ "type": "module",
5
+ "author": {
6
+ "name": "mohammad javad bathaei",
7
+ "email": "javadbat@gmail.com"
8
+ },
9
+ "keywords": [
10
+ "jb",
11
+ "jb-grid",
12
+ "jb-grid react",
13
+ "grid",
14
+ "table",
15
+ "react table",
16
+ "react",
17
+ "mobx"
18
+ ],
19
+ "version": "0.20.2",
20
+ "bugs": "https://github.com/javadbat/jb-grid/issues",
21
+ "license": "MIT",
22
+ "files": [
23
+ "LICENSE",
24
+ "README.md",
25
+ "lib/",
26
+ "dist/",
27
+ "index.js"
28
+ ],
29
+ "main": "index.js",
30
+ "types": "./dist/web-component/jb-grid/react/lib/JBGrid.d.ts",
31
+ "jsnext:main":"index.js",
32
+ "module": "index.js",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git@github.com:javadbat/jb-grid.git"
36
+ },
37
+ "dependencies": {
38
+ "mobx":">=6.0.0",
39
+ "mobx-react":">=7.0.0",
40
+ "jb-searchbar":">=2.3.1"
41
+ }
42
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".",
4
+ },
5
+ "include": [
6
+ "../../../common/scripts/**/*.ts",
7
+ "../../../common/hooks/**/*.ts",
8
+ "../../../common/hooks/**/*.js",
9
+ "lib/**/*.ts",
10
+ "lib/**/*.tsx"
11
+ ],
12
+ "exclude": [
13
+ "node_modules",
14
+ "**/*.spec.ts",
15
+ "dist",
16
+ ],
17
+ "extends":"../../tsconfig-react.json"
18
+ }