@universe-platform/ui 0.1.0-beta.11 → 0.1.0-beta.12

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.
Files changed (3) hide show
  1. package/dist/index.js +256 -171
  2. package/dist/index.mjs +256 -171
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4345,6 +4345,10 @@ function TableBlockClient({
4345
4345
  return calculateMinColumnWidth(colName, false, col == null ? void 0 : col.type);
4346
4346
  }
4347
4347
  });
4348
+ const executeActionRef = (0, import_react14.useRef)(executeAction);
4349
+ (0, import_react14.useEffect)(() => {
4350
+ executeActionRef.current = executeAction;
4351
+ }, [executeAction]);
4348
4352
  const [isMounted, setIsMounted] = (0, import_react14.useState)(false);
4349
4353
  const [isInitialLoading, setIsInitialLoading] = (0, import_react14.useState)(true);
4350
4354
  const [page, setPage] = (0, import_react14.useState)(1);
@@ -4447,6 +4451,7 @@ function TableBlockClient({
4447
4451
  }, []);
4448
4452
  const [data, setData] = (0, import_react14.useState)(() => normalizeRecords(initialRecords));
4449
4453
  const [serverRecords, setServerRecords] = (0, import_react14.useState)(() => normalizeRecords(initialRecords));
4454
+ const filteredData = data;
4450
4455
  (0, import_react14.useEffect)(() => {
4451
4456
  if (initialRecords) {
4452
4457
  const norm = normalizeRecords(initialRecords);
@@ -4484,6 +4489,8 @@ function TableBlockClient({
4484
4489
  const [relationTriggerRect, setRelationTriggerRect] = (0, import_react14.useState)(null);
4485
4490
  const filterButtonRefs = (0, import_react14.useRef)({});
4486
4491
  const [relationOptions, setRelationOptions] = (0, import_react14.useState)({});
4492
+ const [relationFilterOptions, setRelationFilterOptions] = (0, import_react14.useState)({});
4493
+ const [loadingFilterCol, setLoadingFilterCol] = (0, import_react14.useState)(null);
4487
4494
  const relationDictionaryRef = (0, import_react14.useRef)({});
4488
4495
  const mergeRelationOptions = (0, import_react14.useCallback)((colName, newOptions) => {
4489
4496
  if (!Array.isArray(newOptions) || newOptions.length === 0) return;
@@ -4548,7 +4555,8 @@ function TableBlockClient({
4548
4555
  const fetchRequestIdRef = (0, import_react14.useRef)(0);
4549
4556
  const fetchTableData = (0, import_react14.useCallback)((targetPage, targetLimit, targetSearch, targetFiltersKey) => {
4550
4557
  const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
4551
- if (!tableId || !executeAction) return Promise.resolve();
4558
+ const action = executeActionRef.current;
4559
+ if (!tableId || !action) return Promise.resolve();
4552
4560
  const currentRequestId = ++fetchRequestIdRef.current;
4553
4561
  setIsFetching(true);
4554
4562
  let activeFilters = {};
@@ -4557,7 +4565,7 @@ function TableBlockClient({
4557
4565
  } catch (e) {
4558
4566
  }
4559
4567
  const skip = (targetPage - 1) * targetLimit;
4560
- return executeAction("FETCH_TABLE_DATA", {
4568
+ return action("FETCH_TABLE_DATA", {
4561
4569
  tableId,
4562
4570
  page: targetPage,
4563
4571
  limit: targetLimit,
@@ -4606,7 +4614,7 @@ function TableBlockClient({
4606
4614
  setIsInitialLoading(false);
4607
4615
  }
4608
4616
  });
4609
- }, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, executeAction, mergeColumnDefs, mergeWithDirty, mergeRelationOptions]);
4617
+ }, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, mergeColumnDefs, mergeWithDirty, mergeRelationOptions]);
4610
4618
  (0, import_react14.useEffect)(() => {
4611
4619
  fetchTableData(page, limit, debouncedSearch, filtersKey);
4612
4620
  }, [page, limit, debouncedSearch, filtersKey, fetchTableData]);
@@ -4684,6 +4692,42 @@ function TableBlockClient({
4684
4692
  }
4685
4693
  return [];
4686
4694
  }, [schemaColsString, executeAction, mergeRelationOptions]);
4695
+ const fetchRelationFilterOptions = (0, import_react14.useCallback)(async (colName) => {
4696
+ var _a;
4697
+ let parsedCols = [];
4698
+ try {
4699
+ parsedCols = JSON.parse(schemaColsString);
4700
+ } catch (e) {
4701
+ }
4702
+ const col = parsedCols.find((c) => {
4703
+ var _a2;
4704
+ return c.name === colName && ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION";
4705
+ });
4706
+ if (!col || !((_a = col.config) == null ? void 0 : _a.referencedTableId) || !executeAction) return;
4707
+ const currentTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
4708
+ setLoadingFilterCol(colName);
4709
+ try {
4710
+ const res = await executeAction("FETCH_RELATION", {
4711
+ referencedTableId: col.config.referencedTableId,
4712
+ currentTableId,
4713
+ columnName: colName,
4714
+ isFilter: true,
4715
+ displayField: col.config.displayField,
4716
+ take: 1e3
4717
+ });
4718
+ const list = Array.isArray(res) ? res : (res == null ? void 0 : res.data) && Array.isArray(res.data) ? res.data : [];
4719
+ setRelationFilterOptions((prev) => __spreadProps(__spreadValues({}, prev), {
4720
+ [colName]: list
4721
+ }));
4722
+ if (list.length > 0) {
4723
+ mergeRelationOptions(colName, list);
4724
+ }
4725
+ } catch (err) {
4726
+ console.warn(`[TableBlock] Failed to fetch distinct relation filter options for ${colName}:`, err);
4727
+ } finally {
4728
+ setLoadingFilterCol(null);
4729
+ }
4730
+ }, [schemaColsString, schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, executeAction, mergeRelationOptions]);
4687
4731
  const requestedRelationIdsRef = (0, import_react14.useRef)({});
4688
4732
  (0, import_react14.useEffect)(() => {
4689
4733
  if (!executeAction || !data || data.length === 0) return;
@@ -4986,39 +5030,38 @@ function TableBlockClient({
4986
5030
  setData((prev) => [newRow, ...prev]);
4987
5031
  setDirty((prev) => __spreadProps(__spreadValues({}, prev), { added: [newRow, ...prev.added] }));
4988
5032
  };
4989
- const handleCellChange = (rowId, colName, value) => {
5033
+ const handleCellChange = (0, import_react14.useCallback)((rowId, colName, value) => {
4990
5034
  setData((prev) => prev.map(
4991
5035
  (row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
4992
5036
  ));
4993
- const isAdded = dirty.added.some((r) => r.id === rowId);
4994
- if (isAdded) {
4995
- setDirty((prev) => __spreadProps(__spreadValues({}, prev), {
4996
- added: prev.added.map(
4997
- (r) => r.id === rowId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value }) }) : r
4998
- )
4999
- }));
5000
- } else {
5001
- const origData = baseRecordsMap.get(rowId) || {};
5002
- const origValue = origData[colName];
5003
- setDirty((prev) => {
5004
- const currentMods = __spreadValues({}, prev.modified[rowId] || {});
5005
- if (isEqualValues(value, origValue)) {
5006
- delete currentMods[colName];
5007
- } else {
5008
- currentMods[colName] = value;
5009
- }
5010
- const nextModified = __spreadValues({}, prev.modified);
5011
- if (Object.keys(currentMods).length === 0) {
5012
- delete nextModified[rowId];
5013
- } else {
5014
- nextModified[rowId] = currentMods;
5015
- }
5037
+ setDirty((prev) => {
5038
+ const isAdded = prev.added.some((r) => r.id === rowId);
5039
+ if (isAdded) {
5016
5040
  return __spreadProps(__spreadValues({}, prev), {
5017
- modified: nextModified
5041
+ added: prev.added.map(
5042
+ (r) => r.id === rowId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value }) }) : r
5043
+ )
5018
5044
  });
5045
+ }
5046
+ const origData = baseRecordsMap.get(rowId) || {};
5047
+ const origValue = origData[colName];
5048
+ const currentMods = __spreadValues({}, prev.modified[rowId] || {});
5049
+ if (isEqualValues(value, origValue)) {
5050
+ delete currentMods[colName];
5051
+ } else {
5052
+ currentMods[colName] = value;
5053
+ }
5054
+ const nextModified = __spreadValues({}, prev.modified);
5055
+ if (Object.keys(currentMods).length === 0) {
5056
+ delete nextModified[rowId];
5057
+ } else {
5058
+ nextModified[rowId] = currentMods;
5059
+ }
5060
+ return __spreadProps(__spreadValues({}, prev), {
5061
+ modified: nextModified
5019
5062
  });
5020
- }
5021
- };
5063
+ });
5064
+ }, [baseRecordsMap]);
5022
5065
  const triggerSaveSuccess = (0, import_react14.useCallback)(() => {
5023
5066
  setIsSaveSuccess(true);
5024
5067
  setTimeout(() => {
@@ -5049,22 +5092,28 @@ function TableBlockClient({
5049
5092
  });
5050
5093
  }
5051
5094
  }, []);
5052
- const toggleSelectAll = (checked) => {
5053
- const nextSelected = checked ? new Set(filteredData.map((r) => r.id)) : /* @__PURE__ */ new Set();
5054
- setSelectedIds(nextSelected);
5055
- if (emitEvent) {
5056
- emitEvent("SELECTION_CHANGE", { selectedIds: Array.from(nextSelected), componentId });
5057
- }
5058
- };
5059
- const toggleSelectRow = (rowId, checked) => {
5060
- const newSelected = new Set(selectedIds);
5061
- if (checked) newSelected.add(rowId);
5062
- else newSelected.delete(rowId);
5063
- setSelectedIds(newSelected);
5064
- if (emitEvent) {
5065
- emitEvent("SELECTION_CHANGE", { selectedIds: Array.from(newSelected), componentId });
5066
- }
5067
- };
5095
+ const toggleSelectAll = (0, import_react14.useCallback)((checked) => {
5096
+ setSelectedIds(checked ? new Set(filteredData.map((r) => r.id)) : /* @__PURE__ */ new Set());
5097
+ }, [filteredData]);
5098
+ const toggleSelectRow = (0, import_react14.useCallback)((rowId, checked) => {
5099
+ setSelectedIds((prev) => {
5100
+ const next = new Set(prev);
5101
+ if (checked) next.add(rowId);
5102
+ else next.delete(rowId);
5103
+ return next;
5104
+ });
5105
+ }, []);
5106
+ const handleToggleExpand = (0, import_react14.useCallback)((rowId) => {
5107
+ setExpandedRowIds((prev) => {
5108
+ const next = new Set(prev);
5109
+ if (next.has(rowId)) next.delete(rowId);
5110
+ else next.add(rowId);
5111
+ return next;
5112
+ });
5113
+ }, []);
5114
+ const handleMarkForDeletion = (0, import_react14.useCallback)((fileId) => {
5115
+ setPendingDeletions((prev) => [...prev, fileId]);
5116
+ }, []);
5068
5117
  const handleDeleteSelected = () => {
5069
5118
  const idsToDelete = Array.from(selectedIds);
5070
5119
  if (idsToDelete.length === 0) return;
@@ -5143,9 +5192,6 @@ function TableBlockClient({
5143
5192
  setData(serverRecords.map((r) => __spreadProps(__spreadValues({}, r), { data: __spreadValues({}, r.data) })));
5144
5193
  setSelectedIds(/* @__PURE__ */ new Set());
5145
5194
  setPendingDeletions([]);
5146
- if (emitEvent) {
5147
- emitEvent("SELECTION_CHANGE", { selectedIds: [], componentId });
5148
- }
5149
5195
  };
5150
5196
  const handleSave = async () => {
5151
5197
  var _a, _b;
@@ -5313,26 +5359,13 @@ function TableBlockClient({
5313
5359
  }).filter(Boolean);
5314
5360
  }, [relationOptions]);
5315
5361
  const getUniqueRelationOptions = (0, import_react14.useCallback)((col) => {
5362
+ if (relationFilterOptions[col.name]) {
5363
+ return relationFilterOptions[col.name];
5364
+ }
5316
5365
  const seenIds = /* @__PURE__ */ new Set();
5317
5366
  const seenLabels = /* @__PURE__ */ new Set();
5318
5367
  const results = [];
5319
5368
  const options = relationOptions[col.name] || [];
5320
- options.forEach((opt) => {
5321
- const id = String(opt.id || opt._id || "");
5322
- if (!id) return;
5323
- let label = resolveRelationLabel(opt, col);
5324
- if (!label) {
5325
- const fallback = opt.label || opt.name || opt.title;
5326
- if (fallback && typeof fallback === "string" && !isRawObjectId(fallback)) {
5327
- label = fallback.trim();
5328
- }
5329
- }
5330
- if (label && label.trim() && !isRawObjectId(label) && !seenLabels.has(label.trim())) {
5331
- seenIds.add(id);
5332
- seenLabels.add(label.trim());
5333
- results.push({ id, label: label.trim() });
5334
- }
5335
- });
5336
5369
  data.forEach((row) => {
5337
5370
  if (!(row == null ? void 0 : row.data)) return;
5338
5371
  const ids = normalizeRelationValue(row.data[col.name]);
@@ -5355,8 +5388,7 @@ function TableBlockClient({
5355
5388
  });
5356
5389
  });
5357
5390
  return results.sort((a, b) => a.label.localeCompare(b.label));
5358
- }, [data, relationOptions]);
5359
- const filteredData = data;
5391
+ }, [data, relationOptions, relationFilterOptions]);
5360
5392
  const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
5361
5393
  const columnTotals = (0, import_react14.useMemo)(() => {
5362
5394
  const totals = {};
@@ -5809,9 +5841,7 @@ function TableBlockClient({
5809
5841
  setRelationTriggerRect(btn.getBoundingClientRect());
5810
5842
  }
5811
5843
  setActiveRelationCol(col.name);
5812
- if (!relationOptions[col.name] || relationOptions[col.name].length < 100) {
5813
- refetchRelation(col.name, { take: 1e3 });
5814
- }
5844
+ fetchRelationFilterOptions(col.name);
5815
5845
  }
5816
5846
  } else {
5817
5847
  setActiveSearchCol(col.name);
@@ -5844,106 +5874,37 @@ function TableBlockClient({
5844
5874
  var _a;
5845
5875
  return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
5846
5876
  });
5847
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react14.default.Fragment, { children: [
5848
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
5849
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", style: { width: 72, minWidth: 72, maxWidth: 72 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-center gap-1.5", children: [
5850
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
5851
- "input",
5852
- {
5853
- type: "checkbox",
5854
- checked: selectedIds.has(row.id),
5855
- onChange: (e) => toggleSelectRow(row.id, e.target.checked),
5856
- disabled: isLoading || isUpdatingActive,
5857
- className: "w-4 h-4 rounded border-slate-300 text-brand"
5858
- }
5859
- ),
5860
- hasSubTableCols && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
5861
- "button",
5862
- {
5863
- type: "button",
5864
- onClick: () => setExpandedRowIds((prev) => {
5865
- const next = new Set(prev);
5866
- if (next.has(row.id)) next.delete(row.id);
5867
- else next.add(row.id);
5868
- return next;
5869
- }),
5870
- className: "w-5 h-5 rounded-full bg-slate-500 hover:bg-slate-600 text-white flex items-center justify-center transition-colors cursor-pointer shrink-0 shadow-sm",
5871
- title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
5872
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: `w-3 h-3 transition-transform duration-150 ${isExpanded ? "rotate-90" : "rotate-180"}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "3", d: "M9 5l7 7-7 7" }) })
5873
- }
5874
- )
5875
- ] }) }),
5876
- filteredColumns.map((col) => {
5877
- var _a;
5878
- const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
5879
- const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
5880
- const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
5881
- const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
5882
- let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
5883
- if (value === void 0 && col.defaultValue !== void 0) {
5884
- value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
5885
- if (colType === "CURRENCY" || colType === "NUMBER") {
5886
- if (isNaN(value)) value = null;
5887
- }
5888
- }
5889
- if (value === void 0) value = null;
5890
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
5891
- "td",
5892
- {
5893
- className: `border-b border-l border-slate-200 p-0 relative ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
5894
- style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
5895
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
5896
- InputComponent,
5897
- {
5898
- value,
5899
- column: col,
5900
- rowId: row.id,
5901
- onChange: (v) => handleCellChange(row.id, col.name, v),
5902
- context: {
5903
- tableName: (schema == null ? void 0 : schema.name) || (schema == null ? void 0 : schema.tableName) || (schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.id) || "Table",
5904
- tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
5905
- onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
5906
- relationOptions,
5907
- relationDictionaryRef,
5908
- refetchRelation,
5909
- executeAction,
5910
- emitEvent,
5911
- pageState,
5912
- componentId,
5913
- orgId,
5914
- updateQuietly: handleQuietCellChange,
5915
- triggerSaveSuccess,
5916
- rowData: row.data
5917
- }
5918
- }
5919
- )
5920
- },
5921
- col.name
5922
- );
5923
- }),
5924
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
5925
- ] }),
5926
- isExpanded && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
5927
- ExpandedSubTables,
5928
- {
5929
- rowId: row.id,
5930
- rowData: row.data,
5931
- subTableColumns,
5932
- filteredColumnsLength: filteredColumns.length,
5933
- handleCellChange,
5934
- context: {
5935
- executeAction,
5936
- orgId,
5937
- parentTableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
5938
- tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
5939
- rowData: row.data,
5940
- updateQuietly: handleQuietCellChange,
5941
- triggerSaveSuccess,
5942
- onUpdateColumnConfig: handleUpdateColumnConfig
5943
- }
5944
- }
5945
- )
5946
- ] }, row.id);
5877
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
5878
+ TableRow,
5879
+ {
5880
+ row,
5881
+ isSelected: selectedIds.has(row.id),
5882
+ isExpanded,
5883
+ filteredColumns,
5884
+ columnWidths,
5885
+ hasSubTableCols,
5886
+ subTableColumns,
5887
+ isLoading: isLoading || isFetching,
5888
+ isUpdatingActive,
5889
+ onToggleSelect: toggleSelectRow,
5890
+ onToggleExpand: handleToggleExpand,
5891
+ handleCellChange,
5892
+ handleQuietCellChange,
5893
+ handleUpdateColumnConfig,
5894
+ onMarkForDeletion: handleMarkForDeletion,
5895
+ triggerSaveSuccess,
5896
+ schema,
5897
+ orgId,
5898
+ componentId,
5899
+ pageState,
5900
+ relationOptions,
5901
+ relationDictionaryRef,
5902
+ refetchRelation,
5903
+ executeAction,
5904
+ emitEvent
5905
+ },
5906
+ row.id
5907
+ );
5947
5908
  }) }),
5948
5909
  showSummary && filteredData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tfoot", { className: "bg-slate-50 border-t-2 border-slate-300 sticky bottom-0 z-10 shadow-[0_-2px_4px_rgba(0,0,0,0.02)]", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { children: [
5949
5910
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center font-bold text-slate-600 text-xs", children: '\u05E1\u05D4"\u05DB' }),
@@ -6039,7 +6000,8 @@ function TableBlockClient({
6039
6000
  filterValue: currentSelected,
6040
6001
  onSelectionChange: (newSelected) => {
6041
6002
  handleApplyColumnFilter(activeRelationCol, newSelected);
6042
- }
6003
+ },
6004
+ isLoading: loadingFilterCol === activeRelationCol
6043
6005
  }
6044
6006
  );
6045
6007
  })()
@@ -6096,6 +6058,129 @@ function ExpandedSubTables({
6096
6058
  ) })
6097
6059
  ] }) });
6098
6060
  }
6061
+ var TableRow = import_react14.default.memo(function TableRow2({
6062
+ row,
6063
+ isSelected,
6064
+ isExpanded,
6065
+ filteredColumns,
6066
+ columnWidths,
6067
+ hasSubTableCols,
6068
+ subTableColumns,
6069
+ isLoading,
6070
+ isUpdatingActive,
6071
+ onToggleSelect,
6072
+ onToggleExpand,
6073
+ handleCellChange,
6074
+ handleQuietCellChange,
6075
+ handleUpdateColumnConfig,
6076
+ onMarkForDeletion,
6077
+ triggerSaveSuccess,
6078
+ schema,
6079
+ orgId,
6080
+ componentId,
6081
+ pageState,
6082
+ relationOptions,
6083
+ relationDictionaryRef,
6084
+ refetchRelation,
6085
+ executeAction,
6086
+ emitEvent
6087
+ }) {
6088
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react14.default.Fragment, { children: [
6089
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { className: `hover:bg-blue-50/30 transition-colors group ${isSelected ? "bg-blue-50/40" : ""}`, children: [
6090
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", style: { width: 72, minWidth: 72, maxWidth: 72 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-center gap-1.5", children: [
6091
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
6092
+ "input",
6093
+ {
6094
+ type: "checkbox",
6095
+ checked: isSelected,
6096
+ onChange: (e) => onToggleSelect(row.id, e.target.checked),
6097
+ disabled: isLoading || isUpdatingActive,
6098
+ className: "w-4 h-4 rounded border-slate-300 text-brand"
6099
+ }
6100
+ ),
6101
+ hasSubTableCols && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
6102
+ "button",
6103
+ {
6104
+ type: "button",
6105
+ onClick: () => onToggleExpand(row.id),
6106
+ className: "w-5 h-5 rounded-full bg-slate-500 hover:bg-slate-600 text-white flex items-center justify-center transition-colors cursor-pointer shrink-0 shadow-sm",
6107
+ title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
6108
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: `w-3 h-3 transition-transform duration-150 ${isExpanded ? "rotate-90" : "rotate-180"}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "3", d: "M9 5l7 7-7 7" }) })
6109
+ }
6110
+ )
6111
+ ] }) }),
6112
+ filteredColumns.map((col) => {
6113
+ var _a;
6114
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
6115
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
6116
+ const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
6117
+ const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
6118
+ let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
6119
+ if (value === void 0 && col.defaultValue !== void 0) {
6120
+ value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
6121
+ if (colType === "CURRENCY" || colType === "NUMBER") {
6122
+ if (isNaN(value)) value = null;
6123
+ }
6124
+ }
6125
+ if (value === void 0) value = null;
6126
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
6127
+ "td",
6128
+ {
6129
+ className: `border-b border-l border-slate-200 p-0 relative ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
6130
+ style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
6131
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
6132
+ InputComponent,
6133
+ {
6134
+ value,
6135
+ column: col,
6136
+ rowId: row.id,
6137
+ onChange: (v) => handleCellChange(row.id, col.name, v),
6138
+ context: {
6139
+ tableName: (schema == null ? void 0 : schema.name) || (schema == null ? void 0 : schema.tableName) || (schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.id) || "Table",
6140
+ tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
6141
+ onMarkForDeletion,
6142
+ relationOptions,
6143
+ relationDictionaryRef,
6144
+ refetchRelation,
6145
+ executeAction,
6146
+ emitEvent,
6147
+ pageState,
6148
+ componentId,
6149
+ orgId,
6150
+ updateQuietly: handleQuietCellChange,
6151
+ triggerSaveSuccess,
6152
+ rowData: row.data
6153
+ }
6154
+ }
6155
+ )
6156
+ },
6157
+ col.name
6158
+ );
6159
+ }),
6160
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
6161
+ ] }),
6162
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
6163
+ ExpandedSubTables,
6164
+ {
6165
+ rowId: row.id,
6166
+ rowData: row.data,
6167
+ subTableColumns,
6168
+ filteredColumnsLength: filteredColumns.length,
6169
+ handleCellChange,
6170
+ context: {
6171
+ executeAction,
6172
+ orgId,
6173
+ parentTableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
6174
+ tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
6175
+ rowData: row.data,
6176
+ updateQuietly: handleQuietCellChange,
6177
+ triggerSaveSuccess,
6178
+ onUpdateColumnConfig: handleUpdateColumnConfig
6179
+ }
6180
+ }
6181
+ )
6182
+ ] });
6183
+ });
6099
6184
 
6100
6185
  // src/components/TableBlock/TableBlock.tsx
6101
6186
  var import_jsx_runtime12 = require("react/jsx-runtime");
package/dist/index.mjs CHANGED
@@ -4279,6 +4279,10 @@ function TableBlockClient({
4279
4279
  return calculateMinColumnWidth(colName, false, col == null ? void 0 : col.type);
4280
4280
  }
4281
4281
  });
4282
+ const executeActionRef = useRef8(executeAction);
4283
+ useEffect10(() => {
4284
+ executeActionRef.current = executeAction;
4285
+ }, [executeAction]);
4282
4286
  const [isMounted, setIsMounted] = useState12(false);
4283
4287
  const [isInitialLoading, setIsInitialLoading] = useState12(true);
4284
4288
  const [page, setPage] = useState12(1);
@@ -4381,6 +4385,7 @@ function TableBlockClient({
4381
4385
  }, []);
4382
4386
  const [data, setData] = useState12(() => normalizeRecords(initialRecords));
4383
4387
  const [serverRecords, setServerRecords] = useState12(() => normalizeRecords(initialRecords));
4388
+ const filteredData = data;
4384
4389
  useEffect10(() => {
4385
4390
  if (initialRecords) {
4386
4391
  const norm = normalizeRecords(initialRecords);
@@ -4418,6 +4423,8 @@ function TableBlockClient({
4418
4423
  const [relationTriggerRect, setRelationTriggerRect] = useState12(null);
4419
4424
  const filterButtonRefs = useRef8({});
4420
4425
  const [relationOptions, setRelationOptions] = useState12({});
4426
+ const [relationFilterOptions, setRelationFilterOptions] = useState12({});
4427
+ const [loadingFilterCol, setLoadingFilterCol] = useState12(null);
4421
4428
  const relationDictionaryRef = useRef8({});
4422
4429
  const mergeRelationOptions = useCallback10((colName, newOptions) => {
4423
4430
  if (!Array.isArray(newOptions) || newOptions.length === 0) return;
@@ -4482,7 +4489,8 @@ function TableBlockClient({
4482
4489
  const fetchRequestIdRef = useRef8(0);
4483
4490
  const fetchTableData = useCallback10((targetPage, targetLimit, targetSearch, targetFiltersKey) => {
4484
4491
  const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
4485
- if (!tableId || !executeAction) return Promise.resolve();
4492
+ const action = executeActionRef.current;
4493
+ if (!tableId || !action) return Promise.resolve();
4486
4494
  const currentRequestId = ++fetchRequestIdRef.current;
4487
4495
  setIsFetching(true);
4488
4496
  let activeFilters = {};
@@ -4491,7 +4499,7 @@ function TableBlockClient({
4491
4499
  } catch (e) {
4492
4500
  }
4493
4501
  const skip = (targetPage - 1) * targetLimit;
4494
- return executeAction("FETCH_TABLE_DATA", {
4502
+ return action("FETCH_TABLE_DATA", {
4495
4503
  tableId,
4496
4504
  page: targetPage,
4497
4505
  limit: targetLimit,
@@ -4540,7 +4548,7 @@ function TableBlockClient({
4540
4548
  setIsInitialLoading(false);
4541
4549
  }
4542
4550
  });
4543
- }, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, executeAction, mergeColumnDefs, mergeWithDirty, mergeRelationOptions]);
4551
+ }, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, mergeColumnDefs, mergeWithDirty, mergeRelationOptions]);
4544
4552
  useEffect10(() => {
4545
4553
  fetchTableData(page, limit, debouncedSearch, filtersKey);
4546
4554
  }, [page, limit, debouncedSearch, filtersKey, fetchTableData]);
@@ -4618,6 +4626,42 @@ function TableBlockClient({
4618
4626
  }
4619
4627
  return [];
4620
4628
  }, [schemaColsString, executeAction, mergeRelationOptions]);
4629
+ const fetchRelationFilterOptions = useCallback10(async (colName) => {
4630
+ var _a;
4631
+ let parsedCols = [];
4632
+ try {
4633
+ parsedCols = JSON.parse(schemaColsString);
4634
+ } catch (e) {
4635
+ }
4636
+ const col = parsedCols.find((c) => {
4637
+ var _a2;
4638
+ return c.name === colName && ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION";
4639
+ });
4640
+ if (!col || !((_a = col.config) == null ? void 0 : _a.referencedTableId) || !executeAction) return;
4641
+ const currentTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
4642
+ setLoadingFilterCol(colName);
4643
+ try {
4644
+ const res = await executeAction("FETCH_RELATION", {
4645
+ referencedTableId: col.config.referencedTableId,
4646
+ currentTableId,
4647
+ columnName: colName,
4648
+ isFilter: true,
4649
+ displayField: col.config.displayField,
4650
+ take: 1e3
4651
+ });
4652
+ const list = Array.isArray(res) ? res : (res == null ? void 0 : res.data) && Array.isArray(res.data) ? res.data : [];
4653
+ setRelationFilterOptions((prev) => __spreadProps(__spreadValues({}, prev), {
4654
+ [colName]: list
4655
+ }));
4656
+ if (list.length > 0) {
4657
+ mergeRelationOptions(colName, list);
4658
+ }
4659
+ } catch (err) {
4660
+ console.warn(`[TableBlock] Failed to fetch distinct relation filter options for ${colName}:`, err);
4661
+ } finally {
4662
+ setLoadingFilterCol(null);
4663
+ }
4664
+ }, [schemaColsString, schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, executeAction, mergeRelationOptions]);
4621
4665
  const requestedRelationIdsRef = useRef8({});
4622
4666
  useEffect10(() => {
4623
4667
  if (!executeAction || !data || data.length === 0) return;
@@ -4920,39 +4964,38 @@ function TableBlockClient({
4920
4964
  setData((prev) => [newRow, ...prev]);
4921
4965
  setDirty((prev) => __spreadProps(__spreadValues({}, prev), { added: [newRow, ...prev.added] }));
4922
4966
  };
4923
- const handleCellChange = (rowId, colName, value) => {
4967
+ const handleCellChange = useCallback10((rowId, colName, value) => {
4924
4968
  setData((prev) => prev.map(
4925
4969
  (row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
4926
4970
  ));
4927
- const isAdded = dirty.added.some((r) => r.id === rowId);
4928
- if (isAdded) {
4929
- setDirty((prev) => __spreadProps(__spreadValues({}, prev), {
4930
- added: prev.added.map(
4931
- (r) => r.id === rowId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value }) }) : r
4932
- )
4933
- }));
4934
- } else {
4935
- const origData = baseRecordsMap.get(rowId) || {};
4936
- const origValue = origData[colName];
4937
- setDirty((prev) => {
4938
- const currentMods = __spreadValues({}, prev.modified[rowId] || {});
4939
- if (isEqualValues(value, origValue)) {
4940
- delete currentMods[colName];
4941
- } else {
4942
- currentMods[colName] = value;
4943
- }
4944
- const nextModified = __spreadValues({}, prev.modified);
4945
- if (Object.keys(currentMods).length === 0) {
4946
- delete nextModified[rowId];
4947
- } else {
4948
- nextModified[rowId] = currentMods;
4949
- }
4971
+ setDirty((prev) => {
4972
+ const isAdded = prev.added.some((r) => r.id === rowId);
4973
+ if (isAdded) {
4950
4974
  return __spreadProps(__spreadValues({}, prev), {
4951
- modified: nextModified
4975
+ added: prev.added.map(
4976
+ (r) => r.id === rowId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value }) }) : r
4977
+ )
4952
4978
  });
4979
+ }
4980
+ const origData = baseRecordsMap.get(rowId) || {};
4981
+ const origValue = origData[colName];
4982
+ const currentMods = __spreadValues({}, prev.modified[rowId] || {});
4983
+ if (isEqualValues(value, origValue)) {
4984
+ delete currentMods[colName];
4985
+ } else {
4986
+ currentMods[colName] = value;
4987
+ }
4988
+ const nextModified = __spreadValues({}, prev.modified);
4989
+ if (Object.keys(currentMods).length === 0) {
4990
+ delete nextModified[rowId];
4991
+ } else {
4992
+ nextModified[rowId] = currentMods;
4993
+ }
4994
+ return __spreadProps(__spreadValues({}, prev), {
4995
+ modified: nextModified
4953
4996
  });
4954
- }
4955
- };
4997
+ });
4998
+ }, [baseRecordsMap]);
4956
4999
  const triggerSaveSuccess = useCallback10(() => {
4957
5000
  setIsSaveSuccess(true);
4958
5001
  setTimeout(() => {
@@ -4983,22 +5026,28 @@ function TableBlockClient({
4983
5026
  });
4984
5027
  }
4985
5028
  }, []);
4986
- const toggleSelectAll = (checked) => {
4987
- const nextSelected = checked ? new Set(filteredData.map((r) => r.id)) : /* @__PURE__ */ new Set();
4988
- setSelectedIds(nextSelected);
4989
- if (emitEvent) {
4990
- emitEvent("SELECTION_CHANGE", { selectedIds: Array.from(nextSelected), componentId });
4991
- }
4992
- };
4993
- const toggleSelectRow = (rowId, checked) => {
4994
- const newSelected = new Set(selectedIds);
4995
- if (checked) newSelected.add(rowId);
4996
- else newSelected.delete(rowId);
4997
- setSelectedIds(newSelected);
4998
- if (emitEvent) {
4999
- emitEvent("SELECTION_CHANGE", { selectedIds: Array.from(newSelected), componentId });
5000
- }
5001
- };
5029
+ const toggleSelectAll = useCallback10((checked) => {
5030
+ setSelectedIds(checked ? new Set(filteredData.map((r) => r.id)) : /* @__PURE__ */ new Set());
5031
+ }, [filteredData]);
5032
+ const toggleSelectRow = useCallback10((rowId, checked) => {
5033
+ setSelectedIds((prev) => {
5034
+ const next = new Set(prev);
5035
+ if (checked) next.add(rowId);
5036
+ else next.delete(rowId);
5037
+ return next;
5038
+ });
5039
+ }, []);
5040
+ const handleToggleExpand = useCallback10((rowId) => {
5041
+ setExpandedRowIds((prev) => {
5042
+ const next = new Set(prev);
5043
+ if (next.has(rowId)) next.delete(rowId);
5044
+ else next.add(rowId);
5045
+ return next;
5046
+ });
5047
+ }, []);
5048
+ const handleMarkForDeletion = useCallback10((fileId) => {
5049
+ setPendingDeletions((prev) => [...prev, fileId]);
5050
+ }, []);
5002
5051
  const handleDeleteSelected = () => {
5003
5052
  const idsToDelete = Array.from(selectedIds);
5004
5053
  if (idsToDelete.length === 0) return;
@@ -5077,9 +5126,6 @@ function TableBlockClient({
5077
5126
  setData(serverRecords.map((r) => __spreadProps(__spreadValues({}, r), { data: __spreadValues({}, r.data) })));
5078
5127
  setSelectedIds(/* @__PURE__ */ new Set());
5079
5128
  setPendingDeletions([]);
5080
- if (emitEvent) {
5081
- emitEvent("SELECTION_CHANGE", { selectedIds: [], componentId });
5082
- }
5083
5129
  };
5084
5130
  const handleSave = async () => {
5085
5131
  var _a, _b;
@@ -5247,26 +5293,13 @@ function TableBlockClient({
5247
5293
  }).filter(Boolean);
5248
5294
  }, [relationOptions]);
5249
5295
  const getUniqueRelationOptions = useCallback10((col) => {
5296
+ if (relationFilterOptions[col.name]) {
5297
+ return relationFilterOptions[col.name];
5298
+ }
5250
5299
  const seenIds = /* @__PURE__ */ new Set();
5251
5300
  const seenLabels = /* @__PURE__ */ new Set();
5252
5301
  const results = [];
5253
5302
  const options = relationOptions[col.name] || [];
5254
- options.forEach((opt) => {
5255
- const id = String(opt.id || opt._id || "");
5256
- if (!id) return;
5257
- let label = resolveRelationLabel(opt, col);
5258
- if (!label) {
5259
- const fallback = opt.label || opt.name || opt.title;
5260
- if (fallback && typeof fallback === "string" && !isRawObjectId(fallback)) {
5261
- label = fallback.trim();
5262
- }
5263
- }
5264
- if (label && label.trim() && !isRawObjectId(label) && !seenLabels.has(label.trim())) {
5265
- seenIds.add(id);
5266
- seenLabels.add(label.trim());
5267
- results.push({ id, label: label.trim() });
5268
- }
5269
- });
5270
5303
  data.forEach((row) => {
5271
5304
  if (!(row == null ? void 0 : row.data)) return;
5272
5305
  const ids = normalizeRelationValue(row.data[col.name]);
@@ -5289,8 +5322,7 @@ function TableBlockClient({
5289
5322
  });
5290
5323
  });
5291
5324
  return results.sort((a, b) => a.label.localeCompare(b.label));
5292
- }, [data, relationOptions]);
5293
- const filteredData = data;
5325
+ }, [data, relationOptions, relationFilterOptions]);
5294
5326
  const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
5295
5327
  const columnTotals = useMemo6(() => {
5296
5328
  const totals = {};
@@ -5743,9 +5775,7 @@ function TableBlockClient({
5743
5775
  setRelationTriggerRect(btn.getBoundingClientRect());
5744
5776
  }
5745
5777
  setActiveRelationCol(col.name);
5746
- if (!relationOptions[col.name] || relationOptions[col.name].length < 100) {
5747
- refetchRelation(col.name, { take: 1e3 });
5748
- }
5778
+ fetchRelationFilterOptions(col.name);
5749
5779
  }
5750
5780
  } else {
5751
5781
  setActiveSearchCol(col.name);
@@ -5778,106 +5808,37 @@ function TableBlockClient({
5778
5808
  var _a;
5779
5809
  return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
5780
5810
  });
5781
- return /* @__PURE__ */ jsxs11(React11.Fragment, { children: [
5782
- /* @__PURE__ */ jsxs11("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
5783
- /* @__PURE__ */ jsx11("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", style: { width: 72, minWidth: 72, maxWidth: 72 }, children: /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-center gap-1.5", children: [
5784
- /* @__PURE__ */ jsx11(
5785
- "input",
5786
- {
5787
- type: "checkbox",
5788
- checked: selectedIds.has(row.id),
5789
- onChange: (e) => toggleSelectRow(row.id, e.target.checked),
5790
- disabled: isLoading || isUpdatingActive,
5791
- className: "w-4 h-4 rounded border-slate-300 text-brand"
5792
- }
5793
- ),
5794
- hasSubTableCols && /* @__PURE__ */ jsx11(
5795
- "button",
5796
- {
5797
- type: "button",
5798
- onClick: () => setExpandedRowIds((prev) => {
5799
- const next = new Set(prev);
5800
- if (next.has(row.id)) next.delete(row.id);
5801
- else next.add(row.id);
5802
- return next;
5803
- }),
5804
- className: "w-5 h-5 rounded-full bg-slate-500 hover:bg-slate-600 text-white flex items-center justify-center transition-colors cursor-pointer shrink-0 shadow-sm",
5805
- title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
5806
- children: /* @__PURE__ */ jsx11("svg", { className: `w-3 h-3 transition-transform duration-150 ${isExpanded ? "rotate-90" : "rotate-180"}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "3", d: "M9 5l7 7-7 7" }) })
5807
- }
5808
- )
5809
- ] }) }),
5810
- filteredColumns.map((col) => {
5811
- var _a;
5812
- const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
5813
- const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
5814
- const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
5815
- const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
5816
- let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
5817
- if (value === void 0 && col.defaultValue !== void 0) {
5818
- value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
5819
- if (colType === "CURRENCY" || colType === "NUMBER") {
5820
- if (isNaN(value)) value = null;
5821
- }
5822
- }
5823
- if (value === void 0) value = null;
5824
- return /* @__PURE__ */ jsx11(
5825
- "td",
5826
- {
5827
- className: `border-b border-l border-slate-200 p-0 relative ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
5828
- style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
5829
- children: /* @__PURE__ */ jsx11(
5830
- InputComponent,
5831
- {
5832
- value,
5833
- column: col,
5834
- rowId: row.id,
5835
- onChange: (v) => handleCellChange(row.id, col.name, v),
5836
- context: {
5837
- tableName: (schema == null ? void 0 : schema.name) || (schema == null ? void 0 : schema.tableName) || (schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.id) || "Table",
5838
- tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
5839
- onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
5840
- relationOptions,
5841
- relationDictionaryRef,
5842
- refetchRelation,
5843
- executeAction,
5844
- emitEvent,
5845
- pageState,
5846
- componentId,
5847
- orgId,
5848
- updateQuietly: handleQuietCellChange,
5849
- triggerSaveSuccess,
5850
- rowData: row.data
5851
- }
5852
- }
5853
- )
5854
- },
5855
- col.name
5856
- );
5857
- }),
5858
- /* @__PURE__ */ jsx11("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
5859
- ] }),
5860
- isExpanded && /* @__PURE__ */ jsx11(
5861
- ExpandedSubTables,
5862
- {
5863
- rowId: row.id,
5864
- rowData: row.data,
5865
- subTableColumns,
5866
- filteredColumnsLength: filteredColumns.length,
5867
- handleCellChange,
5868
- context: {
5869
- executeAction,
5870
- orgId,
5871
- parentTableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
5872
- tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
5873
- rowData: row.data,
5874
- updateQuietly: handleQuietCellChange,
5875
- triggerSaveSuccess,
5876
- onUpdateColumnConfig: handleUpdateColumnConfig
5877
- }
5878
- }
5879
- )
5880
- ] }, row.id);
5811
+ return /* @__PURE__ */ jsx11(
5812
+ TableRow,
5813
+ {
5814
+ row,
5815
+ isSelected: selectedIds.has(row.id),
5816
+ isExpanded,
5817
+ filteredColumns,
5818
+ columnWidths,
5819
+ hasSubTableCols,
5820
+ subTableColumns,
5821
+ isLoading: isLoading || isFetching,
5822
+ isUpdatingActive,
5823
+ onToggleSelect: toggleSelectRow,
5824
+ onToggleExpand: handleToggleExpand,
5825
+ handleCellChange,
5826
+ handleQuietCellChange,
5827
+ handleUpdateColumnConfig,
5828
+ onMarkForDeletion: handleMarkForDeletion,
5829
+ triggerSaveSuccess,
5830
+ schema,
5831
+ orgId,
5832
+ componentId,
5833
+ pageState,
5834
+ relationOptions,
5835
+ relationDictionaryRef,
5836
+ refetchRelation,
5837
+ executeAction,
5838
+ emitEvent
5839
+ },
5840
+ row.id
5841
+ );
5881
5842
  }) }),
5882
5843
  showSummary && filteredData.length > 0 && /* @__PURE__ */ jsx11("tfoot", { className: "bg-slate-50 border-t-2 border-slate-300 sticky bottom-0 z-10 shadow-[0_-2px_4px_rgba(0,0,0,0.02)]", children: /* @__PURE__ */ jsxs11("tr", { children: [
5883
5844
  /* @__PURE__ */ jsx11("td", { className: "border-b border-l border-slate-200 p-1.5 text-center font-bold text-slate-600 text-xs", children: '\u05E1\u05D4"\u05DB' }),
@@ -5973,7 +5934,8 @@ function TableBlockClient({
5973
5934
  filterValue: currentSelected,
5974
5935
  onSelectionChange: (newSelected) => {
5975
5936
  handleApplyColumnFilter(activeRelationCol, newSelected);
5976
- }
5937
+ },
5938
+ isLoading: loadingFilterCol === activeRelationCol
5977
5939
  }
5978
5940
  );
5979
5941
  })()
@@ -6030,6 +5992,129 @@ function ExpandedSubTables({
6030
5992
  ) })
6031
5993
  ] }) });
6032
5994
  }
5995
+ var TableRow = React11.memo(function TableRow2({
5996
+ row,
5997
+ isSelected,
5998
+ isExpanded,
5999
+ filteredColumns,
6000
+ columnWidths,
6001
+ hasSubTableCols,
6002
+ subTableColumns,
6003
+ isLoading,
6004
+ isUpdatingActive,
6005
+ onToggleSelect,
6006
+ onToggleExpand,
6007
+ handleCellChange,
6008
+ handleQuietCellChange,
6009
+ handleUpdateColumnConfig,
6010
+ onMarkForDeletion,
6011
+ triggerSaveSuccess,
6012
+ schema,
6013
+ orgId,
6014
+ componentId,
6015
+ pageState,
6016
+ relationOptions,
6017
+ relationDictionaryRef,
6018
+ refetchRelation,
6019
+ executeAction,
6020
+ emitEvent
6021
+ }) {
6022
+ return /* @__PURE__ */ jsxs11(React11.Fragment, { children: [
6023
+ /* @__PURE__ */ jsxs11("tr", { className: `hover:bg-blue-50/30 transition-colors group ${isSelected ? "bg-blue-50/40" : ""}`, children: [
6024
+ /* @__PURE__ */ jsx11("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", style: { width: 72, minWidth: 72, maxWidth: 72 }, children: /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-center gap-1.5", children: [
6025
+ /* @__PURE__ */ jsx11(
6026
+ "input",
6027
+ {
6028
+ type: "checkbox",
6029
+ checked: isSelected,
6030
+ onChange: (e) => onToggleSelect(row.id, e.target.checked),
6031
+ disabled: isLoading || isUpdatingActive,
6032
+ className: "w-4 h-4 rounded border-slate-300 text-brand"
6033
+ }
6034
+ ),
6035
+ hasSubTableCols && /* @__PURE__ */ jsx11(
6036
+ "button",
6037
+ {
6038
+ type: "button",
6039
+ onClick: () => onToggleExpand(row.id),
6040
+ className: "w-5 h-5 rounded-full bg-slate-500 hover:bg-slate-600 text-white flex items-center justify-center transition-colors cursor-pointer shrink-0 shadow-sm",
6041
+ title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
6042
+ children: /* @__PURE__ */ jsx11("svg", { className: `w-3 h-3 transition-transform duration-150 ${isExpanded ? "rotate-90" : "rotate-180"}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "3", d: "M9 5l7 7-7 7" }) })
6043
+ }
6044
+ )
6045
+ ] }) }),
6046
+ filteredColumns.map((col) => {
6047
+ var _a;
6048
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
6049
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
6050
+ const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
6051
+ const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
6052
+ let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
6053
+ if (value === void 0 && col.defaultValue !== void 0) {
6054
+ value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
6055
+ if (colType === "CURRENCY" || colType === "NUMBER") {
6056
+ if (isNaN(value)) value = null;
6057
+ }
6058
+ }
6059
+ if (value === void 0) value = null;
6060
+ return /* @__PURE__ */ jsx11(
6061
+ "td",
6062
+ {
6063
+ className: `border-b border-l border-slate-200 p-0 relative ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
6064
+ style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
6065
+ children: /* @__PURE__ */ jsx11(
6066
+ InputComponent,
6067
+ {
6068
+ value,
6069
+ column: col,
6070
+ rowId: row.id,
6071
+ onChange: (v) => handleCellChange(row.id, col.name, v),
6072
+ context: {
6073
+ tableName: (schema == null ? void 0 : schema.name) || (schema == null ? void 0 : schema.tableName) || (schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.id) || "Table",
6074
+ tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
6075
+ onMarkForDeletion,
6076
+ relationOptions,
6077
+ relationDictionaryRef,
6078
+ refetchRelation,
6079
+ executeAction,
6080
+ emitEvent,
6081
+ pageState,
6082
+ componentId,
6083
+ orgId,
6084
+ updateQuietly: handleQuietCellChange,
6085
+ triggerSaveSuccess,
6086
+ rowData: row.data
6087
+ }
6088
+ }
6089
+ )
6090
+ },
6091
+ col.name
6092
+ );
6093
+ }),
6094
+ /* @__PURE__ */ jsx11("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
6095
+ ] }),
6096
+ isExpanded && /* @__PURE__ */ jsx11(
6097
+ ExpandedSubTables,
6098
+ {
6099
+ rowId: row.id,
6100
+ rowData: row.data,
6101
+ subTableColumns,
6102
+ filteredColumnsLength: filteredColumns.length,
6103
+ handleCellChange,
6104
+ context: {
6105
+ executeAction,
6106
+ orgId,
6107
+ parentTableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
6108
+ tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
6109
+ rowData: row.data,
6110
+ updateQuietly: handleQuietCellChange,
6111
+ triggerSaveSuccess,
6112
+ onUpdateColumnConfig: handleUpdateColumnConfig
6113
+ }
6114
+ }
6115
+ )
6116
+ ] });
6117
+ });
6033
6118
 
6034
6119
  // src/components/TableBlock/TableBlock.tsx
6035
6120
  import { jsx as jsx12 } from "react/jsx-runtime";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@universe-platform/ui",
3
- "version": "0.1.0-beta.11",
3
+ "version": "0.1.0-beta.12",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",