@mkt-loitd/react-table-grid-custom 1.4.6 → 1.4.7

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/dist/index.js CHANGED
@@ -204,34 +204,7 @@ var import_lodash3 = require("lodash");
204
204
  var import_react2 = require("react");
205
205
  var import_react_data_grid = require("react-data-grid");
206
206
  var import_styles = require("react-data-grid/lib/styles.css");
207
-
208
- // src/component/Icons.tsx
209
207
  var import_jsx_runtime = require("react/jsx-runtime");
210
- var LoadingIcon = ({
211
- isSpin = false,
212
- h = 30,
213
- w = 30,
214
- size = 30,
215
- className
216
- }) => {
217
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
218
- "svg",
219
- {
220
- className: `${isSpin ? "animate-spin" : ""} ${className != null ? className : ""}`,
221
- viewBox: "0 0 1024 1024",
222
- focusable: "false",
223
- "data-icon": "loading",
224
- width: size || w,
225
- height: size || h,
226
- fill: "currentColor",
227
- "aria-hidden": "true",
228
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z" })
229
- }
230
- );
231
- };
232
-
233
- // src/component/ui/Table/ReactTableGridCustom.tsx
234
- var import_jsx_runtime2 = require("react/jsx-runtime");
235
208
  var ReactTableGridCustomInner = (props) => {
236
209
  const {
237
210
  classNameWapperTable,
@@ -271,7 +244,7 @@ var ReactTableGridCustomInner = (props) => {
271
244
  renderHeaderCell: () => {
272
245
  if (!onSelectedRowsChange) return null;
273
246
  const allSelected = (selectedRows == null ? void 0 : selectedRows.size) === data.length && data.length > 0;
274
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
247
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
275
248
  "input",
276
249
  {
277
250
  type: "checkbox",
@@ -290,7 +263,7 @@ var ReactTableGridCustomInner = (props) => {
290
263
  },
291
264
  renderCell: ({ row }) => {
292
265
  const key = customRowKeyGetter(row);
293
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
266
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
294
267
  "input",
295
268
  {
296
269
  type: "checkbox",
@@ -339,30 +312,27 @@ var ReactTableGridCustomInner = (props) => {
339
312
  pageSize,
340
313
  selectColumn
341
314
  ]);
342
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
315
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
343
316
  "div",
344
317
  {
345
318
  className: cn(
346
319
  "wapper_table flex flex-col h-full min-h-0 relative",
347
320
  classNameWapperTable
348
321
  ),
349
- children: [
350
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
351
- import_react_data_grid.DataGrid,
352
- {
353
- rows: data,
354
- columns: newColumns,
355
- selectedRows,
356
- onSelectedRowsChange,
357
- rowKeyGetter: isSelectRow ? customRowKeyGetter : void 0,
358
- sortColumns,
359
- onSortColumnsChange,
360
- onCellClick: ({ row, rowIdx }) => onRowClick == null ? void 0 : onRowClick(row, rowIdx),
361
- onCellDoubleClick: ({ row, rowIdx }) => onRowDoubleClick == null ? void 0 : onRowDoubleClick(row, rowIdx)
362
- }
363
- ),
364
- fetching && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "absolute inset-0 flex items-center justify-center bg-white/60 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LoadingIcon, { isSpin: true }) })
365
- ]
322
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
323
+ import_react_data_grid.DataGrid,
324
+ {
325
+ rows: data,
326
+ columns: newColumns,
327
+ selectedRows,
328
+ onSelectedRowsChange,
329
+ rowKeyGetter: isSelectRow ? customRowKeyGetter : void 0,
330
+ sortColumns,
331
+ onSortColumnsChange,
332
+ onCellClick: ({ row, rowIdx }) => onRowClick == null ? void 0 : onRowClick(row, rowIdx),
333
+ onCellDoubleClick: ({ row, rowIdx }) => onRowDoubleClick == null ? void 0 : onRowDoubleClick(row, rowIdx)
334
+ }
335
+ )
366
336
  }
367
337
  );
368
338
  };
@@ -372,7 +342,7 @@ var ReactTableGridCustom = (0, import_react2.memo)(
372
342
 
373
343
  // src/component/ui/Table/TableStyleContextWapper.tsx
374
344
  var import_react3 = require("react");
375
- var import_jsx_runtime3 = require("react/jsx-runtime");
345
+ var import_jsx_runtime2 = require("react/jsx-runtime");
376
346
  var isClient = typeof window !== "undefined";
377
347
  var TableStyleContextWapperInner = ({
378
348
  children,
@@ -380,11 +350,11 @@ var TableStyleContextWapperInner = ({
380
350
  idWapper: externalId
381
351
  }) => {
382
352
  if (!isClient) {
383
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children });
353
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
384
354
  }
385
355
  const reactId = (0, import_react3.useId)();
386
356
  const idWapper = externalId != null ? externalId : reactId;
387
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
357
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
388
358
  "div",
389
359
  {
390
360
  id: `wapper_menu_context-${idWapper}`,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/helpers/functions.ts","../src/helpers/table.ts","../src/utils.ts","../src/hooks/useShowHideColumn.ts","../src/type/table.ts","../src/component/ui/Table/ReactTableGridCustom.tsx","../src/component/Icons.tsx","../src/component/ui/Table/TableStyleContextWapper.tsx"],"sourcesContent":["/* =========================\n * Common types\n * ========================= */\nexport interface IPaginationParams {\n pageSize?: number\n page?: number\n}\n\nexport type Maybe<T> = T | undefined | null\n\n/* =========================\n * Hooks\n * ========================= */\nexport { useShowHideColumn } from './hooks/useShowHideColumn'\n\n/* =========================\n * Components (runtime-safe)\n * ========================= */\nexport { ReactTableGridCustom } \nfrom './component/ui/Table/ReactTableGridCustom'\n\n/* =========================\n * EXPORT TYPES (100% SAFE)\n * ========================= */\n\n// table\nexport type {\n IReactTableGridCustom\n} from './component/ui/Table/table-type'\n\n// columns\nexport type {\n TColumnsTable\n} from './type/table-type'\n\n// react-data-grid (types only)\nexport type {\n Column,\n ColumnOrColumnGroup\n} from 'react-data-grid'\n\n/* =========================\n * TableStyleContextWapper\n * ========================= */\nexport { TableStyleContextWapper }\nfrom './component/ui/Table/TableStyleContextWapper'\n\nexport type { TableStyleWapperProps }\nfrom './component/ui/Table/TableStyleContextWapper'\n\nexport { getTableStyleWapperId }\nfrom './component/ui/Table/TableStyleContextWapper'\n\n","import { deleteDB, IDBPDatabase, openDB } from 'idb'\nimport { pickBy } from 'lodash'\nimport moment from 'moment'\nimport { optionSelect } from '../type/preload-stubs'\nimport { IObjectParams, IToggleValues } from '../type/renderer'\nexport const setLocalStore = (key: string, value: string): void => {\n if (typeof window !== 'undefined') {\n localStorage.setItem(key, value)\n }\n}\n\nexport const getLocalStore = (key: string): string | null => {\n if (typeof window !== 'undefined') {\n return localStorage.getItem(key)\n } else {\n return null\n }\n}\n\nexport function convertViToEn(str: string, toUpperCase = false): string {\n str = str.toLowerCase()\n str = str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g, 'a')\n str = str.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g, 'e')\n str = str.replace(/ì|í|ị|ỉ|ĩ/g, 'i')\n str = str.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g, 'o')\n str = str.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g, 'u')\n str = str.replace(/ỳ|ý|ỵ|ỷ|ỹ/g, 'y')\n str = str.replace(/đ/g, 'd')\n // Some system encode vietnamese combining accent as individual utf-8 characters\n str = str.replace(/\\u0300|\\u0301|\\u0303|\\u0309|\\u0323/g, '') // Huyền sắc hỏi ngã nặng\n str = str.replace(/\\u02C6|\\u0306|\\u031B/g, '') // Â, Ê, Ă, Ơ, Ư\n\n return toUpperCase ? str.toUpperCase() : str\n}\n\nexport const convertNumber = (value: number | string): { value: number; check: boolean } => {\n let num = 0\n if (value) {\n value = value.toString().replace(/[.]/g, '')\n value = value.trim()\n num = Number(value)\n }\n\n const regex = /^-?\\d*$/\n const check = regex.test(num.toString())\n return {\n value: num,\n check\n }\n}\n\nexport const changeTitleDocmemt = (title?: string): void => {\n document.title = `${title} - Phần Mềm MKT`\n}\n\nexport const numberConvert = (num: string | number): string => {\n let t = '0'\n if (num) {\n if (typeof num === 'string') {\n num = Number(num)\n }\n t = num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.')\n }\n return t\n}\n\nexport const pickBySearch = <T extends Record<string, unknown>>(obj: T): Partial<T> => {\n const filteredObj = pickBy(obj, (value) => value !== '')\n return filteredObj as Partial<T>\n}\n\nexport const getValueSelected = (value?: unknown, options?: optionSelect[]): optionSelect[] => {\n const currentValue = (options ?? [])?.filter((otp) => {\n return Array.isArray(value) ? value?.includes(otp.value) : otp?.value === value\n })\n return currentValue\n}\n\nexport const toggleValues = ({ array, value }: IToggleValues): string[] => {\n if (array.includes(value)) {\n return array.filter((item) => item !== value)\n } else {\n return [...array, value]\n }\n}\n\nexport const arrayLocal = (array?: string): string[] => {\n try {\n const data = array ? JSON.parse(array) : []\n return Array.isArray(data) ? data : []\n } catch {\n return []\n }\n}\n\nexport const formatDate = (\n date?: string | number | Date,\n format: string = 'DD/MM/YYYY HH:mm:ss A'\n): string => {\n return moment(date).format(format)\n}\n\nexport const parseObject = (obj?: string): object => {\n try {\n const data = obj ? JSON.parse(obj) : {}\n return typeof data === 'object' ? data : {}\n } catch {\n return {}\n }\n}\nexport const bufferToBlob = (buffer: ArrayBuffer | Uint8Array, type: string): Blob => {\n return new Blob([buffer as BlobPart], { type })\n}\nconst DB_NAME = 'appDB'\nconst DB_VERSION = 5\nconst STORE_NAME = 'selectedRecords'\nconst HISTORY_STORE = 'recordHistory'\ninterface SelectedRecordEntry {\n actionType: string\n selectedRecords: string[]\n}\n\ninterface RecordHistoryEntry {\n id: string\n previousAction: string[]\n}\n\ntype AppDBSchema = {\n selectedRecords: SelectedRecordEntry\n recordHistory: RecordHistoryEntry\n}\n\nconst requiredStores = [STORE_NAME, HISTORY_STORE]\n\nconst createAppDB = async (): Promise<IDBPDatabase<AppDBSchema>> => {\n return openDB<AppDBSchema>(DB_NAME, DB_VERSION, {\n upgrade(db) {\n for (const storeName of Array.from(db.objectStoreNames)) {\n db.deleteObjectStore(storeName)\n }\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n const store = db.createObjectStore(STORE_NAME, {\n keyPath: 'actionType'\n })\n store.createIndex('by_actionType', 'actionType')\n }\n\n if (!db.objectStoreNames.contains(HISTORY_STORE)) {\n db.createObjectStore(HISTORY_STORE, { keyPath: 'id' })\n }\n }\n })\n}\n\nexport const openAppDB = async (): Promise<IDBPDatabase<AppDBSchema>> => {\n try {\n const db = await createAppDB()\n const hasAllStores = requiredStores.every((store) => db.objectStoreNames.contains(store))\n if (!hasAllStores) {\n console.warn('[IndexedDB] Missing required stores. Resetting DB...')\n db.close()\n await deleteDB(DB_NAME)\n return await createAppDB()\n }\n return db\n } catch (error) {\n if ((error as { name: string })?.name === 'VersionError') {\n console.warn('[IndexedDB] Version downgrade detected. Resetting DB...')\n await deleteDB(DB_NAME)\n return await createAppDB()\n }\n\n console.error('[IndexedDB] Failed to open DB:', error)\n throw error\n }\n}\n\nexport const saveSelectedRecords = async (\n ACTION_TYPE: string,\n selectedRecords: Set<string>\n): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction(STORE_NAME, 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n\n const data: SelectedRecordEntry = {\n actionType: ACTION_TYPE,\n selectedRecords: Array.from(selectedRecords)\n }\n\n await store.put(data)\n await tx.done\n}\n\nexport const getSelectedRecords = async (ACTION_TYPE: string): Promise<Set<string>> => {\n const db = await openAppDB()\n const store = db.transaction(STORE_NAME).objectStore(STORE_NAME)\n\n const record = await store.get(ACTION_TYPE)\n\n return new Set(record?.selectedRecords ?? [])\n}\nexport const removeUidsFromAllPathsAndSaveHistory = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction([STORE_NAME, HISTORY_STORE], 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n const historyStore = tx.objectStore(HISTORY_STORE)\n\n const allRecords = await store.getAll()\n\n const historyMap: Record<string, string[]> = {}\n\n for (const uid of uids) {\n historyMap[uid] = []\n }\n\n for (const record of allRecords) {\n let updated = false\n\n for (const uid of uids) {\n if (record.selectedRecords.includes(uid)) {\n record.selectedRecords = record.selectedRecords.filter((id: string) => id !== uid)\n historyMap[uid].push(record.actionType)\n updated = true\n }\n }\n\n if (updated) {\n await store.put(record)\n }\n }\n\n // Ghi lại lịch sử path đã bị xóa cho từng UID\n for (const [uid, paths] of Object.entries(historyMap)) {\n if (paths.length > 0) {\n await historyStore.put({ id: uid, previousAction: paths })\n }\n }\n\n await tx.done\n}\n\nexport const restoreUidsToPreviousPaths = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction([STORE_NAME, HISTORY_STORE], 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n const historyStore = tx.objectStore(HISTORY_STORE)\n\n for (const uid of uids) {\n const history = await historyStore.get(uid)\n if (history?.previousAction?.length) {\n for (const actionType of history.previousAction) {\n const record = (await store.get(actionType)) || {\n actionType,\n selectedRecords: []\n }\n\n if (!record.selectedRecords.includes(uid)) {\n record.selectedRecords.push(uid)\n }\n\n await store.put(record)\n }\n\n await historyStore.delete(uid)\n }\n }\n\n await tx.done\n}\nexport const deleteUidsCompletely = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction(['selectedRecords', 'recordHistory'], 'readwrite')\n const store = tx.objectStore('selectedRecords')\n const historyStore = tx.objectStore('recordHistory')\n\n const allRecords = await store.getAll()\n\n for (const record of allRecords) {\n const originalLength = record.selectedRecords.length\n record.selectedRecords = record.selectedRecords.filter((id: string) => !uids.includes(id))\n\n if (record.selectedRecords.length !== originalLength) {\n await store.put(record)\n }\n }\n for (const uid of uids) {\n await historyStore.delete(uid)\n }\n\n await tx.done\n}\n\nexport const getSelectedCategoryDataByPath = (): string[] => {\n try {\n const saved = localStorage.getItem('selectedCategoryData')\n if (saved) {\n const data = JSON.parse(saved)\n const localPath = window.location.hash.replace(/^#/, '') || '/'\n const categoryData = data[localPath]\n if (categoryData && Array.isArray(categoryData.categoryIds)) {\n return categoryData.categoryIds\n }\n }\n } catch (err) {\n console.warn('Failed to parse localStorage category data:', err)\n }\n\n return []\n}\n\nexport const handleAsyncConfigSearchInitialValue = (): IObjectParams => {\n const defaultConfig: IObjectParams = {\n page: 1,\n pageSize: 1000,\n filterType: 'all'\n }\n\n const categoryIds = getSelectedCategoryDataByPath()\n if (categoryIds.length > 0) {\n return {\n ...defaultConfig,\n categoryId: categoryIds\n }\n }\n\n return defaultConfig\n}\n","import { ICalculatorTotalPage, IPaginationParams } from \"../type/table-type\"\n\nexport const calculatorTotalPage = ({ total = 0, pageSize = 0 }: ICalculatorTotalPage): number => {\n if (!pageSize || (pageSize && pageSize <= 0)) return 0\n return Math.ceil(total / pageSize)\n}\n\nexport const STT = (data?: IPaginationParams, index?: number): number => {\n let stt = 1\n let current_page = 0\n let per_page = 0\n\n if (data?.page !== undefined && data?.pageSize !== undefined) {\n current_page = data.page\n per_page = data.pageSize\n }\n\n let i = (current_page - 1) * per_page\n i = isNaN(i) ? 0 : i\n stt = i + (index ?? 0) + 1\n\n return stt\n}\n","import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import { arrayLocal, getLocalStore, setLocalStore, toggleValues } from '../helpers'\nimport { useCallback, useMemo, useState } from 'react'\nimport { Column } from 'react-data-grid'\nimport { TColumnsTable, useShowHideColumnParameter, useShowHideColumnReturn } from '../type/table-type'\nimport { uniq } from 'lodash'\nimport { isColumn } from '../type/table'\n\nconst useShowHideColumn = <T, SR = unknown>({\n nameLocal = 'table',\n columns,\n ignoreColumns\n}: useShowHideColumnParameter<T, SR>): useShowHideColumnReturn<T, SR> => {\n const nameLocalLocation = `${nameLocal}_location`\n const [locationColumns, setLocationColumns] = useState<string[]>(() => {\n const dataLocal = getLocalStore(nameLocalLocation)\n if (dataLocal) {\n return arrayLocal(dataLocal)\n }\n return []\n })\n const [hiddenColumns, setHiddenColumns] = useState<string[]>(() => {\n const dataLocal = getLocalStore(nameLocal)\n if (dataLocal) {\n return arrayLocal(dataLocal)\n }\n return []\n })\n\n const handleFindLocation = useCallback(\n (filterColumns: TColumnsTable<T, SR>, arrLoctions = locationColumns) => {\n return arrLoctions?.length > 0\n ? arrLoctions?.reduce(\n (total, current) => {\n const currentColumns = filterColumns?.find((item) => {\n const newItem = item as Column<T>\n return newItem?.key === current\n })\n\n if (currentColumns) {\n total = [...total, currentColumns]\n }\n return total\n },\n [] as TColumnsTable<T, SR>\n )\n : filterColumns\n },\n [locationColumns]\n )\n\n const newCloumnKeys = useMemo(\n () =>\n columns\n ?.filter(isColumn)\n .map(column => column.key),\n [columns]\n )\n\n\n const newColumns = useMemo(() => {\n const filterColumns: TColumnsTable<T, SR> =\n columns?.filter(column => {\n if (!isColumn(column)) return true\n\n const key = column.key\n\n if (ignoreColumns?.includes(key)) return true\n if (hiddenColumns?.includes(key)) return false\n\n return true\n }) ?? []\n\n return handleFindLocation(filterColumns)\n }, [columns, hiddenColumns, locationColumns, ignoreColumns])\n\n const newShowhideColumns = useMemo(() => {\n if (!ignoreColumns) return columns\n\n return (\n columns?.filter(column => {\n if (!isColumn(column)) return true\n return !ignoreColumns.includes(column.key)\n }) ?? []\n )\n }, [columns, ignoreColumns])\n\n const changeHiddenColumn = useCallback(\n (key: string | string[]) => {\n let newData = [...hiddenColumns]\n if (typeof key === 'string') {\n newData = toggleValues({\n array: newData,\n value: key\n })\n } else {\n newData = key\n }\n setLocalStore(nameLocal, JSON.stringify(newData))\n setHiddenColumns(newData)\n },\n [hiddenColumns, nameLocalLocation]\n )\n\n const handleChangeLocation = useCallback(\n (key: string[]) => {\n let newKey = key\n newKey = uniq([...key, ...newCloumnKeys])\n setLocationColumns(newKey)\n setLocalStore(nameLocalLocation, JSON.stringify(newKey))\n },\n [newCloumnKeys]\n )\n\n return {\n hiddenColumns,\n setHiddenColumns,\n columnsTable: newColumns,\n changeHiddenColumn,\n newShowhideColumns,\n locationColumns,\n handleFindLocation,\n handleChangeLocation\n }\n}\n\nexport { useShowHideColumn }\n","import { UseMutateFunction } from '@tanstack/react-query'\nimport { FormikProps } from 'formik'\nimport { Dispatch, HTMLAttributes, ReactNode, SetStateAction } from 'react'\nimport { Props } from 'react-select'\nimport type { IFieldUpdateAndCheck, IMainResponse, ISettingSystem } from './preload-stubs'\nimport type { JobDetail, Proxy } from './vitechgroup-stubs'\n\nimport type { Column, ColumnOrColumnGroup } from 'react-data-grid'\n\nexport function isColumn<T, SR>(\n column: ColumnOrColumnGroup<T, SR>\n): column is Column<T, SR> {\n return 'key' in column\n}\n\nexport interface ITableData {\n t: any\n dataJobDetail?: JobDetail[]\n totalAction?: number\n settingSystem?: ISettingSystem\n readProxyByField?: UseMutateFunction<\n IMainResponse<Proxy[]>,\n Error,\n IFieldUpdateAndCheck<Proxy, undefined, string[]>[],\n unknown\n >\n}\n\nexport interface CustomSelectProps<T> extends Props, Omit<WapperLabelFormProps, 'children'> {\n className?: string\n height?: string\n name: string\n formik?: FormikProps<T>\n msgError?: string\n changeSelected?: (selected?: Record<string, string>) => void\n setValueSearch?: Dispatch<SetStateAction<string>>\n positionMenu?: string\n}\n\nexport interface WapperLabelFormProps {\n classWapper?: HTMLAttributes<HTMLDivElement>['className']\n label?: string\n clsLabelWrapper?: string\n isRequired?: boolean\n children?: ReactNode\n isVertical?: boolean\n}\n","'use client'\n\nimport { get } from 'lodash'\nimport {\n Key,\n memo,\n useCallback,\n useMemo\n} from 'react'\nimport {\n DataGrid,\n type Column,\n type ColumnOrColumnGroup\n} from 'react-data-grid'\nimport 'react-data-grid/lib/styles.css'\n\nimport { cn } from '../../../helpers'\nimport { STT } from '../../../helpers/table'\nimport { LoadingIcon } from '../../Icons'\nimport type { IReactTableGridCustom } from './table-type'\nimport './ReactTableGridCustom.css'\n\nconst ReactTableGridCustomInner = <\n T,\n SR = unknown,\n K extends Key = Key\n>(\n props: IReactTableGridCustom<T, SR, K>\n) => {\n const {\n classNameWapperTable,\n hiddenSTT,\n data,\n page,\n pageSize,\n columns,\n rowKeyGetter = 'uid',\n\n enableSelectRow,\n selectedRows,\n onSelectedRowsChange,\n\n sortColumns,\n onSortColumnsChange,\n\n fetching,\n onRowClick,\n onRowDoubleClick\n } = props\n\n const isSelectRow =\n enableSelectRow && selectedRows !== undefined\n\n /* =========================\n * Row key\n * ========================= */\n const customRowKeyGetter = useCallback(\n (row: T): K => {\n if (typeof rowKeyGetter === 'function') {\n return rowKeyGetter(row)\n }\n return get(row, rowKeyGetter) as K\n },\n [rowKeyGetter]\n )\n\n /* =========================\n * Select column (CUSTOM)\n * ========================= */\n const selectColumn = useMemo<Column<T, SR>>(\n () => ({\n key: '__select__',\n name: '',\n width: 44,\n frozen: true,\n sortable: false,\n resizable: false,\n\n renderHeaderCell: () => {\n if (!onSelectedRowsChange) return null\n\n const allSelected =\n selectedRows?.size === data.length && data.length > 0\n\n return (\n <input\n type=\"checkbox\"\n checked={allSelected}\n onChange={(e) => {\n if (e.target.checked) {\n onSelectedRowsChange(\n new Set(data.map(customRowKeyGetter))\n )\n } else {\n onSelectedRowsChange(new Set())\n }\n }}\n />\n )\n },\n\n renderCell: ({ row }) => {\n const key = customRowKeyGetter(row)\n\n return (\n <input\n type=\"checkbox\"\n checked={selectedRows?.has(key)}\n onChange={() => {\n if (!onSelectedRowsChange) return\n\n const next = new Set(selectedRows)\n if (next.has(key)) {\n next.delete(key)\n } else {\n next.add(key)\n }\n onSelectedRowsChange(next)\n }}\n />\n )\n }\n }),\n [\n customRowKeyGetter,\n data,\n selectedRows,\n onSelectedRowsChange\n ]\n )\n\n /* =========================\n * Columns\n * ========================= */\n const newColumns = useMemo<\n readonly ColumnOrColumnGroup<T, SR>[]\n >(() => {\n const cols = [...columns]\n\n if (isSelectRow) {\n cols.unshift(selectColumn)\n }\n\n if (!hiddenSTT) {\n cols.unshift({\n key: '__index__',\n name: 'STT',\n width: 80,\n sortable: false,\n renderCell: ({ rowIdx }) =>\n STT({ page, pageSize }, rowIdx)\n })\n }\n\n return cols\n }, [\n columns,\n hiddenSTT,\n isSelectRow,\n page,\n pageSize,\n selectColumn\n ])\n\n return (\n <div\n className={cn(\n 'wapper_table flex flex-col h-full min-h-0 relative',\n classNameWapperTable\n )}\n >\n <DataGrid<T, SR, K>\n rows={data}\n columns={newColumns}\n selectedRows={selectedRows}\n onSelectedRowsChange={onSelectedRowsChange}\n rowKeyGetter={isSelectRow ? customRowKeyGetter : undefined}\n sortColumns={sortColumns}\n onSortColumnsChange={onSortColumnsChange}\n onCellClick={({ row, rowIdx }) =>\n onRowClick?.(row, rowIdx)\n }\n onCellDoubleClick={({ row, rowIdx }) =>\n onRowDoubleClick?.(row, rowIdx)\n }\n />\n\n {fetching && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white/60 z-10\">\n <LoadingIcon isSpin />\n </div>\n )}\n </div>\n )\n}\n\n/* =========================\n * Export\n * ========================= */\nexport const ReactTableGridCustom = memo(\n ReactTableGridCustomInner\n) as typeof ReactTableGridCustomInner\n","import { JSX } from \"react\"\n\nexport const LoadingIcon = ({\n isSpin = false,\n h = 30,\n w = 30,\n size = 30,\n className\n}: {\n isSpin?: boolean\n w?: number\n h?: number\n size?: number\n className?: string\n}): JSX.Element => {\n return (\n <svg\n className={`${isSpin ? 'animate-spin' : ''} ${className ?? ''}`}\n viewBox=\"0 0 1024 1024\"\n focusable=\"false\"\n data-icon=\"loading\"\n width={size || w}\n height={size || h}\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z\"></path>\n </svg>\n )\n}\n\nexport const ArrowIcon = ({\n h,\n w,\n size,\n className\n}: {\n w?: number\n h?: number\n size?: number\n className?: string\n}): JSX.Element => {\n return (\n <svg\n className={className}\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 16 16\"\n height={size ?? h}\n width={size ?? w}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M8 4a.5.5 0 0 1 .5.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5A.5.5 0 0 1 8 4\"\n ></path>\n </svg>\n )\n}\n","import { FC, memo, ReactNode, useId } from 'react'\n\n/* =========================\n * Props\n * ========================= */\nexport interface TableStyleWapperProps {\n children?: ReactNode\n clsTablecustom?: string\n idWapper?: string // có thể truyền id từ ngoài\n}\n\n/* =========================\n * Client guard\n * ========================= */\nconst isClient = typeof window !== 'undefined'\n\n/* =========================\n * Component\n * ========================= */\nconst TableStyleContextWapperInner: FC<TableStyleWapperProps> = ({\n children,\n clsTablecustom,\n idWapper: externalId\n}) => {\n // server / electron preload → render children\n if (!isClient) {\n return <>{children}</>\n }\n\n // ƯU TIÊN: id ngoài → useId → fallback\n const reactId = useId()\n const idWapper = externalId ?? reactId\n\n return (\n <div\n id={`wapper_menu_context-${idWapper}`}\n className={`border border-[#dedede] rounded-xl overflow-hidden bg-white flex-1 h-full flex flex-col min-h-[360px] ${clsTablecustom ?? ''}`}\n >\n {children}\n </div>\n )\n}\n\n/* =========================\n * Export component (SAFE)\n * ========================= */\nexport const TableStyleContextWapper = memo(\n TableStyleContextWapperInner\n)\n\n/* =========================\n * Helper (EXPORT RIÊNG – SAFE)\n * ========================= */\nexport const getTableStyleWapperId = (externalId?: string) =>\n `wapper_menu_context-${externalId ?? 'default'}`\n"],"mappings":"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","names":["import_lodash","import_lodash","import_react","import_jsx_runtime","import_react","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/helpers/functions.ts","../src/helpers/table.ts","../src/utils.ts","../src/hooks/useShowHideColumn.ts","../src/type/table.ts","../src/component/ui/Table/ReactTableGridCustom.tsx","../src/component/ui/Table/TableStyleContextWapper.tsx"],"sourcesContent":["/* =========================\n * Common types\n * ========================= */\nexport interface IPaginationParams {\n pageSize?: number\n page?: number\n}\n\nexport type Maybe<T> = T | undefined | null\n\n/* =========================\n * Hooks\n * ========================= */\nexport { useShowHideColumn } from './hooks/useShowHideColumn'\n\n/* =========================\n * Components (runtime-safe)\n * ========================= */\nexport { ReactTableGridCustom } \nfrom './component/ui/Table/ReactTableGridCustom'\n\n/* =========================\n * EXPORT TYPES (100% SAFE)\n * ========================= */\n\n// table\nexport type {\n IReactTableGridCustom\n} from './component/ui/Table/table-type'\n\n// columns\nexport type {\n TColumnsTable\n} from './type/table-type'\n\n// react-data-grid (types only)\nexport type {\n Column,\n ColumnOrColumnGroup\n} from 'react-data-grid'\n\n/* =========================\n * TableStyleContextWapper\n * ========================= */\nexport { TableStyleContextWapper }\nfrom './component/ui/Table/TableStyleContextWapper'\n\nexport type { TableStyleWapperProps }\nfrom './component/ui/Table/TableStyleContextWapper'\n\nexport { getTableStyleWapperId }\nfrom './component/ui/Table/TableStyleContextWapper'\n\n","import { deleteDB, IDBPDatabase, openDB } from 'idb'\nimport { pickBy } from 'lodash'\nimport moment from 'moment'\nimport { optionSelect } from '../type/preload-stubs'\nimport { IObjectParams, IToggleValues } from '../type/renderer'\nexport const setLocalStore = (key: string, value: string): void => {\n if (typeof window !== 'undefined') {\n localStorage.setItem(key, value)\n }\n}\n\nexport const getLocalStore = (key: string): string | null => {\n if (typeof window !== 'undefined') {\n return localStorage.getItem(key)\n } else {\n return null\n }\n}\n\nexport function convertViToEn(str: string, toUpperCase = false): string {\n str = str.toLowerCase()\n str = str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g, 'a')\n str = str.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g, 'e')\n str = str.replace(/ì|í|ị|ỉ|ĩ/g, 'i')\n str = str.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g, 'o')\n str = str.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g, 'u')\n str = str.replace(/ỳ|ý|ỵ|ỷ|ỹ/g, 'y')\n str = str.replace(/đ/g, 'd')\n // Some system encode vietnamese combining accent as individual utf-8 characters\n str = str.replace(/\\u0300|\\u0301|\\u0303|\\u0309|\\u0323/g, '') // Huyền sắc hỏi ngã nặng\n str = str.replace(/\\u02C6|\\u0306|\\u031B/g, '') // Â, Ê, Ă, Ơ, Ư\n\n return toUpperCase ? str.toUpperCase() : str\n}\n\nexport const convertNumber = (value: number | string): { value: number; check: boolean } => {\n let num = 0\n if (value) {\n value = value.toString().replace(/[.]/g, '')\n value = value.trim()\n num = Number(value)\n }\n\n const regex = /^-?\\d*$/\n const check = regex.test(num.toString())\n return {\n value: num,\n check\n }\n}\n\nexport const changeTitleDocmemt = (title?: string): void => {\n document.title = `${title} - Phần Mềm MKT`\n}\n\nexport const numberConvert = (num: string | number): string => {\n let t = '0'\n if (num) {\n if (typeof num === 'string') {\n num = Number(num)\n }\n t = num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.')\n }\n return t\n}\n\nexport const pickBySearch = <T extends Record<string, unknown>>(obj: T): Partial<T> => {\n const filteredObj = pickBy(obj, (value) => value !== '')\n return filteredObj as Partial<T>\n}\n\nexport const getValueSelected = (value?: unknown, options?: optionSelect[]): optionSelect[] => {\n const currentValue = (options ?? [])?.filter((otp) => {\n return Array.isArray(value) ? value?.includes(otp.value) : otp?.value === value\n })\n return currentValue\n}\n\nexport const toggleValues = ({ array, value }: IToggleValues): string[] => {\n if (array.includes(value)) {\n return array.filter((item) => item !== value)\n } else {\n return [...array, value]\n }\n}\n\nexport const arrayLocal = (array?: string): string[] => {\n try {\n const data = array ? JSON.parse(array) : []\n return Array.isArray(data) ? data : []\n } catch {\n return []\n }\n}\n\nexport const formatDate = (\n date?: string | number | Date,\n format: string = 'DD/MM/YYYY HH:mm:ss A'\n): string => {\n return moment(date).format(format)\n}\n\nexport const parseObject = (obj?: string): object => {\n try {\n const data = obj ? JSON.parse(obj) : {}\n return typeof data === 'object' ? data : {}\n } catch {\n return {}\n }\n}\nexport const bufferToBlob = (buffer: ArrayBuffer | Uint8Array, type: string): Blob => {\n return new Blob([buffer as BlobPart], { type })\n}\nconst DB_NAME = 'appDB'\nconst DB_VERSION = 5\nconst STORE_NAME = 'selectedRecords'\nconst HISTORY_STORE = 'recordHistory'\ninterface SelectedRecordEntry {\n actionType: string\n selectedRecords: string[]\n}\n\ninterface RecordHistoryEntry {\n id: string\n previousAction: string[]\n}\n\ntype AppDBSchema = {\n selectedRecords: SelectedRecordEntry\n recordHistory: RecordHistoryEntry\n}\n\nconst requiredStores = [STORE_NAME, HISTORY_STORE]\n\nconst createAppDB = async (): Promise<IDBPDatabase<AppDBSchema>> => {\n return openDB<AppDBSchema>(DB_NAME, DB_VERSION, {\n upgrade(db) {\n for (const storeName of Array.from(db.objectStoreNames)) {\n db.deleteObjectStore(storeName)\n }\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n const store = db.createObjectStore(STORE_NAME, {\n keyPath: 'actionType'\n })\n store.createIndex('by_actionType', 'actionType')\n }\n\n if (!db.objectStoreNames.contains(HISTORY_STORE)) {\n db.createObjectStore(HISTORY_STORE, { keyPath: 'id' })\n }\n }\n })\n}\n\nexport const openAppDB = async (): Promise<IDBPDatabase<AppDBSchema>> => {\n try {\n const db = await createAppDB()\n const hasAllStores = requiredStores.every((store) => db.objectStoreNames.contains(store))\n if (!hasAllStores) {\n console.warn('[IndexedDB] Missing required stores. Resetting DB...')\n db.close()\n await deleteDB(DB_NAME)\n return await createAppDB()\n }\n return db\n } catch (error) {\n if ((error as { name: string })?.name === 'VersionError') {\n console.warn('[IndexedDB] Version downgrade detected. Resetting DB...')\n await deleteDB(DB_NAME)\n return await createAppDB()\n }\n\n console.error('[IndexedDB] Failed to open DB:', error)\n throw error\n }\n}\n\nexport const saveSelectedRecords = async (\n ACTION_TYPE: string,\n selectedRecords: Set<string>\n): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction(STORE_NAME, 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n\n const data: SelectedRecordEntry = {\n actionType: ACTION_TYPE,\n selectedRecords: Array.from(selectedRecords)\n }\n\n await store.put(data)\n await tx.done\n}\n\nexport const getSelectedRecords = async (ACTION_TYPE: string): Promise<Set<string>> => {\n const db = await openAppDB()\n const store = db.transaction(STORE_NAME).objectStore(STORE_NAME)\n\n const record = await store.get(ACTION_TYPE)\n\n return new Set(record?.selectedRecords ?? [])\n}\nexport const removeUidsFromAllPathsAndSaveHistory = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction([STORE_NAME, HISTORY_STORE], 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n const historyStore = tx.objectStore(HISTORY_STORE)\n\n const allRecords = await store.getAll()\n\n const historyMap: Record<string, string[]> = {}\n\n for (const uid of uids) {\n historyMap[uid] = []\n }\n\n for (const record of allRecords) {\n let updated = false\n\n for (const uid of uids) {\n if (record.selectedRecords.includes(uid)) {\n record.selectedRecords = record.selectedRecords.filter((id: string) => id !== uid)\n historyMap[uid].push(record.actionType)\n updated = true\n }\n }\n\n if (updated) {\n await store.put(record)\n }\n }\n\n // Ghi lại lịch sử path đã bị xóa cho từng UID\n for (const [uid, paths] of Object.entries(historyMap)) {\n if (paths.length > 0) {\n await historyStore.put({ id: uid, previousAction: paths })\n }\n }\n\n await tx.done\n}\n\nexport const restoreUidsToPreviousPaths = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction([STORE_NAME, HISTORY_STORE], 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n const historyStore = tx.objectStore(HISTORY_STORE)\n\n for (const uid of uids) {\n const history = await historyStore.get(uid)\n if (history?.previousAction?.length) {\n for (const actionType of history.previousAction) {\n const record = (await store.get(actionType)) || {\n actionType,\n selectedRecords: []\n }\n\n if (!record.selectedRecords.includes(uid)) {\n record.selectedRecords.push(uid)\n }\n\n await store.put(record)\n }\n\n await historyStore.delete(uid)\n }\n }\n\n await tx.done\n}\nexport const deleteUidsCompletely = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction(['selectedRecords', 'recordHistory'], 'readwrite')\n const store = tx.objectStore('selectedRecords')\n const historyStore = tx.objectStore('recordHistory')\n\n const allRecords = await store.getAll()\n\n for (const record of allRecords) {\n const originalLength = record.selectedRecords.length\n record.selectedRecords = record.selectedRecords.filter((id: string) => !uids.includes(id))\n\n if (record.selectedRecords.length !== originalLength) {\n await store.put(record)\n }\n }\n for (const uid of uids) {\n await historyStore.delete(uid)\n }\n\n await tx.done\n}\n\nexport const getSelectedCategoryDataByPath = (): string[] => {\n try {\n const saved = localStorage.getItem('selectedCategoryData')\n if (saved) {\n const data = JSON.parse(saved)\n const localPath = window.location.hash.replace(/^#/, '') || '/'\n const categoryData = data[localPath]\n if (categoryData && Array.isArray(categoryData.categoryIds)) {\n return categoryData.categoryIds\n }\n }\n } catch (err) {\n console.warn('Failed to parse localStorage category data:', err)\n }\n\n return []\n}\n\nexport const handleAsyncConfigSearchInitialValue = (): IObjectParams => {\n const defaultConfig: IObjectParams = {\n page: 1,\n pageSize: 1000,\n filterType: 'all'\n }\n\n const categoryIds = getSelectedCategoryDataByPath()\n if (categoryIds.length > 0) {\n return {\n ...defaultConfig,\n categoryId: categoryIds\n }\n }\n\n return defaultConfig\n}\n","import { ICalculatorTotalPage, IPaginationParams } from \"../type/table-type\"\n\nexport const calculatorTotalPage = ({ total = 0, pageSize = 0 }: ICalculatorTotalPage): number => {\n if (!pageSize || (pageSize && pageSize <= 0)) return 0\n return Math.ceil(total / pageSize)\n}\n\nexport const STT = (data?: IPaginationParams, index?: number): number => {\n let stt = 1\n let current_page = 0\n let per_page = 0\n\n if (data?.page !== undefined && data?.pageSize !== undefined) {\n current_page = data.page\n per_page = data.pageSize\n }\n\n let i = (current_page - 1) * per_page\n i = isNaN(i) ? 0 : i\n stt = i + (index ?? 0) + 1\n\n return stt\n}\n","import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import { arrayLocal, getLocalStore, setLocalStore, toggleValues } from '../helpers'\nimport { useCallback, useMemo, useState } from 'react'\nimport { Column } from 'react-data-grid'\nimport { TColumnsTable, useShowHideColumnParameter, useShowHideColumnReturn } from '../type/table-type'\nimport { uniq } from 'lodash'\nimport { isColumn } from '../type/table'\n\nconst useShowHideColumn = <T, SR = unknown>({\n nameLocal = 'table',\n columns,\n ignoreColumns\n}: useShowHideColumnParameter<T, SR>): useShowHideColumnReturn<T, SR> => {\n const nameLocalLocation = `${nameLocal}_location`\n const [locationColumns, setLocationColumns] = useState<string[]>(() => {\n const dataLocal = getLocalStore(nameLocalLocation)\n if (dataLocal) {\n return arrayLocal(dataLocal)\n }\n return []\n })\n const [hiddenColumns, setHiddenColumns] = useState<string[]>(() => {\n const dataLocal = getLocalStore(nameLocal)\n if (dataLocal) {\n return arrayLocal(dataLocal)\n }\n return []\n })\n\n const handleFindLocation = useCallback(\n (filterColumns: TColumnsTable<T, SR>, arrLoctions = locationColumns) => {\n return arrLoctions?.length > 0\n ? arrLoctions?.reduce(\n (total, current) => {\n const currentColumns = filterColumns?.find((item) => {\n const newItem = item as Column<T>\n return newItem?.key === current\n })\n\n if (currentColumns) {\n total = [...total, currentColumns]\n }\n return total\n },\n [] as TColumnsTable<T, SR>\n )\n : filterColumns\n },\n [locationColumns]\n )\n\n const newCloumnKeys = useMemo(\n () =>\n columns\n ?.filter(isColumn)\n .map(column => column.key),\n [columns]\n )\n\n\n const newColumns = useMemo(() => {\n const filterColumns: TColumnsTable<T, SR> =\n columns?.filter(column => {\n if (!isColumn(column)) return true\n\n const key = column.key\n\n if (ignoreColumns?.includes(key)) return true\n if (hiddenColumns?.includes(key)) return false\n\n return true\n }) ?? []\n\n return handleFindLocation(filterColumns)\n }, [columns, hiddenColumns, locationColumns, ignoreColumns])\n\n const newShowhideColumns = useMemo(() => {\n if (!ignoreColumns) return columns\n\n return (\n columns?.filter(column => {\n if (!isColumn(column)) return true\n return !ignoreColumns.includes(column.key)\n }) ?? []\n )\n }, [columns, ignoreColumns])\n\n const changeHiddenColumn = useCallback(\n (key: string | string[]) => {\n let newData = [...hiddenColumns]\n if (typeof key === 'string') {\n newData = toggleValues({\n array: newData,\n value: key\n })\n } else {\n newData = key\n }\n setLocalStore(nameLocal, JSON.stringify(newData))\n setHiddenColumns(newData)\n },\n [hiddenColumns, nameLocalLocation]\n )\n\n const handleChangeLocation = useCallback(\n (key: string[]) => {\n let newKey = key\n newKey = uniq([...key, ...newCloumnKeys])\n setLocationColumns(newKey)\n setLocalStore(nameLocalLocation, JSON.stringify(newKey))\n },\n [newCloumnKeys]\n )\n\n return {\n hiddenColumns,\n setHiddenColumns,\n columnsTable: newColumns,\n changeHiddenColumn,\n newShowhideColumns,\n locationColumns,\n handleFindLocation,\n handleChangeLocation\n }\n}\n\nexport { useShowHideColumn }\n","import { UseMutateFunction } from '@tanstack/react-query'\nimport { FormikProps } from 'formik'\nimport { Dispatch, HTMLAttributes, ReactNode, SetStateAction } from 'react'\nimport { Props } from 'react-select'\nimport type { IFieldUpdateAndCheck, IMainResponse, ISettingSystem } from './preload-stubs'\nimport type { JobDetail, Proxy } from './vitechgroup-stubs'\n\nimport type { Column, ColumnOrColumnGroup } from 'react-data-grid'\n\nexport function isColumn<T, SR>(\n column: ColumnOrColumnGroup<T, SR>\n): column is Column<T, SR> {\n return 'key' in column\n}\n\nexport interface ITableData {\n t: any\n dataJobDetail?: JobDetail[]\n totalAction?: number\n settingSystem?: ISettingSystem\n readProxyByField?: UseMutateFunction<\n IMainResponse<Proxy[]>,\n Error,\n IFieldUpdateAndCheck<Proxy, undefined, string[]>[],\n unknown\n >\n}\n\nexport interface CustomSelectProps<T> extends Props, Omit<WapperLabelFormProps, 'children'> {\n className?: string\n height?: string\n name: string\n formik?: FormikProps<T>\n msgError?: string\n changeSelected?: (selected?: Record<string, string>) => void\n setValueSearch?: Dispatch<SetStateAction<string>>\n positionMenu?: string\n}\n\nexport interface WapperLabelFormProps {\n classWapper?: HTMLAttributes<HTMLDivElement>['className']\n label?: string\n clsLabelWrapper?: string\n isRequired?: boolean\n children?: ReactNode\n isVertical?: boolean\n}\n","'use client'\n\nimport { get } from 'lodash'\nimport {\n Key,\n memo,\n useCallback,\n useMemo\n} from 'react'\nimport {\n DataGrid,\n type Column,\n type ColumnOrColumnGroup\n} from 'react-data-grid'\nimport 'react-data-grid/lib/styles.css'\n\nimport { cn } from '../../../helpers'\nimport { STT } from '../../../helpers/table'\nimport { LoadingIcon } from '../../Icons'\nimport type { IReactTableGridCustom } from './table-type'\nimport './ReactTableGridCustom.css'\n\nconst ReactTableGridCustomInner = <\n T,\n SR = unknown,\n K extends Key = Key\n>(\n props: IReactTableGridCustom<T, SR, K>\n) => {\n const {\n classNameWapperTable,\n hiddenSTT,\n data,\n page,\n pageSize,\n columns,\n rowKeyGetter = 'uid',\n\n enableSelectRow,\n selectedRows,\n onSelectedRowsChange,\n\n sortColumns,\n onSortColumnsChange,\n\n fetching,\n onRowClick,\n onRowDoubleClick\n } = props\n\n const isSelectRow =\n enableSelectRow && selectedRows !== undefined\n\n /* =========================\n * Row key\n * ========================= */\n const customRowKeyGetter = useCallback(\n (row: T): K => {\n if (typeof rowKeyGetter === 'function') {\n return rowKeyGetter(row)\n }\n return get(row, rowKeyGetter) as K\n },\n [rowKeyGetter]\n )\n\n /* =========================\n * Select column (CUSTOM)\n * ========================= */\n const selectColumn = useMemo<Column<T, SR>>(\n () => ({\n key: '__select__',\n name: '',\n width: 44,\n frozen: true,\n sortable: false,\n resizable: false,\n\n renderHeaderCell: () => {\n if (!onSelectedRowsChange) return null\n\n const allSelected =\n selectedRows?.size === data.length && data.length > 0\n\n return (\n <input\n type=\"checkbox\"\n checked={allSelected}\n onChange={(e) => {\n if (e.target.checked) {\n onSelectedRowsChange(\n new Set(data.map(customRowKeyGetter))\n )\n } else {\n onSelectedRowsChange(new Set())\n }\n }}\n />\n )\n },\n\n renderCell: ({ row }) => {\n const key = customRowKeyGetter(row)\n\n return (\n <input\n type=\"checkbox\"\n checked={selectedRows?.has(key)}\n onChange={() => {\n if (!onSelectedRowsChange) return\n\n const next = new Set(selectedRows)\n if (next.has(key)) {\n next.delete(key)\n } else {\n next.add(key)\n }\n onSelectedRowsChange(next)\n }}\n />\n )\n }\n }),\n [\n customRowKeyGetter,\n data,\n selectedRows,\n onSelectedRowsChange\n ]\n )\n\n /* =========================\n * Columns\n * ========================= */\n const newColumns = useMemo<\n readonly ColumnOrColumnGroup<T, SR>[]\n >(() => {\n const cols = [...columns]\n\n if (isSelectRow) {\n cols.unshift(selectColumn)\n }\n\n if (!hiddenSTT) {\n cols.unshift({\n key: '__index__',\n name: 'STT',\n width: 80,\n sortable: false,\n renderCell: ({ rowIdx }) =>\n STT({ page, pageSize }, rowIdx)\n })\n }\n\n return cols\n }, [\n columns,\n hiddenSTT,\n isSelectRow,\n page,\n pageSize,\n selectColumn\n ])\n\n return (\n <div\n className={cn(\n 'wapper_table flex flex-col h-full min-h-0 relative',\n classNameWapperTable\n )}\n >\n <DataGrid<T, SR, K>\n rows={data}\n columns={newColumns}\n selectedRows={selectedRows}\n onSelectedRowsChange={onSelectedRowsChange}\n rowKeyGetter={isSelectRow ? customRowKeyGetter : undefined}\n sortColumns={sortColumns}\n onSortColumnsChange={onSortColumnsChange}\n onCellClick={({ row, rowIdx }) =>\n onRowClick?.(row, rowIdx)\n }\n onCellDoubleClick={({ row, rowIdx }) =>\n onRowDoubleClick?.(row, rowIdx)\n }\n />\n\n {/* {fetching && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white/60 z-10\">\n <LoadingIcon isSpin />\n </div>\n )} */}\n </div>\n )\n}\n\n/* =========================\n * Export\n * ========================= */\nexport const ReactTableGridCustom = memo(\n ReactTableGridCustomInner\n) as typeof ReactTableGridCustomInner\n","import { FC, memo, ReactNode, useId } from 'react'\n\n/* =========================\n * Props\n * ========================= */\nexport interface TableStyleWapperProps {\n children?: ReactNode\n clsTablecustom?: string\n idWapper?: string // có thể truyền id từ ngoài\n}\n\n/* =========================\n * Client guard\n * ========================= */\nconst isClient = typeof window !== 'undefined'\n\n/* =========================\n * Component\n * ========================= */\nconst TableStyleContextWapperInner: FC<TableStyleWapperProps> = ({\n children,\n clsTablecustom,\n idWapper: externalId\n}) => {\n // server / electron preload → render children\n if (!isClient) {\n return <>{children}</>\n }\n\n // ƯU TIÊN: id ngoài → useId → fallback\n const reactId = useId()\n const idWapper = externalId ?? reactId\n\n return (\n <div\n id={`wapper_menu_context-${idWapper}`}\n className={`border border-[#dedede] rounded-xl overflow-hidden bg-white flex-1 h-full flex flex-col min-h-[360px] ${clsTablecustom ?? ''}`}\n >\n {children}\n </div>\n )\n}\n\n/* =========================\n * Export component (SAFE)\n * ========================= */\nexport const TableStyleContextWapper = memo(\n TableStyleContextWapperInner\n)\n\n/* =========================\n * Helper (EXPORT RIÊNG – SAFE)\n * ========================= */\nexport const getTableStyleWapperId = (externalId?: string) =>\n `wapper_menu_context-${externalId ?? 'default'}`\n"],"mappings":"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","names":["import_lodash","import_lodash","import_react","import_react","import_jsx_runtime"]}
package/dist/index.mjs CHANGED
@@ -171,34 +171,7 @@ import {
171
171
  DataGrid
172
172
  } from "react-data-grid";
173
173
  import "react-data-grid/lib/styles.css";
174
-
175
- // src/component/Icons.tsx
176
174
  import { jsx } from "react/jsx-runtime";
177
- var LoadingIcon = ({
178
- isSpin = false,
179
- h = 30,
180
- w = 30,
181
- size = 30,
182
- className
183
- }) => {
184
- return /* @__PURE__ */ jsx(
185
- "svg",
186
- {
187
- className: `${isSpin ? "animate-spin" : ""} ${className != null ? className : ""}`,
188
- viewBox: "0 0 1024 1024",
189
- focusable: "false",
190
- "data-icon": "loading",
191
- width: size || w,
192
- height: size || h,
193
- fill: "currentColor",
194
- "aria-hidden": "true",
195
- children: /* @__PURE__ */ jsx("path", { d: "M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z" })
196
- }
197
- );
198
- };
199
-
200
- // src/component/ui/Table/ReactTableGridCustom.tsx
201
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
202
175
  var ReactTableGridCustomInner = (props) => {
203
176
  const {
204
177
  classNameWapperTable,
@@ -238,7 +211,7 @@ var ReactTableGridCustomInner = (props) => {
238
211
  renderHeaderCell: () => {
239
212
  if (!onSelectedRowsChange) return null;
240
213
  const allSelected = (selectedRows == null ? void 0 : selectedRows.size) === data.length && data.length > 0;
241
- return /* @__PURE__ */ jsx2(
214
+ return /* @__PURE__ */ jsx(
242
215
  "input",
243
216
  {
244
217
  type: "checkbox",
@@ -257,7 +230,7 @@ var ReactTableGridCustomInner = (props) => {
257
230
  },
258
231
  renderCell: ({ row }) => {
259
232
  const key = customRowKeyGetter(row);
260
- return /* @__PURE__ */ jsx2(
233
+ return /* @__PURE__ */ jsx(
261
234
  "input",
262
235
  {
263
236
  type: "checkbox",
@@ -306,30 +279,27 @@ var ReactTableGridCustomInner = (props) => {
306
279
  pageSize,
307
280
  selectColumn
308
281
  ]);
309
- return /* @__PURE__ */ jsxs(
282
+ return /* @__PURE__ */ jsx(
310
283
  "div",
311
284
  {
312
285
  className: cn(
313
286
  "wapper_table flex flex-col h-full min-h-0 relative",
314
287
  classNameWapperTable
315
288
  ),
316
- children: [
317
- /* @__PURE__ */ jsx2(
318
- DataGrid,
319
- {
320
- rows: data,
321
- columns: newColumns,
322
- selectedRows,
323
- onSelectedRowsChange,
324
- rowKeyGetter: isSelectRow ? customRowKeyGetter : void 0,
325
- sortColumns,
326
- onSortColumnsChange,
327
- onCellClick: ({ row, rowIdx }) => onRowClick == null ? void 0 : onRowClick(row, rowIdx),
328
- onCellDoubleClick: ({ row, rowIdx }) => onRowDoubleClick == null ? void 0 : onRowDoubleClick(row, rowIdx)
329
- }
330
- ),
331
- fetching && /* @__PURE__ */ jsx2("div", { className: "absolute inset-0 flex items-center justify-center bg-white/60 z-10", children: /* @__PURE__ */ jsx2(LoadingIcon, { isSpin: true }) })
332
- ]
289
+ children: /* @__PURE__ */ jsx(
290
+ DataGrid,
291
+ {
292
+ rows: data,
293
+ columns: newColumns,
294
+ selectedRows,
295
+ onSelectedRowsChange,
296
+ rowKeyGetter: isSelectRow ? customRowKeyGetter : void 0,
297
+ sortColumns,
298
+ onSortColumnsChange,
299
+ onCellClick: ({ row, rowIdx }) => onRowClick == null ? void 0 : onRowClick(row, rowIdx),
300
+ onCellDoubleClick: ({ row, rowIdx }) => onRowDoubleClick == null ? void 0 : onRowDoubleClick(row, rowIdx)
301
+ }
302
+ )
333
303
  }
334
304
  );
335
305
  };
@@ -339,7 +309,7 @@ var ReactTableGridCustom = memo(
339
309
 
340
310
  // src/component/ui/Table/TableStyleContextWapper.tsx
341
311
  import { memo as memo2, useId } from "react";
342
- import { Fragment, jsx as jsx3 } from "react/jsx-runtime";
312
+ import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
343
313
  var isClient = typeof window !== "undefined";
344
314
  var TableStyleContextWapperInner = ({
345
315
  children,
@@ -347,11 +317,11 @@ var TableStyleContextWapperInner = ({
347
317
  idWapper: externalId
348
318
  }) => {
349
319
  if (!isClient) {
350
- return /* @__PURE__ */ jsx3(Fragment, { children });
320
+ return /* @__PURE__ */ jsx2(Fragment, { children });
351
321
  }
352
322
  const reactId = useId();
353
323
  const idWapper = externalId != null ? externalId : reactId;
354
- return /* @__PURE__ */ jsx3(
324
+ return /* @__PURE__ */ jsx2(
355
325
  "div",
356
326
  {
357
327
  id: `wapper_menu_context-${idWapper}`,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/helpers/functions.ts","../src/helpers/table.ts","../src/utils.ts","../src/hooks/useShowHideColumn.ts","../src/type/table.ts","../src/component/ui/Table/ReactTableGridCustom.tsx","../src/component/Icons.tsx","../src/component/ui/Table/TableStyleContextWapper.tsx"],"sourcesContent":["import { deleteDB, IDBPDatabase, openDB } from 'idb'\nimport { pickBy } from 'lodash'\nimport moment from 'moment'\nimport { optionSelect } from '../type/preload-stubs'\nimport { IObjectParams, IToggleValues } from '../type/renderer'\nexport const setLocalStore = (key: string, value: string): void => {\n if (typeof window !== 'undefined') {\n localStorage.setItem(key, value)\n }\n}\n\nexport const getLocalStore = (key: string): string | null => {\n if (typeof window !== 'undefined') {\n return localStorage.getItem(key)\n } else {\n return null\n }\n}\n\nexport function convertViToEn(str: string, toUpperCase = false): string {\n str = str.toLowerCase()\n str = str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g, 'a')\n str = str.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g, 'e')\n str = str.replace(/ì|í|ị|ỉ|ĩ/g, 'i')\n str = str.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g, 'o')\n str = str.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g, 'u')\n str = str.replace(/ỳ|ý|ỵ|ỷ|ỹ/g, 'y')\n str = str.replace(/đ/g, 'd')\n // Some system encode vietnamese combining accent as individual utf-8 characters\n str = str.replace(/\\u0300|\\u0301|\\u0303|\\u0309|\\u0323/g, '') // Huyền sắc hỏi ngã nặng\n str = str.replace(/\\u02C6|\\u0306|\\u031B/g, '') // Â, Ê, Ă, Ơ, Ư\n\n return toUpperCase ? str.toUpperCase() : str\n}\n\nexport const convertNumber = (value: number | string): { value: number; check: boolean } => {\n let num = 0\n if (value) {\n value = value.toString().replace(/[.]/g, '')\n value = value.trim()\n num = Number(value)\n }\n\n const regex = /^-?\\d*$/\n const check = regex.test(num.toString())\n return {\n value: num,\n check\n }\n}\n\nexport const changeTitleDocmemt = (title?: string): void => {\n document.title = `${title} - Phần Mềm MKT`\n}\n\nexport const numberConvert = (num: string | number): string => {\n let t = '0'\n if (num) {\n if (typeof num === 'string') {\n num = Number(num)\n }\n t = num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.')\n }\n return t\n}\n\nexport const pickBySearch = <T extends Record<string, unknown>>(obj: T): Partial<T> => {\n const filteredObj = pickBy(obj, (value) => value !== '')\n return filteredObj as Partial<T>\n}\n\nexport const getValueSelected = (value?: unknown, options?: optionSelect[]): optionSelect[] => {\n const currentValue = (options ?? [])?.filter((otp) => {\n return Array.isArray(value) ? value?.includes(otp.value) : otp?.value === value\n })\n return currentValue\n}\n\nexport const toggleValues = ({ array, value }: IToggleValues): string[] => {\n if (array.includes(value)) {\n return array.filter((item) => item !== value)\n } else {\n return [...array, value]\n }\n}\n\nexport const arrayLocal = (array?: string): string[] => {\n try {\n const data = array ? JSON.parse(array) : []\n return Array.isArray(data) ? data : []\n } catch {\n return []\n }\n}\n\nexport const formatDate = (\n date?: string | number | Date,\n format: string = 'DD/MM/YYYY HH:mm:ss A'\n): string => {\n return moment(date).format(format)\n}\n\nexport const parseObject = (obj?: string): object => {\n try {\n const data = obj ? JSON.parse(obj) : {}\n return typeof data === 'object' ? data : {}\n } catch {\n return {}\n }\n}\nexport const bufferToBlob = (buffer: ArrayBuffer | Uint8Array, type: string): Blob => {\n return new Blob([buffer as BlobPart], { type })\n}\nconst DB_NAME = 'appDB'\nconst DB_VERSION = 5\nconst STORE_NAME = 'selectedRecords'\nconst HISTORY_STORE = 'recordHistory'\ninterface SelectedRecordEntry {\n actionType: string\n selectedRecords: string[]\n}\n\ninterface RecordHistoryEntry {\n id: string\n previousAction: string[]\n}\n\ntype AppDBSchema = {\n selectedRecords: SelectedRecordEntry\n recordHistory: RecordHistoryEntry\n}\n\nconst requiredStores = [STORE_NAME, HISTORY_STORE]\n\nconst createAppDB = async (): Promise<IDBPDatabase<AppDBSchema>> => {\n return openDB<AppDBSchema>(DB_NAME, DB_VERSION, {\n upgrade(db) {\n for (const storeName of Array.from(db.objectStoreNames)) {\n db.deleteObjectStore(storeName)\n }\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n const store = db.createObjectStore(STORE_NAME, {\n keyPath: 'actionType'\n })\n store.createIndex('by_actionType', 'actionType')\n }\n\n if (!db.objectStoreNames.contains(HISTORY_STORE)) {\n db.createObjectStore(HISTORY_STORE, { keyPath: 'id' })\n }\n }\n })\n}\n\nexport const openAppDB = async (): Promise<IDBPDatabase<AppDBSchema>> => {\n try {\n const db = await createAppDB()\n const hasAllStores = requiredStores.every((store) => db.objectStoreNames.contains(store))\n if (!hasAllStores) {\n console.warn('[IndexedDB] Missing required stores. Resetting DB...')\n db.close()\n await deleteDB(DB_NAME)\n return await createAppDB()\n }\n return db\n } catch (error) {\n if ((error as { name: string })?.name === 'VersionError') {\n console.warn('[IndexedDB] Version downgrade detected. Resetting DB...')\n await deleteDB(DB_NAME)\n return await createAppDB()\n }\n\n console.error('[IndexedDB] Failed to open DB:', error)\n throw error\n }\n}\n\nexport const saveSelectedRecords = async (\n ACTION_TYPE: string,\n selectedRecords: Set<string>\n): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction(STORE_NAME, 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n\n const data: SelectedRecordEntry = {\n actionType: ACTION_TYPE,\n selectedRecords: Array.from(selectedRecords)\n }\n\n await store.put(data)\n await tx.done\n}\n\nexport const getSelectedRecords = async (ACTION_TYPE: string): Promise<Set<string>> => {\n const db = await openAppDB()\n const store = db.transaction(STORE_NAME).objectStore(STORE_NAME)\n\n const record = await store.get(ACTION_TYPE)\n\n return new Set(record?.selectedRecords ?? [])\n}\nexport const removeUidsFromAllPathsAndSaveHistory = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction([STORE_NAME, HISTORY_STORE], 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n const historyStore = tx.objectStore(HISTORY_STORE)\n\n const allRecords = await store.getAll()\n\n const historyMap: Record<string, string[]> = {}\n\n for (const uid of uids) {\n historyMap[uid] = []\n }\n\n for (const record of allRecords) {\n let updated = false\n\n for (const uid of uids) {\n if (record.selectedRecords.includes(uid)) {\n record.selectedRecords = record.selectedRecords.filter((id: string) => id !== uid)\n historyMap[uid].push(record.actionType)\n updated = true\n }\n }\n\n if (updated) {\n await store.put(record)\n }\n }\n\n // Ghi lại lịch sử path đã bị xóa cho từng UID\n for (const [uid, paths] of Object.entries(historyMap)) {\n if (paths.length > 0) {\n await historyStore.put({ id: uid, previousAction: paths })\n }\n }\n\n await tx.done\n}\n\nexport const restoreUidsToPreviousPaths = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction([STORE_NAME, HISTORY_STORE], 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n const historyStore = tx.objectStore(HISTORY_STORE)\n\n for (const uid of uids) {\n const history = await historyStore.get(uid)\n if (history?.previousAction?.length) {\n for (const actionType of history.previousAction) {\n const record = (await store.get(actionType)) || {\n actionType,\n selectedRecords: []\n }\n\n if (!record.selectedRecords.includes(uid)) {\n record.selectedRecords.push(uid)\n }\n\n await store.put(record)\n }\n\n await historyStore.delete(uid)\n }\n }\n\n await tx.done\n}\nexport const deleteUidsCompletely = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction(['selectedRecords', 'recordHistory'], 'readwrite')\n const store = tx.objectStore('selectedRecords')\n const historyStore = tx.objectStore('recordHistory')\n\n const allRecords = await store.getAll()\n\n for (const record of allRecords) {\n const originalLength = record.selectedRecords.length\n record.selectedRecords = record.selectedRecords.filter((id: string) => !uids.includes(id))\n\n if (record.selectedRecords.length !== originalLength) {\n await store.put(record)\n }\n }\n for (const uid of uids) {\n await historyStore.delete(uid)\n }\n\n await tx.done\n}\n\nexport const getSelectedCategoryDataByPath = (): string[] => {\n try {\n const saved = localStorage.getItem('selectedCategoryData')\n if (saved) {\n const data = JSON.parse(saved)\n const localPath = window.location.hash.replace(/^#/, '') || '/'\n const categoryData = data[localPath]\n if (categoryData && Array.isArray(categoryData.categoryIds)) {\n return categoryData.categoryIds\n }\n }\n } catch (err) {\n console.warn('Failed to parse localStorage category data:', err)\n }\n\n return []\n}\n\nexport const handleAsyncConfigSearchInitialValue = (): IObjectParams => {\n const defaultConfig: IObjectParams = {\n page: 1,\n pageSize: 1000,\n filterType: 'all'\n }\n\n const categoryIds = getSelectedCategoryDataByPath()\n if (categoryIds.length > 0) {\n return {\n ...defaultConfig,\n categoryId: categoryIds\n }\n }\n\n return defaultConfig\n}\n","import { ICalculatorTotalPage, IPaginationParams } from \"../type/table-type\"\n\nexport const calculatorTotalPage = ({ total = 0, pageSize = 0 }: ICalculatorTotalPage): number => {\n if (!pageSize || (pageSize && pageSize <= 0)) return 0\n return Math.ceil(total / pageSize)\n}\n\nexport const STT = (data?: IPaginationParams, index?: number): number => {\n let stt = 1\n let current_page = 0\n let per_page = 0\n\n if (data?.page !== undefined && data?.pageSize !== undefined) {\n current_page = data.page\n per_page = data.pageSize\n }\n\n let i = (current_page - 1) * per_page\n i = isNaN(i) ? 0 : i\n stt = i + (index ?? 0) + 1\n\n return stt\n}\n","import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import { arrayLocal, getLocalStore, setLocalStore, toggleValues } from '../helpers'\nimport { useCallback, useMemo, useState } from 'react'\nimport { Column } from 'react-data-grid'\nimport { TColumnsTable, useShowHideColumnParameter, useShowHideColumnReturn } from '../type/table-type'\nimport { uniq } from 'lodash'\nimport { isColumn } from '../type/table'\n\nconst useShowHideColumn = <T, SR = unknown>({\n nameLocal = 'table',\n columns,\n ignoreColumns\n}: useShowHideColumnParameter<T, SR>): useShowHideColumnReturn<T, SR> => {\n const nameLocalLocation = `${nameLocal}_location`\n const [locationColumns, setLocationColumns] = useState<string[]>(() => {\n const dataLocal = getLocalStore(nameLocalLocation)\n if (dataLocal) {\n return arrayLocal(dataLocal)\n }\n return []\n })\n const [hiddenColumns, setHiddenColumns] = useState<string[]>(() => {\n const dataLocal = getLocalStore(nameLocal)\n if (dataLocal) {\n return arrayLocal(dataLocal)\n }\n return []\n })\n\n const handleFindLocation = useCallback(\n (filterColumns: TColumnsTable<T, SR>, arrLoctions = locationColumns) => {\n return arrLoctions?.length > 0\n ? arrLoctions?.reduce(\n (total, current) => {\n const currentColumns = filterColumns?.find((item) => {\n const newItem = item as Column<T>\n return newItem?.key === current\n })\n\n if (currentColumns) {\n total = [...total, currentColumns]\n }\n return total\n },\n [] as TColumnsTable<T, SR>\n )\n : filterColumns\n },\n [locationColumns]\n )\n\n const newCloumnKeys = useMemo(\n () =>\n columns\n ?.filter(isColumn)\n .map(column => column.key),\n [columns]\n )\n\n\n const newColumns = useMemo(() => {\n const filterColumns: TColumnsTable<T, SR> =\n columns?.filter(column => {\n if (!isColumn(column)) return true\n\n const key = column.key\n\n if (ignoreColumns?.includes(key)) return true\n if (hiddenColumns?.includes(key)) return false\n\n return true\n }) ?? []\n\n return handleFindLocation(filterColumns)\n }, [columns, hiddenColumns, locationColumns, ignoreColumns])\n\n const newShowhideColumns = useMemo(() => {\n if (!ignoreColumns) return columns\n\n return (\n columns?.filter(column => {\n if (!isColumn(column)) return true\n return !ignoreColumns.includes(column.key)\n }) ?? []\n )\n }, [columns, ignoreColumns])\n\n const changeHiddenColumn = useCallback(\n (key: string | string[]) => {\n let newData = [...hiddenColumns]\n if (typeof key === 'string') {\n newData = toggleValues({\n array: newData,\n value: key\n })\n } else {\n newData = key\n }\n setLocalStore(nameLocal, JSON.stringify(newData))\n setHiddenColumns(newData)\n },\n [hiddenColumns, nameLocalLocation]\n )\n\n const handleChangeLocation = useCallback(\n (key: string[]) => {\n let newKey = key\n newKey = uniq([...key, ...newCloumnKeys])\n setLocationColumns(newKey)\n setLocalStore(nameLocalLocation, JSON.stringify(newKey))\n },\n [newCloumnKeys]\n )\n\n return {\n hiddenColumns,\n setHiddenColumns,\n columnsTable: newColumns,\n changeHiddenColumn,\n newShowhideColumns,\n locationColumns,\n handleFindLocation,\n handleChangeLocation\n }\n}\n\nexport { useShowHideColumn }\n","import { UseMutateFunction } from '@tanstack/react-query'\nimport { FormikProps } from 'formik'\nimport { Dispatch, HTMLAttributes, ReactNode, SetStateAction } from 'react'\nimport { Props } from 'react-select'\nimport type { IFieldUpdateAndCheck, IMainResponse, ISettingSystem } from './preload-stubs'\nimport type { JobDetail, Proxy } from './vitechgroup-stubs'\n\nimport type { Column, ColumnOrColumnGroup } from 'react-data-grid'\n\nexport function isColumn<T, SR>(\n column: ColumnOrColumnGroup<T, SR>\n): column is Column<T, SR> {\n return 'key' in column\n}\n\nexport interface ITableData {\n t: any\n dataJobDetail?: JobDetail[]\n totalAction?: number\n settingSystem?: ISettingSystem\n readProxyByField?: UseMutateFunction<\n IMainResponse<Proxy[]>,\n Error,\n IFieldUpdateAndCheck<Proxy, undefined, string[]>[],\n unknown\n >\n}\n\nexport interface CustomSelectProps<T> extends Props, Omit<WapperLabelFormProps, 'children'> {\n className?: string\n height?: string\n name: string\n formik?: FormikProps<T>\n msgError?: string\n changeSelected?: (selected?: Record<string, string>) => void\n setValueSearch?: Dispatch<SetStateAction<string>>\n positionMenu?: string\n}\n\nexport interface WapperLabelFormProps {\n classWapper?: HTMLAttributes<HTMLDivElement>['className']\n label?: string\n clsLabelWrapper?: string\n isRequired?: boolean\n children?: ReactNode\n isVertical?: boolean\n}\n","'use client'\n\nimport { get } from 'lodash'\nimport {\n Key,\n memo,\n useCallback,\n useMemo\n} from 'react'\nimport {\n DataGrid,\n type Column,\n type ColumnOrColumnGroup\n} from 'react-data-grid'\nimport 'react-data-grid/lib/styles.css'\n\nimport { cn } from '../../../helpers'\nimport { STT } from '../../../helpers/table'\nimport { LoadingIcon } from '../../Icons'\nimport type { IReactTableGridCustom } from './table-type'\nimport './ReactTableGridCustom.css'\n\nconst ReactTableGridCustomInner = <\n T,\n SR = unknown,\n K extends Key = Key\n>(\n props: IReactTableGridCustom<T, SR, K>\n) => {\n const {\n classNameWapperTable,\n hiddenSTT,\n data,\n page,\n pageSize,\n columns,\n rowKeyGetter = 'uid',\n\n enableSelectRow,\n selectedRows,\n onSelectedRowsChange,\n\n sortColumns,\n onSortColumnsChange,\n\n fetching,\n onRowClick,\n onRowDoubleClick\n } = props\n\n const isSelectRow =\n enableSelectRow && selectedRows !== undefined\n\n /* =========================\n * Row key\n * ========================= */\n const customRowKeyGetter = useCallback(\n (row: T): K => {\n if (typeof rowKeyGetter === 'function') {\n return rowKeyGetter(row)\n }\n return get(row, rowKeyGetter) as K\n },\n [rowKeyGetter]\n )\n\n /* =========================\n * Select column (CUSTOM)\n * ========================= */\n const selectColumn = useMemo<Column<T, SR>>(\n () => ({\n key: '__select__',\n name: '',\n width: 44,\n frozen: true,\n sortable: false,\n resizable: false,\n\n renderHeaderCell: () => {\n if (!onSelectedRowsChange) return null\n\n const allSelected =\n selectedRows?.size === data.length && data.length > 0\n\n return (\n <input\n type=\"checkbox\"\n checked={allSelected}\n onChange={(e) => {\n if (e.target.checked) {\n onSelectedRowsChange(\n new Set(data.map(customRowKeyGetter))\n )\n } else {\n onSelectedRowsChange(new Set())\n }\n }}\n />\n )\n },\n\n renderCell: ({ row }) => {\n const key = customRowKeyGetter(row)\n\n return (\n <input\n type=\"checkbox\"\n checked={selectedRows?.has(key)}\n onChange={() => {\n if (!onSelectedRowsChange) return\n\n const next = new Set(selectedRows)\n if (next.has(key)) {\n next.delete(key)\n } else {\n next.add(key)\n }\n onSelectedRowsChange(next)\n }}\n />\n )\n }\n }),\n [\n customRowKeyGetter,\n data,\n selectedRows,\n onSelectedRowsChange\n ]\n )\n\n /* =========================\n * Columns\n * ========================= */\n const newColumns = useMemo<\n readonly ColumnOrColumnGroup<T, SR>[]\n >(() => {\n const cols = [...columns]\n\n if (isSelectRow) {\n cols.unshift(selectColumn)\n }\n\n if (!hiddenSTT) {\n cols.unshift({\n key: '__index__',\n name: 'STT',\n width: 80,\n sortable: false,\n renderCell: ({ rowIdx }) =>\n STT({ page, pageSize }, rowIdx)\n })\n }\n\n return cols\n }, [\n columns,\n hiddenSTT,\n isSelectRow,\n page,\n pageSize,\n selectColumn\n ])\n\n return (\n <div\n className={cn(\n 'wapper_table flex flex-col h-full min-h-0 relative',\n classNameWapperTable\n )}\n >\n <DataGrid<T, SR, K>\n rows={data}\n columns={newColumns}\n selectedRows={selectedRows}\n onSelectedRowsChange={onSelectedRowsChange}\n rowKeyGetter={isSelectRow ? customRowKeyGetter : undefined}\n sortColumns={sortColumns}\n onSortColumnsChange={onSortColumnsChange}\n onCellClick={({ row, rowIdx }) =>\n onRowClick?.(row, rowIdx)\n }\n onCellDoubleClick={({ row, rowIdx }) =>\n onRowDoubleClick?.(row, rowIdx)\n }\n />\n\n {fetching && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white/60 z-10\">\n <LoadingIcon isSpin />\n </div>\n )}\n </div>\n )\n}\n\n/* =========================\n * Export\n * ========================= */\nexport const ReactTableGridCustom = memo(\n ReactTableGridCustomInner\n) as typeof ReactTableGridCustomInner\n","import { JSX } from \"react\"\n\nexport const LoadingIcon = ({\n isSpin = false,\n h = 30,\n w = 30,\n size = 30,\n className\n}: {\n isSpin?: boolean\n w?: number\n h?: number\n size?: number\n className?: string\n}): JSX.Element => {\n return (\n <svg\n className={`${isSpin ? 'animate-spin' : ''} ${className ?? ''}`}\n viewBox=\"0 0 1024 1024\"\n focusable=\"false\"\n data-icon=\"loading\"\n width={size || w}\n height={size || h}\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z\"></path>\n </svg>\n )\n}\n\nexport const ArrowIcon = ({\n h,\n w,\n size,\n className\n}: {\n w?: number\n h?: number\n size?: number\n className?: string\n}): JSX.Element => {\n return (\n <svg\n className={className}\n stroke=\"currentColor\"\n fill=\"currentColor\"\n strokeWidth=\"0\"\n viewBox=\"0 0 16 16\"\n height={size ?? h}\n width={size ?? w}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M8 4a.5.5 0 0 1 .5.5v5.793l2.146-2.147a.5.5 0 0 1 .708.708l-3 3a.5.5 0 0 1-.708 0l-3-3a.5.5 0 1 1 .708-.708L7.5 10.293V4.5A.5.5 0 0 1 8 4\"\n ></path>\n </svg>\n )\n}\n","import { FC, memo, ReactNode, useId } from 'react'\n\n/* =========================\n * Props\n * ========================= */\nexport interface TableStyleWapperProps {\n children?: ReactNode\n clsTablecustom?: string\n idWapper?: string // có thể truyền id từ ngoài\n}\n\n/* =========================\n * Client guard\n * ========================= */\nconst isClient = typeof window !== 'undefined'\n\n/* =========================\n * Component\n * ========================= */\nconst TableStyleContextWapperInner: FC<TableStyleWapperProps> = ({\n children,\n clsTablecustom,\n idWapper: externalId\n}) => {\n // server / electron preload → render children\n if (!isClient) {\n return <>{children}</>\n }\n\n // ƯU TIÊN: id ngoài → useId → fallback\n const reactId = useId()\n const idWapper = externalId ?? reactId\n\n return (\n <div\n id={`wapper_menu_context-${idWapper}`}\n className={`border border-[#dedede] rounded-xl overflow-hidden bg-white flex-1 h-full flex flex-col min-h-[360px] ${clsTablecustom ?? ''}`}\n >\n {children}\n </div>\n )\n}\n\n/* =========================\n * Export component (SAFE)\n * ========================= */\nexport const TableStyleContextWapper = memo(\n TableStyleContextWapperInner\n)\n\n/* =========================\n * Helper (EXPORT RIÊNG – SAFE)\n * ========================= */\nexport const getTableStyleWapperId = (externalId?: string) =>\n `wapper_menu_context-${externalId ?? 'default'}`\n"],"mappings":"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","names":["useCallback","useMemo","jsx","useCallback","useMemo","memo","jsx"]}
1
+ {"version":3,"sources":["../src/helpers/functions.ts","../src/helpers/table.ts","../src/utils.ts","../src/hooks/useShowHideColumn.ts","../src/type/table.ts","../src/component/ui/Table/ReactTableGridCustom.tsx","../src/component/ui/Table/TableStyleContextWapper.tsx"],"sourcesContent":["import { deleteDB, IDBPDatabase, openDB } from 'idb'\nimport { pickBy } from 'lodash'\nimport moment from 'moment'\nimport { optionSelect } from '../type/preload-stubs'\nimport { IObjectParams, IToggleValues } from '../type/renderer'\nexport const setLocalStore = (key: string, value: string): void => {\n if (typeof window !== 'undefined') {\n localStorage.setItem(key, value)\n }\n}\n\nexport const getLocalStore = (key: string): string | null => {\n if (typeof window !== 'undefined') {\n return localStorage.getItem(key)\n } else {\n return null\n }\n}\n\nexport function convertViToEn(str: string, toUpperCase = false): string {\n str = str.toLowerCase()\n str = str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g, 'a')\n str = str.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g, 'e')\n str = str.replace(/ì|í|ị|ỉ|ĩ/g, 'i')\n str = str.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g, 'o')\n str = str.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g, 'u')\n str = str.replace(/ỳ|ý|ỵ|ỷ|ỹ/g, 'y')\n str = str.replace(/đ/g, 'd')\n // Some system encode vietnamese combining accent as individual utf-8 characters\n str = str.replace(/\\u0300|\\u0301|\\u0303|\\u0309|\\u0323/g, '') // Huyền sắc hỏi ngã nặng\n str = str.replace(/\\u02C6|\\u0306|\\u031B/g, '') // Â, Ê, Ă, Ơ, Ư\n\n return toUpperCase ? str.toUpperCase() : str\n}\n\nexport const convertNumber = (value: number | string): { value: number; check: boolean } => {\n let num = 0\n if (value) {\n value = value.toString().replace(/[.]/g, '')\n value = value.trim()\n num = Number(value)\n }\n\n const regex = /^-?\\d*$/\n const check = regex.test(num.toString())\n return {\n value: num,\n check\n }\n}\n\nexport const changeTitleDocmemt = (title?: string): void => {\n document.title = `${title} - Phần Mềm MKT`\n}\n\nexport const numberConvert = (num: string | number): string => {\n let t = '0'\n if (num) {\n if (typeof num === 'string') {\n num = Number(num)\n }\n t = num.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.')\n }\n return t\n}\n\nexport const pickBySearch = <T extends Record<string, unknown>>(obj: T): Partial<T> => {\n const filteredObj = pickBy(obj, (value) => value !== '')\n return filteredObj as Partial<T>\n}\n\nexport const getValueSelected = (value?: unknown, options?: optionSelect[]): optionSelect[] => {\n const currentValue = (options ?? [])?.filter((otp) => {\n return Array.isArray(value) ? value?.includes(otp.value) : otp?.value === value\n })\n return currentValue\n}\n\nexport const toggleValues = ({ array, value }: IToggleValues): string[] => {\n if (array.includes(value)) {\n return array.filter((item) => item !== value)\n } else {\n return [...array, value]\n }\n}\n\nexport const arrayLocal = (array?: string): string[] => {\n try {\n const data = array ? JSON.parse(array) : []\n return Array.isArray(data) ? data : []\n } catch {\n return []\n }\n}\n\nexport const formatDate = (\n date?: string | number | Date,\n format: string = 'DD/MM/YYYY HH:mm:ss A'\n): string => {\n return moment(date).format(format)\n}\n\nexport const parseObject = (obj?: string): object => {\n try {\n const data = obj ? JSON.parse(obj) : {}\n return typeof data === 'object' ? data : {}\n } catch {\n return {}\n }\n}\nexport const bufferToBlob = (buffer: ArrayBuffer | Uint8Array, type: string): Blob => {\n return new Blob([buffer as BlobPart], { type })\n}\nconst DB_NAME = 'appDB'\nconst DB_VERSION = 5\nconst STORE_NAME = 'selectedRecords'\nconst HISTORY_STORE = 'recordHistory'\ninterface SelectedRecordEntry {\n actionType: string\n selectedRecords: string[]\n}\n\ninterface RecordHistoryEntry {\n id: string\n previousAction: string[]\n}\n\ntype AppDBSchema = {\n selectedRecords: SelectedRecordEntry\n recordHistory: RecordHistoryEntry\n}\n\nconst requiredStores = [STORE_NAME, HISTORY_STORE]\n\nconst createAppDB = async (): Promise<IDBPDatabase<AppDBSchema>> => {\n return openDB<AppDBSchema>(DB_NAME, DB_VERSION, {\n upgrade(db) {\n for (const storeName of Array.from(db.objectStoreNames)) {\n db.deleteObjectStore(storeName)\n }\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n const store = db.createObjectStore(STORE_NAME, {\n keyPath: 'actionType'\n })\n store.createIndex('by_actionType', 'actionType')\n }\n\n if (!db.objectStoreNames.contains(HISTORY_STORE)) {\n db.createObjectStore(HISTORY_STORE, { keyPath: 'id' })\n }\n }\n })\n}\n\nexport const openAppDB = async (): Promise<IDBPDatabase<AppDBSchema>> => {\n try {\n const db = await createAppDB()\n const hasAllStores = requiredStores.every((store) => db.objectStoreNames.contains(store))\n if (!hasAllStores) {\n console.warn('[IndexedDB] Missing required stores. Resetting DB...')\n db.close()\n await deleteDB(DB_NAME)\n return await createAppDB()\n }\n return db\n } catch (error) {\n if ((error as { name: string })?.name === 'VersionError') {\n console.warn('[IndexedDB] Version downgrade detected. Resetting DB...')\n await deleteDB(DB_NAME)\n return await createAppDB()\n }\n\n console.error('[IndexedDB] Failed to open DB:', error)\n throw error\n }\n}\n\nexport const saveSelectedRecords = async (\n ACTION_TYPE: string,\n selectedRecords: Set<string>\n): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction(STORE_NAME, 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n\n const data: SelectedRecordEntry = {\n actionType: ACTION_TYPE,\n selectedRecords: Array.from(selectedRecords)\n }\n\n await store.put(data)\n await tx.done\n}\n\nexport const getSelectedRecords = async (ACTION_TYPE: string): Promise<Set<string>> => {\n const db = await openAppDB()\n const store = db.transaction(STORE_NAME).objectStore(STORE_NAME)\n\n const record = await store.get(ACTION_TYPE)\n\n return new Set(record?.selectedRecords ?? [])\n}\nexport const removeUidsFromAllPathsAndSaveHistory = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction([STORE_NAME, HISTORY_STORE], 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n const historyStore = tx.objectStore(HISTORY_STORE)\n\n const allRecords = await store.getAll()\n\n const historyMap: Record<string, string[]> = {}\n\n for (const uid of uids) {\n historyMap[uid] = []\n }\n\n for (const record of allRecords) {\n let updated = false\n\n for (const uid of uids) {\n if (record.selectedRecords.includes(uid)) {\n record.selectedRecords = record.selectedRecords.filter((id: string) => id !== uid)\n historyMap[uid].push(record.actionType)\n updated = true\n }\n }\n\n if (updated) {\n await store.put(record)\n }\n }\n\n // Ghi lại lịch sử path đã bị xóa cho từng UID\n for (const [uid, paths] of Object.entries(historyMap)) {\n if (paths.length > 0) {\n await historyStore.put({ id: uid, previousAction: paths })\n }\n }\n\n await tx.done\n}\n\nexport const restoreUidsToPreviousPaths = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction([STORE_NAME, HISTORY_STORE], 'readwrite')\n const store = tx.objectStore(STORE_NAME)\n const historyStore = tx.objectStore(HISTORY_STORE)\n\n for (const uid of uids) {\n const history = await historyStore.get(uid)\n if (history?.previousAction?.length) {\n for (const actionType of history.previousAction) {\n const record = (await store.get(actionType)) || {\n actionType,\n selectedRecords: []\n }\n\n if (!record.selectedRecords.includes(uid)) {\n record.selectedRecords.push(uid)\n }\n\n await store.put(record)\n }\n\n await historyStore.delete(uid)\n }\n }\n\n await tx.done\n}\nexport const deleteUidsCompletely = async (uids: string[]): Promise<void> => {\n const db = await openAppDB()\n const tx = db.transaction(['selectedRecords', 'recordHistory'], 'readwrite')\n const store = tx.objectStore('selectedRecords')\n const historyStore = tx.objectStore('recordHistory')\n\n const allRecords = await store.getAll()\n\n for (const record of allRecords) {\n const originalLength = record.selectedRecords.length\n record.selectedRecords = record.selectedRecords.filter((id: string) => !uids.includes(id))\n\n if (record.selectedRecords.length !== originalLength) {\n await store.put(record)\n }\n }\n for (const uid of uids) {\n await historyStore.delete(uid)\n }\n\n await tx.done\n}\n\nexport const getSelectedCategoryDataByPath = (): string[] => {\n try {\n const saved = localStorage.getItem('selectedCategoryData')\n if (saved) {\n const data = JSON.parse(saved)\n const localPath = window.location.hash.replace(/^#/, '') || '/'\n const categoryData = data[localPath]\n if (categoryData && Array.isArray(categoryData.categoryIds)) {\n return categoryData.categoryIds\n }\n }\n } catch (err) {\n console.warn('Failed to parse localStorage category data:', err)\n }\n\n return []\n}\n\nexport const handleAsyncConfigSearchInitialValue = (): IObjectParams => {\n const defaultConfig: IObjectParams = {\n page: 1,\n pageSize: 1000,\n filterType: 'all'\n }\n\n const categoryIds = getSelectedCategoryDataByPath()\n if (categoryIds.length > 0) {\n return {\n ...defaultConfig,\n categoryId: categoryIds\n }\n }\n\n return defaultConfig\n}\n","import { ICalculatorTotalPage, IPaginationParams } from \"../type/table-type\"\n\nexport const calculatorTotalPage = ({ total = 0, pageSize = 0 }: ICalculatorTotalPage): number => {\n if (!pageSize || (pageSize && pageSize <= 0)) return 0\n return Math.ceil(total / pageSize)\n}\n\nexport const STT = (data?: IPaginationParams, index?: number): number => {\n let stt = 1\n let current_page = 0\n let per_page = 0\n\n if (data?.page !== undefined && data?.pageSize !== undefined) {\n current_page = data.page\n per_page = data.pageSize\n }\n\n let i = (current_page - 1) * per_page\n i = isNaN(i) ? 0 : i\n stt = i + (index ?? 0) + 1\n\n return stt\n}\n","import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs))\n}\n","import { arrayLocal, getLocalStore, setLocalStore, toggleValues } from '../helpers'\nimport { useCallback, useMemo, useState } from 'react'\nimport { Column } from 'react-data-grid'\nimport { TColumnsTable, useShowHideColumnParameter, useShowHideColumnReturn } from '../type/table-type'\nimport { uniq } from 'lodash'\nimport { isColumn } from '../type/table'\n\nconst useShowHideColumn = <T, SR = unknown>({\n nameLocal = 'table',\n columns,\n ignoreColumns\n}: useShowHideColumnParameter<T, SR>): useShowHideColumnReturn<T, SR> => {\n const nameLocalLocation = `${nameLocal}_location`\n const [locationColumns, setLocationColumns] = useState<string[]>(() => {\n const dataLocal = getLocalStore(nameLocalLocation)\n if (dataLocal) {\n return arrayLocal(dataLocal)\n }\n return []\n })\n const [hiddenColumns, setHiddenColumns] = useState<string[]>(() => {\n const dataLocal = getLocalStore(nameLocal)\n if (dataLocal) {\n return arrayLocal(dataLocal)\n }\n return []\n })\n\n const handleFindLocation = useCallback(\n (filterColumns: TColumnsTable<T, SR>, arrLoctions = locationColumns) => {\n return arrLoctions?.length > 0\n ? arrLoctions?.reduce(\n (total, current) => {\n const currentColumns = filterColumns?.find((item) => {\n const newItem = item as Column<T>\n return newItem?.key === current\n })\n\n if (currentColumns) {\n total = [...total, currentColumns]\n }\n return total\n },\n [] as TColumnsTable<T, SR>\n )\n : filterColumns\n },\n [locationColumns]\n )\n\n const newCloumnKeys = useMemo(\n () =>\n columns\n ?.filter(isColumn)\n .map(column => column.key),\n [columns]\n )\n\n\n const newColumns = useMemo(() => {\n const filterColumns: TColumnsTable<T, SR> =\n columns?.filter(column => {\n if (!isColumn(column)) return true\n\n const key = column.key\n\n if (ignoreColumns?.includes(key)) return true\n if (hiddenColumns?.includes(key)) return false\n\n return true\n }) ?? []\n\n return handleFindLocation(filterColumns)\n }, [columns, hiddenColumns, locationColumns, ignoreColumns])\n\n const newShowhideColumns = useMemo(() => {\n if (!ignoreColumns) return columns\n\n return (\n columns?.filter(column => {\n if (!isColumn(column)) return true\n return !ignoreColumns.includes(column.key)\n }) ?? []\n )\n }, [columns, ignoreColumns])\n\n const changeHiddenColumn = useCallback(\n (key: string | string[]) => {\n let newData = [...hiddenColumns]\n if (typeof key === 'string') {\n newData = toggleValues({\n array: newData,\n value: key\n })\n } else {\n newData = key\n }\n setLocalStore(nameLocal, JSON.stringify(newData))\n setHiddenColumns(newData)\n },\n [hiddenColumns, nameLocalLocation]\n )\n\n const handleChangeLocation = useCallback(\n (key: string[]) => {\n let newKey = key\n newKey = uniq([...key, ...newCloumnKeys])\n setLocationColumns(newKey)\n setLocalStore(nameLocalLocation, JSON.stringify(newKey))\n },\n [newCloumnKeys]\n )\n\n return {\n hiddenColumns,\n setHiddenColumns,\n columnsTable: newColumns,\n changeHiddenColumn,\n newShowhideColumns,\n locationColumns,\n handleFindLocation,\n handleChangeLocation\n }\n}\n\nexport { useShowHideColumn }\n","import { UseMutateFunction } from '@tanstack/react-query'\nimport { FormikProps } from 'formik'\nimport { Dispatch, HTMLAttributes, ReactNode, SetStateAction } from 'react'\nimport { Props } from 'react-select'\nimport type { IFieldUpdateAndCheck, IMainResponse, ISettingSystem } from './preload-stubs'\nimport type { JobDetail, Proxy } from './vitechgroup-stubs'\n\nimport type { Column, ColumnOrColumnGroup } from 'react-data-grid'\n\nexport function isColumn<T, SR>(\n column: ColumnOrColumnGroup<T, SR>\n): column is Column<T, SR> {\n return 'key' in column\n}\n\nexport interface ITableData {\n t: any\n dataJobDetail?: JobDetail[]\n totalAction?: number\n settingSystem?: ISettingSystem\n readProxyByField?: UseMutateFunction<\n IMainResponse<Proxy[]>,\n Error,\n IFieldUpdateAndCheck<Proxy, undefined, string[]>[],\n unknown\n >\n}\n\nexport interface CustomSelectProps<T> extends Props, Omit<WapperLabelFormProps, 'children'> {\n className?: string\n height?: string\n name: string\n formik?: FormikProps<T>\n msgError?: string\n changeSelected?: (selected?: Record<string, string>) => void\n setValueSearch?: Dispatch<SetStateAction<string>>\n positionMenu?: string\n}\n\nexport interface WapperLabelFormProps {\n classWapper?: HTMLAttributes<HTMLDivElement>['className']\n label?: string\n clsLabelWrapper?: string\n isRequired?: boolean\n children?: ReactNode\n isVertical?: boolean\n}\n","'use client'\n\nimport { get } from 'lodash'\nimport {\n Key,\n memo,\n useCallback,\n useMemo\n} from 'react'\nimport {\n DataGrid,\n type Column,\n type ColumnOrColumnGroup\n} from 'react-data-grid'\nimport 'react-data-grid/lib/styles.css'\n\nimport { cn } from '../../../helpers'\nimport { STT } from '../../../helpers/table'\nimport { LoadingIcon } from '../../Icons'\nimport type { IReactTableGridCustom } from './table-type'\nimport './ReactTableGridCustom.css'\n\nconst ReactTableGridCustomInner = <\n T,\n SR = unknown,\n K extends Key = Key\n>(\n props: IReactTableGridCustom<T, SR, K>\n) => {\n const {\n classNameWapperTable,\n hiddenSTT,\n data,\n page,\n pageSize,\n columns,\n rowKeyGetter = 'uid',\n\n enableSelectRow,\n selectedRows,\n onSelectedRowsChange,\n\n sortColumns,\n onSortColumnsChange,\n\n fetching,\n onRowClick,\n onRowDoubleClick\n } = props\n\n const isSelectRow =\n enableSelectRow && selectedRows !== undefined\n\n /* =========================\n * Row key\n * ========================= */\n const customRowKeyGetter = useCallback(\n (row: T): K => {\n if (typeof rowKeyGetter === 'function') {\n return rowKeyGetter(row)\n }\n return get(row, rowKeyGetter) as K\n },\n [rowKeyGetter]\n )\n\n /* =========================\n * Select column (CUSTOM)\n * ========================= */\n const selectColumn = useMemo<Column<T, SR>>(\n () => ({\n key: '__select__',\n name: '',\n width: 44,\n frozen: true,\n sortable: false,\n resizable: false,\n\n renderHeaderCell: () => {\n if (!onSelectedRowsChange) return null\n\n const allSelected =\n selectedRows?.size === data.length && data.length > 0\n\n return (\n <input\n type=\"checkbox\"\n checked={allSelected}\n onChange={(e) => {\n if (e.target.checked) {\n onSelectedRowsChange(\n new Set(data.map(customRowKeyGetter))\n )\n } else {\n onSelectedRowsChange(new Set())\n }\n }}\n />\n )\n },\n\n renderCell: ({ row }) => {\n const key = customRowKeyGetter(row)\n\n return (\n <input\n type=\"checkbox\"\n checked={selectedRows?.has(key)}\n onChange={() => {\n if (!onSelectedRowsChange) return\n\n const next = new Set(selectedRows)\n if (next.has(key)) {\n next.delete(key)\n } else {\n next.add(key)\n }\n onSelectedRowsChange(next)\n }}\n />\n )\n }\n }),\n [\n customRowKeyGetter,\n data,\n selectedRows,\n onSelectedRowsChange\n ]\n )\n\n /* =========================\n * Columns\n * ========================= */\n const newColumns = useMemo<\n readonly ColumnOrColumnGroup<T, SR>[]\n >(() => {\n const cols = [...columns]\n\n if (isSelectRow) {\n cols.unshift(selectColumn)\n }\n\n if (!hiddenSTT) {\n cols.unshift({\n key: '__index__',\n name: 'STT',\n width: 80,\n sortable: false,\n renderCell: ({ rowIdx }) =>\n STT({ page, pageSize }, rowIdx)\n })\n }\n\n return cols\n }, [\n columns,\n hiddenSTT,\n isSelectRow,\n page,\n pageSize,\n selectColumn\n ])\n\n return (\n <div\n className={cn(\n 'wapper_table flex flex-col h-full min-h-0 relative',\n classNameWapperTable\n )}\n >\n <DataGrid<T, SR, K>\n rows={data}\n columns={newColumns}\n selectedRows={selectedRows}\n onSelectedRowsChange={onSelectedRowsChange}\n rowKeyGetter={isSelectRow ? customRowKeyGetter : undefined}\n sortColumns={sortColumns}\n onSortColumnsChange={onSortColumnsChange}\n onCellClick={({ row, rowIdx }) =>\n onRowClick?.(row, rowIdx)\n }\n onCellDoubleClick={({ row, rowIdx }) =>\n onRowDoubleClick?.(row, rowIdx)\n }\n />\n\n {/* {fetching && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white/60 z-10\">\n <LoadingIcon isSpin />\n </div>\n )} */}\n </div>\n )\n}\n\n/* =========================\n * Export\n * ========================= */\nexport const ReactTableGridCustom = memo(\n ReactTableGridCustomInner\n) as typeof ReactTableGridCustomInner\n","import { FC, memo, ReactNode, useId } from 'react'\n\n/* =========================\n * Props\n * ========================= */\nexport interface TableStyleWapperProps {\n children?: ReactNode\n clsTablecustom?: string\n idWapper?: string // có thể truyền id từ ngoài\n}\n\n/* =========================\n * Client guard\n * ========================= */\nconst isClient = typeof window !== 'undefined'\n\n/* =========================\n * Component\n * ========================= */\nconst TableStyleContextWapperInner: FC<TableStyleWapperProps> = ({\n children,\n clsTablecustom,\n idWapper: externalId\n}) => {\n // server / electron preload → render children\n if (!isClient) {\n return <>{children}</>\n }\n\n // ƯU TIÊN: id ngoài → useId → fallback\n const reactId = useId()\n const idWapper = externalId ?? reactId\n\n return (\n <div\n id={`wapper_menu_context-${idWapper}`}\n className={`border border-[#dedede] rounded-xl overflow-hidden bg-white flex-1 h-full flex flex-col min-h-[360px] ${clsTablecustom ?? ''}`}\n >\n {children}\n </div>\n )\n}\n\n/* =========================\n * Export component (SAFE)\n * ========================= */\nexport const TableStyleContextWapper = memo(\n TableStyleContextWapperInner\n)\n\n/* =========================\n * Helper (EXPORT RIÊNG – SAFE)\n * ========================= */\nexport const getTableStyleWapperId = (externalId?: string) =>\n `wapper_menu_context-${externalId ?? 'default'}`\n"],"mappings":"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","names":["useCallback","useMemo","useCallback","useMemo","memo","jsx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mkt-loitd/react-table-grid-custom",
3
- "version": "1.4.6",
3
+ "version": "1.4.7",
4
4
  "description": "React Table Grid Custom component",
5
5
  "license": "ISC",
6
6
  "private": false,