@farmzone/fz-react-ui 1.0.16 → 1.0.18

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.d.cts CHANGED
@@ -652,6 +652,7 @@ interface Column<T> {
652
652
  sortable?: boolean;
653
653
  sort?: "asc" | "desc" | null;
654
654
  fixed?: TableFixed;
655
+ tooltipText?: (value: unknown, record: T, index: number) => ReactNode;
655
656
  }
656
657
 
657
658
  interface CheckboxInfo {
@@ -970,6 +971,7 @@ type SelectOption<P> = BaseOption<P> & {
970
971
  placeholder?: string;
971
972
  containerClassName?: string;
972
973
  canReset?: boolean;
974
+ autoSubmit?: boolean;
973
975
  };
974
976
  type RadioOption<P> = BaseOption<P> & {
975
977
  type: "radio";
package/dist/index.d.ts CHANGED
@@ -652,6 +652,7 @@ interface Column<T> {
652
652
  sortable?: boolean;
653
653
  sort?: "asc" | "desc" | null;
654
654
  fixed?: TableFixed;
655
+ tooltipText?: (value: unknown, record: T, index: number) => ReactNode;
655
656
  }
656
657
 
657
658
  interface CheckboxInfo {
@@ -970,6 +971,7 @@ type SelectOption<P> = BaseOption<P> & {
970
971
  placeholder?: string;
971
972
  containerClassName?: string;
972
973
  canReset?: boolean;
974
+ autoSubmit?: boolean;
973
975
  };
974
976
  type RadioOption<P> = BaseOption<P> & {
975
977
  type: "radio";
package/dist/index.js CHANGED
@@ -4105,45 +4105,15 @@ function TableHeader(props) {
4105
4105
  };
4106
4106
  };
4107
4107
  const renderColumnTitle = (column, isClickableHead) => {
4108
- const baseClasses = "pt-0.5 select-none";
4108
+ const baseClasses = "pt-0.5 select-none truncate";
4109
4109
  const subTitleClasses = column.key === "subTitle" ? "inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800" : "";
4110
- if (column.align === "left") {
4111
- return /* @__PURE__ */ jsxs("div", { className: "flex item-center w-full", children: [
4112
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: `pl-3 truncate ${baseClasses} ${isClickableHead} ${subTitleClasses}`, children: column.title }) }),
4113
- column.sortable && /* @__PURE__ */ jsx(
4114
- "div",
4115
- {
4116
- className: `w-5 flex flex-col gap-[1.5px] items-center justify-center cursor-pointer ${isClickableHead}`,
4117
- children: renderSortIcon(column.key)
4118
- }
4119
- )
4120
- ] });
4121
- }
4122
- if (column.align === "center") {
4123
- return /* @__PURE__ */ jsxs("div", { className: "flex justify-center w-full", children: [
4124
- /* @__PURE__ */ jsx("div", { className: `flex items-center justify-center ${column.sortable ? "pl-5" : ""}`, children: /* @__PURE__ */ jsx("span", { className: `whitespace-nowrap ${baseClasses} ${isClickableHead} ${subTitleClasses}`, children: column.title }) }),
4125
- column.sortable && /* @__PURE__ */ jsx(
4126
- "div",
4127
- {
4128
- className: `w-5 flex flex-col gap-[1.5px] items-center justify-center cursor-pointer ${isClickableHead}`,
4129
- children: renderSortIcon(column.key)
4130
- }
4131
- )
4132
- ] });
4133
- }
4134
- if (column.align === "right") {
4135
- return /* @__PURE__ */ jsxs("div", { className: "flex justify-end w-full", children: [
4136
- column.sortable && /* @__PURE__ */ jsx(
4137
- "div",
4138
- {
4139
- className: `w-5 flex flex-col gap-[1.5px] items-center justify-center cursor-pointer ${isClickableHead}`,
4140
- children: renderSortIcon(column.key)
4141
- }
4142
- ),
4143
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: `pr-3 truncate ${baseClasses} ${isClickableHead} ${subTitleClasses}`, children: column.title }) })
4144
- ] });
4145
- }
4146
- return /* @__PURE__ */ jsx("span", { className: `px-1.5 truncate ${baseClasses} ${isClickableHead} ${subTitleClasses}`, children: column.title });
4110
+ const hasSortIcon = column.sortable;
4111
+ const textAlignClass = column.align === "center" ? "text-center" : column.align === "right" ? "text-right" : "text-left";
4112
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center w-full", children: [
4113
+ hasSortIcon && column.align === "center" && /* @__PURE__ */ jsx("div", { className: "w-5 shrink-0" }),
4114
+ /* @__PURE__ */ jsx("span", { className: `flex-1 px-3 ${textAlignClass} ${baseClasses} ${isClickableHead} ${subTitleClasses}`, children: column.title }),
4115
+ hasSortIcon && /* @__PURE__ */ jsx("div", { className: `w-6 shrink-0 flex items-center justify-center cursor-pointer ${isClickableHead}`, children: renderSortIcon(column.key) })
4116
+ ] });
4147
4117
  };
4148
4118
  const createGroupHeaders = () => {
4149
4119
  const mainGroups2 = {};
@@ -4563,32 +4533,64 @@ function TableEmpty(props) {
4563
4533
  /* @__PURE__ */ jsx("span", { className: "text-md text-gray-500", children: "\uB4F1\uB85D\uB41C \uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4." })
4564
4534
  ] }) }) });
4565
4535
  }
4536
+ function TableCellTooltip({ children, content }) {
4537
+ return /* @__PURE__ */ jsx(TooltipPrimitive.Provider, { delayDuration: 0, children: /* @__PURE__ */ jsxs(TooltipPrimitive.Root, { children: [
4538
+ /* @__PURE__ */ jsx(TooltipPrimitive.Trigger, { asChild: true, children }),
4539
+ /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
4540
+ TooltipPrimitive.Content,
4541
+ {
4542
+ side: "bottom",
4543
+ sideOffset: 5,
4544
+ collisionPadding: 8,
4545
+ className: "relative animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 z-50 w-full max-w-[500px] origin-(--radix-tooltip-content-transform-origin) rounded-md bg-neutral-700 text-sm font-medium text-white",
4546
+ style: { zIndex: Z_INDEX.TOOLTIP },
4547
+ children: [
4548
+ /* @__PURE__ */ jsx(
4549
+ "div",
4550
+ {
4551
+ className: "px-3 py-[5px] break-words whitespace-normal custom-view-scrollbar",
4552
+ style: { overflowY: "auto", maxHeight: "250px" },
4553
+ children: content
4554
+ }
4555
+ ),
4556
+ /* @__PURE__ */ jsx(
4557
+ TooltipPrimitive.Arrow,
4558
+ {
4559
+ className: cn(
4560
+ "z-50 w-2.5 h-2.5 translate-y-[calc(-50%_-_0px)] rotate-45 rounded-[2px]",
4561
+ "bg-neutral-700 !fill-neutral-700"
4562
+ ),
4563
+ style: { fill: "currentColor" }
4564
+ }
4565
+ )
4566
+ ]
4567
+ }
4568
+ ) })
4569
+ ] }) });
4570
+ }
4566
4571
  function TableCellContent(props) {
4567
4572
  const { cellContent, tooltipText, align, tooltipConfig, onCellClick } = props;
4568
- const textRef = useRef(null);
4569
4573
  const [isOverflowing, setIsOverflowing] = useState(false);
4570
- useEffect(() => {
4571
- if (tooltipConfig !== "overflow") return;
4572
- const el = textRef.current;
4573
- if (!el) return;
4574
- const check = () => setIsOverflowing(el.scrollWidth > el.clientWidth);
4575
- check();
4576
- const observer = new ResizeObserver(check);
4577
- observer.observe(el);
4578
- return () => observer.disconnect();
4579
- }, [tooltipConfig]);
4574
+ const observerRef = useRef(null);
4575
+ const refCallback = useCallback(
4576
+ (el) => {
4577
+ observerRef.current?.disconnect();
4578
+ observerRef.current = null;
4579
+ if (!el || tooltipConfig !== "overflow") return;
4580
+ const check = () => setIsOverflowing(el.scrollWidth > el.clientWidth);
4581
+ const observer = new ResizeObserver(check);
4582
+ observer.observe(el);
4583
+ observerRef.current = observer;
4584
+ },
4585
+ [tooltipConfig]
4586
+ );
4580
4587
  const shouldShowTooltip = tooltipConfig === "always" || tooltipConfig === "overflow" && isOverflowing;
4581
4588
  const textAlign = align === "center" ? "center" : align === "right" ? "right" : "left";
4582
- return /* @__PURE__ */ jsx(
4583
- "div",
4584
- {
4585
- ref: textRef,
4586
- className: `ellipsis-1-line table-item w-full min-w-0 ${onCellClick ? "hover:text-main cursor-pointer" : "cursor-default"}`,
4587
- style: { textAlign },
4588
- onClick: onCellClick,
4589
- children: shouldShowTooltip ? /* @__PURE__ */ jsx(Tooltip2, { content: tooltipText, position: "bottom", asChild: true, children: /* @__PURE__ */ jsx("span", { children: cellContent }) }) : cellContent
4590
- }
4591
- );
4589
+ const divClassName = `ellipsis-1-line table-item w-full min-w-0 ${onCellClick ? "hover:text-main cursor-pointer" : "cursor-default"}`;
4590
+ if (!shouldShowTooltip) {
4591
+ return /* @__PURE__ */ jsx("div", { ref: refCallback, className: divClassName, style: { textAlign }, onClick: onCellClick, children: cellContent });
4592
+ }
4593
+ return /* @__PURE__ */ jsx(TableCellTooltip, { content: tooltipText, children: /* @__PURE__ */ jsx("div", { ref: refCallback, className: divClassName, style: { textAlign }, onClick: onCellClick, children: cellContent }) });
4592
4594
  }
4593
4595
 
4594
4596
  // src/components/Table/config/utils.ts
@@ -4706,7 +4708,13 @@ function Table(props) {
4706
4708
  showHorizontalDivider = true,
4707
4709
  showVerticalDivider = true
4708
4710
  } = props;
4709
- const { fixed = false, onSelectionChange, selectedKeys = [], disabledKeys = [], disabledTooltip } = checkboxInfo ?? {};
4711
+ const {
4712
+ fixed = false,
4713
+ onSelectionChange,
4714
+ selectedKeys = [],
4715
+ disabledKeys = [],
4716
+ disabledTooltip
4717
+ } = checkboxInfo ?? {};
4710
4718
  const scrollRef = useRef(null);
4711
4719
  const footerRef = useRef(null);
4712
4720
  const [tableHeight, setTableHeight] = useState(500);
@@ -5012,6 +5020,11 @@ function Table(props) {
5012
5020
  }
5013
5021
  }
5014
5022
  }, [orderedColumns]);
5023
+ const tableMinWidth = useMemo(() => {
5024
+ const allUserColsHaveWidth = orderedColumns.every((col) => col.key === "__checkbox__" || col.width !== void 0);
5025
+ if (!allUserColsHaveWidth) return void 0;
5026
+ return orderedColumns.reduce((sum, col) => sum + parseColPx(col), 0);
5027
+ }, [orderedColumns]);
5015
5028
  const estimatedLeadingPinnedWidth = useMemo(
5016
5029
  () => leadingPinnedCols.reduce((sum, col) => sum + parseColPx(col), 0),
5017
5030
  [leadingPinnedCols]
@@ -5095,7 +5108,7 @@ function Table(props) {
5095
5108
  TableCellContent,
5096
5109
  {
5097
5110
  cellContent,
5098
- tooltipText: String(record[col.key] ?? ""),
5111
+ tooltipText: col.tooltipText ? col.tooltipText(record[col.key], record, rowIdx) : String(record[col.key] ?? ""),
5099
5112
  align: align ?? "",
5100
5113
  tooltipConfig: col.key === "__checkbox__" ? false : tooltipConfig,
5101
5114
  onCellClick: col.key !== "__checkbox__" && onRowClickRef.current ? () => onRowClickRef.current?.(record, rowIdx) : void 0
@@ -5181,51 +5194,63 @@ function Table(props) {
5181
5194
  ref: scrollRef,
5182
5195
  className: "relative w-full overflow-y-auto overflow-x-auto custom-view-scrollbar bg-white",
5183
5196
  style: { height: `${tableHeight}px` },
5184
- children: /* @__PURE__ */ jsxs("table", { className: "w-full table-fixed border-spacing-0", children: [
5185
- /* @__PURE__ */ jsx(
5186
- TableHeader,
5187
- {
5188
- columns: orderedColumns,
5189
- getAlignStyle,
5190
- sortOption,
5191
- onSortChange,
5192
- onColumnDragStartCapture: handleColumnDragStartCapture,
5193
- onColumnDragStart: handleColumnDragStart,
5194
- onColumnDrop: handleColumnDrop,
5195
- onColumnDragEnd: handleColumnDragEnd,
5196
- onColumnDragOver: handleColumnDragOver,
5197
- isColumnDraggable
5198
- }
5199
- ),
5200
- /* @__PURE__ */ jsx("tbody", { className: "w-full h-full", children: showSkeleton ? Array.from({ length: 3 }).map((_, rowIdx) => /* @__PURE__ */ jsxs("tr", { className: "hover:bg-gray-50", children: [
5201
- leadingPinnedCols.map((col, idx) => /* @__PURE__ */ jsx(SkeletonTd, { col, showSquare: idx === 0 && !!checkboxInfo }, `leading-${idx}`)),
5202
- leftColspan > 0 && /* @__PURE__ */ jsx("td", { colSpan: leftColspan, style: { padding: 0, border: "none" } }),
5203
- virtualItems.map((vc) => /* @__PURE__ */ jsx(SkeletonTd, { col: groupCols[vc.index] }, `group-${vc.index}`)),
5204
- rightColspan > 0 && /* @__PURE__ */ jsx("td", { colSpan: rightColspan, style: { padding: 0, border: "none" } }),
5205
- trailingPinnedCols.map((col, idx) => /* @__PURE__ */ jsx(SkeletonTd, { col }, `trailing-${idx}`))
5206
- ] }, rowIdx)) : showEmpty ? /* @__PURE__ */ jsx(TableEmpty, { columnCount: allColumns.length }) : rows.map((row) => {
5207
- const rowId = String(getRowKey(row.original, row.index));
5208
- return /* @__PURE__ */ jsx(
5209
- TableDataRow,
5210
- {
5211
- record: row.original,
5212
- rowIdx: row.index,
5213
- rowId,
5214
- draggable: rowDraggable && !showSkeleton,
5215
- onDragStart: handleRowDragStart,
5216
- onDragOver: handleRowDragOver,
5217
- onDrop: handleRowDrop,
5218
- onDragEnd: handleRowDragEnd,
5219
- leftColspan,
5220
- rightColspan,
5221
- renderLeadingPinnedCols,
5222
- renderVisibleGroupCols,
5223
- renderTrailingPinnedCols
5224
- },
5225
- row.id
5226
- );
5227
- }) })
5228
- ] })
5197
+ children: /* @__PURE__ */ jsxs(
5198
+ "table",
5199
+ {
5200
+ className: `table-fixed border-spacing-0${tableMinWidth === void 0 ? " w-full" : ""}`,
5201
+ style: tableMinWidth !== void 0 ? { width: tableMinWidth, minWidth: tableMinWidth } : {
5202
+ minWidth: orderedColumns.reduce(
5203
+ (sum, col) => sum + (col.key === "__checkbox__" || col.width !== void 0 ? parseColPx(col) : 80),
5204
+ 0
5205
+ )
5206
+ },
5207
+ children: [
5208
+ /* @__PURE__ */ jsx(
5209
+ TableHeader,
5210
+ {
5211
+ columns: orderedColumns,
5212
+ getAlignStyle,
5213
+ sortOption,
5214
+ onSortChange,
5215
+ onColumnDragStartCapture: handleColumnDragStartCapture,
5216
+ onColumnDragStart: handleColumnDragStart,
5217
+ onColumnDrop: handleColumnDrop,
5218
+ onColumnDragEnd: handleColumnDragEnd,
5219
+ onColumnDragOver: handleColumnDragOver,
5220
+ isColumnDraggable
5221
+ }
5222
+ ),
5223
+ /* @__PURE__ */ jsx("tbody", { className: "w-full h-full", children: showSkeleton ? Array.from({ length: 3 }).map((_, rowIdx) => /* @__PURE__ */ jsxs("tr", { className: "hover:bg-gray-50", children: [
5224
+ leadingPinnedCols.map((col, idx) => /* @__PURE__ */ jsx(SkeletonTd, { col, showSquare: idx === 0 && !!checkboxInfo }, `leading-${idx}`)),
5225
+ leftColspan > 0 && /* @__PURE__ */ jsx("td", { colSpan: leftColspan, style: { padding: 0, border: "none" } }),
5226
+ virtualItems.map((vc) => /* @__PURE__ */ jsx(SkeletonTd, { col: groupCols[vc.index] }, `group-${vc.index}`)),
5227
+ rightColspan > 0 && /* @__PURE__ */ jsx("td", { colSpan: rightColspan, style: { padding: 0, border: "none" } }),
5228
+ trailingPinnedCols.map((col, idx) => /* @__PURE__ */ jsx(SkeletonTd, { col }, `trailing-${idx}`))
5229
+ ] }, rowIdx)) : showEmpty ? /* @__PURE__ */ jsx(TableEmpty, { columnCount: allColumns.length }) : rows.map((row) => {
5230
+ const rowId = String(getRowKey(row.original, row.index));
5231
+ return /* @__PURE__ */ jsx(
5232
+ TableDataRow,
5233
+ {
5234
+ record: row.original,
5235
+ rowIdx: row.index,
5236
+ rowId,
5237
+ draggable: rowDraggable && !showSkeleton,
5238
+ onDragStart: handleRowDragStart,
5239
+ onDragOver: handleRowDragOver,
5240
+ onDrop: handleRowDrop,
5241
+ onDragEnd: handleRowDragEnd,
5242
+ leftColspan,
5243
+ rightColspan,
5244
+ renderLeadingPinnedCols,
5245
+ renderVisibleGroupCols,
5246
+ renderTrailingPinnedCols
5247
+ },
5248
+ row.id
5249
+ );
5250
+ }) })
5251
+ ]
5252
+ }
5253
+ )
5229
5254
  }
5230
5255
  ),
5231
5256
  !showSkeleton && (paginationInfo || renderFooter?.renderLeft || renderFooter?.renderRight) && /* @__PURE__ */ jsx("div", { ref: footerRef, children: /* @__PURE__ */ jsx(
@@ -7744,11 +7769,22 @@ function PageFilter(props) {
7744
7769
  primaryColor
7745
7770
  } = props;
7746
7771
  const initialValuesRef = useRef(values);
7772
+ const pendingAutoSubmitRef = useRef(null);
7773
+ const onSubmitRef = useRef(onSubmit);
7774
+ onSubmitRef.current = onSubmit;
7775
+ useEffect(() => {
7776
+ const pending = pendingAutoSubmitRef.current;
7777
+ if (pending && String(values[pending.key] ?? "") === pending.value) {
7778
+ pendingAutoSubmitRef.current = null;
7779
+ onSubmitRef.current();
7780
+ }
7781
+ }, [values]);
7747
7782
  const handleInputChange = (key) => (e) => {
7748
7783
  onChange({ [key]: e.target.value });
7749
7784
  };
7750
- const handleSelectChange = (key) => (value) => {
7785
+ const handleSelectChange = (key, autoSubmit) => (value) => {
7751
7786
  onChange({ [key]: value });
7787
+ if (autoSubmit) pendingAutoSubmitRef.current = { key, value };
7752
7788
  };
7753
7789
  const handleRadioChange = (key) => (value) => {
7754
7790
  onChange({ [key]: value });
@@ -7763,9 +7799,11 @@ function PageFilter(props) {
7763
7799
  onChange({ [key]: checked ? "true" : "false" });
7764
7800
  };
7765
7801
  const handleSubmit = () => {
7802
+ pendingAutoSubmitRef.current = null;
7766
7803
  onSubmit();
7767
7804
  };
7768
7805
  const handleReset = () => {
7806
+ pendingAutoSubmitRef.current = null;
7769
7807
  onChange(initialValuesRef.current);
7770
7808
  onReset?.();
7771
7809
  };
@@ -7791,7 +7829,7 @@ function PageFilter(props) {
7791
7829
  Select2,
7792
7830
  {
7793
7831
  value: currentValue,
7794
- onChange: handleSelectChange(optionKey),
7832
+ onChange: handleSelectChange(optionKey, option.autoSubmit),
7795
7833
  options: option.options,
7796
7834
  placeholder: option.placeholder || "\uC120\uD0DD",
7797
7835
  canReset: option.canReset ?? true,