@algorithm-shift/design-system 1.3.119 → 1.3.121

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
@@ -3012,13 +3012,61 @@ function resolveDate(option, customOption) {
3012
3012
  switch (option) {
3013
3013
  case "today":
3014
3014
  return /* @__PURE__ */ new Date();
3015
- case "custom":
3016
- return customOption ? new Date(customOption) : void 0;
3015
+ case "custom": {
3016
+ if (!customOption) return void 0;
3017
+ const d = new Date(customOption);
3018
+ return !isNaN(d.getTime()) ? d : void 0;
3019
+ }
3017
3020
  case "none":
3018
3021
  default:
3019
3022
  return void 0;
3020
3023
  }
3021
3024
  }
3025
+ function resolveDefaultDate(option, customOption) {
3026
+ if (!option || option === "none") return void 0;
3027
+ const now = /* @__PURE__ */ new Date();
3028
+ switch (option) {
3029
+ case "today":
3030
+ return new Date(now);
3031
+ case "currentPlus1Week": {
3032
+ const d = new Date(now);
3033
+ d.setDate(d.getDate() + 7);
3034
+ return d;
3035
+ }
3036
+ case "currentPlus1Year": {
3037
+ const d = new Date(now);
3038
+ d.setFullYear(d.getFullYear() + 1);
3039
+ return d;
3040
+ }
3041
+ case "previousDay": {
3042
+ const d = new Date(now);
3043
+ d.setDate(d.getDate() - 1);
3044
+ return d;
3045
+ }
3046
+ case "previous1Week": {
3047
+ const d = new Date(now);
3048
+ d.setDate(d.getDate() - 7);
3049
+ return d;
3050
+ }
3051
+ case "previous1Month": {
3052
+ const d = new Date(now);
3053
+ d.setMonth(d.getMonth() - 1);
3054
+ return d;
3055
+ }
3056
+ case "previous1Year": {
3057
+ const d = new Date(now);
3058
+ d.setFullYear(d.getFullYear() - 1);
3059
+ return d;
3060
+ }
3061
+ case "custom": {
3062
+ if (!customOption) return void 0;
3063
+ const d = new Date(customOption);
3064
+ return !isNaN(d.getTime()) ? d : void 0;
3065
+ }
3066
+ default:
3067
+ return void 0;
3068
+ }
3069
+ }
3022
3070
  function DateTimePicker({
3023
3071
  className,
3024
3072
  style,
@@ -3036,6 +3084,8 @@ function DateTimePicker({
3036
3084
  const customMinimumDate = props.customMinimumDate ?? "";
3037
3085
  const maximumDate = props.maximumDate ?? "none";
3038
3086
  const customMaximumDate = props.customMaximumDate ?? "";
3087
+ const defaultDateValue = props.defaultDateValue ?? "none";
3088
+ const customDefaultDate = props.customDefaultDate ?? "";
3039
3089
  const isEditable = props.isEditable ?? true;
3040
3090
  const isDisabled = props.isDisabled ?? false;
3041
3091
  const isReadonly = props.isReadonly ?? false;
@@ -3043,9 +3093,11 @@ function DateTimePicker({
3043
3093
  const minDate = resolveDate(minimumDate, customMinimumDate);
3044
3094
  const maxDate = resolveDate(maximumDate, customMaximumDate);
3045
3095
  const [date, setDate] = React8.useState(() => {
3046
- if (!props.value) return void 0;
3047
- const d = new Date(props.value);
3048
- return isNaN(d.getTime()) ? void 0 : d;
3096
+ if (props.value) {
3097
+ const d = new Date(props.value);
3098
+ if (!isNaN(d.getTime())) return d;
3099
+ }
3100
+ return resolveDefaultDate(defaultDateValue, customDefaultDate);
3049
3101
  });
3050
3102
  const initialHours = date ? date.getHours() : 0;
3051
3103
  const initialMinutes = date ? date.getMinutes() : 0;
@@ -3060,26 +3112,6 @@ function DateTimePicker({
3060
3112
  React8.useEffect(() => {
3061
3113
  setAmPm(hours >= 12 ? "PM" : "AM");
3062
3114
  }, [hours]);
3063
- React8.useEffect(() => {
3064
- if (!props.value) {
3065
- setDate(void 0);
3066
- return;
3067
- }
3068
- const d = new Date(props.value);
3069
- if (!isNaN(d.getTime())) {
3070
- setDate(d);
3071
- setHours(d.getHours());
3072
- setMinutes(d.getMinutes());
3073
- }
3074
- }, [props.value]);
3075
- const [year, setYear] = React8.useState(date ? date.getFullYear() : (/* @__PURE__ */ new Date()).getFullYear());
3076
- React8.useEffect(() => {
3077
- if (!date) return;
3078
- const newDate = new Date(date);
3079
- newDate.setFullYear(year);
3080
- setDate(newDate);
3081
- emitChange(newDate);
3082
- }, [year]);
3083
3115
  const emitChange = (nextDate) => {
3084
3116
  if (!props.onChange) return;
3085
3117
  let valueString = "";
@@ -3101,6 +3133,36 @@ function DateTimePicker({
3101
3133
  };
3102
3134
  props.onChange(event, props.name || "");
3103
3135
  };
3136
+ React8.useEffect(() => {
3137
+ if (!props.value) {
3138
+ const defaultDate = resolveDefaultDate(defaultDateValue, customDefaultDate);
3139
+ setDate(defaultDate);
3140
+ if (defaultDate) {
3141
+ setYear(defaultDate.getFullYear());
3142
+ setHours(defaultDate.getHours());
3143
+ setMinutes(defaultDate.getMinutes());
3144
+ emitChange(defaultDate);
3145
+ } else {
3146
+ setHours(0);
3147
+ setMinutes(0);
3148
+ }
3149
+ return;
3150
+ }
3151
+ const d = new Date(props.value);
3152
+ if (!isNaN(d.getTime())) {
3153
+ setDate(d);
3154
+ setHours(d.getHours());
3155
+ setMinutes(d.getMinutes());
3156
+ }
3157
+ }, [props.value, defaultDateValue, customDefaultDate]);
3158
+ const [year, setYear] = React8.useState(date ? date.getFullYear() : (/* @__PURE__ */ new Date()).getFullYear());
3159
+ React8.useEffect(() => {
3160
+ if (!date) return;
3161
+ const newDate = new Date(date);
3162
+ newDate.setFullYear(year);
3163
+ setDate(newDate);
3164
+ emitChange(newDate);
3165
+ }, [year]);
3104
3166
  const updateDateTime = (nextBaseDate, h = hours, m = minutes) => {
3105
3167
  if (!nextBaseDate) {
3106
3168
  setDate(void 0);
@@ -3331,7 +3393,7 @@ function DateTimePicker({
3331
3393
  name: props.name,
3332
3394
  autoComplete: isAutocomplete ? "on" : "off",
3333
3395
  readOnly: isReadonly,
3334
- value: !date ? "" : mode === "date" ? (0, import_date_fns.format)(date, "yyyy-MM-dd") : mode === "time" ? (0, import_date_fns.format)(date, "HH:mm:ss") : date.toISOString(),
3396
+ value: !date || isNaN(date.getTime()) ? "" : mode === "date" ? (0, import_date_fns.format)(date, "yyyy-MM-dd") : mode === "time" ? (0, import_date_fns.format)(date, "HH:mm:ss") : date.toISOString(),
3335
3397
  onChange: () => {
3336
3398
  }
3337
3399
  }
@@ -3468,7 +3530,6 @@ function LazyMultiSelectDropdown({
3468
3530
  onChange,
3469
3531
  placeholder,
3470
3532
  className,
3471
- id,
3472
3533
  disabled,
3473
3534
  readOnly,
3474
3535
  source,
@@ -3534,10 +3595,10 @@ function LazyMultiSelectDropdown({
3534
3595
  }
3535
3596
  };
3536
3597
  const selectedOptions = (0, import_react30.useMemo)(() => {
3537
- return normalizedValue.map((id2) => {
3538
- const fromLazy = lazyOptions.find((opt) => opt.value === id2);
3598
+ return normalizedValue.map((id) => {
3599
+ const fromLazy = lazyOptions.find((opt) => opt.value === id);
3539
3600
  if (fromLazy) return fromLazy;
3540
- return { value: id2, label: id2 };
3601
+ return { value: id, label: id };
3541
3602
  });
3542
3603
  }, [normalizedValue, lazyOptions]);
3543
3604
  (0, import_react30.useEffect)(() => {
@@ -3572,11 +3633,11 @@ function LazyMultiSelectDropdown({
3572
3633
  } else {
3573
3634
  updated = ensureUnique([...normalizedValue, val]);
3574
3635
  }
3575
- onChange?.(convertOutput(updated), id);
3636
+ onChange?.(convertOutput(updated), props.name ?? "");
3576
3637
  };
3577
3638
  const removeTag = (val) => {
3578
3639
  const updated = normalizedValue.filter((v) => v !== val);
3579
- onChange?.(convertOutput(updated), id);
3640
+ onChange?.(convertOutput(updated), props.name ?? "");
3580
3641
  };
3581
3642
  const handleFocus = () => {
3582
3643
  if (!disabled) {
@@ -6045,51 +6106,48 @@ var import_react36 = __toESM(require("react"));
6045
6106
  var import_axios4 = __toESM(require("axios"));
6046
6107
  var import_recharts = require("recharts");
6047
6108
  var import_jsx_runtime68 = require("react/jsx-runtime");
6048
- var getRandomColor = () => {
6049
- const palette = [
6050
- "#2563eb",
6051
- "#1d4ed8",
6052
- "#1e40af",
6053
- "#1e3a8a",
6054
- "#1e293b",
6055
- "#10b981",
6056
- "#059669",
6057
- "#047857",
6058
- "#065f46",
6059
- "#022c22",
6060
- "#f59e0b",
6061
- "#d97706",
6062
- "#b45309",
6063
- "#92400e",
6064
- "#422006",
6065
- "#ef4444",
6066
- "#dc2626",
6067
- "#b91c1c",
6068
- "#991b1b",
6069
- "#7f1d1d",
6070
- "#8b5cf6",
6071
- "#7c3aed",
6072
- "#6d28d9",
6073
- "#5b21b6",
6074
- "#4c1d95",
6075
- "#14b8a6",
6076
- "#0d9488",
6077
- "#0f766e",
6078
- "#115e59",
6079
- "#134e4a",
6080
- "#ec4899",
6081
- "#db2777",
6082
- "#be185d",
6083
- "#9d174d",
6084
- "#831843",
6085
- "#22c55e",
6086
- "#16a34a",
6087
- "#15803d",
6088
- "#166534",
6089
- "#14532d"
6090
- ];
6091
- return palette[Math.floor(Math.random() * palette.length)];
6092
- };
6109
+ var palette = [
6110
+ "#2563eb",
6111
+ "#1d4ed8",
6112
+ "#1e40af",
6113
+ "#1e3a8a",
6114
+ "#1e293b",
6115
+ "#10b981",
6116
+ "#059669",
6117
+ "#047857",
6118
+ "#065f46",
6119
+ "#022c22",
6120
+ "#f59e0b",
6121
+ "#d97706",
6122
+ "#b45309",
6123
+ "#92400e",
6124
+ "#422006",
6125
+ "#ef4444",
6126
+ "#dc2626",
6127
+ "#b91c1c",
6128
+ "#991b1b",
6129
+ "#7f1d1d",
6130
+ "#8b5cf6",
6131
+ "#7c3aed",
6132
+ "#6d28d9",
6133
+ "#5b21b6",
6134
+ "#4c1d95",
6135
+ "#14b8a6",
6136
+ "#0d9488",
6137
+ "#0f766e",
6138
+ "#115e59",
6139
+ "#134e4a",
6140
+ "#ec4899",
6141
+ "#db2777",
6142
+ "#be185d",
6143
+ "#9d174d",
6144
+ "#831843",
6145
+ "#22c55e",
6146
+ "#16a34a",
6147
+ "#15803d",
6148
+ "#166534",
6149
+ "#14532d"
6150
+ ];
6093
6151
  var ChartComponent = ({
6094
6152
  className,
6095
6153
  style,
@@ -6097,25 +6155,30 @@ var ChartComponent = ({
6097
6155
  dataKey,
6098
6156
  dataLabel,
6099
6157
  apiUrl,
6158
+ source,
6100
6159
  isPaginationEnabled,
6101
6160
  limit = 10,
6102
6161
  canvasMode,
6162
+ showLegends = true,
6163
+ legendPosition = "bottom",
6164
+ onLegendClick,
6103
6165
  ...props
6104
6166
  }) => {
6167
+ const useApi = source === "api" && !!apiUrl;
6105
6168
  const [rawData, setRawData] = (0, import_react36.useState)([]);
6106
6169
  const [rawMeta, setRawMeta] = (0, import_react36.useState)(null);
6107
6170
  const [localLoading, setLocalLoading] = (0, import_react36.useState)(false);
6108
6171
  const [currentPage, setCurrentPage] = (0, import_react36.useState)(1);
6109
- const effectiveData = apiUrl ? rawData : props.data || [];
6110
- const effectiveLoading = apiUrl ? localLoading : externalLoading;
6172
+ const effectiveData = useApi ? rawData : props.data || [];
6173
+ const effectiveLoading = useApi ? localLoading : externalLoading;
6111
6174
  (0, import_react36.useEffect)(() => {
6112
- if (apiUrl) {
6175
+ if (useApi) {
6113
6176
  setCurrentPage(1);
6114
6177
  }
6115
- }, [apiUrl]);
6178
+ }, [useApi]);
6116
6179
  const fetchData = (0, import_react36.useCallback)(async (page) => {
6117
6180
  if (!apiUrl) return;
6118
- const cancelled = false;
6181
+ let cancelled = false;
6119
6182
  try {
6120
6183
  setLocalLoading(true);
6121
6184
  const params = new URLSearchParams({
@@ -6151,9 +6214,9 @@ var ChartComponent = ({
6151
6214
  }
6152
6215
  }, [apiUrl, limit]);
6153
6216
  (0, import_react36.useEffect)(() => {
6154
- if (!apiUrl) return;
6217
+ if (!useApi) return;
6155
6218
  fetchData(currentPage);
6156
- }, [apiUrl, currentPage, fetchData]);
6219
+ }, [useApi, currentPage, fetchData]);
6157
6220
  const handlePageChange = (newPage) => {
6158
6221
  if (rawMeta && (newPage < 1 || newPage > rawMeta.pages)) return;
6159
6222
  setCurrentPage(newPage);
@@ -6162,15 +6225,59 @@ var ChartComponent = ({
6162
6225
  if (!Array.isArray(effectiveData) || effectiveData.length === 0 || !dataKey || !dataLabel) {
6163
6226
  return [];
6164
6227
  }
6165
- return effectiveData.map((item) => ({
6228
+ return effectiveData.map((item, index) => ({
6166
6229
  ...item,
6167
6230
  [dataKey]: Number(item[dataKey] || 0),
6168
- fill: getRandomColor()
6231
+ fill: item.fill || palette[index % palette.length]
6169
6232
  }));
6170
6233
  }, [effectiveData, dataKey, dataLabel]);
6171
6234
  const chartType = props.chartType || "bar";
6172
- const legendsPosition = ["middle", "bottom"].includes(props.legendsPosition) ? props.legendsPosition : "top";
6173
- if (effectiveLoading || data.length === 0) {
6235
+ const forceMobile = canvasMode === "mobile" || canvasMode === "tablet";
6236
+ const renderLegends = (0, import_react36.useMemo)(() => {
6237
+ if (!showLegends || !dataKey || !dataLabel) return null;
6238
+ const isLegendRight2 = !forceMobile && legendPosition === "right";
6239
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6240
+ "div",
6241
+ {
6242
+ className: isLegendRight2 ? "flex flex-col gap-2 w-full min-w-0 justify-start" : "flex flex-wrap justify-center gap-2 mt-4 w-full max-w-4xl",
6243
+ children: data.map((d, index) => {
6244
+ const value = d[dataKey] ?? 0;
6245
+ const displayValue = value >= 1e3 ? `${(value / 1e3).toFixed(0)}k` : value.toLocaleString();
6246
+ const payload = {
6247
+ name: d[dataLabel],
6248
+ value,
6249
+ [dataLabel]: d[dataLabel],
6250
+ [dataKey]: value
6251
+ };
6252
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
6253
+ "div",
6254
+ {
6255
+ role: onLegendClick ? "button" : void 0,
6256
+ tabIndex: onLegendClick ? 0 : void 0,
6257
+ onClick: onLegendClick ? () => onLegendClick(payload) : void 0,
6258
+ onKeyDown: onLegendClick ? (e) => e.key === "Enter" && onLegendClick(payload) : void 0,
6259
+ className: `flex items-center space-x-2 rounded-lg border border-gray-200/50 px-3 py-1.5 min-w-[180px] w-[180px] bg-white/80 backdrop-blur-sm shadow-sm hover:shadow-md transition-all ${onLegendClick ? "cursor-pointer" : ""}`,
6260
+ children: [
6261
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6262
+ "span",
6263
+ {
6264
+ className: "inline-block w-[12px] h-[12px] rounded-full shrink-0 border-2 border-white/50",
6265
+ style: { backgroundColor: d.fill }
6266
+ }
6267
+ ),
6268
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "min-w-0 flex-1", children: [
6269
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "text-gray-900 text-[11px] md:text-[13px] font-semibold block truncate leading-tight capitalize", children: d[dataLabel] }),
6270
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "text-xs text-gray-600 font-medium", children: displayValue })
6271
+ ] })
6272
+ ]
6273
+ },
6274
+ `legend-${index}`
6275
+ );
6276
+ })
6277
+ }
6278
+ );
6279
+ }, [data, dataLabel, dataKey, showLegends, onLegendClick, legendPosition, forceMobile]);
6280
+ if (effectiveLoading) {
6174
6281
  return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
6175
6282
  "div",
6176
6283
  {
@@ -6201,141 +6308,167 @@ var ChartComponent = ({
6201
6308
  }
6202
6309
  );
6203
6310
  }
6204
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: `${className} h-[450px]`, style, children: [
6205
- isPaginationEnabled && rawMeta && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-center justify-between mb-4 px-2", children: [
6206
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-center space-x-2 sm:hidden w-full justify-center", children: [
6207
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6208
- "button",
6209
- {
6210
- onClick: () => handlePageChange(currentPage - 1),
6211
- disabled: currentPage === 1 || localLoading,
6212
- className: "flex-1 px-3 py-2 text-xs font-medium rounded-lg border bg-white shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 flex items-center justify-center space-x-1 min-w-0",
6213
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "\u2190 Prev" })
6214
- }
6215
- ),
6216
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "px-2 py-2 text-xs font-semibold text-gray-700 min-w-[36px] text-center flex-shrink-0", children: currentPage }),
6217
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6218
- "button",
6219
- {
6220
- onClick: () => handlePageChange(currentPage + 1),
6221
- disabled: currentPage >= rawMeta.pages || localLoading,
6222
- className: "flex-1 px-3 py-2 text-xs font-medium rounded-lg border bg-white shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 flex items-center justify-center space-x-1 min-w-0",
6223
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "Next \u2192" })
6224
- }
6225
- )
6226
- ] }),
6227
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-center space-x-2 hidden sm:flex", children: [
6228
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6229
- "button",
6311
+ if (data.length === 0) {
6312
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6313
+ "div",
6314
+ {
6315
+ className: `relative flex flex-col items-center justify-center w-full h-[300px] md:h-[400px] bg-gradient-to-br from-gray-50 to-gray-100 rounded-xl p-6 ${className}`,
6316
+ style,
6317
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "text-center", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "inline-flex items-center space-x-2 bg-white/80 px-6 py-3 rounded-xl backdrop-blur-sm border border-gray-200 shadow-lg", children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "text-sm font-medium text-gray-600", children: "No data" }) }) })
6318
+ }
6319
+ );
6320
+ }
6321
+ const isLegendRight = !forceMobile && legendPosition === "right";
6322
+ return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
6323
+ "div",
6324
+ {
6325
+ className: `relative flex ${isLegendRight ? "flex-row items-stretch gap-4" : "flex-col items-center"} ${className}`,
6326
+ style,
6327
+ children: [
6328
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
6329
+ "div",
6230
6330
  {
6231
- onClick: () => handlePageChange(currentPage - 1),
6232
- disabled: currentPage === 1 || localLoading,
6233
- className: "px-3 py-1.5 text-sm font-medium rounded-lg border bg-white shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 flex items-center space-x-1",
6234
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "\u2190 Prev" })
6331
+ className: `relative flex items-center justify-center ${isLegendRight ? "flex-[2] min-w-0 max-w-[70%] h-[450px]" : "w-full md:w-[75%] h-[450px] mb-2"}`,
6332
+ children: [
6333
+ isPaginationEnabled && rawMeta && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-center justify-between mb-4 px-2", children: [
6334
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-center space-x-2 sm:hidden w-full justify-center", children: [
6335
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6336
+ "button",
6337
+ {
6338
+ onClick: () => handlePageChange(currentPage - 1),
6339
+ disabled: currentPage === 1 || localLoading,
6340
+ className: "flex-1 px-3 py-2 text-xs font-medium rounded-lg border bg-white shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 flex items-center justify-center space-x-1 min-w-0",
6341
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "\u2190 Prev" })
6342
+ }
6343
+ ),
6344
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "px-2 py-2 text-xs font-semibold text-gray-700 min-w-[36px] text-center flex-shrink-0", children: currentPage }),
6345
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6346
+ "button",
6347
+ {
6348
+ onClick: () => handlePageChange(currentPage + 1),
6349
+ disabled: currentPage >= rawMeta.pages || localLoading,
6350
+ className: "flex-1 px-3 py-2 text-xs font-medium rounded-lg border bg-white shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 flex items-center justify-center space-x-1 min-w-0",
6351
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "Next \u2192" })
6352
+ }
6353
+ )
6354
+ ] }),
6355
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "hidden sm:flex items-center space-x-2", children: [
6356
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6357
+ "button",
6358
+ {
6359
+ onClick: () => handlePageChange(currentPage - 1),
6360
+ disabled: currentPage === 1 || localLoading,
6361
+ className: "px-3 py-1.5 text-sm font-medium rounded-lg border bg-white shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 flex items-center space-x-1",
6362
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "\u2190 Prev" })
6363
+ }
6364
+ ),
6365
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "px-3 py-1 text-sm font-medium text-gray-700", children: currentPage }),
6366
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6367
+ "button",
6368
+ {
6369
+ onClick: () => handlePageChange(currentPage + 1),
6370
+ disabled: currentPage >= rawMeta.pages || localLoading,
6371
+ className: "px-3 py-1.5 text-sm font-medium rounded-lg border bg-white shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 flex items-center space-x-1",
6372
+ children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "Next \u2192" })
6373
+ }
6374
+ )
6375
+ ] })
6376
+ ] }),
6377
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_recharts.ResponsiveContainer, { width: "100%", height: "100%", children: chartType === "bar" ? /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_recharts.BarChart, { data, children: [
6378
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_recharts.CartesianGrid, { strokeDasharray: "3 3" }),
6379
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6380
+ import_recharts.XAxis,
6381
+ {
6382
+ dataKey: dataLabel,
6383
+ angle: -45,
6384
+ textAnchor: "end",
6385
+ interval: 0,
6386
+ tickFormatter: (value) => value?.toString().length > 10 ? `${value.toString().substring(0, 10)}...` : value,
6387
+ tick: {
6388
+ fontSize: 13,
6389
+ fontWeight: 500,
6390
+ fill: "#666",
6391
+ fontFamily: "inherit"
6392
+ },
6393
+ height: 80,
6394
+ className: "hidden sm:block"
6395
+ }
6396
+ ),
6397
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6398
+ import_recharts.YAxis,
6399
+ {
6400
+ tickFormatter: (value) => `${(value / 1e3).toFixed(0)}k`,
6401
+ tick: {
6402
+ fontSize: 12,
6403
+ fill: "#94a3b8",
6404
+ fontWeight: 500
6405
+ },
6406
+ domain: ["dataMin", "dataMax"],
6407
+ width: 60
6408
+ }
6409
+ ),
6410
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_recharts.Tooltip, { formatter: (value) => [`${value}`, "Count"] }),
6411
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6412
+ import_recharts.Bar,
6413
+ {
6414
+ dataKey,
6415
+ radius: [6, 6, 0, 0],
6416
+ isAnimationActive: false
6417
+ }
6418
+ )
6419
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_recharts.AreaChart, { data, children: [
6420
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("linearGradient", { id: "colorCount", x1: "0", y1: "0", x2: "0", y2: "1", children: [
6421
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("stop", { offset: "5%", stopColor: "#00695C", stopOpacity: 0.8 }),
6422
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("stop", { offset: "95%", stopColor: "#00695C", stopOpacity: 0 })
6423
+ ] }) }),
6424
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_recharts.CartesianGrid, { strokeDasharray: "3 3" }),
6425
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6426
+ import_recharts.XAxis,
6427
+ {
6428
+ dataKey: dataLabel,
6429
+ angle: 0,
6430
+ interval: 0,
6431
+ tick: {
6432
+ fontSize: 13,
6433
+ fontWeight: 500,
6434
+ fill: "#666",
6435
+ fontFamily: "inherit"
6436
+ }
6437
+ }
6438
+ ),
6439
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6440
+ import_recharts.YAxis,
6441
+ {
6442
+ tickFormatter: (value) => `${(value / 1e3).toFixed(0)}k`,
6443
+ tick: {
6444
+ fontSize: 12,
6445
+ fill: "#94a3b8",
6446
+ fontWeight: 500
6447
+ },
6448
+ domain: ["dataMin", "dataMax"],
6449
+ width: 60
6450
+ }
6451
+ ),
6452
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_recharts.Tooltip, { formatter: (value) => `${value}k` }),
6453
+ /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6454
+ import_recharts.Area,
6455
+ {
6456
+ type: "monotone",
6457
+ dataKey,
6458
+ stroke: "#00695C",
6459
+ fillOpacity: 1,
6460
+ fill: "url(#colorCount)",
6461
+ isAnimationActive: false
6462
+ }
6463
+ )
6464
+ ] }) })
6465
+ ]
6235
6466
  }
6236
6467
  ),
6237
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "px-3 py-1 text-sm font-medium text-gray-700", children: currentPage }),
6238
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6239
- "button",
6240
- {
6241
- onClick: () => handlePageChange(currentPage + 1),
6242
- disabled: currentPage >= rawMeta.pages || localLoading,
6243
- className: "px-3 py-1.5 text-sm font-medium rounded-lg border bg-white shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-200 flex items-center space-x-1",
6244
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "Next \u2192" })
6245
- }
6246
- )
6247
- ] })
6248
- ] }),
6249
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_recharts.ResponsiveContainer, { width: "100%", height: "100%", children: chartType === "bar" ? /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_recharts.BarChart, { data, children: [
6250
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_recharts.CartesianGrid, { strokeDasharray: "3 3" }),
6251
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6252
- import_recharts.XAxis,
6253
- {
6254
- dataKey: dataLabel,
6255
- angle: -45,
6256
- textAnchor: "end",
6257
- interval: 0,
6258
- tickFormatter: (value) => value?.toString().length > 10 ? `${value.toString().substring(0, 10)}...` : value,
6259
- tick: {
6260
- fontSize: 13,
6261
- fontWeight: 500,
6262
- fill: "#666",
6263
- fontFamily: "inherit"
6264
- },
6265
- height: 80,
6266
- className: "hidden sm:block"
6267
- }
6268
- ),
6269
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6270
- import_recharts.YAxis,
6271
- {
6272
- tickFormatter: (value) => `${(value / 1e3).toFixed(0)}k`,
6273
- tick: {
6274
- fontSize: 12,
6275
- fill: "#94a3b8",
6276
- fontWeight: 500
6277
- },
6278
- domain: ["dataMin", "dataMax"],
6279
- width: 60
6280
- }
6281
- ),
6282
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_recharts.Tooltip, { formatter: (value) => [`${value}`, "Count"] }),
6283
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_recharts.Legend, { verticalAlign: legendsPosition, align: "center" }),
6284
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6285
- import_recharts.Bar,
6286
- {
6287
- dataKey,
6288
- radius: [6, 6, 0, 0],
6289
- isAnimationActive: false
6290
- }
6291
- )
6292
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_recharts.AreaChart, { data, children: [
6293
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("linearGradient", { id: "colorCount", x1: "0", y1: "0", x2: "0", y2: "1", children: [
6294
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("stop", { offset: "5%", stopColor: "#00695C", stopOpacity: 0.8 }),
6295
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("stop", { offset: "95%", stopColor: "#00695C", stopOpacity: 0 })
6296
- ] }) }),
6297
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_recharts.CartesianGrid, { strokeDasharray: "3 3" }),
6298
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6299
- import_recharts.XAxis,
6300
- {
6301
- dataKey: dataLabel,
6302
- angle: 0,
6303
- interval: 0,
6304
- tick: {
6305
- fontSize: 13,
6306
- fontWeight: 500,
6307
- fill: "#666",
6308
- fontFamily: "inherit"
6309
- }
6310
- }
6311
- ),
6312
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6313
- import_recharts.YAxis,
6314
- {
6315
- tickFormatter: (value) => `${(value / 1e3).toFixed(0)}k`,
6316
- tick: {
6317
- fontSize: 12,
6318
- fill: "#94a3b8",
6319
- fontWeight: 500
6320
- },
6321
- domain: ["dataMin", "dataMax"],
6322
- width: 60
6323
- }
6324
- ),
6325
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_recharts.Tooltip, { formatter: (value) => `${value}k` }),
6326
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
6327
- import_recharts.Area,
6328
- {
6329
- type: "monotone",
6330
- dataKey,
6331
- stroke: "#00695C",
6332
- fillOpacity: 1,
6333
- fill: "url(#colorCount)",
6334
- isAnimationActive: false
6335
- }
6336
- )
6337
- ] }) })
6338
- ] });
6468
+ showLegends && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: isLegendRight ? "flex flex-col w-[30%] min-w-[180px] justify-center" : "w-full", children: renderLegends })
6469
+ ]
6470
+ }
6471
+ );
6339
6472
  };
6340
6473
  var BarChart_default = import_react36.default.memo(ChartComponent);
6341
6474
 
@@ -6344,8 +6477,8 @@ var import_react37 = __toESM(require("react"));
6344
6477
  var import_axios5 = __toESM(require("axios"));
6345
6478
  var import_recharts2 = require("recharts");
6346
6479
  var import_jsx_runtime69 = require("react/jsx-runtime");
6347
- var getRandomColor2 = () => {
6348
- const palette = [
6480
+ var getRandomColor = () => {
6481
+ const palette2 = [
6349
6482
  "#2563eb",
6350
6483
  "#1d4ed8",
6351
6484
  "#1e40af",
@@ -6407,7 +6540,7 @@ var getRandomColor2 = () => {
6407
6540
  "#155e75",
6408
6541
  "#164e63"
6409
6542
  ];
6410
- return palette[Math.floor(Math.random() * palette.length)];
6543
+ return palette2[Math.floor(Math.random() * palette2.length)];
6411
6544
  };
6412
6545
  var DonutChart = ({
6413
6546
  className,
@@ -6416,16 +6549,20 @@ var DonutChart = ({
6416
6549
  dataKey = "value",
6417
6550
  dataLabel = "name",
6418
6551
  apiUrl,
6552
+ source,
6553
+ legendPosition = "bottom",
6554
+ onLegendClick,
6419
6555
  ...props
6420
6556
  }) => {
6421
6557
  const showLegends = props.showLegends ?? true;
6422
6558
  const canvasMode = props.canvasMode;
6559
+ const useApi = source === "api" && !!apiUrl;
6423
6560
  const [rawData, setRawData] = (0, import_react37.useState)([]);
6424
6561
  const [localLoading, setLocalLoading] = (0, import_react37.useState)(false);
6425
- const effectiveData = apiUrl ? rawData : props.data || [];
6426
- const effectiveLoading = apiUrl ? localLoading : externalLoading;
6562
+ const effectiveData = useApi ? rawData : props.data || [];
6563
+ const effectiveLoading = useApi ? localLoading : externalLoading;
6427
6564
  (0, import_react37.useEffect)(() => {
6428
- if (!apiUrl) return;
6565
+ if (!useApi) return;
6429
6566
  let cancelled = false;
6430
6567
  const fetchData = async () => {
6431
6568
  try {
@@ -6459,12 +6596,12 @@ var DonutChart = ({
6459
6596
  return () => {
6460
6597
  cancelled = true;
6461
6598
  };
6462
- }, [apiUrl]);
6599
+ }, [useApi, apiUrl]);
6463
6600
  const data = (0, import_react37.useMemo)(() => {
6464
6601
  if (!Array.isArray(effectiveData) || effectiveData.length === 0) return [];
6465
6602
  return effectiveData.map((item) => ({
6466
6603
  ...item,
6467
- color: item.color || getRandomColor2(),
6604
+ color: item.color || getRandomColor(),
6468
6605
  [dataKey]: Number(item[dataKey] ?? 0),
6469
6606
  [dataLabel]: item[dataLabel] ?? "Unknown"
6470
6607
  }));
@@ -6512,42 +6649,59 @@ var DonutChart = ({
6512
6649
  }, []);
6513
6650
  const renderLegends = (0, import_react37.useMemo)(() => {
6514
6651
  if (!showLegends) return null;
6515
- return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "flex flex-wrap justify-center gap-2 mt-4 w-full max-w-4xl", children: chartData.map((d, index) => {
6516
- const actualValue = data.find(
6517
- (item) => item[dataLabel] === d[dataLabel]
6518
- )?.[dataKey] ?? d[dataKey];
6519
- const displayValue = actualValue >= 1e3 ? `${(actualValue / 1e3).toFixed(0)}k` : actualValue.toLocaleString();
6520
- return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
6521
- "div",
6522
- {
6523
- className: "flex items-center space-x-2 rounded-lg border border-gray-200/50 px-3 py-1.5 w-[48%] sm:w-[32%] md:w-auto bg-white/80 backdrop-blur-sm shadow-sm hover:shadow-md transition-all",
6524
- children: [
6525
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6526
- "span",
6527
- {
6528
- className: "inline-block w-[12px] h-[12px] rounded-full shrink-0 border-2 border-white/50",
6529
- style: { backgroundColor: d.color }
6530
- }
6531
- ),
6532
- /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "min-w-0 flex-1", children: [
6533
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "text-gray-900 text-[11px] md:text-[13px] font-semibold block truncate leading-tight", children: d[dataLabel] }),
6534
- /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "flex items-center gap-1 text-xs text-gray-600 font-medium", children: [
6535
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: displayValue }),
6536
- /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { children: [
6537
- (actualValue / total * 100).toFixed(1),
6538
- "%"
6539
- ] }),
6540
- d.isBoosted && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "text-[9px] px-1 py-0.5 bg-blue-100 text-blue-700 rounded-full", children: "min" })
6541
- ] })
6542
- ] })
6543
- ]
6544
- },
6545
- `legend-${index}`
6546
- );
6547
- }) });
6548
- }, [chartData, data, dataLabel, dataKey, total, showLegends]);
6652
+ const isLegendRight2 = !forceMobile && legendPosition === "right";
6653
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6654
+ "div",
6655
+ {
6656
+ className: isLegendRight2 ? "flex flex-col gap-2 w-full min-w-0 justify-start" : "flex flex-wrap justify-center gap-2 mt-4 w-full max-w-4xl",
6657
+ children: chartData.map((d, index) => {
6658
+ const actualValue = data.find(
6659
+ (item) => item[dataLabel] === d[dataLabel]
6660
+ )?.[dataKey] ?? d[dataKey];
6661
+ const displayValue = actualValue >= 1e3 ? `${(actualValue / 1e3).toFixed(0)}k` : actualValue.toLocaleString();
6662
+ const payload = {
6663
+ name: d[dataLabel],
6664
+ value: actualValue,
6665
+ [dataLabel]: d[dataLabel],
6666
+ [dataKey]: actualValue
6667
+ };
6668
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
6669
+ "div",
6670
+ {
6671
+ role: onLegendClick ? "button" : void 0,
6672
+ tabIndex: onLegendClick ? 0 : void 0,
6673
+ onClick: onLegendClick ? () => onLegendClick(payload) : void 0,
6674
+ onKeyDown: onLegendClick ? (e) => e.key === "Enter" && onLegendClick(payload) : void 0,
6675
+ className: `flex items-center space-x-2 rounded-lg border border-gray-200/50 px-3 py-1.5 w-[48%] sm:w-[32%] md:w-auto bg-white/80 backdrop-blur-sm shadow-sm hover:shadow-md transition-all ${onLegendClick ? "cursor-pointer" : ""}`,
6676
+ children: [
6677
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6678
+ "span",
6679
+ {
6680
+ className: "inline-block w-[12px] h-[12px] rounded-full shrink-0 border-2 border-white/50",
6681
+ style: { backgroundColor: d.color }
6682
+ }
6683
+ ),
6684
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "min-w-0 flex-1", children: [
6685
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "text-gray-900 text-[11px] md:text-[13px] font-semibold block truncate leading-tight", children: d[dataLabel] }),
6686
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "flex items-center gap-1 text-xs text-gray-600 font-medium", children: [
6687
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: displayValue }),
6688
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("span", { children: [
6689
+ (actualValue / total * 100).toFixed(1),
6690
+ "%"
6691
+ ] }),
6692
+ d.isBoosted && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "text-[9px] px-1 py-0.5 bg-blue-100 text-blue-700 rounded-full", children: "min" })
6693
+ ] })
6694
+ ] })
6695
+ ]
6696
+ },
6697
+ `legend-${index}`
6698
+ );
6699
+ })
6700
+ }
6701
+ );
6702
+ }, [chartData, data, dataLabel, dataKey, total, showLegends, onLegendClick, legendPosition, forceMobile]);
6549
6703
  if (!mounted) return null;
6550
- if (effectiveLoading || data.length === 0) {
6704
+ if (effectiveLoading) {
6551
6705
  return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
6552
6706
  "div",
6553
6707
  {
@@ -6577,66 +6731,90 @@ var DonutChart = ({
6577
6731
  }
6578
6732
  );
6579
6733
  }
6734
+ if (data.length === 0) {
6735
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6736
+ "div",
6737
+ {
6738
+ className: `relative flex flex-col items-center justify-center w-full h-[300px] md:h-[400px] bg-gradient-to-br from-gray-50 to-gray-100 rounded-xl p-6 ${className}`,
6739
+ style,
6740
+ children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "text-center", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "inline-flex items-center space-x-2 bg-white/80 px-6 py-3 rounded-xl backdrop-blur-sm border border-gray-200 shadow-lg", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "text-sm font-medium text-gray-600", children: "No data" }) }) })
6741
+ }
6742
+ );
6743
+ }
6580
6744
  const { inner, outer } = getDynamicRadius();
6581
6745
  const innerRadius = inner;
6582
6746
  const outerRadius = outer;
6583
- return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: `relative flex flex-col items-center ${className}`, style, children: [
6584
- /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "relative w-full md:w-[75%] h-[280px] md:h-[380px] flex items-center justify-center mb-2", children: [
6585
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_recharts2.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_recharts2.PieChart, { children: [
6586
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6587
- import_recharts2.Pie,
6747
+ const isLegendRight = !forceMobile && legendPosition === "right";
6748
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
6749
+ "div",
6750
+ {
6751
+ className: `relative flex ${isLegendRight ? "flex-row items-stretch gap-4" : "flex-col items-center"} ${className}`,
6752
+ style,
6753
+ children: [
6754
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
6755
+ "div",
6588
6756
  {
6589
- data: chartData,
6590
- cx: "50%",
6591
- cy: "50%",
6592
- innerRadius,
6593
- outerRadius,
6594
- dataKey,
6595
- labelLine: false,
6596
- isAnimationActive: true,
6597
- animationDuration: 800,
6598
- minAngle: 3,
6599
- children: chartData.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6600
- import_recharts2.Cell,
6601
- {
6602
- fill: entry.color,
6603
- stroke: entry.isBoosted ? "#fff" : "transparent",
6604
- strokeWidth: entry.isBoosted ? 1.5 : 0
6605
- },
6606
- `cell-${index}`
6607
- ))
6757
+ className: `relative flex items-center justify-center ${isLegendRight ? "flex-[2] min-w-0 max-w-[70%]" : "w-full md:w-[75%]"} h-[280px] md:h-[380px] ${isLegendRight ? "" : "mb-2"}`,
6758
+ children: [
6759
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_recharts2.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_recharts2.PieChart, { children: [
6760
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6761
+ import_recharts2.Pie,
6762
+ {
6763
+ data: chartData,
6764
+ cx: "50%",
6765
+ cy: "50%",
6766
+ innerRadius,
6767
+ outerRadius,
6768
+ dataKey,
6769
+ labelLine: false,
6770
+ isAnimationActive: true,
6771
+ animationDuration: 800,
6772
+ minAngle: 3,
6773
+ children: chartData.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6774
+ import_recharts2.Cell,
6775
+ {
6776
+ fill: entry.color,
6777
+ stroke: entry.isBoosted ? "#fff" : "transparent",
6778
+ strokeWidth: entry.isBoosted ? 1.5 : 0
6779
+ },
6780
+ `cell-${index}`
6781
+ ))
6782
+ }
6783
+ ),
6784
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6785
+ import_recharts2.Tooltip,
6786
+ {
6787
+ formatter: (value, name, payload) => {
6788
+ const label = payload && payload.payload ? payload.payload[dataLabel] : name;
6789
+ const actualItem = data.find((item) => item[dataLabel] === label);
6790
+ const actualValue = actualItem ? actualItem[dataKey] : value;
6791
+ const valueFormatted = actualValue >= 1e3 ? `${(actualValue / 1e3).toFixed(0)}k` : actualValue.toLocaleString();
6792
+ const percentage = (actualValue / total * 100).toFixed(1);
6793
+ return [
6794
+ `${label}: ${valueFormatted} (${percentage}%)`
6795
+ ];
6796
+ },
6797
+ contentStyle: {
6798
+ backgroundColor: "white",
6799
+ border: "1px solid #e5e7eb",
6800
+ borderRadius: "8px",
6801
+ fontSize: "13px",
6802
+ padding: "8px 12px"
6803
+ }
6804
+ }
6805
+ )
6806
+ ] }) }),
6807
+ total > 0 && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: `absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-center pointer-events-none ${forceMobile ? "text-xl px-2" : "text-3xl px-4"} font-bold bg-white/90 backdrop-blur-sm rounded-full py-1 shadow-lg`, children: /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "text-[#1f2937] leading-tight", children: [
6808
+ formattedTotal,
6809
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "text-sm md:text-base font-normal text-gray-600 block md:inline-block md:ml-1", children: "total" })
6810
+ ] }) })
6811
+ ]
6608
6812
  }
6609
6813
  ),
6610
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
6611
- import_recharts2.Tooltip,
6612
- {
6613
- formatter: (value, name, payload) => {
6614
- const label = payload && payload.payload ? payload.payload[dataLabel] : name;
6615
- const actualItem = data.find((item) => item[dataLabel] === label);
6616
- const actualValue = actualItem ? actualItem[dataKey] : value;
6617
- const valueFormatted = actualValue >= 1e3 ? `${(actualValue / 1e3).toFixed(0)}k` : actualValue.toLocaleString();
6618
- const percentage = (actualValue / total * 100).toFixed(1);
6619
- return [
6620
- `${label}: ${valueFormatted} (${percentage}%)`
6621
- ];
6622
- },
6623
- contentStyle: {
6624
- backgroundColor: "white",
6625
- border: "1px solid #e5e7eb",
6626
- borderRadius: "8px",
6627
- fontSize: "13px",
6628
- padding: "8px 12px"
6629
- }
6630
- }
6631
- )
6632
- ] }) }),
6633
- total > 0 && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: `absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-center pointer-events-none ${forceMobile ? "text-xl px-2" : "text-3xl px-4"} font-bold bg-white/90 backdrop-blur-sm rounded-full py-1 shadow-lg`, children: /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "text-[#1f2937] leading-tight", children: [
6634
- formattedTotal,
6635
- /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "text-sm md:text-base font-normal text-gray-600 block md:inline-block md:ml-1", children: "total" })
6636
- ] }) })
6637
- ] }),
6638
- renderLegends
6639
- ] });
6814
+ showLegends && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: isLegendRight ? "flex flex-col w-[30%] min-w-[180px] justify-center" : "w-full", children: renderLegends })
6815
+ ]
6816
+ }
6817
+ );
6640
6818
  };
6641
6819
  var PieChart_default = import_react37.default.memo(DonutChart);
6642
6820