@eztrak/shared 0.8.1 → 0.11.0

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.
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/components/index.ts
31
31
  var components_exports = {};
32
32
  __export(components_exports, {
33
+ CardSkeleton: () => CardSkeleton,
33
34
  CustomCellEditor: () => CustomCellEditor,
34
35
  CustomPagination: () => CustomPagination,
35
36
  EztrakTabs: () => EztrakTabs,
@@ -265,18 +266,92 @@ var import_react_router_dom = require("react-router-dom");
265
266
  // src/utils/handleApiError.ts
266
267
  var import_react_hot_toast = __toESM(require("react-hot-toast"));
267
268
  var import_sweetalert2 = __toESM(require("sweetalert2"));
269
+ var BRAND_ORANGE = "#FF7335";
270
+ var CANCEL_RED = "#ff0000";
271
+ function getConfirmErrorMessage(error) {
272
+ if (error && typeof error === "object") {
273
+ const err = error;
274
+ return err.data?.message || err.data?.title || err.message || "Something went wrong. Please try again.";
275
+ }
276
+ return "Something went wrong. Please try again.";
277
+ }
268
278
  function confirmationAlert(onConfirm, options = {}) {
269
- void import_sweetalert2.default.fire({
270
- title: options.title ?? "Are you sure?",
271
- text: options.text,
272
- icon: options.icon ?? "warning",
279
+ const {
280
+ title = options.inputExpectedValue ? "Confirmation Required" : "Are you sure?",
281
+ text,
282
+ html,
283
+ icon = "warning",
284
+ confirmButtonText = "Yes",
285
+ cancelButtonText = "Cancel",
286
+ confirmButtonColor = BRAND_ORANGE,
287
+ cancelButtonColor = CANCEL_RED,
288
+ showLoaderOnConfirm = false,
289
+ inputExpectedValue,
290
+ inputPlaceholder = "Type confirmation text to proceed",
291
+ reverseButtons,
292
+ focusCancel,
293
+ zIndex
294
+ } = options;
295
+ const hasInput = Boolean(inputExpectedValue);
296
+ const useLoader = showLoaderOnConfirm || hasInput;
297
+ const inputHtml = html ?? (hasInput ? `
298
+ ${text ? `<p style="margin-bottom: 15px;">${text}</p>` : ""}
299
+ <p style="margin-bottom: 10px; font-weight: bold; color: #666;">
300
+ Please type "<span style="color: ${BRAND_ORANGE}; font-weight: bold;">${inputExpectedValue}</span>" to confirm:
301
+ </p>
302
+ ` : void 0);
303
+ const swalOptions = {
304
+ title,
305
+ icon,
273
306
  showCancelButton: true,
274
- confirmButtonText: options.confirmButtonText ?? "Yes",
275
- cancelButtonText: options.cancelButtonText ?? "Cancel",
276
- confirmButtonColor: "#FF7335"
277
- }).then((result) => {
278
- if (result.isConfirmed) {
279
- onConfirm();
307
+ confirmButtonText,
308
+ cancelButtonText,
309
+ confirmButtonColor,
310
+ cancelButtonColor,
311
+ reverseButtons,
312
+ focusCancel,
313
+ allowOutsideClick: () => !import_sweetalert2.default.isLoading(),
314
+ allowEscapeKey: () => !import_sweetalert2.default.isLoading(),
315
+ didOpen: () => {
316
+ if (zIndex == null) return;
317
+ const container = import_sweetalert2.default.getContainer();
318
+ if (container) container.style.zIndex = String(zIndex);
319
+ }
320
+ };
321
+ if (hasInput) {
322
+ swalOptions.html = inputHtml;
323
+ swalOptions.input = "text";
324
+ swalOptions.inputPlaceholder = inputPlaceholder;
325
+ swalOptions.inputValidator = (value) => {
326
+ if (!value?.trim()) return "You need to enter the confirmation text!";
327
+ if (value.trim() !== inputExpectedValue.trim()) {
328
+ return `Please type "${inputExpectedValue}" exactly as shown!`;
329
+ }
330
+ return null;
331
+ };
332
+ } else if (html) {
333
+ swalOptions.html = html;
334
+ } else {
335
+ swalOptions.text = text;
336
+ }
337
+ if (useLoader) {
338
+ swalOptions.showLoaderOnConfirm = true;
339
+ swalOptions.preConfirm = (inputValue) => {
340
+ if (hasInput && inputValue?.trim() !== inputExpectedValue.trim()) {
341
+ import_sweetalert2.default.showValidationMessage(
342
+ `Please type "${inputExpectedValue}" exactly as shown!`
343
+ );
344
+ return false;
345
+ }
346
+ return Promise.resolve().then(() => onConfirm()).catch((error) => {
347
+ import_sweetalert2.default.showValidationMessage(getConfirmErrorMessage(error));
348
+ throw error;
349
+ });
350
+ };
351
+ }
352
+ void import_sweetalert2.default.fire(swalOptions).then((result) => {
353
+ if (result.isConfirmed && !useLoader) {
354
+ void Promise.resolve(onConfirm());
280
355
  }
281
356
  });
282
357
  }
@@ -980,10 +1055,106 @@ function Modal({
980
1055
  return (0, import_react_dom.createPortal)(modalContent, modalRoot);
981
1056
  }
982
1057
 
1058
+ // src/components/skeleton/CardSkeleton.tsx
1059
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1060
+ var DEFAULT_LINE_WIDTHS = ["w-32", "w-48"];
1061
+ function shouldShowAvatar(variant, showAvatar) {
1062
+ return showAvatar ?? variant === "profile";
1063
+ }
1064
+ function shouldShowImage(variant, showImage) {
1065
+ return showImage ?? variant === "image";
1066
+ }
1067
+ function AvatarSkeleton({ className }) {
1068
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1069
+ "svg",
1070
+ {
1071
+ className: cn("w-10 h-10 text-gray-200 dark:text-gray-700", className),
1072
+ "aria-hidden": "true",
1073
+ xmlns: "http://www.w3.org/2000/svg",
1074
+ fill: "currentColor",
1075
+ viewBox: "0 0 20 20",
1076
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M10 0a10 10 0 1 0 10 10A10.011 10.011 0 0 0 10 0Zm0 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Zm0 13a8.949 8.949 0 0 1-4.951-1.488A3.987 3.987 0 0 1 9 13h2a3.987 3.987 0 0 1 3.951 3.512A8.949 8.949 0 0 1 10 18Z" })
1077
+ }
1078
+ );
1079
+ }
1080
+ function SkeletonBlock({
1081
+ widthClass,
1082
+ className,
1083
+ isFirst
1084
+ }) {
1085
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1086
+ "div",
1087
+ {
1088
+ className: cn(
1089
+ isFirst ? "h-2.5 mb-2" : "h-2",
1090
+ "bg-gray-200 rounded-full dark:bg-gray-700",
1091
+ widthClass,
1092
+ className
1093
+ )
1094
+ }
1095
+ );
1096
+ }
1097
+ function CardSkeleton({
1098
+ variant = "profile",
1099
+ count = 1,
1100
+ lines = 2,
1101
+ lineWidths = DEFAULT_LINE_WIDTHS,
1102
+ showAvatar,
1103
+ showImage,
1104
+ animationDuration = "0.7s",
1105
+ className,
1106
+ style,
1107
+ avatarClassName,
1108
+ imageClassName,
1109
+ contentClassName,
1110
+ lineClassName,
1111
+ srLabel = "Loading...",
1112
+ ...props
1113
+ }) {
1114
+ const skeletons = Array.from({ length: Math.max(1, count) }, (_, index) => {
1115
+ const renderAvatar = shouldShowAvatar(variant, showAvatar);
1116
+ const renderImage = shouldShowImage(variant, showImage);
1117
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1118
+ "div",
1119
+ {
1120
+ className: cn("animate-pulse md:p-6 dark:border-gray-700", className),
1121
+ style: { animationDuration, ...style },
1122
+ ...props,
1123
+ children: [
1124
+ renderImage ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1125
+ "div",
1126
+ {
1127
+ className: cn(
1128
+ "mb-4 h-32 w-full rounded-xl bg-gray-200 dark:bg-gray-700",
1129
+ imageClassName
1130
+ )
1131
+ }
1132
+ ) : null,
1133
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn("flex items-center mt-4 gap-4", contentClassName), children: [
1134
+ renderAvatar ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AvatarSkeleton, { className: avatarClassName }) : null,
1135
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children: Array.from({ length: Math.max(1, lines) }, (_2, lineIndex) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1136
+ SkeletonBlock,
1137
+ {
1138
+ widthClass: lineWidths[lineIndex] ?? lineWidths[lineWidths.length - 1] ?? DEFAULT_LINE_WIDTHS[1],
1139
+ className: lineClassName,
1140
+ isFirst: lineIndex === 0
1141
+ },
1142
+ lineIndex
1143
+ )) })
1144
+ ] }),
1145
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "sr-only", children: srLabel })
1146
+ ]
1147
+ },
1148
+ index
1149
+ );
1150
+ });
1151
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: skeletons });
1152
+ }
1153
+
983
1154
  // src/components/tooltip/ToolTip.tsx
984
1155
  var import_react4 = require("react");
985
1156
  var import_react_tooltip = require("react-tooltip");
986
- var import_jsx_runtime7 = require("react/jsx-runtime");
1157
+ var import_jsx_runtime8 = require("react/jsx-runtime");
987
1158
  var defaultTooltipStyle = {
988
1159
  color: "#fff",
989
1160
  borderRadius: "5px",
@@ -1010,10 +1181,10 @@ function ToolTip({
1010
1181
  const tooltipId = `eztrak-tooltip-${generatedId.replace(/:/g, "")}`;
1011
1182
  const tooltipText = String(text ?? "");
1012
1183
  if (disabled || !tooltipText) {
1013
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className, children });
1184
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className, children });
1014
1185
  }
1015
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1016
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1186
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1187
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1017
1188
  "span",
1018
1189
  {
1019
1190
  className,
@@ -1023,7 +1194,7 @@ function ToolTip({
1023
1194
  children
1024
1195
  }
1025
1196
  ),
1026
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1197
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1027
1198
  import_react_tooltip.Tooltip,
1028
1199
  {
1029
1200
  id: tooltipId,
@@ -1067,7 +1238,7 @@ var toDateInputValue = (date) => {
1067
1238
  };
1068
1239
 
1069
1240
  // src/components/tooltip/TooltipText.tsx
1070
- var import_jsx_runtime8 = require("react/jsx-runtime");
1241
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1071
1242
  function TooltipText({
1072
1243
  text = "",
1073
1244
  maxLength = 20,
@@ -1087,7 +1258,7 @@ function TooltipText({
1087
1258
  const displayText = truncateText(fullText, maxLength);
1088
1259
  const isTruncated = displayText !== fullText;
1089
1260
  const tooltipDisabled = !showTooltip || !hasValue || tooltipWhenTruncatedOnly && !isTruncated;
1090
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1261
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1091
1262
  ToolTip,
1092
1263
  {
1093
1264
  text: fullText,
@@ -1099,7 +1270,7 @@ function TooltipText({
1099
1270
  tooltipStyle,
1100
1271
  wrapperTabIndex: tooltipDisabled ? void 0 : 0,
1101
1272
  disabled: tooltipDisabled,
1102
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: cn("inline-block max-w-full align-bottom", textClassName), children: displayText })
1273
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: cn("inline-block max-w-full align-bottom", textClassName), children: displayText })
1103
1274
  }
1104
1275
  );
1105
1276
  }
@@ -1107,9 +1278,9 @@ function TooltipText({
1107
1278
  // src/components/cell-editor/CustomCellEditor.tsx
1108
1279
  var import_react5 = require("react");
1109
1280
  var import_react_hot_toast2 = __toESM(require("react-hot-toast"));
1110
- var import_jsx_runtime9 = require("react/jsx-runtime");
1281
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1111
1282
  function ButtonSpinner() {
1112
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1283
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1113
1284
  "svg",
1114
1285
  {
1115
1286
  className: "animate-spin",
@@ -1119,7 +1290,7 @@ function ButtonSpinner() {
1119
1290
  fill: "none",
1120
1291
  "aria-hidden": true,
1121
1292
  children: [
1122
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1293
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1123
1294
  "circle",
1124
1295
  {
1125
1296
  cx: "12",
@@ -1130,7 +1301,7 @@ function ButtonSpinner() {
1130
1301
  strokeOpacity: "0.25"
1131
1302
  }
1132
1303
  ),
1133
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1304
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1134
1305
  "path",
1135
1306
  {
1136
1307
  d: "M12 2a10 10 0 0 1 10 10",
@@ -1266,7 +1437,7 @@ var CustomCellEditor = (0, import_react5.forwardRef)(
1266
1437
  const defaultInputClass = "w-48 px-2 py-1 text-sm border border-gray-200 rounded-md bg-white focus:outline-none focus:ring-1 focus:ring-blue-400";
1267
1438
  const defaultSaveBtnClass = "px-3 py-1 text-sm font-medium text-white bg-green-500 rounded-md hover:bg-green-600 disabled:opacity-50 whitespace-nowrap shrink-0";
1268
1439
  const defaultCancelBtnClass = "px-3 py-1 text-sm font-medium text-white bg-red-500 rounded-md hover:bg-red-600 disabled:opacity-50 whitespace-nowrap shrink-0";
1269
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1440
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1270
1441
  "div",
1271
1442
  {
1272
1443
  className: cn(
@@ -1275,7 +1446,7 @@ var CustomCellEditor = (0, import_react5.forwardRef)(
1275
1446
  ),
1276
1447
  style: containerStyle,
1277
1448
  children: [
1278
- isDropdown ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1449
+ isDropdown ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1279
1450
  "select",
1280
1451
  {
1281
1452
  ref: selectRef,
@@ -1285,11 +1456,11 @@ var CustomCellEditor = (0, import_react5.forwardRef)(
1285
1456
  className: inputClassName ?? defaultInputClass,
1286
1457
  disabled: isLoading,
1287
1458
  children: [
1288
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: "", disabled: true, children: "Select option..." }),
1289
- normalizedOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
1459
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "", disabled: true, children: "Select option..." }),
1460
+ normalizedOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
1290
1461
  ]
1291
1462
  }
1292
- ) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1463
+ ) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1293
1464
  "input",
1294
1465
  {
1295
1466
  ref: inputRef,
@@ -1302,7 +1473,7 @@ var CustomCellEditor = (0, import_react5.forwardRef)(
1302
1473
  disabled: isLoading
1303
1474
  }
1304
1475
  ),
1305
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1476
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1306
1477
  "button",
1307
1478
  {
1308
1479
  type: "button",
@@ -1311,10 +1482,10 @@ var CustomCellEditor = (0, import_react5.forwardRef)(
1311
1482
  className: saveButtonClassName ?? (saveButtonStyle ? void 0 : defaultSaveBtnClass),
1312
1483
  style: saveButtonStyle,
1313
1484
  title: "Save (Enter)",
1314
- children: isLoading ? loadingIndicator ?? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ButtonSpinner, {}) : saveButtonContent ?? "Save"
1485
+ children: isLoading ? loadingIndicator ?? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ButtonSpinner, {}) : saveButtonContent ?? "Save"
1315
1486
  }
1316
1487
  ),
1317
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1488
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1318
1489
  "button",
1319
1490
  {
1320
1491
  type: "button",
@@ -1334,6 +1505,7 @@ var CustomCellEditor = (0, import_react5.forwardRef)(
1334
1505
  CustomCellEditor.displayName = "CustomCellEditor";
1335
1506
  // Annotate the CommonJS export names for ESM import in node:
1336
1507
  0 && (module.exports = {
1508
+ CardSkeleton,
1337
1509
  CustomCellEditor,
1338
1510
  CustomPagination,
1339
1511
  EztrakTabs,