@underverse-ui/underverse 0.2.42 → 0.2.43

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.cjs CHANGED
@@ -5118,13 +5118,11 @@ var Pagination = ({
5118
5118
  onChange,
5119
5119
  className,
5120
5120
  size = "md",
5121
- variant = "outline",
5122
5121
  showFirstLast = true,
5123
5122
  showPrevNext = true,
5124
5123
  showPageNumbers = true,
5125
5124
  showInfo = false,
5126
5125
  disabled = false,
5127
- alignment = "left",
5128
5126
  pageSize,
5129
5127
  pageSizeOptions,
5130
5128
  onPageSizeChange,
@@ -5132,35 +5130,6 @@ var Pagination = ({
5132
5130
  labels
5133
5131
  }) => {
5134
5132
  const t = useTranslations("Pagination");
5135
- const getTextAlignmentClass = (align) => {
5136
- switch (align) {
5137
- case "left":
5138
- return "text-left";
5139
- case "center":
5140
- return "text-center";
5141
- case "right":
5142
- return "text-right";
5143
- }
5144
- };
5145
- const textAlignmentClass = getTextAlignmentClass(alignment);
5146
- const createPageArray = () => {
5147
- const delta = 2;
5148
- const range = [];
5149
- const left = Math.max(2, page - delta);
5150
- const right = Math.min(totalPages - 1, page + delta);
5151
- range.push(1);
5152
- if (left > 2) range.push("...");
5153
- for (let i = left; i <= right; i++) {
5154
- range.push(i);
5155
- }
5156
- if (right < totalPages - 1) range.push("...");
5157
- if (totalPages > 1) range.push(totalPages);
5158
- return range;
5159
- };
5160
- const getButtonVariant = (isActive) => {
5161
- if (isActive) return "primary";
5162
- return variant === "default" ? "default" : variant;
5163
- };
5164
5133
  React21.useEffect(() => {
5165
5134
  if (disabled) return;
5166
5135
  const handleKey = (e) => {
@@ -5194,116 +5163,135 @@ var Pagination = ({
5194
5163
  }
5195
5164
  };
5196
5165
  if (totalPages <= 1) return null;
5197
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("nav", { className: cn("flex flex-col gap-4", className), "aria-label": labels?.navigationLabel || t("navigationLabel"), children: [
5198
- showInfo && totalItems && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn("text-sm text-muted-foreground", textAlignmentClass), children: labels?.showingResults ? labels.showingResults({ startItem: startItem || 0, endItem: endItem || 0, totalItems }) : t("showingResults", { startItem: startItem || 0, endItem: endItem || 0, totalItems }) }),
5199
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5200
- "div",
5201
- {
5202
- className: cn("flex items-center justify-between", {
5203
- "flex-row-reverse": alignment === "right" || alignment === "center"
5204
- }),
5205
- children: [
5206
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: cn("flex items-center gap-1"), children: [
5207
- showFirstLast && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5208
- Button_default,
5209
- {
5210
- variant: getButtonVariant(false),
5211
- size,
5212
- icon: import_lucide_react13.ChevronsLeft,
5213
- onClick: () => onChange(1),
5214
- disabled: disabled || page === 1,
5215
- className: "hidden sm:flex",
5216
- title: labels?.firstPage || t("firstPage"),
5217
- "aria-label": labels?.firstPage || t("firstPage"),
5218
- "aria-disabled": disabled || page === 1
5219
- }
5220
- ),
5221
- showPrevNext && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5222
- Button_default,
5223
- {
5224
- variant: getButtonVariant(false),
5225
- size,
5226
- icon: import_lucide_react13.ChevronLeft,
5227
- onClick: () => onChange(Math.max(1, page - 1)),
5228
- disabled: disabled || page === 1,
5229
- title: labels?.previousPage || t("previousPage"),
5230
- "aria-label": labels?.previousPage || t("previousPage"),
5231
- "aria-disabled": disabled || page === 1,
5232
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "hidden sm:inline", children: labels?.previous || t("previous") })
5233
- }
5234
- ),
5235
- showPageNumbers && createPageArray().map((p, i) => {
5236
- if (p === "...") {
5237
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button_default, { variant: "ghost", size, disabled: true, icon: import_lucide_react13.MoreHorizontal, className: "cursor-default" }, i);
5238
- }
5239
- const pageNumber = p;
5240
- const isActive = page === pageNumber;
5241
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5242
- Button_default,
5243
- {
5244
- variant: getButtonVariant(isActive),
5245
- size,
5246
- onClick: () => onChange(pageNumber),
5247
- disabled,
5248
- className: cn("min-w-10", isActive && "font-semibold"),
5249
- "aria-label": labels?.pageNumber ? labels.pageNumber(pageNumber) : t("pageNumber", { page: pageNumber }),
5250
- "aria-current": isActive ? "page" : void 0,
5251
- children: pageNumber
5252
- },
5253
- i
5254
- );
5255
- }),
5256
- showPrevNext && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5257
- Button_default,
5258
- {
5259
- variant: getButtonVariant(false),
5260
- size,
5261
- iconRight: import_lucide_react13.ChevronRight,
5262
- onClick: () => onChange(Math.min(totalPages, page + 1)),
5263
- disabled: disabled || page === totalPages,
5264
- title: labels?.nextPage || t("nextPage"),
5265
- "aria-label": labels?.nextPage || t("nextPage"),
5266
- "aria-disabled": disabled || page === totalPages,
5267
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "hidden sm:inline", children: labels?.next || t("next") })
5268
- }
5269
- ),
5270
- showFirstLast && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5271
- Button_default,
5166
+ const createCompactPageArray = () => {
5167
+ const pages = [];
5168
+ if (totalPages <= 5) {
5169
+ for (let i = 1; i <= totalPages; i++) pages.push(i);
5170
+ } else {
5171
+ pages.push(1);
5172
+ if (page > 3) pages.push("...");
5173
+ const start = Math.max(2, page - 1);
5174
+ const end = Math.min(totalPages - 1, page + 1);
5175
+ for (let i = start; i <= end; i++) pages.push(i);
5176
+ if (page < totalPages - 2) pages.push("...");
5177
+ pages.push(totalPages);
5178
+ }
5179
+ return pages;
5180
+ };
5181
+ const sizeClasses2 = {
5182
+ sm: { btn: "h-7 w-7", text: "text-xs", page: "h-7 min-w-7 px-1.5" },
5183
+ md: { btn: "h-8 w-8", text: "text-sm", page: "h-8 min-w-8 px-2" },
5184
+ lg: { btn: "h-9 w-9", text: "text-base", page: "h-9 min-w-9 px-2.5" }
5185
+ };
5186
+ const sizeClass = sizeClasses2[size];
5187
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5188
+ "nav",
5189
+ {
5190
+ className: cn("flex items-center justify-between gap-2", sizeClass.text, "text-muted-foreground", className),
5191
+ "aria-label": labels?.navigationLabel || t("navigationLabel"),
5192
+ children: [
5193
+ showInfo && totalItems && startItem && endItem ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "tabular-nums shrink-0", children: [
5194
+ startItem,
5195
+ "-",
5196
+ endItem,
5197
+ "/",
5198
+ totalItems
5199
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", {}),
5200
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-0.5", children: [
5201
+ showFirstLast && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5202
+ "button",
5203
+ {
5204
+ onClick: () => onChange(1),
5205
+ disabled: disabled || page === 1,
5206
+ className: cn(
5207
+ sizeClass.btn,
5208
+ "p-0 rounded transition-colors hidden sm:flex items-center justify-center",
5209
+ disabled || page === 1 ? "opacity-40 cursor-not-allowed" : "hover:bg-accent hover:text-accent-foreground"
5210
+ ),
5211
+ title: labels?.firstPage || t("firstPage"),
5212
+ "aria-label": labels?.firstPage || t("firstPage"),
5213
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.ChevronsLeft, { className: "h-4 w-4" })
5214
+ }
5215
+ ),
5216
+ showPrevNext && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5217
+ "button",
5218
+ {
5219
+ onClick: () => onChange(Math.max(1, page - 1)),
5220
+ disabled: disabled || page === 1,
5221
+ className: cn(
5222
+ sizeClass.btn,
5223
+ "p-0 rounded transition-colors flex items-center justify-center",
5224
+ disabled || page === 1 ? "opacity-40 cursor-not-allowed" : "hover:bg-accent hover:text-accent-foreground"
5225
+ ),
5226
+ title: labels?.previousPage || t("previousPage"),
5227
+ "aria-label": labels?.previousPage || t("previousPage"),
5228
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.ChevronLeft, { className: "h-4 w-4" })
5229
+ }
5230
+ ),
5231
+ showPageNumbers && createCompactPageArray().map(
5232
+ (p, i) => p === "..." ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "px-1 text-muted-foreground/60", children: "\u2026" }, `dots-${i}`) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5233
+ "button",
5272
5234
  {
5273
- variant: getButtonVariant(false),
5274
- size,
5275
- icon: import_lucide_react13.ChevronsRight,
5276
- onClick: () => onChange(totalPages),
5277
- disabled: disabled || page === totalPages,
5278
- className: "hidden sm:flex",
5279
- title: labels?.lastPage || t("lastPage"),
5280
- "aria-label": labels?.lastPage || t("lastPage"),
5281
- "aria-disabled": disabled || page === totalPages
5282
- }
5235
+ onClick: () => onChange(p),
5236
+ disabled,
5237
+ className: cn(
5238
+ sizeClass.page,
5239
+ "rounded font-medium transition-colors",
5240
+ page === p ? "bg-primary text-primary-foreground" : "hover:bg-accent hover:text-accent-foreground",
5241
+ disabled && "opacity-40 cursor-not-allowed"
5242
+ ),
5243
+ "aria-label": labels?.pageNumber ? labels.pageNumber(p) : t("pageNumber", { page: p }),
5244
+ "aria-current": page === p ? "page" : void 0,
5245
+ children: p
5246
+ },
5247
+ p
5283
5248
  )
5284
- ] }),
5285
- pageSizeOptions && onPageSizeChange && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: cn("flex items-center gap-2 text-sm"), children: [
5286
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "text-muted-foreground", children: [
5287
- labels?.itemsPerPage || t("itemsPerPage"),
5288
- ":"
5289
- ] }),
5290
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "w-20", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5291
- Combobox,
5292
- {
5293
- options: pageSizeOptionsStrings,
5294
- value: pageSize?.toString() || "10",
5295
- onChange: handlePageSizeChange,
5296
- placeholder: "10",
5297
- searchPlaceholder: labels?.search || t("search"),
5298
- emptyText: labels?.noOptions || t("noOptions"),
5299
- disabled
5300
- }
5301
- ) })
5302
- ] })
5303
- ]
5304
- }
5305
- )
5306
- ] });
5249
+ ),
5250
+ showPrevNext && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5251
+ "button",
5252
+ {
5253
+ onClick: () => onChange(Math.min(totalPages, page + 1)),
5254
+ disabled: disabled || page === totalPages,
5255
+ className: cn(
5256
+ sizeClass.btn,
5257
+ "p-0 rounded transition-colors flex items-center justify-center",
5258
+ disabled || page === totalPages ? "opacity-40 cursor-not-allowed" : "hover:bg-accent hover:text-accent-foreground"
5259
+ ),
5260
+ title: labels?.nextPage || t("nextPage"),
5261
+ "aria-label": labels?.nextPage || t("nextPage"),
5262
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.ChevronRight, { className: "h-4 w-4" })
5263
+ }
5264
+ ),
5265
+ showFirstLast && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5266
+ "button",
5267
+ {
5268
+ onClick: () => onChange(totalPages),
5269
+ disabled: disabled || page === totalPages,
5270
+ className: cn(
5271
+ sizeClass.btn,
5272
+ "p-0 rounded transition-colors hidden sm:flex items-center justify-center",
5273
+ disabled || page === totalPages ? "opacity-40 cursor-not-allowed" : "hover:bg-accent hover:text-accent-foreground"
5274
+ ),
5275
+ title: labels?.lastPage || t("lastPage"),
5276
+ "aria-label": labels?.lastPage || t("lastPage"),
5277
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.ChevronsRight, { className: "h-4 w-4" })
5278
+ }
5279
+ )
5280
+ ] }),
5281
+ pageSizeOptions && onPageSizeChange ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5282
+ Combobox,
5283
+ {
5284
+ options: pageSizeOptionsStrings,
5285
+ value: pageSize?.toString() || "10",
5286
+ onChange: handlePageSizeChange,
5287
+ size: "sm",
5288
+ className: "w-14",
5289
+ disabled
5290
+ }
5291
+ ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", {})
5292
+ ]
5293
+ }
5294
+ );
5307
5295
  };
5308
5296
  var SimplePagination = ({
5309
5297
  page,
@@ -5311,103 +5299,128 @@ var SimplePagination = ({
5311
5299
  onChange,
5312
5300
  className,
5313
5301
  size = "md",
5314
- variant = "outline",
5315
5302
  disabled = false,
5316
5303
  showInfo = false,
5317
5304
  totalItems,
5318
5305
  pageSize = 10
5319
5306
  }) => {
5320
5307
  if (totalPages <= 1) return null;
5321
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: cn("flex flex-col gap-2", className), children: [
5322
- showInfo && totalItems && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "text-sm text-muted-foreground text-center", children: [
5323
- "Page ",
5324
- page,
5325
- " of ",
5326
- totalPages,
5327
- " (",
5328
- totalItems,
5329
- " total items)"
5330
- ] }),
5331
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between", children: [
5332
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Button_default, { variant, size, icon: import_lucide_react13.ChevronLeft, onClick: () => onChange(Math.max(1, page - 1)), disabled: disabled || page === 1, children: "Previous" }),
5333
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
5334
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Page" }),
5335
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-medium text-foreground", children: page }),
5336
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "of" }),
5337
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-medium text-foreground", children: totalPages })
5308
+ const sizeClasses2 = {
5309
+ sm: { btn: "h-7 w-7", text: "text-xs" },
5310
+ md: { btn: "h-8 w-8", text: "text-sm" },
5311
+ lg: { btn: "h-9 w-9", text: "text-base" }
5312
+ };
5313
+ const sizeClass = sizeClasses2[size];
5314
+ const startItem = totalItems ? (page - 1) * pageSize + 1 : null;
5315
+ const endItem = totalItems ? Math.min(page * pageSize, totalItems) : null;
5316
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: cn("flex items-center justify-between gap-2", sizeClass.text, "text-muted-foreground", className), children: [
5317
+ showInfo && totalItems && startItem && endItem ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "tabular-nums", children: [
5318
+ startItem,
5319
+ "-",
5320
+ endItem,
5321
+ "/",
5322
+ totalItems
5323
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", {}),
5324
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-0.5", children: [
5325
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5326
+ "button",
5327
+ {
5328
+ onClick: () => onChange(Math.max(1, page - 1)),
5329
+ disabled: disabled || page === 1,
5330
+ className: cn(
5331
+ sizeClass.btn,
5332
+ "p-0 rounded transition-colors flex items-center justify-center",
5333
+ disabled || page === 1 ? "opacity-40 cursor-not-allowed" : "hover:bg-accent hover:text-accent-foreground"
5334
+ ),
5335
+ "aria-label": "Previous page",
5336
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.ChevronLeft, { className: "h-4 w-4" })
5337
+ }
5338
+ ),
5339
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "px-2 tabular-nums font-medium text-foreground", children: [
5340
+ page,
5341
+ "/",
5342
+ totalPages
5338
5343
  ] }),
5339
5344
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5340
- Button_default,
5345
+ "button",
5341
5346
  {
5342
- variant,
5343
- size,
5344
- iconRight: import_lucide_react13.ChevronRight,
5345
5347
  onClick: () => onChange(Math.min(totalPages, page + 1)),
5346
5348
  disabled: disabled || page === totalPages,
5347
- children: "Next"
5349
+ className: cn(
5350
+ sizeClass.btn,
5351
+ "p-0 rounded transition-colors flex items-center justify-center",
5352
+ disabled || page === totalPages ? "opacity-40 cursor-not-allowed" : "hover:bg-accent hover:text-accent-foreground"
5353
+ ),
5354
+ "aria-label": "Next page",
5355
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.ChevronRight, { className: "h-4 w-4" })
5348
5356
  }
5349
5357
  )
5350
- ] })
5358
+ ] }),
5359
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", {})
5351
5360
  ] });
5352
5361
  };
5353
- var CompactPagination = ({
5354
- page,
5355
- totalPages,
5356
- onChange,
5357
- className,
5358
- variant = "outline",
5359
- disabled = false
5360
- }) => {
5362
+ var CompactPagination = ({ page, totalPages, onChange, className, disabled = false }) => {
5361
5363
  if (totalPages <= 1) return null;
5362
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("nav", { className: cn("flex items-center gap-1", className), "aria-label": "Compact Pagination", children: [
5364
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("nav", { className: cn("flex items-center gap-0.5 text-xs text-muted-foreground", className), "aria-label": "Compact Pagination", children: [
5363
5365
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5364
- Button_default,
5366
+ "button",
5365
5367
  {
5366
- variant,
5367
- size: "icon",
5368
- icon: import_lucide_react13.ChevronsLeft,
5369
5368
  onClick: () => onChange(1),
5370
5369
  disabled: disabled || page === 1,
5370
+ className: cn(
5371
+ "h-6 w-6 p-0 rounded transition-colors flex items-center justify-center",
5372
+ disabled || page === 1 ? "opacity-40 cursor-not-allowed" : "hover:bg-accent hover:text-accent-foreground"
5373
+ ),
5371
5374
  title: "First page",
5372
- "aria-label": "First page"
5375
+ "aria-label": "First page",
5376
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.ChevronsLeft, { className: "h-3.5 w-3.5" })
5373
5377
  }
5374
5378
  ),
5375
5379
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5376
- Button_default,
5380
+ "button",
5377
5381
  {
5378
- variant,
5379
- size: "icon",
5380
- icon: import_lucide_react13.ChevronLeft,
5381
5382
  onClick: () => onChange(Math.max(1, page - 1)),
5382
5383
  disabled: disabled || page === 1,
5383
- title: "Previous page"
5384
+ className: cn(
5385
+ "h-6 w-6 p-0 rounded transition-colors flex items-center justify-center",
5386
+ disabled || page === 1 ? "opacity-40 cursor-not-allowed" : "hover:bg-accent hover:text-accent-foreground"
5387
+ ),
5388
+ title: "Previous page",
5389
+ "aria-label": "Previous page",
5390
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.ChevronLeft, { className: "h-3.5 w-3.5" })
5384
5391
  }
5385
5392
  ),
5386
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "px-2 py-1 text-sm text-muted-foreground min-w-16 text-center", children: [
5393
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "px-1.5 tabular-nums", children: [
5387
5394
  page,
5388
- " / ",
5395
+ "/",
5389
5396
  totalPages
5390
5397
  ] }),
5391
5398
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5392
- Button_default,
5399
+ "button",
5393
5400
  {
5394
- variant,
5395
- size: "icon",
5396
- icon: import_lucide_react13.ChevronRight,
5397
5401
  onClick: () => onChange(Math.min(totalPages, page + 1)),
5398
5402
  disabled: disabled || page === totalPages,
5399
- title: "Next page"
5403
+ className: cn(
5404
+ "h-6 w-6 p-0 rounded transition-colors flex items-center justify-center",
5405
+ disabled || page === totalPages ? "opacity-40 cursor-not-allowed" : "hover:bg-accent hover:text-accent-foreground"
5406
+ ),
5407
+ title: "Next page",
5408
+ "aria-label": "Next page",
5409
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.ChevronRight, { className: "h-3.5 w-3.5" })
5400
5410
  }
5401
5411
  ),
5402
5412
  /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5403
- Button_default,
5413
+ "button",
5404
5414
  {
5405
- variant,
5406
- size: "icon",
5407
- icon: import_lucide_react13.ChevronsRight,
5408
5415
  onClick: () => onChange(totalPages),
5409
5416
  disabled: disabled || page === totalPages,
5410
- title: "Last page"
5417
+ className: cn(
5418
+ "h-6 w-6 p-0 rounded transition-colors flex items-center justify-center",
5419
+ disabled || page === totalPages ? "opacity-40 cursor-not-allowed" : "hover:bg-accent hover:text-accent-foreground"
5420
+ ),
5421
+ title: "Last page",
5422
+ "aria-label": "Last page",
5423
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react13.ChevronsRight, { className: "h-3.5 w-3.5" })
5411
5424
  }
5412
5425
  )
5413
5426
  ] });
@@ -5516,7 +5529,8 @@ var DatePicker = ({
5516
5529
  required,
5517
5530
  todayLabel,
5518
5531
  clearLabel,
5519
- weekdayLabels
5532
+ weekdayLabels,
5533
+ disablePastDates = false
5520
5534
  }) => {
5521
5535
  const t = useTranslations("DatePicker");
5522
5536
  const locale = useLocale();
@@ -5620,17 +5634,21 @@ var DatePicker = ({
5620
5634
  for (let i = 0; i < firstDayOfMonth; i++) {
5621
5635
  days.push(/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-8 h-8" }, `empty-${i}`));
5622
5636
  }
5637
+ const today = /* @__PURE__ */ new Date();
5638
+ today.setHours(0, 0, 0, 0);
5623
5639
  for (let day = 1; day <= daysInMonth; day++) {
5624
5640
  const date = new Date(viewDate.getFullYear(), viewDate.getMonth(), day);
5625
5641
  const isSelected = value && date.getDate() === value.getDate() && date.getMonth() === value.getMonth() && date.getFullYear() === value.getFullYear();
5626
5642
  const isToday2 = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
5643
+ const isPastDate = disablePastDates && date < today;
5627
5644
  const totalDaysFromStart = firstDayOfMonth + day - 1;
5628
5645
  const rowIndex = Math.floor(totalDaysFromStart / 7);
5629
5646
  days.push(
5630
5647
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5631
5648
  "button",
5632
5649
  {
5633
- onClick: () => handleDateSelect(date),
5650
+ onClick: () => !isPastDate && handleDateSelect(date),
5651
+ disabled: isPastDate,
5634
5652
  style: {
5635
5653
  animationDelay: isOpen ? `${rowIndex * 50}ms` : "0ms"
5636
5654
  },
@@ -5638,7 +5656,8 @@ var DatePicker = ({
5638
5656
  size === "sm" ? "w-7 h-7 text-[12px]" : "w-8 h-8 text-sm",
5639
5657
  "datepicker-day rounded-md focus:outline-none",
5640
5658
  "transition-colors",
5641
- isSelected ? "bg-primary! text-primary-foreground font-bold ring-2 ring-primary-foreground/60 shadow-lg scale-105 z-10 hover:bg-primary! focus:bg-primary! focus:text-primary-foreground" : "hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
5659
+ isPastDate && "opacity-40 cursor-not-allowed text-muted-foreground",
5660
+ isSelected ? "bg-primary! text-primary-foreground font-bold ring-2 ring-primary-foreground/60 shadow-lg scale-105 z-10 hover:bg-primary! focus:bg-primary! focus:text-primary-foreground" : !isPastDate && "hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
5642
5661
  isToday2 && !isSelected && "bg-accent text-accent-foreground font-semibold"
5643
5662
  ),
5644
5663
  children: day
@@ -5789,7 +5808,7 @@ var DatePicker = ({
5789
5808
  isOpen && dropdownPosition && typeof window !== "undefined" && (0, import_react_dom7.createPortal)(datePickerContent, document.body)
5790
5809
  ] });
5791
5810
  };
5792
- var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select date range...", className }) => {
5811
+ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select date range...", className, disablePastDates = false }) => {
5793
5812
  const locale = useLocale();
5794
5813
  const [isOpen, setIsOpen] = React23.useState(false);
5795
5814
  const [dropdownPosition, setDropdownPosition] = React23.useState(null);
@@ -5850,16 +5869,17 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
5850
5869
  const getDaysInMonth = (d) => new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
5851
5870
  const getFirstDayOfMonth = (d) => new Date(d.getFullYear(), d.getMonth(), 1).getDay();
5852
5871
  const handleSelect = (date) => {
5872
+ const localDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
5853
5873
  if (!tempStart || tempStart && tempEnd) {
5854
- setTempStart(date);
5874
+ setTempStart(localDate);
5855
5875
  setTempEnd(null);
5856
5876
  setHoveredDate(null);
5857
5877
  } else if (tempStart && !tempEnd) {
5858
- if (date < tempStart) {
5859
- setTempStart(date);
5878
+ if (localDate < tempStart) {
5879
+ setTempStart(localDate);
5860
5880
  } else {
5861
- setTempEnd(date);
5862
- onChange(tempStart, date);
5881
+ setTempEnd(localDate);
5882
+ onChange(tempStart, localDate);
5863
5883
  setIsOpen(false);
5864
5884
  }
5865
5885
  }
@@ -5868,9 +5888,12 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
5868
5888
  const nodes = [];
5869
5889
  const daysInMonth = getDaysInMonth(viewDate);
5870
5890
  const firstDay = getFirstDayOfMonth(viewDate);
5891
+ const today = /* @__PURE__ */ new Date();
5892
+ today.setHours(0, 0, 0, 0);
5871
5893
  for (let i = 0; i < firstDay; i++) nodes.push(/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-8 h-8" }, `e-${i}`));
5872
5894
  for (let d = 1; d <= daysInMonth; d++) {
5873
5895
  const date = new Date(viewDate.getFullYear(), viewDate.getMonth(), d);
5896
+ const isPastDate = disablePastDates && date < today;
5874
5897
  const isSelectedStart = isSameDay2(date, tempStart);
5875
5898
  const isSelectedEnd = isSameDay2(date, tempEnd);
5876
5899
  const isHovering = hoveredDate && tempStart && !tempEnd;
@@ -5896,13 +5919,16 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
5896
5919
  /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5897
5920
  "button",
5898
5921
  {
5899
- onClick: () => handleSelect(date),
5900
- onMouseEnter: () => tempStart && !tempEnd && setHoveredDate(date),
5922
+ onClick: () => !isPastDate && handleSelect(date),
5923
+ disabled: isPastDate,
5924
+ onMouseEnter: () => !isPastDate && tempStart && !tempEnd && setHoveredDate(date),
5901
5925
  onMouseLeave: () => tempStart && !tempEnd && setHoveredDate(null),
5902
5926
  className: cn(
5903
5927
  "w-8 h-8 text-sm transition-all duration-200 focus:outline-none relative font-medium",
5928
+ // Disabled/past date state
5929
+ isPastDate && "opacity-40 cursor-not-allowed text-muted-foreground",
5904
5930
  // Default state
5905
- !isInRange && !isRangeStart && !isRangeEnd && "hover:bg-accent hover:text-accent-foreground rounded-md",
5931
+ !isPastDate && !isInRange && !isRangeStart && !isRangeEnd && "hover:bg-accent hover:text-accent-foreground rounded-md",
5906
5932
  // Range selection styling - smooth continuous background
5907
5933
  isInRange && "bg-primary/15 text-foreground shadow-sm",
5908
5934
  (isRangeStart || isRangeEnd) && "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm",
@@ -5912,8 +5938,8 @@ var DateRangePicker = ({ startDate, endDate, onChange, placeholder = "Select dat
5912
5938
  isRangeStart && isRangeEnd && "rounded-md",
5913
5939
  // Single day selection
5914
5940
  // Hover effects for range
5915
- isInRange && "hover:bg-primary/25",
5916
- "focus:bg-accent focus:text-accent-foreground focus:z-10 focus:shadow-md"
5941
+ isInRange && !isPastDate && "hover:bg-primary/25",
5942
+ !isPastDate && "focus:bg-accent focus:text-accent-foreground focus:z-10 focus:shadow-md"
5917
5943
  ),
5918
5944
  children: d
5919
5945
  },
@@ -12386,23 +12412,71 @@ function DataTable({
12386
12412
  ]
12387
12413
  }
12388
12414
  ) }),
12389
- totalItems > 0 && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "border-t bg-muted/30 p-4 rounded-b-md", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
12390
- Pagination,
12391
- {
12392
- page: curPage,
12393
- totalPages: Math.ceil(totalItems / curPageSize),
12394
- onChange: (p) => setCurPage(p),
12395
- className: "",
12396
- showInfo: true,
12397
- totalItems,
12398
- pageSize: curPageSize,
12399
- pageSizeOptions,
12400
- onPageSizeChange: (s) => {
12401
- setCurPage(1);
12402
- setCurPageSize(s);
12415
+ totalItems > 0 && Math.ceil(totalItems / curPageSize) > 1 && /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "flex items-center justify-between gap-2 px-1 pt-3 text-xs text-muted-foreground", children: [
12416
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "tabular-nums", children: [
12417
+ (curPage - 1) * curPageSize + 1,
12418
+ "-",
12419
+ Math.min(curPage * curPageSize, totalItems),
12420
+ "/",
12421
+ totalItems
12422
+ ] }),
12423
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "flex items-center gap-0.5", children: [
12424
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Button_default, { variant: "ghost", size: "sm", className: "h-7 w-7 p-0", onClick: () => setCurPage(Math.max(1, curPage - 1)), disabled: curPage === 1, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) }),
12425
+ (() => {
12426
+ const totalPages = Math.ceil(totalItems / curPageSize);
12427
+ const pages = [];
12428
+ if (totalPages <= 5) {
12429
+ for (let i = 1; i <= totalPages; i++) pages.push(i);
12430
+ } else {
12431
+ pages.push(1);
12432
+ if (curPage > 3) pages.push("...");
12433
+ const start = Math.max(2, curPage - 1);
12434
+ const end = Math.min(totalPages - 1, curPage + 1);
12435
+ for (let i = start; i <= end; i++) pages.push(i);
12436
+ if (curPage < totalPages - 2) pages.push("...");
12437
+ pages.push(totalPages);
12438
+ }
12439
+ return pages.map(
12440
+ (p, i) => p === "..." ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "px-1 text-muted-foreground/60", children: "\u2026" }, `dots-${i}`) : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
12441
+ "button",
12442
+ {
12443
+ onClick: () => setCurPage(p),
12444
+ className: cn(
12445
+ "h-7 min-w-7 px-1.5 rounded text-xs font-medium transition-colors",
12446
+ curPage === p ? "bg-primary text-primary-foreground" : "hover:bg-accent hover:text-accent-foreground"
12447
+ ),
12448
+ children: p
12449
+ },
12450
+ p
12451
+ )
12452
+ );
12453
+ })(),
12454
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
12455
+ Button_default,
12456
+ {
12457
+ variant: "ghost",
12458
+ size: "sm",
12459
+ className: "h-7 w-7 p-0",
12460
+ onClick: () => setCurPage(Math.min(Math.ceil(totalItems / curPageSize), curPage + 1)),
12461
+ disabled: curPage === Math.ceil(totalItems / curPageSize),
12462
+ children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
12463
+ }
12464
+ )
12465
+ ] }),
12466
+ pageSizeOptions && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
12467
+ Combobox,
12468
+ {
12469
+ options: pageSizeOptions.map(String),
12470
+ value: String(curPageSize),
12471
+ onChange: (v) => {
12472
+ setCurPage(1);
12473
+ setCurPageSize(Number(v));
12474
+ },
12475
+ size: "sm",
12476
+ className: "w-14 h-7"
12403
12477
  }
12404
- }
12405
- ) })
12478
+ )
12479
+ ] })
12406
12480
  ] });
12407
12481
  }
12408
12482
  var DataTable_default = DataTable;