@universe-platform/ui 0.1.0-beta.6 → 0.1.0-beta.7

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
@@ -77,7 +77,7 @@ function cn(...inputs) {
77
77
  }
78
78
 
79
79
  // src/components/TableBlock/TableBlockClient.tsx
80
- var import_react6 = require("react");
80
+ var import_react7 = __toESM(require("react"));
81
81
 
82
82
  // src/hooks/useToast.ts
83
83
  var import_react2 = require("react");
@@ -280,12 +280,36 @@ function useToast() {
280
280
  var import_react5 = __toESM(require("react"));
281
281
 
282
282
  // src/components/TableBlock/fields/DrivePickerCell.tsx
283
- var import_react3 = require("react");
283
+ var import_react3 = __toESM(require("react"));
284
284
  var import_lucide_react2 = require("lucide-react");
285
285
  var import_jsx_runtime2 = require("react/jsx-runtime");
286
- function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, context }) {
286
+ function DrivePickerCell({ value, onChange, tableName, column, rowId, onMarkForDeletion, context }) {
287
287
  const [isOpening, setIsOpening] = (0, import_react3.useState)(false);
288
288
  const { showError } = useToast();
289
+ const cellContextId = import_react3.default.useMemo(() => {
290
+ const colName = (column == null ? void 0 : column.name) || "col";
291
+ const rId = rowId || "row";
292
+ return `${rId}-${colName}`;
293
+ }, [rowId, column == null ? void 0 : column.name]);
294
+ const fileList = import_react3.default.useMemo(() => {
295
+ if (!value) return [];
296
+ if (Array.isArray(value)) return value;
297
+ if (typeof value === "object" && (value.fileId || value.fileUrl || value.url)) {
298
+ return [value];
299
+ }
300
+ return [];
301
+ }, [value]);
302
+ (0, import_react3.useEffect)(() => {
303
+ const handleMessage = (event) => {
304
+ var _a, _b, _c;
305
+ if (((_a = event.data) == null ? void 0 : _a.type) === "DRIVE_UPLOAD_SUCCESS" && ((_b = event.data) == null ? void 0 : _b.payload) && ((_c = event.data) == null ? void 0 : _c.cellContextId) === cellContextId) {
306
+ const incoming = Array.isArray(event.data.payload) ? event.data.payload : [event.data.payload];
307
+ onChange([...fileList, ...incoming]);
308
+ }
309
+ };
310
+ window.addEventListener("message", handleMessage);
311
+ return () => window.removeEventListener("message", handleMessage);
312
+ }, [fileList, onChange, cellContextId]);
289
313
  const openUploadPopup = async () => {
290
314
  if (isOpening) return;
291
315
  setIsOpening(true);
@@ -314,34 +338,35 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
314
338
  } catch (e) {
315
339
  }
316
340
  }
317
- const actionResult = await context.executeAction("UPLOAD_DRIVE_FILE", { tableName });
341
+ const actionResult = await context.executeAction("UPLOAD_DRIVE_FILE", { tableName, cellContextId });
318
342
  const folderId = actionResult == null ? void 0 : actionResult.folderId;
319
- const pickerUrl = (actionResult == null ? void 0 : actionResult.pickerUrl) || (folderId ? `/embed/picker?folderId=${encodeURIComponent(folderId)}` : `/embed/picker`);
343
+ let pickerUrl = (actionResult == null ? void 0 : actionResult.pickerUrl) || (folderId ? `/embed/picker?folderId=${encodeURIComponent(folderId)}` : `/embed/picker`);
344
+ if (!pickerUrl.includes("cellContextId=")) {
345
+ const separator = pickerUrl.includes("?") ? "&" : "?";
346
+ pickerUrl = `${pickerUrl}${separator}cellContextId=${encodeURIComponent(cellContextId)}`;
347
+ }
320
348
  if (popup) {
321
349
  popup.location.href = pickerUrl;
322
350
  }
323
- const newFile = await new Promise((resolve) => {
351
+ await new Promise((resolve) => {
324
352
  let timer = null;
325
- const handleMessage = (event) => {
353
+ const handlePopupMessage = (event) => {
326
354
  var _a, _b;
327
- if (((_a = event.data) == null ? void 0 : _a.type) === "DRIVE_UPLOAD_SUCCESS" && ((_b = event.data) == null ? void 0 : _b.payload)) {
328
- window.removeEventListener("message", handleMessage);
355
+ if (((_a = event.data) == null ? void 0 : _a.type) === "DRIVE_UPLOAD_SUCCESS" && ((_b = event.data) == null ? void 0 : _b.cellContextId) === cellContextId) {
356
+ window.removeEventListener("message", handlePopupMessage);
329
357
  if (timer) clearInterval(timer);
330
- resolve(event.data.payload);
358
+ resolve();
331
359
  }
332
360
  };
333
361
  timer = setInterval(() => {
334
362
  if (!popup || popup.closed) {
335
363
  if (timer) clearInterval(timer);
336
- window.removeEventListener("message", handleMessage);
337
- resolve(null);
364
+ window.removeEventListener("message", handlePopupMessage);
365
+ resolve();
338
366
  }
339
367
  }, 800);
340
- window.addEventListener("message", handleMessage);
368
+ window.addEventListener("message", handlePopupMessage);
341
369
  });
342
- if (newFile) {
343
- onChange(newFile);
344
- }
345
370
  }
346
371
  } catch (error) {
347
372
  console.error("[DrivePickerCell] Error uploading file:", error);
@@ -351,40 +376,15 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
351
376
  setIsOpening(false);
352
377
  }
353
378
  };
354
- if (value == null ? void 0 : value.fileUrl) {
355
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center w-full h-8 px-2 gap-1", children: [
356
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
357
- "a",
358
- {
359
- href: value.fileUrl,
360
- target: "_blank",
361
- rel: "noopener noreferrer",
362
- className: "inline-flex items-center gap-1.5 max-w-[calc(100%-24px)] px-2 py-1 rounded-md text-xs font-medium text-blue-700 bg-blue-50 hover:bg-blue-100 transition-colors truncate",
363
- title: value.fileName || "Open file",
364
- children: [
365
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.FileText, { className: "w-3.5 h-3.5 shrink-0" }),
366
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "truncate", children: value.fileName || "Unnamed file" })
367
- ]
368
- }
369
- ),
370
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
371
- "button",
372
- {
373
- type: "button",
374
- onClick: () => {
375
- if ((value == null ? void 0 : value.fileId) && onMarkForDeletion) {
376
- onMarkForDeletion(value.fileId);
377
- }
378
- onChange(null);
379
- },
380
- className: "shrink-0 p-0.5 rounded hover:bg-rose-100 text-slate-400 hover:text-rose-500 transition-colors",
381
- title: "Remove file",
382
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.X, { className: "w-3.5 h-3.5" })
383
- }
384
- )
385
- ] });
386
- }
387
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex items-center w-full h-8 px-2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
379
+ const handleRemoveFile = (indexToRemove) => {
380
+ const fileToRemove = fileList[indexToRemove];
381
+ if ((fileToRemove == null ? void 0 : fileToRemove.fileId) && onMarkForDeletion) {
382
+ onMarkForDeletion(fileToRemove.fileId);
383
+ }
384
+ const updated = fileList.filter((_, idx) => idx !== indexToRemove);
385
+ onChange(updated);
386
+ };
387
+ const renderUploadButton = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex items-center w-full h-8 px-2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
388
388
  "button",
389
389
  {
390
390
  type: "button",
@@ -397,6 +397,38 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
397
397
  ]
398
398
  }
399
399
  ) });
400
+ if (fileList.length > 0) {
401
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col w-full py-1 gap-1", children: [
402
+ fileList.map((file, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center w-full h-8 px-2 gap-1", children: [
403
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
404
+ "a",
405
+ {
406
+ href: file.fileUrl || file.url,
407
+ target: "_blank",
408
+ rel: "noopener noreferrer",
409
+ className: "inline-flex items-center gap-1.5 max-w-[calc(100%-24px)] px-2 py-1 rounded-md text-xs font-medium text-blue-700 bg-blue-50 hover:bg-blue-100 transition-colors truncate",
410
+ title: file.fileName || "Open file",
411
+ children: [
412
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.FileText, { className: "w-3.5 h-3.5 shrink-0" }),
413
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "truncate", children: file.fileName || "Unnamed file" })
414
+ ]
415
+ }
416
+ ),
417
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
418
+ "button",
419
+ {
420
+ type: "button",
421
+ onClick: () => handleRemoveFile(idx),
422
+ className: "shrink-0 p-0.5 rounded hover:bg-rose-100 text-slate-400 hover:text-rose-500 transition-colors",
423
+ title: "Remove file",
424
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.X, { className: "w-3.5 h-3.5" })
425
+ }
426
+ )
427
+ ] }, file.fileId || idx)),
428
+ renderUploadButton()
429
+ ] });
430
+ }
431
+ return renderUploadButton();
400
432
  }
401
433
 
402
434
  // src/components/TableBlock/fields/DatePickerCell.tsx
@@ -831,11 +863,13 @@ var FORM_INPUTS = {
831
863
  className: "w-4 h-4 rounded border-slate-300 text-brand"
832
864
  }
833
865
  ) }),
834
- GOOGLE_DRIVE_FILE: ({ value, onChange, context }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
866
+ GOOGLE_DRIVE_FILE: ({ value, onChange, column, rowId, context }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
835
867
  DrivePickerCell,
836
868
  {
837
- value: value || null,
869
+ value: value || [],
838
870
  onChange,
871
+ column,
872
+ rowId,
839
873
  tableName: context == null ? void 0 : context.tableName,
840
874
  onMarkForDeletion: context == null ? void 0 : context.onMarkForDeletion,
841
875
  context
@@ -893,6 +927,228 @@ var FORM_INPUTS = {
893
927
  }
894
928
  }
895
929
  ),
930
+ PHONE: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
931
+ "input",
932
+ {
933
+ type: "tel",
934
+ className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
935
+ value: value !== void 0 && value !== null ? String(value) : "",
936
+ onChange: (e) => onChange(e.target.value),
937
+ dir: "ltr"
938
+ }
939
+ ),
940
+ GOOGLE_CONTACT: ({ value, column, rowId, onChange, context }) => {
941
+ const [isSyncing, setIsSyncing] = import_react5.default.useState(false);
942
+ const { addToast } = useToast();
943
+ const googleClientIdRef = import_react5.default.useRef(null);
944
+ const ensureGisScript = import_react5.default.useCallback(() => {
945
+ return new Promise((resolve, reject) => {
946
+ var _a, _b, _c;
947
+ if ((_c = (_b = (_a = window.google) == null ? void 0 : _a.accounts) == null ? void 0 : _b.oauth2) == null ? void 0 : _c.initTokenClient) {
948
+ resolve();
949
+ return;
950
+ }
951
+ if (document.querySelector('script[src*="accounts.google.com/gsi/client"]')) {
952
+ const waitForLoad = setInterval(() => {
953
+ var _a2, _b2, _c2;
954
+ if ((_c2 = (_b2 = (_a2 = window.google) == null ? void 0 : _a2.accounts) == null ? void 0 : _b2.oauth2) == null ? void 0 : _c2.initTokenClient) {
955
+ clearInterval(waitForLoad);
956
+ resolve();
957
+ }
958
+ }, 100);
959
+ setTimeout(() => {
960
+ clearInterval(waitForLoad);
961
+ reject(new Error("GIS script load timeout"));
962
+ }, 1e4);
963
+ return;
964
+ }
965
+ const script = document.createElement("script");
966
+ script.src = "https://accounts.google.com/gsi/client";
967
+ script.async = true;
968
+ script.onload = () => resolve();
969
+ script.onerror = () => reject(new Error("Failed to load Google Identity Services"));
970
+ document.head.appendChild(script);
971
+ });
972
+ }, []);
973
+ const requestGisToken = import_react5.default.useCallback(async (hint) => {
974
+ await ensureGisScript();
975
+ if (!googleClientIdRef.current && (context == null ? void 0 : context.executeAction)) {
976
+ try {
977
+ const config = await context.executeAction("GET_GOOGLE_CONFIG", {});
978
+ googleClientIdRef.current = (config == null ? void 0 : config.clientId) || "";
979
+ } catch (e) {
980
+ throw new Error("Failed to fetch Google configuration");
981
+ }
982
+ }
983
+ const clientId = googleClientIdRef.current;
984
+ if (!clientId) {
985
+ throw new Error("Google Client ID is not configured");
986
+ }
987
+ const accessToken = await new Promise((resolve, reject) => {
988
+ const tokenClient = window.google.accounts.oauth2.initTokenClient({
989
+ client_id: clientId,
990
+ scope: "https://www.googleapis.com/auth/contacts https://www.googleapis.com/auth/userinfo.email",
991
+ prompt: hint ? "" : "select_account",
992
+ hint: hint || void 0,
993
+ callback: (tokenResponse) => {
994
+ if (tokenResponse == null ? void 0 : tokenResponse.access_token) {
995
+ resolve(tokenResponse.access_token);
996
+ } else {
997
+ reject(new Error("Google authorization was cancelled or failed"));
998
+ }
999
+ },
1000
+ error_callback: (err) => {
1001
+ reject(new Error((err == null ? void 0 : err.message) || "Google authorization error"));
1002
+ }
1003
+ });
1004
+ tokenClient.requestAccessToken({ hint: hint || void 0 });
1005
+ });
1006
+ let email = "";
1007
+ try {
1008
+ const res = await fetch("https://www.googleapis.com/oauth2/v3/userinfo", {
1009
+ headers: { Authorization: `Bearer ${accessToken}` }
1010
+ });
1011
+ if (res.ok) {
1012
+ const info = await res.json();
1013
+ email = info.email || "";
1014
+ }
1015
+ } catch (e) {
1016
+ }
1017
+ return { accessToken, email };
1018
+ }, [ensureGisScript, context]);
1019
+ const handleSync = async () => {
1020
+ var _a, _b, _c;
1021
+ if (!(context == null ? void 0 : context.executeAction)) return;
1022
+ setIsSyncing(true);
1023
+ try {
1024
+ const mapping = column.contactMapping || {};
1025
+ const rowData = context.rowData || {};
1026
+ let hasPhone = false;
1027
+ if (mapping.phoneCol && rowData[mapping.phoneCol]) hasPhone = true;
1028
+ let hasName = false;
1029
+ if (mapping.nameParts && Array.isArray(mapping.nameParts)) {
1030
+ for (const part of mapping.nameParts) {
1031
+ if (part.type === "LOCAL" && rowData[part.columnId]) hasName = true;
1032
+ if (part.type === "PARENT" && ((_a = context.parentRecord) == null ? void 0 : _a.tableId) === part.parentTableId && ((_c = (_b = context.parentRecord) == null ? void 0 : _b.data) == null ? void 0 : _c[part.columnId])) hasName = true;
1033
+ }
1034
+ }
1035
+ if (!hasPhone) {
1036
+ addToast({ type: "warning", message: "\u05E0\u05D0 \u05DC\u05DE\u05DC\u05D0 \u05DE\u05E1\u05E4\u05E8 \u05D8\u05DC\u05E4\u05D5\u05DF \u05DB\u05D3\u05D9 \u05DC\u05E1\u05E0\u05DB\u05E8\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05DC\u05D2\u05D5\u05D2\u05DC" });
1037
+ setIsSyncing(false);
1038
+ return;
1039
+ }
1040
+ if (!hasName) {
1041
+ addToast({ type: "warning", message: "\u05E0\u05D0 \u05DC\u05DE\u05DC\u05D0 \u05E9\u05DD \u05DB\u05D3\u05D9 \u05DC\u05E1\u05E0\u05DB\u05E8\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05DC\u05D2\u05D5\u05D2\u05DC" });
1042
+ setIsSyncing(false);
1043
+ return;
1044
+ }
1045
+ let accessToken;
1046
+ let userEmail = "";
1047
+ try {
1048
+ const gisResult = await requestGisToken();
1049
+ accessToken = gisResult.accessToken;
1050
+ userEmail = gisResult.email;
1051
+ } catch (gisError) {
1052
+ addToast({ type: "warning", message: gisError.message || "\u05D4\u05D4\u05E8\u05E9\u05D0\u05D4 \u05DC\u05D2\u05D5\u05D2\u05DC \u05E0\u05DB\u05E9\u05DC\u05D4" });
1053
+ setIsSyncing(false);
1054
+ return;
1055
+ }
1056
+ const payload = {
1057
+ nameParts: mapping.nameParts || [],
1058
+ phoneCol: mapping.phoneCol,
1059
+ emailCol: mapping.emailCol,
1060
+ localRowData: rowData,
1061
+ parentRecord: context.parentRecord,
1062
+ accessToken,
1063
+ userEmail
1064
+ };
1065
+ const res = await context.executeAction("SYNC_GOOGLE_CONTACT", payload);
1066
+ if (res && res.synced) {
1067
+ if (context.updateQuietly) {
1068
+ context.updateQuietly(rowId, column.name, res);
1069
+ } else {
1070
+ onChange(res);
1071
+ }
1072
+ if (context.tableId && !rowId.startsWith("temp_")) {
1073
+ await context.executeAction("UPDATE_RECORD", {
1074
+ tableId: context.tableId,
1075
+ recordId: rowId,
1076
+ data: { [column.name]: res }
1077
+ });
1078
+ }
1079
+ }
1080
+ } catch (error) {
1081
+ console.error("Failed to sync contact:", error);
1082
+ addToast({ type: "warning", message: "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E1\u05E0\u05DB\u05E8\u05D5\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8: " + error.message });
1083
+ } finally {
1084
+ setIsSyncing(false);
1085
+ }
1086
+ };
1087
+ const handleUnlink = async () => {
1088
+ let accessToken;
1089
+ try {
1090
+ let emailHint = value == null ? void 0 : value.userEmail;
1091
+ if (!emailHint && (value == null ? void 0 : value.url)) {
1092
+ try {
1093
+ const parsed = new URL(value.url);
1094
+ emailHint = parsed.searchParams.get("authuser") || void 0;
1095
+ } catch (e) {
1096
+ }
1097
+ }
1098
+ const auth = await requestGisToken(emailHint);
1099
+ accessToken = auth.accessToken;
1100
+ } catch (err) {
1101
+ console.warn("[handleUnlink] Could not obtain token via GIS, falling back to server default token:", err);
1102
+ }
1103
+ if ((value == null ? void 0 : value.resourceName) && (context == null ? void 0 : context.executeAction)) {
1104
+ await context.executeAction("DELETE_GOOGLE_CONTACT", {
1105
+ resourceName: value.resourceName,
1106
+ accessToken
1107
+ });
1108
+ }
1109
+ if (context == null ? void 0 : context.updateQuietly) {
1110
+ context.updateQuietly(rowId, column.name, null);
1111
+ } else {
1112
+ onChange(null);
1113
+ }
1114
+ if ((context == null ? void 0 : context.tableId) && (context == null ? void 0 : context.executeAction) && !rowId.startsWith("temp_")) {
1115
+ await context.executeAction("UPDATE_RECORD", {
1116
+ tableId: context.tableId,
1117
+ recordId: rowId,
1118
+ data: { [column.name]: null }
1119
+ });
1120
+ }
1121
+ };
1122
+ if (value && value.synced && value.url) {
1123
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2 h-8 px-2 group", children: [
1124
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { href: value.url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline flex-1 truncate text-sm", children: "\u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05D2\u05D5\u05D2\u05DC" }),
1125
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1126
+ "button",
1127
+ {
1128
+ onClick: handleUnlink,
1129
+ className: "text-slate-400 hover:text-rose-500 opacity-0 group-hover:opacity-100 transition-opacity p-1",
1130
+ title: "\u05D1\u05D8\u05DC \u05E1\u05E0\u05DB\u05E8\u05D5\u05DF",
1131
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
1132
+ }
1133
+ )
1134
+ ] });
1135
+ }
1136
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex items-center h-8 px-2", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1137
+ "button",
1138
+ {
1139
+ onClick: handleSync,
1140
+ disabled: isSyncing,
1141
+ className: "flex items-center gap-1.5 px-3 py-1 bg-blue-50 text-blue-600 hover:bg-blue-100 border border-blue-200 rounded-md text-xs font-medium transition-colors disabled:opacity-50",
1142
+ children: [
1143
+ isSyncing ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "w-3.5 h-3.5 animate-spin", viewBox: "0 0 24 24", fill: "none", children: [
1144
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
1145
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
1146
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 4v16m8-8H4" }) }),
1147
+ "\u05E1\u05E0\u05DB\u05E8\u05DF \u05DC\u05D2\u05D5\u05D2\u05DC"
1148
+ ]
1149
+ }
1150
+ ) });
1151
+ },
896
1152
  DEFAULT: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
897
1153
  "input",
898
1154
  {
@@ -901,12 +1157,459 @@ var FORM_INPUTS = {
901
1157
  value: value !== void 0 && value !== null ? String(value) : "",
902
1158
  onChange: (e) => onChange(e.target.value)
903
1159
  }
904
- )
1160
+ ),
1161
+ SUB_TABLE: ({ value, column }) => {
1162
+ if (!Array.isArray(value)) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
1163
+ const selected = value.filter((e) => e == null ? void 0 : e.isSelected);
1164
+ if (selected.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
1165
+ const displayFields = column.subTableDisplayFields || [];
1166
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "px-1.5 py-1 flex flex-wrap items-center gap-1 h-full", children: selected.map((entry, idx) => {
1167
+ var _a;
1168
+ let label = "";
1169
+ if (entry._resolvedData && displayFields.length > 0) {
1170
+ label = displayFields.map((f) => String(entry._resolvedData[f] || "")).filter(Boolean).join(" ");
1171
+ }
1172
+ if (!label) label = ((_a = entry.recordId) == null ? void 0 : _a.slice(-6)) || "...";
1173
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1174
+ "span",
1175
+ {
1176
+ className: "inline-flex items-center px-1.5 py-0.5 bg-amber-50 text-amber-800 border border-amber-200 rounded-full text-xs font-medium max-w-[140px] truncate",
1177
+ title: label,
1178
+ children: label
1179
+ },
1180
+ entry.recordId || idx
1181
+ );
1182
+ }) });
1183
+ }
905
1184
  };
906
1185
 
1186
+ // src/components/TableBlock/fields/SubTableViewer.tsx
1187
+ var import_react6 = require("react");
1188
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1189
+ function SubTableViewer({ rowId, column, value, onChange, context }) {
1190
+ var _a;
1191
+ const { addToast } = useToast();
1192
+ const entries = Array.isArray(value) ? value : [];
1193
+ const [linkedRecords, setLinkedRecords] = (0, import_react6.useState)([]);
1194
+ const [targetSchema, setTargetSchema] = (0, import_react6.useState)(null);
1195
+ const [isLoading, setIsLoading] = (0, import_react6.useState)(true);
1196
+ const [isSearchOpen, setIsSearchOpen] = (0, import_react6.useState)(false);
1197
+ const [searchQuery, setSearchQuery] = (0, import_react6.useState)("");
1198
+ const [searchResults, setSearchResults] = (0, import_react6.useState)([]);
1199
+ const [isSearching, setIsSearching] = (0, import_react6.useState)(false);
1200
+ const [isCreating, setIsCreating] = (0, import_react6.useState)(false);
1201
+ const [newRecordData, setNewRecordData] = (0, import_react6.useState)({});
1202
+ const searchRef = (0, import_react6.useRef)(null);
1203
+ const searchTimerRef = (0, import_react6.useRef)(null);
1204
+ const executeAction = context == null ? void 0 : context.executeAction;
1205
+ const referencedTableId = column.referencedTableId;
1206
+ const fetchedIdsRef = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
1207
+ (0, import_react6.useEffect)(() => {
1208
+ if (!referencedTableId || !executeAction) {
1209
+ setIsLoading(false);
1210
+ return;
1211
+ }
1212
+ const recordIdsToFetch = entries.map((e) => e.recordId).filter((id) => !fetchedIdsRef.current.has(id));
1213
+ if (recordIdsToFetch.length === 0 && targetSchema) return;
1214
+ if (recordIdsToFetch.length > 0) {
1215
+ recordIdsToFetch.forEach((id) => fetchedIdsRef.current.add(id));
1216
+ }
1217
+ setIsLoading(true);
1218
+ executeAction("FETCH_SUB_TABLE_RECORDS", { referencedTableId, recordIds: recordIdsToFetch }).then((res) => {
1219
+ const payload = (res == null ? void 0 : res.data) || res;
1220
+ if (payload == null ? void 0 : payload.records) {
1221
+ setLinkedRecords((prev) => {
1222
+ const map = new Map(prev.map((r) => [r.id, r]));
1223
+ payload.records.forEach((r) => map.set(r.id, r));
1224
+ return Array.from(map.values());
1225
+ });
1226
+ }
1227
+ if (payload == null ? void 0 : payload.schema) {
1228
+ setTargetSchema(payload.schema);
1229
+ }
1230
+ }).catch(() => {
1231
+ recordIdsToFetch.forEach((id) => fetchedIdsRef.current.delete(id));
1232
+ }).finally(() => setIsLoading(false));
1233
+ }, [referencedTableId, executeAction, entries, targetSchema]);
1234
+ (0, import_react6.useEffect)(() => {
1235
+ const handleClick = (e) => {
1236
+ if (searchRef.current && !searchRef.current.contains(e.target)) {
1237
+ setIsSearchOpen(false);
1238
+ }
1239
+ };
1240
+ if (isSearchOpen) document.addEventListener("mousedown", handleClick);
1241
+ return () => document.removeEventListener("mousedown", handleClick);
1242
+ }, [isSearchOpen]);
1243
+ const handleSearch = (0, import_react6.useCallback)((query) => {
1244
+ setSearchQuery(query);
1245
+ if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
1246
+ if (!query.trim()) {
1247
+ setSearchResults([]);
1248
+ return;
1249
+ }
1250
+ searchTimerRef.current = setTimeout(async () => {
1251
+ if (!executeAction || !referencedTableId) return;
1252
+ setIsSearching(true);
1253
+ try {
1254
+ const excludeIds = entries.map((e) => e.recordId);
1255
+ const res = await executeAction("SEARCH_SUB_TABLE_RECORDS", {
1256
+ referencedTableId,
1257
+ query: query.trim(),
1258
+ excludeIds,
1259
+ limit: 15
1260
+ });
1261
+ setSearchResults(Array.isArray(res) ? res : []);
1262
+ } catch (e) {
1263
+ setSearchResults([]);
1264
+ } finally {
1265
+ setIsSearching(false);
1266
+ }
1267
+ }, 300);
1268
+ }, [executeAction, referencedTableId, entries]);
1269
+ const targetColumns = ((targetSchema == null ? void 0 : targetSchema.columns) || []).filter(
1270
+ (c) => {
1271
+ if (c.name === "_id" || c.type === "SUB_TABLE") return false;
1272
+ return true;
1273
+ }
1274
+ );
1275
+ const [relationOptions, setRelationOptions] = (0, import_react6.useState)({});
1276
+ (0, import_react6.useEffect)(() => {
1277
+ if (!executeAction || targetColumns.length === 0) return;
1278
+ const relationCols = targetColumns.filter((c) => {
1279
+ var _a2;
1280
+ return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION" && c.referencedTableId;
1281
+ });
1282
+ relationCols.forEach(async (col) => {
1283
+ try {
1284
+ const options = await executeAction("FETCH_RELATION", {
1285
+ referencedTableId: col.referencedTableId,
1286
+ displayField: col.displayField
1287
+ });
1288
+ if (options && Array.isArray(options)) {
1289
+ setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
1290
+ }
1291
+ } catch (err) {
1292
+ console.warn(`[SubTableViewer] Could not fetch relation options for column ${col.name}:`, err);
1293
+ }
1294
+ });
1295
+ }, [executeAction, targetColumns]);
1296
+ const refetchRelation = (0, import_react6.useCallback)(async (colName) => {
1297
+ var _a2;
1298
+ const col = targetColumns.find((c) => c.name === colName);
1299
+ if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !col.referencedTableId || !executeAction) return;
1300
+ try {
1301
+ const options = await executeAction("FETCH_RELATION", { referencedTableId: col.referencedTableId, displayField: col.displayField });
1302
+ if (options && Array.isArray(options)) {
1303
+ setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
1304
+ }
1305
+ } catch (err) {
1306
+ console.warn(`[SubTableViewer] Could not refetch relation options for column ${col.name}:`, err);
1307
+ }
1308
+ }, [targetColumns, executeAction]);
1309
+ const updateParentLinkage = async (updated) => {
1310
+ const isNewRow = rowId.startsWith("temp_");
1311
+ if (context == null ? void 0 : context.updateQuietly) {
1312
+ context.updateQuietly(rowId, column.name, updated);
1313
+ } else {
1314
+ onChange(updated);
1315
+ }
1316
+ if (executeAction && (context == null ? void 0 : context.parentTableId) && !isNewRow) {
1317
+ try {
1318
+ const payloadToSave = updated.map(({ recordId, isSelected }) => ({ recordId, isSelected }));
1319
+ await executeAction("UPDATE_RECORD", {
1320
+ tableId: context.parentTableId,
1321
+ recordId: rowId,
1322
+ data: { [column.name]: payloadToSave }
1323
+ });
1324
+ if (context == null ? void 0 : context.triggerSaveSuccess) {
1325
+ context.triggerSaveSuccess();
1326
+ }
1327
+ } catch (err) {
1328
+ console.error("Failed to auto-save parent linkage", err);
1329
+ }
1330
+ }
1331
+ };
1332
+ const handleLinkRecord = (record) => {
1333
+ fetchedIdsRef.current.add(record.id);
1334
+ const newEntry = { recordId: record.id, isSelected: true, _resolvedData: record.data };
1335
+ const updated = [...entries, newEntry];
1336
+ updateParentLinkage(updated);
1337
+ setLinkedRecords((prev) => {
1338
+ const exists = prev.find((r) => r.id === record.id);
1339
+ if (exists) return prev;
1340
+ return [...prev, record];
1341
+ });
1342
+ setSearchQuery("");
1343
+ setSearchResults([]);
1344
+ setIsSearchOpen(false);
1345
+ };
1346
+ const handleUnlinkRecord = (recordId) => {
1347
+ const updated = entries.filter((e) => e.recordId !== recordId);
1348
+ updateParentLinkage(updated);
1349
+ setLinkedRecords((prev) => prev.filter((r) => r.id !== recordId));
1350
+ };
1351
+ const handleToggleSelected = (recordId) => {
1352
+ const record = linkedRecords.find((r) => r.id === recordId);
1353
+ const updated = entries.map(
1354
+ (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { isSelected: !e.isSelected, _resolvedData: (record == null ? void 0 : record.data) || e._resolvedData }) : e
1355
+ );
1356
+ updateParentLinkage(updated);
1357
+ };
1358
+ const handleRecordCellChange = async (recordId, colName, value2) => {
1359
+ const updatedRecords = linkedRecords.map(
1360
+ (r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
1361
+ );
1362
+ setLinkedRecords(updatedRecords);
1363
+ const targetRecord = updatedRecords.find((r) => r.id === recordId);
1364
+ const updatedEntries = entries.map(
1365
+ (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
1366
+ );
1367
+ if (context == null ? void 0 : context.updateQuietly) {
1368
+ context.updateQuietly(rowId, column.name, updatedEntries);
1369
+ } else {
1370
+ onChange(updatedEntries);
1371
+ }
1372
+ if (executeAction && referencedTableId && !recordId.startsWith("temp_")) {
1373
+ try {
1374
+ await executeAction("UPDATE_RECORD", {
1375
+ tableId: referencedTableId,
1376
+ recordId,
1377
+ data: { [colName]: value2 }
1378
+ });
1379
+ if (context == null ? void 0 : context.triggerSaveSuccess) {
1380
+ context.triggerSaveSuccess();
1381
+ }
1382
+ } catch (err) {
1383
+ console.error("[SubTableViewer] Failed to auto-save linked record field", err);
1384
+ }
1385
+ }
1386
+ };
1387
+ const handleCreateRecord = async () => {
1388
+ var _a2;
1389
+ if (!executeAction || !referencedTableId) return;
1390
+ for (const col of targetColumns) {
1391
+ if (col.isRequired) {
1392
+ const val = newRecordData[col.name];
1393
+ if (val === void 0 || val === null || typeof val === "string" && val.trim() === "") {
1394
+ addToast({
1395
+ type: "error",
1396
+ message: `Validation Error: Field '${col.name}' is required but was not provided.`
1397
+ });
1398
+ return;
1399
+ }
1400
+ }
1401
+ }
1402
+ try {
1403
+ const res = await executeAction("CREATE_RECORD", {
1404
+ tableId: referencedTableId,
1405
+ records: [newRecordData]
1406
+ });
1407
+ if (res && res.success === false) {
1408
+ throw new Error(res.error || "Action execution failed");
1409
+ }
1410
+ const created = Array.isArray(res) ? res[0] : ((_a2 = res == null ? void 0 : res.data) == null ? void 0 : _a2[0]) || res;
1411
+ if (created) {
1412
+ const newRecord = {
1413
+ id: String(created.id || created._id),
1414
+ data: created.data || newRecordData
1415
+ };
1416
+ handleLinkRecord(newRecord);
1417
+ setIsCreating(false);
1418
+ setNewRecordData({});
1419
+ }
1420
+ } catch (err) {
1421
+ const msg = (err == null ? void 0 : err.message) || String(err);
1422
+ addToast({
1423
+ type: "error",
1424
+ message: msg
1425
+ });
1426
+ }
1427
+ };
1428
+ const getDisplayLabel = (record) => {
1429
+ const fields = column.subTableDisplayFields || [];
1430
+ if (fields.length === 0) {
1431
+ const firstField = Object.keys(record.data).find((k) => k !== "_id");
1432
+ return firstField ? String(record.data[firstField] || "") : record.id;
1433
+ }
1434
+ return fields.map((f) => String(record.data[f] || "")).filter(Boolean).join(" ");
1435
+ };
1436
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "p-3 animate-in fade-in slide-in-from-top-2 duration-200", dir: "rtl", children: [
1437
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-4 mb-2.5", children: [
1438
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-xs font-bold text-slate-600", children: (_a = targetSchema == null ? void 0 : targetSchema.name) != null ? _a : column.referencedTableName }) }),
1439
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1.5", children: [
1440
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative", ref: searchRef, children: [
1441
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1442
+ "button",
1443
+ {
1444
+ type: "button",
1445
+ onClick: () => setIsSearchOpen((prev) => !prev),
1446
+ className: "h-7 px-2.5 text-[11px] font-semibold bg-blue-50 hover:bg-blue-100 text-blue-700 border border-blue-200 rounded-md transition-colors cursor-pointer flex items-center gap-1",
1447
+ children: [
1448
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
1449
+ "\u05E7\u05D9\u05E9\u05D5\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA"
1450
+ ]
1451
+ }
1452
+ ),
1453
+ isSearchOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "absolute right-0 top-full mt-1 w-72 bg-white border border-slate-200 rounded-lg shadow-xl z-50 p-2", children: [
1454
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1455
+ "input",
1456
+ {
1457
+ type: "text",
1458
+ value: searchQuery,
1459
+ onChange: (e) => handleSearch(e.target.value),
1460
+ placeholder: "\u05D7\u05E4\u05E9 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
1461
+ className: "w-full h-8 px-2.5 text-xs border border-slate-300 rounded-md focus:outline-none focus:ring-1 focus:ring-blue-400 mb-1.5",
1462
+ autoFocus: true
1463
+ }
1464
+ ),
1465
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "max-h-48 overflow-y-auto", children: isSearching ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-4 h-4 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : searchResults.length > 0 ? searchResults.map((r) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1466
+ "button",
1467
+ {
1468
+ type: "button",
1469
+ onClick: () => handleLinkRecord(r),
1470
+ className: "w-full text-right px-2 py-1.5 text-xs hover:bg-blue-50 rounded cursor-pointer transition-colors",
1471
+ children: getDisplayLabel(r)
1472
+ },
1473
+ r.id
1474
+ )) : searchQuery.trim() ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-xs text-slate-400 text-center py-3", children: "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-xs text-slate-400 text-center py-3", children: "\u05D4\u05E7\u05DC\u05D3 \u05DC\u05D7\u05D9\u05E4\u05D5\u05E9..." }) })
1475
+ ] })
1476
+ ] }),
1477
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1478
+ "button",
1479
+ {
1480
+ type: "button",
1481
+ onClick: () => {
1482
+ setIsCreating(true);
1483
+ const initialData = {};
1484
+ targetColumns.forEach((c) => {
1485
+ if (c.defaultValue !== void 0 && c.defaultValue !== null) {
1486
+ initialData[c.name] = c.type === "NUMBER" || c.type === "CURRENCY" ? parseFloat(c.defaultValue) : c.type === "BOOLEAN" ? c.defaultValue === "true" || c.defaultValue === true : c.defaultValue;
1487
+ } else {
1488
+ if (c.type === "NUMBER" || c.type === "CURRENCY") initialData[c.name] = 0;
1489
+ else if (c.type === "BOOLEAN") initialData[c.name] = false;
1490
+ else initialData[c.name] = "";
1491
+ }
1492
+ });
1493
+ setNewRecordData(initialData);
1494
+ },
1495
+ className: "h-7 px-2.5 text-[11px] font-semibold bg-emerald-50 hover:bg-emerald-100 text-emerald-700 border border-emerald-200 rounded-md transition-colors cursor-pointer flex items-center gap-1",
1496
+ children: [
1497
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) }),
1498
+ "\u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4"
1499
+ ]
1500
+ }
1501
+ )
1502
+ ] })
1503
+ ] }),
1504
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-5 h-5 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : entries.length === 0 && !isCreating ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-center py-6 text-xs text-slate-400", children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA. \u05D4\u05E9\u05EA\u05DE\u05E9 \u05D1\u05D7\u05D9\u05E4\u05D5\u05E9 \u05DB\u05D3\u05D9 \u05DC\u05E7\u05E9\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA, \u05D0\u05D5 \u05D4\u05D5\u05E1\u05E3 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4." }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "overflow-x-auto pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { className: "w-full text-xs border-collapse", children: [
1505
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "bg-slate-100/80", children: [
1506
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "border border-slate-200 px-2 py-1.5 text-center w-10 font-semibold text-slate-500", children: "\u05E0\u05D1\u05D7\u05E8" }),
1507
+ targetColumns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "border border-slate-200 px-2 py-1.5 text-right font-semibold text-slate-600 whitespace-nowrap", children: col.name }, col.name)),
1508
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "border border-slate-200 px-2 py-1.5 w-14" })
1509
+ ] }) }),
1510
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tbody", { children: [
1511
+ entries.map((entry) => {
1512
+ const record = linkedRecords.find((r) => r.id === entry.recordId);
1513
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors", children: [
1514
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-slate-200 px-2 py-1 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1515
+ "input",
1516
+ {
1517
+ type: "checkbox",
1518
+ checked: entry.isSelected,
1519
+ onChange: () => handleToggleSelected(entry.recordId),
1520
+ className: "w-3.5 h-3.5 rounded border-slate-300 text-blue-600 cursor-pointer"
1521
+ }
1522
+ ) }),
1523
+ targetColumns.map((col) => {
1524
+ var _a2, _b;
1525
+ const colType = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) || "DEFAULT";
1526
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
1527
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-slate-200 p-0 relative h-8", children: record ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1528
+ InputComponent,
1529
+ {
1530
+ value: (_b = record.data[col.name]) != null ? _b : colType === "BOOLEAN" ? false : "",
1531
+ column: col,
1532
+ rowId: record.id,
1533
+ onChange: (v) => handleRecordCellChange(record.id, col.name, v),
1534
+ context: __spreadProps(__spreadValues({}, context), {
1535
+ tableName: (targetSchema == null ? void 0 : targetSchema.name) || (targetSchema == null ? void 0 : targetSchema.tableName) || (targetSchema == null ? void 0 : targetSchema.title) || (targetSchema == null ? void 0 : targetSchema.id) || "Table",
1536
+ relationOptions,
1537
+ updateRelationOptions: (name, opts) => setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [name]: opts })),
1538
+ refetchRelation,
1539
+ parentRecord: { tableId: (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId), data: context == null ? void 0 : context.rowData },
1540
+ rowData: record.data,
1541
+ tableId: targetSchema == null ? void 0 : targetSchema.id,
1542
+ updateQuietly: (rid, colName, val) => handleRecordCellChange(rid, colName, val)
1543
+ })
1544
+ }
1545
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-slate-300 italic px-2", children: "\u05D8\u05D5\u05E2\u05DF..." }) }, col.name);
1546
+ }),
1547
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-slate-200 px-1 py-1 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1548
+ "button",
1549
+ {
1550
+ type: "button",
1551
+ onClick: () => handleUnlinkRecord(entry.recordId),
1552
+ className: "text-slate-400 hover:text-rose-500 p-0.5 rounded transition-colors cursor-pointer inline-flex items-center justify-center w-full",
1553
+ title: "\u05D4\u05E1\u05E8 \u05E7\u05D9\u05E9\u05D5\u05E8",
1554
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
1555
+ }
1556
+ ) })
1557
+ ] }, entry.recordId);
1558
+ }),
1559
+ isCreating && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "bg-emerald-50/40", children: [
1560
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-emerald-200 px-2 py-1 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-emerald-500 font-bold text-[10px]", children: "\u05D7\u05D3\u05E9" }) }),
1561
+ targetColumns.map((col) => {
1562
+ var _a2, _b;
1563
+ const colType = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) || "DEFAULT";
1564
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
1565
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-emerald-200 p-0 relative h-8", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1566
+ InputComponent,
1567
+ {
1568
+ value: (_b = newRecordData[col.name]) != null ? _b : colType === "BOOLEAN" ? false : "",
1569
+ column: col,
1570
+ rowId: "new_record",
1571
+ onChange: (v) => setNewRecordData((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: v })),
1572
+ context: __spreadProps(__spreadValues({}, context), {
1573
+ tableName: (targetSchema == null ? void 0 : targetSchema.name) || (targetSchema == null ? void 0 : targetSchema.tableName) || (targetSchema == null ? void 0 : targetSchema.title) || (targetSchema == null ? void 0 : targetSchema.id) || "Table",
1574
+ relationOptions,
1575
+ refetchRelation
1576
+ })
1577
+ }
1578
+ ) }, `new_${col.name}`);
1579
+ }),
1580
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-emerald-200 px-1 py-1 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-center gap-1", children: [
1581
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1582
+ "button",
1583
+ {
1584
+ type: "button",
1585
+ onClick: handleCreateRecord,
1586
+ className: "p-1 text-emerald-600 hover:bg-emerald-100 rounded transition-colors",
1587
+ title: "\u05E9\u05DE\u05D5\u05E8",
1588
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) })
1589
+ }
1590
+ ),
1591
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1592
+ "button",
1593
+ {
1594
+ type: "button",
1595
+ onClick: () => {
1596
+ setIsCreating(false);
1597
+ },
1598
+ className: "p-1 text-rose-500 hover:bg-rose-100 rounded transition-colors",
1599
+ title: "\u05D1\u05D9\u05D8\u05D5\u05DC",
1600
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M6 18L18 6M6 6l12 12" }) })
1601
+ }
1602
+ )
1603
+ ] }) })
1604
+ ] })
1605
+ ] })
1606
+ ] }) })
1607
+ ] });
1608
+ }
1609
+
907
1610
  // src/components/TableBlock/TableBlockClient.tsx
908
1611
  var import_lucide_react4 = require("lucide-react");
909
- var import_jsx_runtime5 = require("react/jsx-runtime");
1612
+ var import_jsx_runtime6 = require("react/jsx-runtime");
910
1613
  function TableBlockClient({
911
1614
  data: initialRecords,
912
1615
  settings: schema,
@@ -923,14 +1626,14 @@ function TableBlockClient({
923
1626
  "data-testid": dataTestId
924
1627
  }) {
925
1628
  const { showError, addToast } = useToast();
926
- const [columnWidths, setColumnWidths] = (0, import_react6.useState)({});
927
- const [isMounted, setIsMounted] = (0, import_react6.useState)(false);
1629
+ const [columnWidths, setColumnWidths] = (0, import_react7.useState)({});
1630
+ const [isMounted, setIsMounted] = (0, import_react7.useState)(false);
928
1631
  const tableKey = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id) || (schema == null ? void 0 : schema.name) || "default";
929
- const [page, setPage] = (0, import_react6.useState)(1);
930
- const [limit, setLimit] = (0, import_react6.useState)(50);
931
- const [totalRecords, setTotalRecords] = (0, import_react6.useState)(0);
932
- const [totalPages, setTotalPages] = (0, import_react6.useState)(1);
933
- (0, import_react6.useEffect)(() => {
1632
+ const [page, setPage] = (0, import_react7.useState)(1);
1633
+ const [limit, setLimit] = (0, import_react7.useState)(50);
1634
+ const [totalRecords, setTotalRecords] = (0, import_react7.useState)(0);
1635
+ const [totalPages, setTotalPages] = (0, import_react7.useState)(1);
1636
+ (0, import_react7.useEffect)(() => {
934
1637
  if (typeof window !== "undefined") {
935
1638
  const savedWidths = localStorage.getItem(`table_widths_${tableKey}`);
936
1639
  if (savedWidths) {
@@ -953,7 +1656,7 @@ function TableBlockClient({
953
1656
  }
954
1657
  setIsMounted(true);
955
1658
  }, [tableKey]);
956
- const [showSummary, setShowSummary] = (0, import_react6.useState)(false);
1659
+ const [showSummary, setShowSummary] = (0, import_react7.useState)(false);
957
1660
  const toggleSummary = () => {
958
1661
  setShowSummary((prev) => {
959
1662
  const next = !prev;
@@ -962,8 +1665,8 @@ function TableBlockClient({
962
1665
  return next;
963
1666
  });
964
1667
  };
965
- const [resizingCol, setResizingCol] = (0, import_react6.useState)(null);
966
- (0, import_react6.useEffect)(() => {
1668
+ const [resizingCol, setResizingCol] = (0, import_react7.useState)(null);
1669
+ (0, import_react7.useEffect)(() => {
967
1670
  if (!resizingCol) return;
968
1671
  const handleMouseMove = (e) => {
969
1672
  const diffX = resizingCol.startX - e.clientX;
@@ -1010,7 +1713,7 @@ function TableBlockClient({
1010
1713
  return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
1011
1714
  });
1012
1715
  };
1013
- const mergeColumnDefs = (0, import_react6.useCallback)((existingCols, incomingCols) => {
1716
+ const mergeColumnDefs = (0, import_react7.useCallback)((existingCols, incomingCols) => {
1014
1717
  if (!incomingCols || incomingCols.length === 0) return existingCols || [];
1015
1718
  if (!existingCols || existingCols.length === 0) return incomingCols;
1016
1719
  const existingMap = new Map(existingCols.map((c) => [c.name, c]));
@@ -1030,18 +1733,18 @@ function TableBlockClient({
1030
1733
  return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
1031
1734
  });
1032
1735
  }, []);
1033
- const [localColumns, setLocalColumns] = (0, import_react6.useState)(() => (schema == null ? void 0 : schema.columns) || []);
1034
- (0, import_react6.useEffect)(() => {
1736
+ const [localColumns, setLocalColumns] = (0, import_react7.useState)(() => (schema == null ? void 0 : schema.columns) || []);
1737
+ (0, import_react7.useEffect)(() => {
1035
1738
  if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
1036
1739
  setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
1037
1740
  }
1038
1741
  }, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
1039
- const [dirty, setDirty] = (0, import_react6.useState)({ added: [], modified: {}, deleted: [] });
1040
- const dirtyRef = (0, import_react6.useRef)(dirty);
1041
- (0, import_react6.useEffect)(() => {
1742
+ const [dirty, setDirty] = (0, import_react7.useState)({ added: [], modified: {}, deleted: [] });
1743
+ const dirtyRef = (0, import_react7.useRef)(dirty);
1744
+ (0, import_react7.useEffect)(() => {
1042
1745
  dirtyRef.current = dirty;
1043
1746
  }, [dirty]);
1044
- const mergeWithDirty = (0, import_react6.useCallback)((baseRecords) => {
1747
+ const mergeWithDirty = (0, import_react7.useCallback)((baseRecords) => {
1045
1748
  const { added, modified, deleted } = dirtyRef.current;
1046
1749
  const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
1047
1750
  const modifiedRecords = nonDeleted.map((r) => {
@@ -1054,8 +1757,8 @@ function TableBlockClient({
1054
1757
  const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
1055
1758
  return [...uniqueAdded, ...modifiedRecords];
1056
1759
  }, []);
1057
- const [data, setData] = (0, import_react6.useState)(() => normalizeRecords(initialRecords));
1058
- (0, import_react6.useEffect)(() => {
1760
+ const [data, setData] = (0, import_react7.useState)(() => normalizeRecords(initialRecords));
1761
+ (0, import_react7.useEffect)(() => {
1059
1762
  if (initialRecords) {
1060
1763
  setData(mergeWithDirty(normalizeRecords(initialRecords)));
1061
1764
  }
@@ -1070,19 +1773,19 @@ function TableBlockClient({
1070
1773
  }
1071
1774
  return false;
1072
1775
  };
1073
- const [baseRecordsMap, setBaseRecordsMap] = (0, import_react6.useState)(() => {
1776
+ const [baseRecordsMap, setBaseRecordsMap] = (0, import_react7.useState)(() => {
1074
1777
  const map = /* @__PURE__ */ new Map();
1075
1778
  (normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
1076
1779
  return map;
1077
1780
  });
1078
- (0, import_react6.useEffect)(() => {
1781
+ (0, import_react7.useEffect)(() => {
1079
1782
  if (initialRecords && initialRecords.length > 0) {
1080
1783
  const map = /* @__PURE__ */ new Map();
1081
1784
  (normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
1082
1785
  setBaseRecordsMap(map);
1083
1786
  }
1084
1787
  }, [initialRecords]);
1085
- const refetchTableData = (0, import_react6.useCallback)((targetPage) => {
1788
+ const refetchTableData = (0, import_react7.useCallback)((targetPage) => {
1086
1789
  const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
1087
1790
  if (!tableId || !executeAction) return Promise.resolve();
1088
1791
  const activePage = targetPage !== void 0 ? targetPage : page;
@@ -1116,8 +1819,8 @@ function TableBlockClient({
1116
1819
  }).catch((err) => {
1117
1820
  console.error("[TableBlock] Failed to auto-fetch table data:", err);
1118
1821
  });
1119
- }, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeWithDirty, mergeColumnDefs]);
1120
- (0, import_react6.useEffect)(() => {
1822
+ }, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeColumnDefs]);
1823
+ (0, import_react7.useEffect)(() => {
1121
1824
  refetchTableData();
1122
1825
  }, [refetchTableData]);
1123
1826
  const handleLimitChange = (newLimit) => {
@@ -1133,19 +1836,20 @@ function TableBlockClient({
1133
1836
  const handleNextPage = () => {
1134
1837
  setPage((prev) => Math.min(totalPages, prev + 1));
1135
1838
  };
1136
- (0, import_react6.useEffect)(() => {
1839
+ (0, import_react7.useEffect)(() => {
1137
1840
  if (error) {
1138
1841
  showError(error, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E8\u05DB\u05D9\u05D1");
1139
1842
  }
1140
1843
  }, [error, showError]);
1141
- const [searchQuery, setSearchQuery] = (0, import_react6.useState)("");
1142
- const [selectedIds, setSelectedIds] = (0, import_react6.useState)(/* @__PURE__ */ new Set());
1143
- const [pendingDeletions, setPendingDeletions] = (0, import_react6.useState)([]);
1144
- const [isSaving, setIsSaving] = (0, import_react6.useState)(false);
1145
- const [isSaveSuccess, setIsSaveSuccess] = (0, import_react6.useState)(false);
1146
- const [relationOptions, setRelationOptions] = (0, import_react6.useState)({});
1147
- const schemaColsString = (0, import_react6.useMemo)(() => JSON.stringify(localColumns || []), [localColumns]);
1148
- const refetchRelation = (0, import_react6.useCallback)(async (colName) => {
1844
+ const [searchQuery, setSearchQuery] = (0, import_react7.useState)("");
1845
+ const [selectedIds, setSelectedIds] = (0, import_react7.useState)(/* @__PURE__ */ new Set());
1846
+ const [pendingDeletions, setPendingDeletions] = (0, import_react7.useState)([]);
1847
+ const [isSaving, setIsSaving] = (0, import_react7.useState)(false);
1848
+ const [isSaveSuccess, setIsSaveSuccess] = (0, import_react7.useState)(false);
1849
+ const [relationOptions, setRelationOptions] = (0, import_react7.useState)({});
1850
+ const [expandedRowIds, setExpandedRowIds] = (0, import_react7.useState)(/* @__PURE__ */ new Set());
1851
+ const schemaColsString = (0, import_react7.useMemo)(() => JSON.stringify(localColumns || []), [localColumns]);
1852
+ const refetchRelation = (0, import_react7.useCallback)(async (colName) => {
1149
1853
  var _a;
1150
1854
  let parsedCols = [];
1151
1855
  try {
@@ -1165,7 +1869,7 @@ function TableBlockClient({
1165
1869
  console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
1166
1870
  }
1167
1871
  }, [schemaColsString, executeAction]);
1168
- (0, import_react6.useEffect)(() => {
1872
+ (0, import_react7.useEffect)(() => {
1169
1873
  let parsedCols = [];
1170
1874
  try {
1171
1875
  parsedCols = JSON.parse(schemaColsString);
@@ -1179,7 +1883,7 @@ function TableBlockClient({
1179
1883
  refetchRelation(col.name);
1180
1884
  });
1181
1885
  }, [schemaColsString, refetchRelation]);
1182
- const normalizedColumns = (0, import_react6.useMemo)(() => {
1886
+ const normalizedColumns = (0, import_react7.useMemo)(() => {
1183
1887
  return (localColumns || []).map((col, idx) => {
1184
1888
  const isRequired = col.isRequired === true || String(col.isRequired) === "true";
1185
1889
  const isUnique = col.isUnique === true || String(col.isUnique) === "true";
@@ -1193,17 +1897,17 @@ function TableBlockClient({
1193
1897
  return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
1194
1898
  });
1195
1899
  }, [localColumns]);
1196
- const filteredColumns = (0, import_react6.useMemo)(() => {
1900
+ const filteredColumns = (0, import_react7.useMemo)(() => {
1197
1901
  const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
1198
1902
  return normalizedColumns.filter((col) => !systemFields.includes(col.name) && !col.isHidden);
1199
1903
  }, [normalizedColumns]);
1200
- const customizableColumns = (0, import_react6.useMemo)(() => {
1904
+ const customizableColumns = (0, import_react7.useMemo)(() => {
1201
1905
  const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
1202
1906
  return normalizedColumns.filter((col) => !systemFields.includes(col.name));
1203
1907
  }, [normalizedColumns]);
1204
- const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = (0, import_react6.useState)(false);
1205
- const dropdownRef = (0, import_react6.useRef)(null);
1206
- (0, import_react6.useEffect)(() => {
1908
+ const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = (0, import_react7.useState)(false);
1909
+ const dropdownRef = (0, import_react7.useRef)(null);
1910
+ (0, import_react7.useEffect)(() => {
1207
1911
  const handleClickOutside = (e) => {
1208
1912
  if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
1209
1913
  setIsColumnsDropdownOpen(false);
@@ -1281,8 +1985,8 @@ function TableBlockClient({
1281
1985
  }
1282
1986
  }
1283
1987
  };
1284
- const [draggedColName, setDraggedColName] = (0, import_react6.useState)(null);
1285
- const [dragOverColName, setDragOverColName] = (0, import_react6.useState)(null);
1988
+ const [draggedColName, setDraggedColName] = (0, import_react7.useState)(null);
1989
+ const [dragOverColName, setDragOverColName] = (0, import_react7.useState)(null);
1286
1990
  const handleColumnReorder = async (draggedName, dropTargetName) => {
1287
1991
  var _a;
1288
1992
  if (draggedName === dropTargetName) return;
@@ -1324,6 +2028,10 @@ function TableBlockClient({
1324
2028
  var _a;
1325
2029
  const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
1326
2030
  let initialValue = col.defaultValue;
2031
+ if (typeUpper === "SUB_TABLE") {
2032
+ defaultData[col.name] = [];
2033
+ return;
2034
+ }
1327
2035
  if (initialValue !== void 0 && initialValue !== null && initialValue !== "") {
1328
2036
  if (typeUpper === "CURRENCY" || typeUpper === "NUMBER") {
1329
2037
  initialValue = parseFloat(initialValue);
@@ -1407,6 +2115,36 @@ function TableBlockClient({
1407
2115
  });
1408
2116
  }
1409
2117
  };
2118
+ const triggerSaveSuccess = (0, import_react7.useCallback)(() => {
2119
+ setIsSaveSuccess(true);
2120
+ setTimeout(() => {
2121
+ setIsSaveSuccess(false);
2122
+ }, 2500);
2123
+ }, []);
2124
+ const handleQuietCellChange = (0, import_react7.useCallback)((rowId, colName, value) => {
2125
+ setData((prev) => prev.map(
2126
+ (row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
2127
+ ));
2128
+ if (rowId.startsWith("temp_")) {
2129
+ setDirty((prev) => {
2130
+ if (!prev.added.some((r) => r.id === rowId)) return prev;
2131
+ return __spreadProps(__spreadValues({}, prev), {
2132
+ added: prev.added.map(
2133
+ (r) => r.id === rowId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value }) }) : r
2134
+ )
2135
+ });
2136
+ });
2137
+ } else {
2138
+ setBaseRecordsMap((prev) => {
2139
+ const next = new Map(prev);
2140
+ const rowData = next.get(rowId);
2141
+ if (rowData) {
2142
+ next.set(rowId, __spreadProps(__spreadValues({}, rowData), { [colName]: value }));
2143
+ }
2144
+ return next;
2145
+ });
2146
+ }
2147
+ }, []);
1410
2148
  const toggleSelectAll = (checked) => {
1411
2149
  const nextSelected = checked ? new Set(filteredData.map((r) => r.id)) : /* @__PURE__ */ new Set();
1412
2150
  setSelectedIds(nextSelected);
@@ -1436,9 +2174,15 @@ function TableBlockClient({
1436
2174
  const row = data.find((r) => r.id === id);
1437
2175
  if (row) {
1438
2176
  driveCols.forEach((col) => {
1439
- const fileObj = row.data[col.name];
1440
- if (fileObj && fileObj.fileId) {
1441
- filesToDelete.push(fileObj.fileId);
2177
+ const fileVal = row.data[col.name];
2178
+ if (Array.isArray(fileVal)) {
2179
+ fileVal.forEach((fileObj) => {
2180
+ if (fileObj && fileObj.fileId) {
2181
+ filesToDelete.push(fileObj.fileId);
2182
+ }
2183
+ });
2184
+ } else if (fileVal && fileVal.fileId) {
2185
+ filesToDelete.push(fileVal.fileId);
1442
2186
  }
1443
2187
  });
1444
2188
  }
@@ -1465,7 +2209,7 @@ function TableBlockClient({
1465
2209
  const formatPayload = (payload) => {
1466
2210
  const formatted = {};
1467
2211
  (localColumns || []).forEach((col) => {
1468
- var _a;
2212
+ var _a, _b;
1469
2213
  if (["_id", "id", "createdAt", "updatedAt", "orgId", "tableId", "isSelected"].includes(col.name)) return;
1470
2214
  let val = payload[col.name];
1471
2215
  if (val !== void 0) {
@@ -1475,6 +2219,11 @@ function TableBlockClient({
1475
2219
  if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
1476
2220
  val = val === "" ? 0 : Number(val);
1477
2221
  if (isNaN(val)) val = 0;
2222
+ } else if (((_b = col.type) == null ? void 0 : _b.toUpperCase()) === "SUB_TABLE" && Array.isArray(val)) {
2223
+ val = val.map((item) => {
2224
+ const _a2 = item, { _resolvedData } = _a2, rest = __objRest(_a2, ["_resolvedData"]);
2225
+ return rest;
2226
+ });
1478
2227
  }
1479
2228
  formatted[col.name] = val;
1480
2229
  }
@@ -1607,7 +2356,7 @@ function TableBlockClient({
1607
2356
  setIsSaving(false);
1608
2357
  }
1609
2358
  };
1610
- const filteredData = (0, import_react6.useMemo)(() => {
2359
+ const filteredData = (0, import_react7.useMemo)(() => {
1611
2360
  if (!searchQuery) return data;
1612
2361
  const lowerQuery = searchQuery.toLowerCase();
1613
2362
  return data.filter(
@@ -1618,7 +2367,7 @@ function TableBlockClient({
1618
2367
  }, [data, searchQuery]);
1619
2368
  const isUpdatingActive = Boolean(isUpdating || isSaving);
1620
2369
  const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
1621
- const columnTotals = (0, import_react6.useMemo)(() => {
2370
+ const columnTotals = (0, import_react7.useMemo)(() => {
1622
2371
  const totals = {};
1623
2372
  if (!showSummary) return totals;
1624
2373
  filteredColumns.forEach((col) => {
@@ -1636,7 +2385,7 @@ function TableBlockClient({
1636
2385
  });
1637
2386
  return totals;
1638
2387
  }, [filteredData, filteredColumns, showSummary]);
1639
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2388
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1640
2389
  "div",
1641
2390
  {
1642
2391
  id: componentId,
@@ -1644,34 +2393,34 @@ function TableBlockClient({
1644
2393
  className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs min-h-[350px] overflow-hidden ${className}`,
1645
2394
  dir: "rtl",
1646
2395
  children: [
1647
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
1648
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
1649
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: errorMessage })
2396
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
2397
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
2398
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: errorMessage })
1650
2399
  ] }) }),
1651
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-3 p-3.5 sm:p-4 bg-slate-50 border-b border-slate-200", children: [
1652
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center gap-2.5", children: [
1653
- ((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: schema.title || schema.name }) }),
1654
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2400
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-3 p-3.5 sm:p-4 bg-slate-50 border-b border-slate-200", children: [
2401
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-center gap-2.5", children: [
2402
+ ((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: schema.title || schema.name }) }),
2403
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1655
2404
  "button",
1656
2405
  {
1657
2406
  onClick: handleAddRow,
1658
2407
  disabled: isLoading || isUpdatingActive,
1659
2408
  className: "w-9 h-9 bg-emerald-600 hover:bg-emerald-700 active:bg-emerald-800 text-white rounded-lg shadow-xs flex items-center justify-center transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
1660
2409
  title: "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
1661
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
2410
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
1662
2411
  }
1663
2412
  ),
1664
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2413
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1665
2414
  "button",
1666
2415
  {
1667
2416
  onClick: handleDuplicateRow,
1668
2417
  disabled: isLoading || isUpdatingActive || selectedIds.size !== 1,
1669
2418
  className: "w-9 h-9 bg-blue-50 hover:bg-blue-100 border border-blue-200 text-blue-700 rounded-lg shadow-2xs flex items-center justify-center transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
1670
2419
  title: "\u05E9\u05DB\u05E4\u05DC \u05E9\u05D5\u05E8\u05D4 \u05E0\u05D1\u05D7\u05E8\u05EA",
1671
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Copy, { className: "w-4 h-4 text-blue-600 shrink-0" })
2420
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Copy, { className: "w-4 h-4 text-blue-600 shrink-0" })
1672
2421
  }
1673
2422
  ),
1674
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2423
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1675
2424
  "button",
1676
2425
  {
1677
2426
  onClick: handleDeleteSelected,
@@ -1679,12 +2428,12 @@ function TableBlockClient({
1679
2428
  className: "w-9 h-9 bg-rose-50 hover:bg-rose-100 border border-rose-200 text-rose-700 rounded-lg shadow-2xs flex items-center justify-center relative transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
1680
2429
  title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
1681
2430
  children: [
1682
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
1683
- selectedIds.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "absolute -top-1.5 -right-1.5 bg-rose-600 text-white min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs", children: selectedIds.size })
2431
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
2432
+ selectedIds.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "absolute -top-1.5 -right-1.5 bg-rose-600 text-white min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs", children: selectedIds.size })
1684
2433
  ]
1685
2434
  }
1686
2435
  ),
1687
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2436
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1688
2437
  "button",
1689
2438
  {
1690
2439
  onClick: toggleSummary,
@@ -1692,13 +2441,13 @@ function TableBlockClient({
1692
2441
  className: `h-9 px-3 border font-semibold rounded-lg shadow-2xs flex items-center gap-1.5 text-xs transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer ${showSummary ? "bg-indigo-50 border-indigo-200 text-indigo-700 hover:bg-indigo-100" : "bg-white border-slate-300 text-slate-700 hover:bg-slate-100"}`,
1693
2442
  title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
1694
2443
  children: [
1695
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
1696
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
2444
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
2445
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
1697
2446
  ]
1698
2447
  }
1699
2448
  ),
1700
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
1701
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2449
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
2450
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1702
2451
  "button",
1703
2452
  {
1704
2453
  onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
@@ -1706,16 +2455,16 @@ function TableBlockClient({
1706
2455
  className: "h-9 px-3 bg-white hover:bg-slate-100 border border-slate-300 text-slate-700 font-semibold rounded-lg shadow-2xs flex items-center gap-1.5 text-xs transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
1707
2456
  title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
1708
2457
  children: [
1709
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" }) }),
1710
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: `w-3.5 h-3.5 text-slate-500 transition-transform ${isColumnsDropdownOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
2458
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" }) }),
2459
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: `w-3.5 h-3.5 text-slate-500 transition-transform ${isColumnsDropdownOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
1711
2460
  ]
1712
2461
  }
1713
2462
  ),
1714
- isColumnsDropdownOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "absolute right-0 top-full mt-1.5 w-56 bg-white border border-slate-200 rounded-xl shadow-xl z-50 p-1.5 dir-rtl animate-in fade-in slide-in-from-top-2 duration-150", children: [
1715
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "px-2 py-1.5 text-xs font-bold text-slate-500 border-b border-slate-100 mb-1 flex items-center justify-between", children: [
1716
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1.5", children: [
1717
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
1718
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "text-[10px] font-normal text-slate-400", children: [
2463
+ isColumnsDropdownOpen && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "absolute right-0 top-full mt-1.5 w-56 bg-white border border-slate-200 rounded-xl shadow-xl z-50 p-1.5 dir-rtl animate-in fade-in slide-in-from-top-2 duration-150", children: [
2464
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "px-2 py-1.5 text-xs font-bold text-slate-500 border-b border-slate-100 mb-1 flex items-center justify-between", children: [
2465
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2466
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
2467
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-[10px] font-normal text-slate-400", children: [
1719
2468
  "(",
1720
2469
  customizableColumns.filter((c) => !c.isHidden).length,
1721
2470
  "/",
@@ -1723,7 +2472,7 @@ function TableBlockClient({
1723
2472
  ")"
1724
2473
  ] })
1725
2474
  ] }),
1726
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2475
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1727
2476
  "button",
1728
2477
  {
1729
2478
  type: "button",
@@ -1733,7 +2482,7 @@ function TableBlockClient({
1733
2482
  }
1734
2483
  )
1735
2484
  ] }),
1736
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
2485
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
1737
2486
  const isRequired = col.isRequired === true || String(col.isRequired) === "true";
1738
2487
  const isUnique = col.isUnique === true || String(col.isUnique) === "true";
1739
2488
  const isProtected = isRequired || isUnique;
@@ -1747,7 +2496,7 @@ function TableBlockClient({
1747
2496
  protectedExplanation = "\u05E9\u05D3\u05D4 \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9 - \u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D4\u05D5\u05E8\u05D9\u05D3 \u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5 \u05DE\u05D4\u05EA\u05E6\u05D5\u05D2\u05D4";
1748
2497
  }
1749
2498
  const badgeLabel = isRequired && isUnique ? "\u05D7\u05D5\u05D1\u05D4 + \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9" : isRequired ? "\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4" : "\u05E9\u05D3\u05D4 \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9";
1750
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2499
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1751
2500
  "div",
1752
2501
  {
1753
2502
  onClick: () => {
@@ -1758,8 +2507,8 @@ function TableBlockClient({
1758
2507
  title: isProtected ? protectedExplanation : void 0,
1759
2508
  className: `group flex items-center justify-between px-2.5 py-1.5 rounded-lg text-xs transition-colors select-none ${isProtected ? "opacity-75 bg-slate-50 border border-slate-100/70 cursor-not-allowed" : "hover:bg-slate-100 active:bg-slate-200 cursor-pointer"}`,
1760
2509
  children: [
1761
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
1762
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2510
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
2511
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1763
2512
  "input",
1764
2513
  {
1765
2514
  type: "checkbox",
@@ -1770,16 +2519,16 @@ function TableBlockClient({
1770
2519
  className: "w-3.5 h-3.5 rounded border-slate-300 text-brand focus:ring-brand/20 cursor-pointer disabled:cursor-not-allowed disabled:opacity-60"
1771
2520
  }
1772
2521
  ),
1773
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
2522
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
1774
2523
  ] }),
1775
- isProtected && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2524
+ isProtected && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1776
2525
  "div",
1777
2526
  {
1778
2527
  className: "flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-semibold bg-amber-50 text-amber-800 border border-amber-200/80 cursor-help",
1779
2528
  title: protectedExplanation,
1780
2529
  children: [
1781
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3 h-3 text-amber-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: "2.2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }),
1782
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: badgeLabel })
2530
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-3 h-3 text-amber-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: "2.2", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }),
2531
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: badgeLabel })
1783
2532
  ]
1784
2533
  }
1785
2534
  )
@@ -1790,9 +2539,9 @@ function TableBlockClient({
1790
2539
  }) })
1791
2540
  ] })
1792
2541
  ] }),
1793
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
1794
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
1795
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2542
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
2543
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
2544
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1796
2545
  "input",
1797
2546
  {
1798
2547
  placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
@@ -1802,45 +2551,45 @@ function TableBlockClient({
1802
2551
  className: "w-full h-9 px-3 pr-9 text-xs border border-slate-300 rounded-lg bg-white shadow-2xs focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 text-slate-800 disabled:opacity-50"
1803
2552
  }
1804
2553
  ),
1805
- searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2554
+ searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1806
2555
  "button",
1807
2556
  {
1808
2557
  type: "button",
1809
2558
  onClick: () => setSearchQuery(""),
1810
2559
  className: "absolute right-2.5 top-2.5 text-slate-400 hover:text-slate-600 transition-colors p-0.5 rounded-full hover:bg-slate-100 cursor-pointer",
1811
2560
  title: "Clear search",
1812
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.X, { className: "w-3.5 h-3.5" })
2561
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.X, { className: "w-3.5 h-3.5" })
1813
2562
  }
1814
- ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4 h-4 text-slate-400 absolute right-2.5 top-2.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
2563
+ ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4 h-4 text-slate-400 absolute right-2.5 top-2.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
1815
2564
  ] })
1816
2565
  ] }),
1817
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-3", children: [
1818
- isUpdatingActive ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "text-xs text-blue-600 font-semibold flex items-center gap-1.5 bg-blue-50 border border-blue-200 px-3 py-1.5 rounded-lg animate-pulse", children: [
1819
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
2566
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-3", children: [
2567
+ isUpdatingActive ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-xs text-blue-600 font-semibold flex items-center gap-1.5 bg-blue-50 border border-blue-200 px-3 py-1.5 rounded-lg animate-pulse", children: [
2568
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
1820
2569
  "\u05DE\u05E2\u05D3\u05DB\u05DF..."
1821
- ] }) : isSaveSuccess ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "text-xs text-emerald-700 font-semibold flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 px-3 py-1.5 rounded-lg animate-in fade-in duration-200", children: [
1822
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
2570
+ ] }) : isSaveSuccess ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-xs text-emerald-700 font-semibold flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 px-3 py-1.5 rounded-lg animate-in fade-in duration-200", children: [
2571
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
1823
2572
  "\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
1824
- ] }) : hasChanges ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-xs font-semibold text-amber-700 animate-in fade-in", children: "\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5" }) : null,
1825
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2573
+ ] }) : hasChanges ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-xs font-semibold text-amber-700 animate-in fade-in", children: "\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5" }) : null,
2574
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1826
2575
  "button",
1827
2576
  {
1828
2577
  onClick: handleSave,
1829
2578
  disabled: isUpdatingActive || isLoading || !hasChanges,
1830
2579
  className: `h-9 px-4 text-xs font-bold rounded-lg shadow-2xs transition-all flex items-center justify-center cursor-pointer ${hasChanges && !isUpdatingActive && !isLoading ? "bg-brand hover:bg-brand-hover active:bg-[#00897b] text-white shadow-teal-500/20" : "opacity-50 grayscale bg-slate-200 text-slate-400 cursor-not-allowed"}`,
1831
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
2580
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
1832
2581
  }
1833
2582
  )
1834
2583
  ] })
1835
2584
  ] }),
1836
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `overflow-x-auto relative min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
1837
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
1838
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
1839
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
2585
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `overflow-x-auto relative min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
2586
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
2587
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
2588
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
1840
2589
  ] }),
1841
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
1842
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
1843
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "border-b border-l border-slate-200 p-2.5 w-10 text-center shrink-0", style: { width: 50, minWidth: 50, maxWidth: 50 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2590
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
2591
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { children: [
2592
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("th", { className: "border-b border-l border-slate-200 p-2.5 w-10 text-center shrink-0", style: { width: 50, minWidth: 50, maxWidth: 50 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1844
2593
  "input",
1845
2594
  {
1846
2595
  type: "checkbox",
@@ -1854,7 +2603,7 @@ function TableBlockClient({
1854
2603
  const isDragging = draggedColName === col.name;
1855
2604
  const isDragOver = dragOverColName === col.name;
1856
2605
  const currentWidth = columnWidths[col.name] || 200;
1857
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2606
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1858
2607
  "th",
1859
2608
  {
1860
2609
  style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
@@ -1890,7 +2639,7 @@ function TableBlockClient({
1890
2639
  },
1891
2640
  className: `relative border-b border-l border-slate-200 px-4 py-2.5 font-semibold text-slate-700 whitespace-nowrap select-none cursor-grab active:cursor-grabbing transition-colors ${isDragging ? "opacity-40 bg-slate-200 border-dashed border-2 border-brand" : ""} ${isDragOver ? "bg-blue-50 border-r-4 border-r-brand text-brand font-bold" : "hover:bg-slate-200/60"}`,
1892
2641
  children: [
1893
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2642
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1894
2643
  "div",
1895
2644
  {
1896
2645
  onMouseDown: (e) => {
@@ -1902,16 +2651,16 @@ function TableBlockClient({
1902
2651
  title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
1903
2652
  }
1904
2653
  ),
1905
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between gap-2 group overflow-hidden", title: "\u05D2\u05E8\u05D5\u05E8 \u05DC\u05E9\u05D9\u05E0\u05D5\u05D9 \u05E1\u05D3\u05E8 \u05D4\u05E2\u05DE\u05D5\u05D3\u05D4", children: [
1906
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate", children: col.name }),
1907
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2654
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between gap-2 group overflow-hidden", title: "\u05D2\u05E8\u05D5\u05E8 \u05DC\u05E9\u05D9\u05E0\u05D5\u05D9 \u05E1\u05D3\u05E8 \u05D4\u05E2\u05DE\u05D5\u05D3\u05D4", children: [
2655
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: col.name }),
2656
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1908
2657
  "svg",
1909
2658
  {
1910
2659
  className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
1911
2660
  fill: "none",
1912
2661
  viewBox: "0 0 24 24",
1913
2662
  stroke: "currentColor",
1914
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
2663
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
1915
2664
  }
1916
2665
  )
1917
2666
  ] })
@@ -1920,59 +2669,112 @@ function TableBlockClient({
1920
2669
  col.name
1921
2670
  );
1922
2671
  }),
1923
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none" })
2672
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none" })
1924
2673
  ] }) }),
1925
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col items-center justify-center gap-2", children: [
1926
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }),
1927
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
1928
- ] }) }) }) : filteredData.map((row) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
1929
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1930
- "input",
1931
- {
1932
- type: "checkbox",
1933
- checked: selectedIds.has(row.id),
1934
- onChange: (e) => toggleSelectRow(row.id, e.target.checked),
1935
- disabled: isLoading || isUpdatingActive,
1936
- className: "w-4 h-4 rounded border-slate-300 text-brand"
1937
- }
1938
- ) }),
1939
- filteredColumns.map((col) => {
2674
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col items-center justify-center gap-2", children: [
2675
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }),
2676
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
2677
+ ] }) }) }) : filteredData.map((row) => {
2678
+ const hasSubTableCols = filteredColumns.some((c) => {
1940
2679
  var _a;
1941
- const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
1942
- const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
1943
- let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
1944
- if (value === void 0 && col.defaultValue !== void 0) {
1945
- value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
1946
- if (colType === "CURRENCY" || colType === "NUMBER") {
1947
- if (isNaN(value)) value = null;
1948
- }
1949
- }
1950
- if (value === void 0) value = null;
1951
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border-b border-l border-slate-200 p-0 relative", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1952
- InputComponent,
2680
+ return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
2681
+ });
2682
+ const isExpanded = expandedRowIds.has(row.id);
2683
+ const subTableColumns = filteredColumns.filter((c) => {
2684
+ var _a;
2685
+ return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
2686
+ });
2687
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react7.default.Fragment, { children: [
2688
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
2689
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-center gap-1", children: [
2690
+ hasSubTableCols && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2691
+ "button",
2692
+ {
2693
+ type: "button",
2694
+ onClick: () => setExpandedRowIds((prev) => {
2695
+ const next = new Set(prev);
2696
+ if (next.has(row.id)) next.delete(row.id);
2697
+ else next.add(row.id);
2698
+ return next;
2699
+ }),
2700
+ className: "text-slate-400 hover:text-blue-600 p-0.5 rounded transition-colors cursor-pointer",
2701
+ title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
2702
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: `w-3.5 h-3.5 transition-transform duration-150 ${isExpanded ? "rotate-90" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 5l7 7-7 7" }) })
2703
+ }
2704
+ ),
2705
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2706
+ "input",
2707
+ {
2708
+ type: "checkbox",
2709
+ checked: selectedIds.has(row.id),
2710
+ onChange: (e) => toggleSelectRow(row.id, e.target.checked),
2711
+ disabled: isLoading || isUpdatingActive,
2712
+ className: "w-4 h-4 rounded border-slate-300 text-brand"
2713
+ }
2714
+ )
2715
+ ] }) }),
2716
+ filteredColumns.map((col) => {
2717
+ var _a;
2718
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
2719
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
2720
+ let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
2721
+ if (value === void 0 && col.defaultValue !== void 0) {
2722
+ value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
2723
+ if (colType === "CURRENCY" || colType === "NUMBER") {
2724
+ if (isNaN(value)) value = null;
2725
+ }
2726
+ }
2727
+ if (value === void 0) value = null;
2728
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-l border-slate-200 p-0 relative", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2729
+ InputComponent,
2730
+ {
2731
+ value,
2732
+ column: col,
2733
+ rowId: row.id,
2734
+ onChange: (v) => handleCellChange(row.id, col.name, v),
2735
+ context: {
2736
+ 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",
2737
+ tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
2738
+ onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
2739
+ relationOptions,
2740
+ refetchRelation,
2741
+ executeAction,
2742
+ emitEvent,
2743
+ pageState,
2744
+ componentId,
2745
+ orgId,
2746
+ updateQuietly: handleQuietCellChange,
2747
+ triggerSaveSuccess,
2748
+ rowData: row.data
2749
+ }
2750
+ }
2751
+ ) }, col.name);
2752
+ }),
2753
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
2754
+ ] }),
2755
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2756
+ ExpandedSubTables,
1953
2757
  {
1954
- value,
1955
- column: col,
1956
2758
  rowId: row.id,
1957
- onChange: (v) => handleCellChange(row.id, col.name, v),
2759
+ rowData: row.data,
2760
+ subTableColumns,
2761
+ filteredColumnsLength: filteredColumns.length,
2762
+ handleCellChange,
1958
2763
  context: {
1959
- 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",
1960
- onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
1961
- relationOptions,
1962
- refetchRelation,
1963
2764
  executeAction,
1964
- emitEvent,
1965
- pageState,
1966
- componentId,
1967
- orgId
2765
+ orgId,
2766
+ parentTableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
2767
+ tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
2768
+ rowData: row.data,
2769
+ updateQuietly: handleQuietCellChange,
2770
+ triggerSaveSuccess
1968
2771
  }
1969
2772
  }
1970
- ) }, col.name);
1971
- }),
1972
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
1973
- ] }, row.id)) }),
1974
- showSummary && filteredData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.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_runtime5.jsxs)("tr", { children: [
1975
- /* @__PURE__ */ (0, import_jsx_runtime5.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' }),
2773
+ )
2774
+ ] }, row.id);
2775
+ }) }),
2776
+ showSummary && filteredData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.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_runtime6.jsxs)("tr", { children: [
2777
+ /* @__PURE__ */ (0, import_jsx_runtime6.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' }),
1976
2778
  filteredColumns.map((col) => {
1977
2779
  var _a;
1978
2780
  const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
@@ -1986,16 +2788,16 @@ function TableBlockClient({
1986
2788
  displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
1987
2789
  }
1988
2790
  }
1989
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border-b border-l border-slate-200 p-2 text-sm font-semibold text-slate-700 bg-slate-50 relative", children: isNumeric && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate", children: displayVal }) }) }, col.name);
2791
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-l border-slate-200 p-2 text-sm font-semibold text-slate-700 bg-slate-50 relative", children: isNumeric && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: displayVal }) }) }, col.name);
1990
2792
  }),
1991
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
2793
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
1992
2794
  ] }) })
1993
2795
  ] })
1994
2796
  ] }),
1995
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-3 px-4 py-3 bg-slate-50 border-t border-slate-200 text-xs text-slate-600 rounded-b-xl", children: [
1996
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
1997
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
1998
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2797
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-3 px-4 py-3 bg-slate-50 border-t border-slate-200 text-xs text-slate-600 rounded-b-xl", children: [
2798
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
2799
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
2800
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1999
2801
  "select",
2000
2802
  {
2001
2803
  value: limit,
@@ -2003,27 +2805,27 @@ function TableBlockClient({
2003
2805
  disabled: isLoading || isUpdatingActive,
2004
2806
  className: "bg-white border border-slate-300 rounded-lg px-2.5 py-1 text-slate-700 font-semibold shadow-2xs cursor-pointer focus:outline-none focus:ring-2 focus:ring-brand disabled:opacity-50",
2005
2807
  children: [
2006
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: 20, children: "20" }),
2007
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: 50, children: "50" }),
2008
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: 100, children: "100" })
2808
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: 20, children: "20" }),
2809
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: 50, children: "50" }),
2810
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: 100, children: "100" })
2009
2811
  ]
2010
2812
  }
2011
2813
  )
2012
2814
  ] }),
2013
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-4", children: [
2014
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "font-medium text-slate-600", children: [
2815
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-4", children: [
2816
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-medium text-slate-600", children: [
2015
2817
  "\u05E2\u05DE\u05D5\u05D3 ",
2016
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { className: "text-slate-900", children: page }),
2818
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { className: "text-slate-900", children: page }),
2017
2819
  " \u05DE\u05EA\u05D5\u05DA ",
2018
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { className: "text-slate-900", children: totalPages || 1 }),
2019
- totalRecords > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "text-slate-500 font-normal", children: [
2820
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { className: "text-slate-900", children: totalPages || 1 }),
2821
+ totalRecords > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-slate-500 font-normal", children: [
2020
2822
  " (",
2021
2823
  totalRecords,
2022
2824
  ' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
2023
2825
  ] })
2024
2826
  ] }),
2025
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2026
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2827
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2828
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2027
2829
  "button",
2028
2830
  {
2029
2831
  onClick: handlePrevPage,
@@ -2033,7 +2835,7 @@ function TableBlockClient({
2033
2835
  children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
2034
2836
  }
2035
2837
  ),
2036
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2838
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2037
2839
  "button",
2038
2840
  {
2039
2841
  onClick: handleNextPage,
@@ -2050,11 +2852,60 @@ function TableBlockClient({
2050
2852
  }
2051
2853
  );
2052
2854
  }
2855
+ function ExpandedSubTables({
2856
+ rowId,
2857
+ rowData,
2858
+ subTableColumns,
2859
+ filteredColumnsLength,
2860
+ handleCellChange,
2861
+ context
2862
+ }) {
2863
+ var _a;
2864
+ const [activeTab, setActiveTab] = (0, import_react7.useState)((_a = subTableColumns[0]) == null ? void 0 : _a.name);
2865
+ if (subTableColumns.length === 0) return null;
2866
+ if (subTableColumns.length === 1) {
2867
+ const stCol = subTableColumns[0];
2868
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2869
+ SubTableViewer,
2870
+ {
2871
+ rowId,
2872
+ column: stCol,
2873
+ value: (rowData == null ? void 0 : rowData[stCol.name]) || [],
2874
+ onChange: (newVal) => handleCellChange(rowId, stCol.name, newVal),
2875
+ context
2876
+ }
2877
+ ) }) });
2878
+ }
2879
+ const activeCol = subTableColumns.find((c) => c.name === activeTab) || subTableColumns[0];
2880
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50 overflow-hidden", children: [
2881
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex border-b border-slate-200 bg-slate-100/50 px-2 pt-2 gap-1 overflow-hidden", children: subTableColumns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2882
+ "button",
2883
+ {
2884
+ type: "button",
2885
+ onClick: () => setActiveTab(col.name),
2886
+ className: `px-4 py-2 text-sm font-semibold rounded-t-lg transition-colors whitespace-nowrap cursor-pointer relative top-[1px] ${activeTab === col.name ? "bg-white border border-slate-200 border-b-transparent text-brand" : "bg-transparent border border-transparent text-slate-500 hover:text-slate-700 hover:bg-slate-200/50"}`,
2887
+ children: col.name
2888
+ },
2889
+ col.name
2890
+ )) }),
2891
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "bg-white", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2892
+ SubTableViewer,
2893
+ {
2894
+ rowId,
2895
+ column: activeCol,
2896
+ value: (rowData == null ? void 0 : rowData[activeCol.name]) || [],
2897
+ onChange: (newVal) => handleCellChange(rowId, activeCol.name, newVal),
2898
+ context
2899
+ },
2900
+ activeCol.name
2901
+ ) })
2902
+ ] }) });
2903
+ }
2053
2904
 
2054
2905
  // src/components/TableBlock/TableBlock.tsx
2055
- var import_jsx_runtime6 = require("react/jsx-runtime");
2906
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2056
2907
  function TableBlock(props) {
2057
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TableBlockClient, __spreadValues({}, props));
2908
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableBlockClient, __spreadValues({}, props));
2058
2909
  }
2059
2910
 
2060
2911
  // src/registry.ts