@eztrak/shared 0.7.3 → 0.7.4

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.
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import react__default, { ReactNode, InputHTMLAttributes } from 'react';
2
+ import react__default, { ReactNode, InputHTMLAttributes, CSSProperties } from 'react';
3
3
 
4
4
  type EztrakTab = {
5
5
  id: string;
@@ -169,24 +169,52 @@ interface DropdownOption {
169
169
  interface CellEditPayload {
170
170
  propertyName: string;
171
171
  propertyValue: string | number | null;
172
- entityId: string | number;
173
- entityName: string;
172
+ entityId?: string | number;
173
+ entityName?: string;
174
174
  }
175
175
  interface CustomCellEditorRef {
176
176
  getValue: () => string | number | null | undefined;
177
177
  isCancelBeforeStart: () => boolean;
178
178
  isCancelAfterEnd: () => boolean;
179
+ /** Tells AG Grid to render this editor as a floating popup, free of column width */
180
+ isPopup: () => boolean;
179
181
  }
180
182
  interface CustomCellEditorProps {
181
183
  value: string | number | null | undefined;
182
184
  name: string;
183
185
  inputType?: CellEditorInputType;
184
186
  stopEditing: (cancel?: boolean) => void;
185
- entityId: string | number;
187
+ entityId?: string | number;
186
188
  entityName?: string;
187
189
  onSave: (payload: CellEditPayload) => Promise<void>;
190
+ /** Standard {value, label} dropdown options */
188
191
  dropdownOptions?: DropdownOption[];
192
+ /** Raw options array with custom key shapes (use with valueKey/labelKey) */
193
+ customOptions?: Record<string, unknown>[];
194
+ /** Key to read as option value from customOptions items (default: "value") */
195
+ valueKey?: string;
196
+ /** Key to read as option label from customOptions items (default: "label") */
197
+ labelKey?: string;
198
+ /** Extra inline styles applied to the wrapper div (merged with default layout) */
199
+ containerStyle?: CSSProperties;
200
+ /** Tailwind/CSS class(es) for the wrapper div */
189
201
  className?: string;
202
+ /** Tailwind/CSS class(es) applied directly to the <input> or <select> */
203
+ inputClassName?: string;
204
+ /** Replaces the built-in ButtonSpinner when isLoading is true */
205
+ loadingIndicator?: ReactNode;
206
+ /** Replaces the default FaCheck icon in the save button */
207
+ saveButtonContent?: ReactNode;
208
+ /** Replaces the default FaTimes icon in the cancel button */
209
+ cancelButtonContent?: ReactNode;
210
+ /** Inline styles for the save button */
211
+ saveButtonStyle?: CSSProperties;
212
+ /** Inline styles for the cancel button */
213
+ cancelButtonStyle?: CSSProperties;
214
+ /** Extra class(es) for the save button */
215
+ saveButtonClassName?: string;
216
+ /** Extra class(es) for the cancel button */
217
+ cancelButtonClassName?: string;
190
218
  }
191
219
 
192
220
  declare const CustomCellEditor: react.ForwardRefExoticComponent<CustomCellEditorProps & react.RefAttributes<CustomCellEditorRef>>;
@@ -981,7 +981,6 @@ function Modal({
981
981
  // src/components/cell-editor/CustomCellEditor.tsx
982
982
  var import_react4 = require("react");
983
983
  var import_react_hot_toast2 = __toESM(require("react-hot-toast"));
984
- var import_fa2 = require("react-icons/fa");
985
984
 
986
985
  // src/utils/helpers.ts
987
986
  var toDateInputValue = (date) => {
@@ -1010,8 +1009,8 @@ function ButtonSpinner() {
1010
1009
  "svg",
1011
1010
  {
1012
1011
  className: "animate-spin",
1013
- width: 8,
1014
- height: 8,
1012
+ width: 12,
1013
+ height: 12,
1015
1014
  viewBox: "0 0 24 24",
1016
1015
  fill: "none",
1017
1016
  "aria-hidden": true,
@@ -1059,47 +1058,59 @@ var CustomCellEditor = (0, import_react4.forwardRef)(
1059
1058
  entityName = "Record",
1060
1059
  onSave,
1061
1060
  dropdownOptions = [],
1062
- className
1061
+ customOptions,
1062
+ valueKey = "value",
1063
+ labelKey = "label",
1064
+ containerStyle,
1065
+ className,
1066
+ inputClassName,
1067
+ loadingIndicator,
1068
+ saveButtonContent,
1069
+ cancelButtonContent,
1070
+ saveButtonStyle,
1071
+ cancelButtonStyle,
1072
+ saveButtonClassName,
1073
+ cancelButtonClassName
1063
1074
  }, ref) => {
1064
1075
  const normalizedInitial = normalizeInitialValue(initialValue, inputType);
1065
1076
  const [value, setValue] = (0, import_react4.useState)(normalizedInitial);
1066
1077
  const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
1067
1078
  const inputRef = (0, import_react4.useRef)(null);
1068
1079
  const selectRef = (0, import_react4.useRef)(null);
1080
+ const normalizedOptions = (0, import_react4.useMemo)(() => {
1081
+ if (customOptions && customOptions.length > 0) {
1082
+ return customOptions.map((opt) => ({
1083
+ value: String(opt[valueKey] ?? ""),
1084
+ label: String(opt[labelKey] ?? "")
1085
+ }));
1086
+ }
1087
+ return dropdownOptions;
1088
+ }, [customOptions, dropdownOptions, valueKey, labelKey]);
1089
+ const isDropdown = inputType === "dropdown" || normalizedOptions.length > 0;
1069
1090
  (0, import_react4.useImperativeHandle)(ref, () => ({
1070
1091
  getValue: () => value,
1071
1092
  isCancelBeforeStart: () => false,
1072
- isCancelAfterEnd: () => false
1093
+ isCancelAfterEnd: () => false,
1094
+ isPopup: () => true
1073
1095
  }));
1074
1096
  (0, import_react4.useEffect)(() => {
1075
- if (inputType === "dropdown") {
1076
- const el2 = selectRef.current;
1077
- if (el2) {
1078
- el2.focus();
1079
- }
1097
+ if (isDropdown) {
1098
+ selectRef.current?.focus();
1080
1099
  return;
1081
1100
  }
1082
1101
  const el = inputRef.current;
1083
- if (!el) {
1084
- return;
1085
- }
1102
+ if (!el) return;
1086
1103
  el.focus();
1087
1104
  if (inputType !== "date") {
1088
1105
  el.select();
1089
1106
  }
1090
- }, [inputType]);
1107
+ }, [isDropdown, inputType]);
1091
1108
  const handleSave = async () => {
1092
- if (isLoading) {
1093
- return;
1094
- }
1109
+ if (isLoading) return;
1095
1110
  if (String(value) === String(normalizedInitial)) {
1096
1111
  stopEditing();
1097
1112
  return;
1098
1113
  }
1099
- if (!entityId) {
1100
- import_react_hot_toast2.default.error("Entity ID is required");
1101
- return;
1102
- }
1103
1114
  if (!name) {
1104
1115
  import_react_hot_toast2.default.error("Property name is required");
1105
1116
  return;
@@ -1148,26 +1159,30 @@ var CustomCellEditor = (0, import_react4.forwardRef)(
1148
1159
  setValue(event.target.value);
1149
1160
  };
1150
1161
  const isSaveDisabled = isLoading || String(value) === String(normalizedInitial);
1162
+ 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";
1163
+ 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";
1164
+ 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";
1151
1165
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1152
1166
  "div",
1153
1167
  {
1154
1168
  className: cn(
1155
- "flex items-center w-full h-full min-h-0 overflow-hidden gap-0.5 min-w-[80px]",
1169
+ "flex items-center gap-2 px-2 py-1 min-w-[320px] bg-white border border-gray-200 rounded-md shadow-md",
1156
1170
  className
1157
1171
  ),
1172
+ style: containerStyle,
1158
1173
  children: [
1159
- inputType === "dropdown" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1174
+ isDropdown ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1160
1175
  "select",
1161
1176
  {
1162
1177
  ref: selectRef,
1163
1178
  value: String(value),
1164
1179
  onChange: handleDropdownChange,
1165
1180
  onKeyDown: handleKeyDown,
1166
- className: "flex-1 h-full p-0 text-[10px] border border-gray-300 rounded-sm focus:outline-none focus:ring-1 focus:ring-blue-400 min-w-0 truncate",
1181
+ className: inputClassName ?? defaultInputClass,
1167
1182
  disabled: isLoading,
1168
1183
  children: [
1169
1184
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "", disabled: true, children: "Select option..." }),
1170
- dropdownOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
1185
+ normalizedOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
1171
1186
  ]
1172
1187
  }
1173
1188
  ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
@@ -1178,35 +1193,35 @@ var CustomCellEditor = (0, import_react4.forwardRef)(
1178
1193
  value: String(value),
1179
1194
  onChange: handleInputChange,
1180
1195
  onKeyDown: handleKeyDown,
1181
- className: "flex-1 h-full p-0 text-[10px] border border-gray-300 rounded-sm focus:outline-none focus:ring-1 focus:ring-blue-400 min-w-0 truncate",
1196
+ className: inputClassName ?? defaultInputClass,
1182
1197
  placeholder: "...",
1183
1198
  disabled: isLoading
1184
1199
  }
1185
1200
  ),
1186
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center shrink-0 gap-0.5", children: [
1187
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1188
- "button",
1189
- {
1190
- type: "button",
1191
- onClick: handleSave,
1192
- disabled: isSaveDisabled,
1193
- className: "flex items-center justify-center w-4 h-4 text-white bg-green-500 rounded-sm hover:bg-green-600 disabled:opacity-50",
1194
- title: "Save (Enter)",
1195
- children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ButtonSpinner, {}) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_fa2.FaCheck, { size: 7, "aria-hidden": true })
1196
- }
1197
- ),
1198
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1199
- "button",
1200
- {
1201
- type: "button",
1202
- onClick: handleCancel,
1203
- disabled: isLoading,
1204
- className: "flex items-center justify-center w-4 h-4 text-white bg-red-500 rounded-sm hover:bg-red-600 disabled:opacity-50",
1205
- title: "Cancel (Escape)",
1206
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_fa2.FaTimes, { size: 7, "aria-hidden": true })
1207
- }
1208
- )
1209
- ] })
1201
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1202
+ "button",
1203
+ {
1204
+ type: "button",
1205
+ onClick: handleSave,
1206
+ disabled: isSaveDisabled,
1207
+ className: saveButtonClassName ?? (saveButtonStyle ? void 0 : defaultSaveBtnClass),
1208
+ style: saveButtonStyle,
1209
+ title: "Save (Enter)",
1210
+ children: isLoading ? loadingIndicator ?? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ButtonSpinner, {}) : saveButtonContent ?? "Save"
1211
+ }
1212
+ ),
1213
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1214
+ "button",
1215
+ {
1216
+ type: "button",
1217
+ onClick: handleCancel,
1218
+ disabled: isLoading,
1219
+ className: cancelButtonClassName ?? (cancelButtonStyle ? void 0 : defaultCancelBtnClass),
1220
+ style: cancelButtonStyle,
1221
+ title: "Cancel (Escape)",
1222
+ children: cancelButtonContent ?? "Cancel"
1223
+ }
1224
+ )
1210
1225
  ]
1211
1226
  }
1212
1227
  );