warqadui 0.0.30 → 0.0.31

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
@@ -71,6 +71,7 @@ __export(index_exports, {
71
71
  ThemeToggle: () => ThemeToggle,
72
72
  WarqadProvider: () => WarqadProvider,
73
73
  generatePdf: () => generatePdf,
74
+ storage: () => storage,
74
75
  useA4StatementView: () => useA4DataView_default,
75
76
  useApi: () => useApis_default,
76
77
  useModal: () => useModal,
@@ -2851,7 +2852,8 @@ function DataTable({
2851
2852
  defaultExpanded = false,
2852
2853
  onChange,
2853
2854
  selectable = true,
2854
- filterables = true
2855
+ filterables = true,
2856
+ emptyState
2855
2857
  }) {
2856
2858
  const { theme } = useWarqadConfig();
2857
2859
  const primaryColor = theme?.primaryColor;
@@ -3079,7 +3081,7 @@ function DataTable({
3079
3081
  {
3080
3082
  colSpan: columns.length,
3081
3083
  className: "h-32 text-center text-sm text-gray-500",
3082
- children: "No results found."
3084
+ children: emptyState || "No results found."
3083
3085
  }
3084
3086
  ) }) }),
3085
3087
  table.getFooterGroups().some(
@@ -3145,6 +3147,85 @@ var import_react16 = __toESM(require("react"));
3145
3147
  var import_react_table2 = require("@tanstack/react-table");
3146
3148
  var import_lucide_react11 = require("lucide-react");
3147
3149
  var import_jsx_runtime24 = require("react/jsx-runtime");
3150
+ var TableCell = import_react16.default.memo(
3151
+ ({
3152
+ cell,
3153
+ rowPadding,
3154
+ verticalLines
3155
+ }) => {
3156
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3157
+ "td",
3158
+ {
3159
+ className: cn(
3160
+ rowPadding,
3161
+ "text-sm text-gray-700 dark:text-gray-200",
3162
+ verticalLines && "border-x border-gray-200 dark:border-zinc-800",
3163
+ cell.column.id === "_index" && "w-[1%] min-w-[40px] max-w-[40px] whitespace-nowrap",
3164
+ cell.column.columnDef.meta?.className
3165
+ ),
3166
+ style: {
3167
+ width: cell.column.columnDef.meta?.width ?? cell.column.getSize(),
3168
+ minWidth: cell.column.columnDef.meta?.width ?? cell.column.columnDef.minSize,
3169
+ maxWidth: cell.column.columnDef.meta?.width ?? cell.column.columnDef.maxSize
3170
+ },
3171
+ children: (0, import_react_table2.flexRender)(cell.column.columnDef.cell, cell.getContext())
3172
+ },
3173
+ cell.id
3174
+ );
3175
+ },
3176
+ (prev, next) => {
3177
+ return prev.cell.getValue() === next.cell.getValue() && prev.cell.row.getIsExpanded() === next.cell.row.getIsExpanded() && prev.cell.row.getIsSelected() === next.cell.row.getIsSelected() && prev.rowPadding === next.rowPadding && prev.verticalLines === next.verticalLines;
3178
+ }
3179
+ );
3180
+ var TableRow = import_react16.default.memo(
3181
+ ({
3182
+ row,
3183
+ rowPadding,
3184
+ verticalLines,
3185
+ renderSubComponent,
3186
+ hasSubComponent,
3187
+ columnsCount
3188
+ }) => {
3189
+ const isExpanded = row.getIsExpanded();
3190
+ const subComponentVisible = renderSubComponent && isExpanded && hasSubComponent(row.original);
3191
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react16.default.Fragment, { children: [
3192
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3193
+ "tr",
3194
+ {
3195
+ className: `border-b border-gray-200 dark:border-zinc-800 hover:bg-gray-50/50 dark:hover:bg-zinc-900/50 transition-colors last:border-b-0 ${renderSubComponent && hasSubComponent(row.original) ? "cursor-pointer" : ""}`,
3196
+ "data-state": row.getIsSelected() && "selected",
3197
+ onClick: (e) => {
3198
+ if (renderSubComponent && hasSubComponent(row.original)) {
3199
+ const target = e.target;
3200
+ if (!target.closest("button, a, input, select, textarea")) {
3201
+ row.toggleExpanded();
3202
+ }
3203
+ }
3204
+ },
3205
+ children: row.getVisibleCells().map((cell) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3206
+ TableCell,
3207
+ {
3208
+ cell,
3209
+ rowPadding,
3210
+ verticalLines
3211
+ },
3212
+ cell.id
3213
+ ))
3214
+ }
3215
+ ),
3216
+ subComponentVisible && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("tr", { className: "border-b border-gray-200 dark:border-zinc-800 bg-gray-50/20 dark:bg-zinc-900/20", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("td", { colSpan: columnsCount, className: "px-2 py-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "relative pl-6 pb-2 pr-2 pt-2 h-full", children: [
3217
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute left-2 top-0 bottom-2 w-6 border-l-2 border-b-2 rounded-bl-xl border-(--theme-primary) dark:border-(--theme-primary) pointer-events-none" }),
3218
+ renderSubComponent({
3219
+ row: row.original,
3220
+ index: row.index
3221
+ })
3222
+ ] }) }) })
3223
+ ] });
3224
+ },
3225
+ (prev, next) => {
3226
+ return prev.row.original === next.row.original && prev.row.getIsExpanded() === next.row.getIsExpanded() && prev.row.getIsSelected() === next.row.getIsSelected() && prev.rowPadding === next.rowPadding && prev.verticalLines === next.verticalLines;
3227
+ }
3228
+ );
3148
3229
  function PostTable({
3149
3230
  columns: userColumns,
3150
3231
  data: controlledData,
@@ -3158,7 +3239,8 @@ function PostTable({
3158
3239
  renderSubComponent,
3159
3240
  hasSubComponent = () => true,
3160
3241
  // default to true if renderSubComponent is provided
3161
- defaultExpanded = false
3242
+ defaultExpanded = false,
3243
+ submitLoading = false
3162
3244
  }) {
3163
3245
  const { theme } = useWarqadConfig();
3164
3246
  const primaryColor = theme?.primaryColor;
@@ -3206,18 +3288,46 @@ function PostTable({
3206
3288
  const [editingIndex, setEditingIndex] = (0, import_react16.useState)(null);
3207
3289
  const [isSavingAsync, setIsSavingAsync] = (0, import_react16.useState)(false);
3208
3290
  const [fieldErrors, setFieldErrors] = (0, import_react16.useState)({});
3209
- const handleSaveField = async () => {
3210
- if (Object.keys(entryData).length === 0) return;
3211
- let newData = [...data];
3212
- if (editingIndex !== null) {
3213
- newData[editingIndex] = {
3214
- ...newData[editingIndex],
3215
- ...entryData
3291
+ const latestStateRef = (0, import_react16.useRef)({
3292
+ data,
3293
+ entryData,
3294
+ editingIndex,
3295
+ isSavingAsync,
3296
+ submitLoading,
3297
+ fieldErrors,
3298
+ onChange
3299
+ });
3300
+ (0, import_react16.useEffect)(() => {
3301
+ latestStateRef.current = {
3302
+ data,
3303
+ entryData,
3304
+ editingIndex,
3305
+ isSavingAsync,
3306
+ submitLoading,
3307
+ fieldErrors,
3308
+ onChange
3309
+ };
3310
+ });
3311
+ const handleSaveField = (0, import_react16.useCallback)(async () => {
3312
+ const {
3313
+ data: data2,
3314
+ entryData: entryData2,
3315
+ editingIndex: editingIndex2,
3316
+ isSavingAsync: isSavingAsync2,
3317
+ submitLoading: submitLoading2,
3318
+ onChange: onChange2
3319
+ } = latestStateRef.current;
3320
+ if (Object.keys(entryData2).length === 0) return;
3321
+ let newData = [...data2];
3322
+ if (editingIndex2 !== null) {
3323
+ newData[editingIndex2] = {
3324
+ ...newData[editingIndex2],
3325
+ ...entryData2
3216
3326
  };
3217
3327
  } else {
3218
- newData = [...newData, entryData];
3328
+ newData = [...newData, entryData2];
3219
3329
  }
3220
- if (onChange) {
3330
+ if (onChange2) {
3221
3331
  setIsSavingAsync(true);
3222
3332
  try {
3223
3333
  const actions = {
@@ -3241,9 +3351,9 @@ function PostTable({
3241
3351
  }));
3242
3352
  }
3243
3353
  };
3244
- const type = editingIndex !== null ? "edit" : "add";
3245
- const result = await onChange({
3246
- entryData,
3354
+ const type = editingIndex2 !== null ? "edit" : "add";
3355
+ const result = await onChange2({
3356
+ entryData: entryData2,
3247
3357
  actions,
3248
3358
  actionType: type,
3249
3359
  fullData: newData
@@ -3261,23 +3371,24 @@ function PostTable({
3261
3371
  setEntryData({});
3262
3372
  setFieldErrors({});
3263
3373
  setIsSavingAsync(false);
3264
- if (editingIndex !== null) {
3374
+ if (editingIndex2 !== null) {
3265
3375
  setEditingIndex(null);
3266
3376
  } else {
3267
3377
  focusAndScrollEntryRow();
3268
3378
  }
3269
- };
3270
- const handleCancelEdit = () => {
3379
+ }, []);
3380
+ const handleCancelEdit = (0, import_react16.useCallback)(() => {
3271
3381
  setEditingIndex(null);
3272
3382
  setEntryData({});
3273
3383
  setFieldErrors({});
3274
- };
3275
- const handleEdit = (index2, rowOriginal) => {
3384
+ }, []);
3385
+ const handleEdit = (0, import_react16.useCallback)((index2, rowOriginal) => {
3276
3386
  setEditingIndex(index2);
3277
3387
  setEntryData(rowOriginal);
3278
- };
3279
- const handleDelete = (index2) => {
3280
- const newData = data.filter((_, i) => i !== index2);
3388
+ }, []);
3389
+ const handleDelete = (0, import_react16.useCallback)((index2) => {
3390
+ const { data: data2, editingIndex: editingIndex2, onChange: onChange2 } = latestStateRef.current;
3391
+ const newData = data2.filter((_, i) => i !== index2);
3281
3392
  setData(newData);
3282
3393
  const actions = {
3283
3394
  focus: (columnId) => {
@@ -3300,44 +3411,47 @@ function PostTable({
3300
3411
  }));
3301
3412
  }
3302
3413
  };
3303
- onChange?.({
3304
- entryData: data[index2],
3414
+ onChange2?.({
3415
+ entryData: data2[index2],
3305
3416
  actions,
3306
3417
  actionType: "delete",
3307
3418
  fullData: newData
3308
3419
  });
3309
- if (editingIndex === index2) {
3420
+ if (editingIndex2 === index2) {
3310
3421
  handleCancelEdit();
3311
- } else if (editingIndex !== null && editingIndex > index2) {
3312
- setEditingIndex(editingIndex - 1);
3422
+ } else if (editingIndex2 !== null && editingIndex2 > index2) {
3423
+ setEditingIndex(editingIndex2 - 1);
3313
3424
  }
3314
- };
3315
- const actionColumn = {
3425
+ }, [handleCancelEdit]);
3426
+ const actionColumn = (0, import_react16.useMemo)(() => ({
3316
3427
  id: "actions",
3317
3428
  header: "Actions",
3318
- cell: ({ row }) => {
3429
+ cell: ({ row, table: table2 }) => {
3430
+ const { handleEdit: handleEdit2, handleDelete: handleDelete2, submitLoading: submitLoading2, isSavingAsync: isSavingAsync2 } = table2.options.meta;
3319
3431
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-2", children: [
3320
3432
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3321
3433
  "button",
3322
3434
  {
3323
- onClick: () => handleEdit(row.index, row.original),
3324
- className: "p-1 px-2 rounded-md hover:bg-gray-100 dark:hover:bg-zinc-800 text-gray-500 hover:text-(--theme-primary) dark:hover:text-(--theme-primary) transition-colors",
3435
+ onClick: () => handleEdit2(row.index, row.original),
3436
+ disabled: submitLoading2 || isSavingAsync2,
3437
+ className: "p-1 px-2 rounded-md hover:bg-gray-100 dark:hover:bg-zinc-800 text-gray-500 hover:text-(--theme-primary) dark:hover:text-(--theme-primary) transition-colors disabled:opacity-50",
3325
3438
  title: "Edit",
3326
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Edit2, { size: 16 })
3439
+ children: submitLoading2 || isSavingAsync2 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Loader2, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Edit2, { size: 16 })
3327
3440
  }
3328
3441
  ),
3329
3442
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3330
3443
  "button",
3331
3444
  {
3332
- onClick: () => handleDelete(row.index),
3333
- className: "p-1 px-2 rounded-md hover:bg-gray-100 dark:hover:bg-zinc-800 text-gray-500 hover:text-red-600 dark:hover:text-red-400 transition-colors",
3445
+ onClick: () => handleDelete2(row.index),
3446
+ disabled: submitLoading2 || isSavingAsync2,
3447
+ className: "p-1 px-2 rounded-md hover:bg-gray-100 dark:hover:bg-zinc-800 text-gray-500 hover:text-red-600 dark:hover:text-red-400 transition-colors disabled:opacity-50",
3334
3448
  title: "Delete",
3335
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Trash2, { size: 16 })
3449
+ children: submitLoading2 || isSavingAsync2 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Loader2, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Trash2, { size: 16 })
3336
3450
  }
3337
3451
  )
3338
3452
  ] });
3339
3453
  }
3340
- };
3454
+ }), []);
3341
3455
  const columns = (0, import_react16.useMemo)(() => {
3342
3456
  const mappedUserColumns = userColumns.map((col) => ({
3343
3457
  ...col,
@@ -3386,6 +3500,12 @@ function PostTable({
3386
3500
  columnFilters,
3387
3501
  columnVisibility,
3388
3502
  expanded
3503
+ },
3504
+ meta: {
3505
+ handleEdit,
3506
+ handleDelete,
3507
+ submitLoading,
3508
+ isSavingAsync
3389
3509
  }
3390
3510
  });
3391
3511
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
@@ -3440,54 +3560,18 @@ function PostTable({
3440
3560
  ))
3441
3561
  },
3442
3562
  `skeleton-${i}`
3443
- )) : table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react16.default.Fragment, { children: [
3444
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3445
- "tr",
3446
- {
3447
- className: `border-b border-gray-200 dark:border-zinc-800 hover:bg-gray-50/50 dark:hover:bg-zinc-900/50 transition-colors last:border-b-0 ${renderSubComponent && hasSubComponent(row.original) ? "cursor-pointer" : ""}`,
3448
- "data-state": row.getIsSelected() && "selected",
3449
- onClick: (e) => {
3450
- if (renderSubComponent && hasSubComponent(row.original)) {
3451
- const target = e.target;
3452
- if (!target.closest(
3453
- "button, a, input, select, textarea"
3454
- )) {
3455
- row.toggleExpanded();
3456
- }
3457
- }
3458
- },
3459
- children: row.getVisibleCells().map((cell) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3460
- "td",
3461
- {
3462
- className: cn(
3463
- rowPadding,
3464
- "text-sm text-gray-700 dark:text-gray-200",
3465
- verticalLines && "border-x border-gray-200 dark:border-zinc-800",
3466
- cell.column.id === "_index" && "w-[1%] min-w-[40px] max-w-[40px] whitespace-nowrap",
3467
- cell.column.columnDef.meta?.className
3468
- ),
3469
- style: {
3470
- width: cell.column.columnDef.meta?.width ?? cell.column.getSize(),
3471
- minWidth: cell.column.columnDef.meta?.width ?? cell.column.columnDef.minSize,
3472
- maxWidth: cell.column.columnDef.meta?.width ?? cell.column.columnDef.maxSize
3473
- },
3474
- children: (0, import_react_table2.flexRender)(
3475
- cell.column.columnDef.cell,
3476
- cell.getContext()
3477
- )
3478
- },
3479
- cell.id
3480
- ))
3481
- }
3482
- ),
3483
- renderSubComponent && row.getIsExpanded() && hasSubComponent(row.original) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("tr", { className: "border-b border-gray-200 dark:border-zinc-800 bg-gray-50/20 dark:bg-zinc-900/20", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("td", { colSpan: columns.length, className: "px-2 py-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "relative pl-6 pb-2 pr-2 pt-2 h-full", children: [
3484
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute left-2 top-0 bottom-2 w-6 border-l-2 border-b-2 rounded-bl-xl border-(--theme-primary) dark:border-(--theme-primary) pointer-events-none" }),
3485
- renderSubComponent({
3486
- row: row.original,
3487
- index: row.index
3488
- })
3489
- ] }) }) })
3490
- ] }, row.id)) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3563
+ )) : table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3564
+ TableRow,
3565
+ {
3566
+ row,
3567
+ rowPadding,
3568
+ verticalLines,
3569
+ renderSubComponent,
3570
+ hasSubComponent,
3571
+ columnsCount: columns.length
3572
+ },
3573
+ row.id
3574
+ )) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3491
3575
  "td",
3492
3576
  {
3493
3577
  colSpan: columns.length,
@@ -3523,17 +3607,17 @@ function PostTable({
3523
3607
  "button",
3524
3608
  {
3525
3609
  onClick: handleSaveField,
3526
- disabled: isSavingAsync,
3610
+ disabled: isSavingAsync || submitLoading,
3527
3611
  className: "flex-1 h-8 flex items-center justify-center rounded-lg bg-green-500/10 text-green-600 dark:bg-emerald-500/20 dark:text-emerald-400 hover:bg-green-500 hover:text-white dark:hover:bg-emerald-500 transition-colors shadow-sm active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed",
3528
3612
  title: "Update",
3529
- children: isSavingAsync ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "w-3.5 h-3.5 rounded-full border-2 border-emerald-500/30 border-t-emerald-500 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Check, { size: 16, strokeWidth: 2.5 })
3613
+ children: isSavingAsync || submitLoading ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Loader2, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Check, { size: 16, strokeWidth: 2.5 })
3530
3614
  }
3531
3615
  ),
3532
3616
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
3533
3617
  "button",
3534
3618
  {
3535
3619
  onClick: handleCancelEdit,
3536
- disabled: isSavingAsync,
3620
+ disabled: isSavingAsync || submitLoading,
3537
3621
  className: "flex-1 h-8 flex items-center justify-center rounded-lg bg-red-500/10 text-red-600 dark:bg-red-500/20 dark:text-red-400 hover:bg-red-500 hover:text-white dark:hover:bg-red-500 transition-colors shadow-sm active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed",
3538
3622
  title: "Cancel",
3539
3623
  children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.X, { size: 16, strokeWidth: 2.5 })
@@ -3547,15 +3631,15 @@ function PostTable({
3547
3631
  "button",
3548
3632
  {
3549
3633
  onClick: handleSaveField,
3550
- disabled: isSavingAsync,
3634
+ disabled: isSavingAsync || submitLoading,
3551
3635
  className: "w-full cursor-pointer h-8 flex items-center justify-center gap-1.5 rounded-lg text-white text-xs font-medium transition-all shadow-sm hover:shadow-md hover:-translate-y-px active:scale-95 active:translate-y-0 hover:brightness-110 disabled:opacity-50 disabled:cursor-not-allowed",
3552
3636
  style: {
3553
3637
  backgroundColor: "var(--theme-primary)"
3554
3638
  },
3555
3639
  title: "Add Row",
3556
3640
  children: [
3557
- isSavingAsync ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "w-3.5 h-3.5 rounded-full border-2 border-white/30 border-t-white animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Plus, { size: 14, strokeWidth: 2.5 }),
3558
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: isSavingAsync ? "Adding..." : "Add" })
3641
+ isSavingAsync || submitLoading ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Loader2, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Plus, { size: 14, strokeWidth: 2.5 }),
3642
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: isSavingAsync || submitLoading ? "Adding..." : "Add" })
3559
3643
  ]
3560
3644
  }
3561
3645
  ) }) })
@@ -3708,7 +3792,8 @@ function SimpleTable({
3708
3792
  startIndex = 0,
3709
3793
  isLoading = false,
3710
3794
  title,
3711
- enableSearch = false
3795
+ enableSearch = false,
3796
+ emptyState
3712
3797
  }) {
3713
3798
  const columns = (0, import_react17.useMemo)(() => {
3714
3799
  const cols = userColumns.filter((col) => !col.hide).map((col) => ({
@@ -3790,8 +3875,8 @@ function SimpleTable({
3790
3875
  "td",
3791
3876
  {
3792
3877
  colSpan: columns.length,
3793
- className: "text-center py-8 text-gray-500 font-medium",
3794
- children: "No transactions found."
3878
+ className: "text-center text-gray-500 font-medium",
3879
+ children: emptyState || /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "py-8", children: "No transactions found." })
3795
3880
  }
3796
3881
  ) }) : table.getRowModel().rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
3797
3882
  "tr",
@@ -4064,24 +4149,22 @@ var useA4StatementView = ({
4064
4149
  }
4065
4150
  );
4066
4151
  const DisplayInfoGridEl = Array.isArray(info) && info.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { id: "a4-info-grid", className: "px-8", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(InfoGrid, { className: "mb-4", items: info, isLoading }) }) : null;
4067
- if (!isLoading && (error || !data || data.length === 0)) {
4068
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex flex-col relative w-full items-center justify-center p-8 min-h-96", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col items-center justify-center p-12 bg-gray-50/50 dark:bg-zinc-900/30 rounded-2xl border border-dashed border-gray-300 dark:border-zinc-700 w-full max-w-xl text-center shadow-sm", children: [
4069
- error ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "w-16 h-16 bg-red-100 dark:bg-red-500/10 rounded-full flex items-center justify-center mb-6", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react12.AlertCircle, { className: "w-8 h-8 text-red-600 dark:text-red-500" }) }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "w-16 h-16 bg-gray-200 dark:bg-zinc-800 rounded-full flex items-center justify-center mb-6", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react12.FileX, { className: "w-8 h-8 text-gray-500 dark:text-gray-400" }) }),
4070
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h3", { className: "text-xl font-bold text-gray-900 dark:text-white mb-2", children: error ? "Failed to Load Statement" : "No Records Found" }),
4071
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-sm text-gray-500 dark:text-gray-400 max-w-xs mb-8 leading-relaxed", children: error ? typeof error === "string" ? error : "An unexpected error occurred while fetching the statement data." : "There are no transactions or records available in this requested statement." }),
4072
- url && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
4073
- "button",
4074
- {
4075
- onClick: () => get({ url, v, params, delay }),
4076
- className: "flex items-center gap-2 px-6 py-2.5 bg-black dark:bg-white text-white dark:text-black font-semibold rounded-lg shadow-md hover:bg-gray-800 dark:hover:bg-gray-100 transition-all active:scale-95",
4077
- children: [
4078
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react12.RefreshCw, { size: 16 }),
4079
- "Try Again"
4080
- ]
4081
- }
4082
- )
4083
- ] }) });
4084
- }
4152
+ const emptyState = !isLoading && (error || !data || data.length === 0) ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex flex-col relative w-full items-center justify-center py-12 min-h-[300px]", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col items-center justify-center p-8 bg-gray-50/50 dark:bg-zinc-900/30 rounded-2xl border border-dashed border-gray-300 dark:border-zinc-700 w-full max-w-lg text-center shadow-sm", children: [
4153
+ error ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "w-14 h-14 bg-red-100 dark:bg-red-500/10 rounded-full flex items-center justify-center mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react12.AlertCircle, { className: "w-7 h-7 text-red-600 dark:text-red-500" }) }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "w-14 h-14 bg-gray-200 dark:bg-zinc-800 rounded-full flex items-center justify-center mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react12.FileX, { className: "w-7 h-7 text-gray-500 dark:text-gray-400" }) }),
4154
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h3", { className: "text-lg font-bold text-gray-900 dark:text-white mb-2", children: error ? "Failed to Load Statement" : "No Records Found" }),
4155
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-sm text-gray-500 dark:text-gray-400 max-w-xs mb-6 leading-relaxed", children: error ? typeof error === "string" ? error : "An unexpected error occurred while fetching the statement data." : "There are no transactions or records available in this requested statement." }),
4156
+ url && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
4157
+ "button",
4158
+ {
4159
+ onClick: () => get({ url, v, params, delay }),
4160
+ className: "flex items-center gap-2 px-5 py-2 bg-black dark:bg-white text-white dark:text-black font-semibold rounded-lg shadow-md hover:bg-gray-800 dark:hover:bg-gray-100 transition-all active:scale-95 text-sm",
4161
+ children: [
4162
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react12.RefreshCw, { size: 14 }),
4163
+ "Try Again"
4164
+ ]
4165
+ }
4166
+ )
4167
+ ] }) }) : void 0;
4085
4168
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col relative w-full items-center", children: [
4086
4169
  isMeasuring && filteredDisplayData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "absolute top-0 opacity-0 pointer-events-none -left-full", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4087
4170
  "div",
@@ -4176,7 +4259,7 @@ var useA4StatementView = ({
4176
4259
  ] }),
4177
4260
  pageIndex === 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "hidden print:flex mb-4 border-b border-gray-200 print:border-gray-200 pb-2 items-center gap-2 justify-between px-2 mt-2", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("h3", { className: "text-sm font-bold text-gray-800 print:text-gray-800 uppercase tracking-wide shrink-0", children: "Recent Transactions" }) }),
4178
4261
  pageIndex > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "h-5 print:h-0" }),
4179
- (pageData.length > 0 || isLoading) && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4262
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
4180
4263
  SimpleTable,
4181
4264
  {
4182
4265
  columns,
@@ -4186,6 +4269,7 @@ var useA4StatementView = ({
4186
4269
  index,
4187
4270
  startIndex: pages.slice(0, pageIndex).reduce((acc, curr) => acc + curr.length, 0),
4188
4271
  verticalLines,
4272
+ emptyState,
4189
4273
  isLoading: isLoading || isMeasuring && pages.length === 1 && pages[0].length === 0
4190
4274
  }
4191
4275
  ),
@@ -4267,30 +4351,28 @@ var useTransaction = ({
4267
4351
  createTitle = "Add New",
4268
4352
  ...rest
4269
4353
  }) => {
4270
- if (!isLoading && (error || !data || data.length === 0)) {
4271
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
4272
- "div",
4273
- {
4274
- className: `flex flex-col relative w-full items-center justify-center p-8 min-h-96 ${className}`,
4275
- children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col items-center justify-center p-12 bg-gray-50/50 dark:bg-zinc-900/30 rounded-2xl border border-dashed border-gray-300 dark:border-zinc-700 w-full max-w-xl text-center shadow-sm", children: [
4276
- error ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-16 h-16 bg-red-100 dark:bg-red-500/10 rounded-full flex items-center justify-center mb-6", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react13.AlertCircle, { className: "w-8 h-8 text-red-600 dark:text-red-500" }) }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-16 h-16 bg-gray-200 dark:bg-zinc-800 rounded-full flex items-center justify-center mb-6", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react13.FileX, { className: "w-8 h-8 text-gray-500 dark:text-gray-400" }) }),
4277
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h3", { className: "text-xl font-bold text-gray-900 dark:text-white mb-2", children: error ? "Failed to Load Data" : "No Records Found" }),
4278
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-sm text-gray-500 dark:text-gray-400 max-w-xs mb-8 leading-relaxed", children: error ? typeof error === "string" ? error : "An unexpected error occurred while fetching the data." : "There are no transactions or records available to display here." }),
4279
- url && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
4280
- "button",
4281
- {
4282
- onClick: () => get({ url, v, params, delay }),
4283
- className: "flex items-center gap-2 px-6 py-2.5 bg-black dark:bg-white text-white dark:text-black font-semibold rounded-lg shadow-md hover:bg-gray-800 dark:hover:bg-gray-100 transition-all active:scale-95",
4284
- children: [
4285
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react13.RefreshCw, { size: 16 }),
4286
- "Try Again"
4287
- ]
4288
- }
4289
- )
4290
- ] })
4291
- }
4292
- );
4293
- }
4354
+ const emptyState = !isLoading && (error || !data || data.length === 0) ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
4355
+ "div",
4356
+ {
4357
+ className: `flex flex-col relative w-full items-center justify-center py-12 min-h-[300px] ${className}`,
4358
+ children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col items-center justify-center p-8 bg-gray-50/50 dark:bg-zinc-900/30 rounded-2xl border border-dashed border-gray-300 dark:border-zinc-700 w-full max-w-lg text-center shadow-sm", children: [
4359
+ error ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-14 h-14 bg-red-100 dark:bg-red-500/10 rounded-full flex items-center justify-center mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react13.AlertCircle, { className: "w-7 h-7 text-red-600 dark:text-red-500" }) }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-14 h-14 bg-gray-200 dark:bg-zinc-800 rounded-full flex items-center justify-center mb-4", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react13.FileX, { className: "w-7 h-7 text-gray-500 dark:text-gray-400" }) }),
4360
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h3", { className: "text-lg font-bold text-gray-900 dark:text-white mb-2", children: error ? "Failed to Load Data" : "No Records Found" }),
4361
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-sm text-gray-500 dark:text-gray-400 max-w-xs mb-6 leading-relaxed", children: error ? typeof error === "string" ? error : "An unexpected error occurred while fetching the data." : "There are no transactions or records available to display here." }),
4362
+ url && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
4363
+ "button",
4364
+ {
4365
+ onClick: () => get({ url, v, params, delay }),
4366
+ className: "flex items-center gap-2 px-5 py-2 bg-black dark:bg-white text-white dark:text-black font-semibold rounded-lg shadow-md hover:bg-gray-800 dark:hover:bg-gray-100 transition-all active:scale-95 text-sm",
4367
+ children: [
4368
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react13.RefreshCw, { size: 14 }),
4369
+ "Try Again"
4370
+ ]
4371
+ }
4372
+ )
4373
+ ] })
4374
+ }
4375
+ ) : void 0;
4294
4376
  return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Card, { children: [
4295
4377
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Card.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("header", { className: "flex items-center justify-between gap-4 py-2", children: [
4296
4378
  /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "space-y-1", children: [
@@ -4334,6 +4416,7 @@ var useTransaction = ({
4334
4416
  verticalLines,
4335
4417
  index,
4336
4418
  rowPadding,
4419
+ emptyState,
4337
4420
  ...rest
4338
4421
  }
4339
4422
  ) }) })
@@ -4475,6 +4558,66 @@ var generatePdf = async (elementId, options = {}) => {
4475
4558
  throw error;
4476
4559
  }
4477
4560
  };
4561
+
4562
+ // src/utils/storage.ts
4563
+ var isBrowser = typeof window !== "undefined" && typeof localStorage !== "undefined";
4564
+ var storage = {
4565
+ set(key, value) {
4566
+ if (!isBrowser) return;
4567
+ try {
4568
+ localStorage.setItem(key, JSON.stringify(value));
4569
+ } catch (error) {
4570
+ console.error(`[storage] Error saving key "${key}":`, error);
4571
+ }
4572
+ },
4573
+ get(key) {
4574
+ if (!isBrowser) return key ? null : {};
4575
+ if (key !== void 0) {
4576
+ try {
4577
+ const item = localStorage.getItem(key);
4578
+ if (item === null) return null;
4579
+ return JSON.parse(item);
4580
+ } catch (error) {
4581
+ const rawValue = localStorage.getItem(key);
4582
+ return rawValue;
4583
+ }
4584
+ }
4585
+ const allItems = {};
4586
+ for (let i = 0; i < localStorage.length; i++) {
4587
+ const k = localStorage.key(i);
4588
+ if (k) {
4589
+ const value = localStorage.getItem(k);
4590
+ try {
4591
+ allItems[k] = value ? JSON.parse(value) : null;
4592
+ } catch {
4593
+ allItems[k] = value;
4594
+ }
4595
+ }
4596
+ }
4597
+ return allItems;
4598
+ },
4599
+ remove(key) {
4600
+ if (!isBrowser) return;
4601
+ localStorage.removeItem(key);
4602
+ },
4603
+ clear() {
4604
+ if (!isBrowser) return;
4605
+ localStorage.clear();
4606
+ },
4607
+ has(key) {
4608
+ if (!isBrowser) return false;
4609
+ return localStorage.getItem(key) !== null;
4610
+ },
4611
+ keys() {
4612
+ if (!isBrowser) return [];
4613
+ const keys = [];
4614
+ for (let i = 0; i < localStorage.length; i++) {
4615
+ const key = localStorage.key(i);
4616
+ if (key) keys.push(key);
4617
+ }
4618
+ return keys;
4619
+ }
4620
+ };
4478
4621
  // Annotate the CommonJS export names for ESM import in node:
4479
4622
  0 && (module.exports = {
4480
4623
  A4DataView,
@@ -4518,6 +4661,7 @@ var generatePdf = async (elementId, options = {}) => {
4518
4661
  ThemeToggle,
4519
4662
  WarqadProvider,
4520
4663
  generatePdf,
4664
+ storage,
4521
4665
  useA4StatementView,
4522
4666
  useApi,
4523
4667
  useModal,