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

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
@@ -58,16 +58,18 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
58
58
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
59
59
 
60
60
  // src/index.ts
61
- var index_exports = {};
62
- __export(index_exports, {
61
+ var src_exports = {};
62
+ __export(src_exports, {
63
63
  TableBlock: () => TableBlock,
64
64
  ToastContext: () => ToastContext,
65
65
  ToastProvider: () => ToastProvider,
66
66
  UNIVERSE_COMPONENTS: () => UNIVERSE_COMPONENTS,
67
67
  cn: () => cn,
68
+ formatPhoneDisplay: () => formatPhoneDisplay,
69
+ openWhatsAppChat: () => openWhatsAppChat,
68
70
  useToast: () => useToast
69
71
  });
70
- module.exports = __toCommonJS(index_exports);
72
+ module.exports = __toCommonJS(src_exports);
71
73
 
72
74
  // src/utils/cn.ts
73
75
  var import_clsx = require("clsx");
@@ -76,8 +78,38 @@ function cn(...inputs) {
76
78
  return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
77
79
  }
78
80
 
81
+ // src/utils/whatsapp.ts
82
+ function openWhatsAppChat(phone, defaultCountryCode = "972") {
83
+ if (!phone || typeof window === "undefined") return;
84
+ let cleaned = phone.replace(/\D/g, "");
85
+ if (cleaned.startsWith("0")) {
86
+ cleaned = defaultCountryCode + cleaned.substring(1);
87
+ }
88
+ const appUrl = `whatsapp://send?phone=${cleaned}`;
89
+ const webUrl = `https://web.whatsapp.com/send?phone=${cleaned}`;
90
+ const start = Date.now();
91
+ window.location.href = appUrl;
92
+ setTimeout(() => {
93
+ if (typeof document !== "undefined" && document.hasFocus() && Date.now() - start < 2e3) {
94
+ window.open(webUrl, "_blank", "noopener,noreferrer");
95
+ }
96
+ }, 1200);
97
+ }
98
+ function formatPhoneDisplay(phone) {
99
+ if (!phone) return "";
100
+ const digits = phone.replace(/\D/g, "");
101
+ if (digits.length === 10 && digits.startsWith("05")) {
102
+ return `${digits.slice(0, 3)}-${digits.slice(3, 6)}-${digits.slice(6)}`;
103
+ }
104
+ if (digits.length === 12 && digits.startsWith("9725")) {
105
+ const local = "0" + digits.slice(3);
106
+ return `${local.slice(0, 3)}-${local.slice(3, 6)}-${local.slice(6)}`;
107
+ }
108
+ return phone;
109
+ }
110
+
79
111
  // src/components/TableBlock/TableBlockClient.tsx
80
- var import_react6 = require("react");
112
+ var import_react7 = __toESM(require("react"));
81
113
 
82
114
  // src/hooks/useToast.ts
83
115
  var import_react2 = require("react");
@@ -280,12 +312,36 @@ function useToast() {
280
312
  var import_react5 = __toESM(require("react"));
281
313
 
282
314
  // src/components/TableBlock/fields/DrivePickerCell.tsx
283
- var import_react3 = require("react");
315
+ var import_react3 = __toESM(require("react"));
284
316
  var import_lucide_react2 = require("lucide-react");
285
317
  var import_jsx_runtime2 = require("react/jsx-runtime");
286
- function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, context }) {
318
+ function DrivePickerCell({ value, onChange, tableName, column, rowId, onMarkForDeletion, context }) {
287
319
  const [isOpening, setIsOpening] = (0, import_react3.useState)(false);
288
320
  const { showError } = useToast();
321
+ const cellContextId = import_react3.default.useMemo(() => {
322
+ const colName = (column == null ? void 0 : column.name) || "col";
323
+ const rId = rowId || "row";
324
+ return `${rId}-${colName}`;
325
+ }, [rowId, column == null ? void 0 : column.name]);
326
+ const fileList = import_react3.default.useMemo(() => {
327
+ if (!value) return [];
328
+ if (Array.isArray(value)) return value;
329
+ if (typeof value === "object" && (value.fileId || value.fileUrl || value.url)) {
330
+ return [value];
331
+ }
332
+ return [];
333
+ }, [value]);
334
+ (0, import_react3.useEffect)(() => {
335
+ const handleMessage = (event) => {
336
+ var _a, _b, _c;
337
+ 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) {
338
+ const incoming = Array.isArray(event.data.payload) ? event.data.payload : [event.data.payload];
339
+ onChange([...fileList, ...incoming]);
340
+ }
341
+ };
342
+ window.addEventListener("message", handleMessage);
343
+ return () => window.removeEventListener("message", handleMessage);
344
+ }, [fileList, onChange, cellContextId]);
289
345
  const openUploadPopup = async () => {
290
346
  if (isOpening) return;
291
347
  setIsOpening(true);
@@ -314,34 +370,35 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
314
370
  } catch (e) {
315
371
  }
316
372
  }
317
- const actionResult = await context.executeAction("UPLOAD_DRIVE_FILE", { tableName });
373
+ const actionResult = await context.executeAction("UPLOAD_DRIVE_FILE", { tableName, cellContextId });
318
374
  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`);
375
+ let pickerUrl = (actionResult == null ? void 0 : actionResult.pickerUrl) || (folderId ? `/embed/picker?folderId=${encodeURIComponent(folderId)}` : `/embed/picker`);
376
+ if (!pickerUrl.includes("cellContextId=")) {
377
+ const separator = pickerUrl.includes("?") ? "&" : "?";
378
+ pickerUrl = `${pickerUrl}${separator}cellContextId=${encodeURIComponent(cellContextId)}`;
379
+ }
320
380
  if (popup) {
321
381
  popup.location.href = pickerUrl;
322
382
  }
323
- const newFile = await new Promise((resolve) => {
383
+ await new Promise((resolve) => {
324
384
  let timer = null;
325
- const handleMessage = (event) => {
385
+ const handlePopupMessage = (event) => {
326
386
  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);
387
+ if (((_a = event.data) == null ? void 0 : _a.type) === "DRIVE_UPLOAD_SUCCESS" && ((_b = event.data) == null ? void 0 : _b.cellContextId) === cellContextId) {
388
+ window.removeEventListener("message", handlePopupMessage);
329
389
  if (timer) clearInterval(timer);
330
- resolve(event.data.payload);
390
+ resolve();
331
391
  }
332
392
  };
333
393
  timer = setInterval(() => {
334
394
  if (!popup || popup.closed) {
335
395
  if (timer) clearInterval(timer);
336
- window.removeEventListener("message", handleMessage);
337
- resolve(null);
396
+ window.removeEventListener("message", handlePopupMessage);
397
+ resolve();
338
398
  }
339
399
  }, 800);
340
- window.addEventListener("message", handleMessage);
400
+ window.addEventListener("message", handlePopupMessage);
341
401
  });
342
- if (newFile) {
343
- onChange(newFile);
344
- }
345
402
  }
346
403
  } catch (error) {
347
404
  console.error("[DrivePickerCell] Error uploading file:", error);
@@ -351,40 +408,15 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
351
408
  setIsOpening(false);
352
409
  }
353
410
  };
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)(
411
+ const handleRemoveFile = (indexToRemove) => {
412
+ const fileToRemove = fileList[indexToRemove];
413
+ if ((fileToRemove == null ? void 0 : fileToRemove.fileId) && onMarkForDeletion) {
414
+ onMarkForDeletion(fileToRemove.fileId);
415
+ }
416
+ const updated = fileList.filter((_, idx) => idx !== indexToRemove);
417
+ onChange(updated);
418
+ };
419
+ 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
420
  "button",
389
421
  {
390
422
  type: "button",
@@ -397,6 +429,38 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
397
429
  ]
398
430
  }
399
431
  ) });
432
+ if (fileList.length > 0) {
433
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col w-full py-1 gap-1", children: [
434
+ fileList.map((file, idx) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center w-full h-8 px-2 gap-1", children: [
435
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
436
+ "a",
437
+ {
438
+ href: file.fileUrl || file.url,
439
+ target: "_blank",
440
+ rel: "noopener noreferrer",
441
+ 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",
442
+ title: file.fileName || "Open file",
443
+ children: [
444
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.FileText, { className: "w-3.5 h-3.5 shrink-0" }),
445
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "truncate", children: file.fileName || "Unnamed file" })
446
+ ]
447
+ }
448
+ ),
449
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
450
+ "button",
451
+ {
452
+ type: "button",
453
+ onClick: () => handleRemoveFile(idx),
454
+ className: "shrink-0 p-0.5 rounded hover:bg-rose-100 text-slate-400 hover:text-rose-500 transition-colors",
455
+ title: "Remove file",
456
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.X, { className: "w-3.5 h-3.5" })
457
+ }
458
+ )
459
+ ] }, file.fileId || idx)),
460
+ renderUploadButton()
461
+ ] });
462
+ }
463
+ return renderUploadButton();
400
464
  }
401
465
 
402
466
  // src/components/TableBlock/fields/DatePickerCell.tsx
@@ -831,11 +895,13 @@ var FORM_INPUTS = {
831
895
  className: "w-4 h-4 rounded border-slate-300 text-brand"
832
896
  }
833
897
  ) }),
834
- GOOGLE_DRIVE_FILE: ({ value, onChange, context }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
898
+ GOOGLE_DRIVE_FILE: ({ value, onChange, column, rowId, context }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
835
899
  DrivePickerCell,
836
900
  {
837
- value: value || null,
901
+ value: value || [],
838
902
  onChange,
903
+ column,
904
+ rowId,
839
905
  tableName: context == null ? void 0 : context.tableName,
840
906
  onMarkForDeletion: context == null ? void 0 : context.onMarkForDeletion,
841
907
  context
@@ -893,6 +959,249 @@ var FORM_INPUTS = {
893
959
  }
894
960
  }
895
961
  ),
962
+ PHONE: ({ value, onChange, column }) => {
963
+ var _a;
964
+ const enableWhatsApp = (_a = column == null ? void 0 : column.config) == null ? void 0 : _a.enableWhatsApp;
965
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center w-full h-full px-2 gap-1.5", children: [
966
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
967
+ "input",
968
+ {
969
+ type: "tel",
970
+ className: "w-full h-8 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm flex-1",
971
+ value: value !== void 0 && value !== null ? String(value) : "",
972
+ onChange: (e) => onChange(e.target.value),
973
+ dir: "ltr"
974
+ }
975
+ ),
976
+ enableWhatsApp && value && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
977
+ "button",
978
+ {
979
+ type: "button",
980
+ className: "text-emerald-500 cursor-pointer hover:opacity-80 transition-opacity shrink-0 p-1 rounded hover:bg-emerald-50",
981
+ title: "\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4",
982
+ onClick: (e) => {
983
+ e.stopPropagation();
984
+ openWhatsAppChat(String(value));
985
+ },
986
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "w-4 h-4", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) })
987
+ }
988
+ )
989
+ ] });
990
+ },
991
+ GOOGLE_CONTACT: ({ value, column, rowId, onChange, context }) => {
992
+ const [isSyncing, setIsSyncing] = import_react5.default.useState(false);
993
+ const { addToast } = useToast();
994
+ const googleClientIdRef = import_react5.default.useRef(null);
995
+ const ensureGisScript = import_react5.default.useCallback(() => {
996
+ return new Promise((resolve, reject) => {
997
+ var _a, _b, _c;
998
+ if ((_c = (_b = (_a = window.google) == null ? void 0 : _a.accounts) == null ? void 0 : _b.oauth2) == null ? void 0 : _c.initTokenClient) {
999
+ resolve();
1000
+ return;
1001
+ }
1002
+ if (document.querySelector('script[src*="accounts.google.com/gsi/client"]')) {
1003
+ const waitForLoad = setInterval(() => {
1004
+ var _a2, _b2, _c2;
1005
+ if ((_c2 = (_b2 = (_a2 = window.google) == null ? void 0 : _a2.accounts) == null ? void 0 : _b2.oauth2) == null ? void 0 : _c2.initTokenClient) {
1006
+ clearInterval(waitForLoad);
1007
+ resolve();
1008
+ }
1009
+ }, 100);
1010
+ setTimeout(() => {
1011
+ clearInterval(waitForLoad);
1012
+ reject(new Error("GIS script load timeout"));
1013
+ }, 1e4);
1014
+ return;
1015
+ }
1016
+ const script = document.createElement("script");
1017
+ script.src = "https://accounts.google.com/gsi/client";
1018
+ script.async = true;
1019
+ script.onload = () => resolve();
1020
+ script.onerror = () => reject(new Error("Failed to load Google Identity Services"));
1021
+ document.head.appendChild(script);
1022
+ });
1023
+ }, []);
1024
+ const requestGisToken = import_react5.default.useCallback(async (hint) => {
1025
+ await ensureGisScript();
1026
+ if (!googleClientIdRef.current && (context == null ? void 0 : context.executeAction)) {
1027
+ try {
1028
+ const config = await context.executeAction("GET_GOOGLE_CONFIG", {});
1029
+ googleClientIdRef.current = (config == null ? void 0 : config.clientId) || "";
1030
+ } catch (e) {
1031
+ throw new Error("Failed to fetch Google configuration");
1032
+ }
1033
+ }
1034
+ const clientId = googleClientIdRef.current;
1035
+ if (!clientId) {
1036
+ throw new Error("Google Client ID is not configured");
1037
+ }
1038
+ const accessToken = await new Promise((resolve, reject) => {
1039
+ const tokenClient = window.google.accounts.oauth2.initTokenClient({
1040
+ client_id: clientId,
1041
+ scope: "https://www.googleapis.com/auth/contacts https://www.googleapis.com/auth/userinfo.email",
1042
+ prompt: hint ? "" : "select_account",
1043
+ hint: hint || void 0,
1044
+ callback: (tokenResponse) => {
1045
+ if (tokenResponse == null ? void 0 : tokenResponse.access_token) {
1046
+ resolve(tokenResponse.access_token);
1047
+ } else {
1048
+ reject(new Error("Google authorization was cancelled or failed"));
1049
+ }
1050
+ },
1051
+ error_callback: (err) => {
1052
+ reject(new Error((err == null ? void 0 : err.message) || "Google authorization error"));
1053
+ }
1054
+ });
1055
+ tokenClient.requestAccessToken({ hint: hint || void 0 });
1056
+ });
1057
+ let email = "";
1058
+ try {
1059
+ const res = await fetch("https://www.googleapis.com/oauth2/v3/userinfo", {
1060
+ headers: { Authorization: `Bearer ${accessToken}` }
1061
+ });
1062
+ if (res.ok) {
1063
+ const info = await res.json();
1064
+ email = info.email || "";
1065
+ }
1066
+ } catch (e) {
1067
+ }
1068
+ return { accessToken, email };
1069
+ }, [ensureGisScript, context]);
1070
+ const handleSync = async () => {
1071
+ var _a, _b, _c;
1072
+ if (!(context == null ? void 0 : context.executeAction)) return;
1073
+ setIsSyncing(true);
1074
+ try {
1075
+ const mapping = column.contactMapping || {};
1076
+ const rowData = context.rowData || {};
1077
+ let hasPhone = false;
1078
+ if (mapping.phoneCol && rowData[mapping.phoneCol]) hasPhone = true;
1079
+ let hasName = false;
1080
+ if (mapping.nameParts && Array.isArray(mapping.nameParts)) {
1081
+ for (const part of mapping.nameParts) {
1082
+ if (part.type === "LOCAL" && rowData[part.columnId]) hasName = true;
1083
+ 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;
1084
+ }
1085
+ }
1086
+ if (!hasPhone) {
1087
+ 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" });
1088
+ setIsSyncing(false);
1089
+ return;
1090
+ }
1091
+ if (!hasName) {
1092
+ 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" });
1093
+ setIsSyncing(false);
1094
+ return;
1095
+ }
1096
+ let accessToken;
1097
+ let userEmail = "";
1098
+ try {
1099
+ const gisResult = await requestGisToken();
1100
+ accessToken = gisResult.accessToken;
1101
+ userEmail = gisResult.email;
1102
+ } catch (gisError) {
1103
+ addToast({ type: "warning", message: gisError.message || "\u05D4\u05D4\u05E8\u05E9\u05D0\u05D4 \u05DC\u05D2\u05D5\u05D2\u05DC \u05E0\u05DB\u05E9\u05DC\u05D4" });
1104
+ setIsSyncing(false);
1105
+ return;
1106
+ }
1107
+ const payload = {
1108
+ nameParts: mapping.nameParts || [],
1109
+ phoneCol: mapping.phoneCol,
1110
+ emailCol: mapping.emailCol,
1111
+ localRowData: rowData,
1112
+ parentRecord: context.parentRecord,
1113
+ accessToken,
1114
+ userEmail
1115
+ };
1116
+ const res = await context.executeAction("SYNC_GOOGLE_CONTACT", payload);
1117
+ if (res && res.synced) {
1118
+ if (context.updateQuietly) {
1119
+ context.updateQuietly(rowId, column.name, res);
1120
+ } else {
1121
+ onChange(res);
1122
+ }
1123
+ if (context.tableId && !rowId.startsWith("temp_")) {
1124
+ await context.executeAction("UPDATE_RECORD", {
1125
+ tableId: context.tableId,
1126
+ recordId: rowId,
1127
+ data: { [column.name]: res }
1128
+ });
1129
+ }
1130
+ }
1131
+ } catch (error) {
1132
+ console.error("Failed to sync contact:", error);
1133
+ addToast({ type: "warning", message: "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E1\u05E0\u05DB\u05E8\u05D5\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8: " + error.message });
1134
+ } finally {
1135
+ setIsSyncing(false);
1136
+ }
1137
+ };
1138
+ const handleUnlink = async () => {
1139
+ let accessToken;
1140
+ try {
1141
+ let emailHint = value == null ? void 0 : value.userEmail;
1142
+ if (!emailHint && (value == null ? void 0 : value.url)) {
1143
+ try {
1144
+ const parsed = new URL(value.url);
1145
+ emailHint = parsed.searchParams.get("authuser") || void 0;
1146
+ } catch (e) {
1147
+ }
1148
+ }
1149
+ const auth = await requestGisToken(emailHint);
1150
+ accessToken = auth.accessToken;
1151
+ } catch (err) {
1152
+ console.warn("[handleUnlink] Could not obtain token via GIS, falling back to server default token:", err);
1153
+ }
1154
+ if ((value == null ? void 0 : value.resourceName) && (context == null ? void 0 : context.executeAction)) {
1155
+ await context.executeAction("DELETE_GOOGLE_CONTACT", {
1156
+ resourceName: value.resourceName,
1157
+ accessToken
1158
+ });
1159
+ }
1160
+ if (context == null ? void 0 : context.updateQuietly) {
1161
+ context.updateQuietly(rowId, column.name, null);
1162
+ } else {
1163
+ onChange(null);
1164
+ }
1165
+ if ((context == null ? void 0 : context.tableId) && (context == null ? void 0 : context.executeAction) && !rowId.startsWith("temp_")) {
1166
+ await context.executeAction("UPDATE_RECORD", {
1167
+ tableId: context.tableId,
1168
+ recordId: rowId,
1169
+ data: { [column.name]: null }
1170
+ });
1171
+ }
1172
+ };
1173
+ if (value && value.synced && value.url) {
1174
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1.5 h-8 px-2 group whitespace-nowrap", children: [
1175
+ /* @__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-xs whitespace-nowrap", children: "\u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05D2\u05D5\u05D2\u05DC" }),
1176
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1177
+ "button",
1178
+ {
1179
+ type: "button",
1180
+ onClick: handleUnlink,
1181
+ className: "text-slate-400 hover:text-rose-500 opacity-0 group-hover:opacity-100 transition-opacity p-1 shrink-0",
1182
+ title: "\u05D1\u05D8\u05DC \u05E1\u05E0\u05DB\u05E8\u05D5\u05DF",
1183
+ children: /* @__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: "M6 18L18 6M6 6l12 12" }) })
1184
+ }
1185
+ )
1186
+ ] });
1187
+ }
1188
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex items-center h-8 px-2 whitespace-nowrap", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1189
+ "button",
1190
+ {
1191
+ type: "button",
1192
+ onClick: handleSync,
1193
+ disabled: isSyncing,
1194
+ className: "inline-flex items-center gap-1.5 px-2.5 py-1 bg-blue-50 text-blue-600 hover:bg-blue-100 border border-blue-200 rounded-md text-xs font-medium transition-colors whitespace-nowrap shrink-0 disabled:opacity-50 cursor-pointer",
1195
+ children: [
1196
+ isSyncing ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "w-3.5 h-3.5 animate-spin shrink-0", viewBox: "0 0 24 24", fill: "none", children: [
1197
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
1198
+ /* @__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" })
1199
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "w-3.5 h-3.5 shrink-0", 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" }) }),
1200
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "whitespace-nowrap", children: "\u05E1\u05E0\u05DB\u05E8\u05DF \u05DC\u05D2\u05D5\u05D2\u05DC" })
1201
+ ]
1202
+ }
1203
+ ) });
1204
+ },
896
1205
  DEFAULT: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
897
1206
  "input",
898
1207
  {
@@ -901,12 +1210,1045 @@ var FORM_INPUTS = {
901
1210
  value: value !== void 0 && value !== null ? String(value) : "",
902
1211
  onChange: (e) => onChange(e.target.value)
903
1212
  }
904
- )
1213
+ ),
1214
+ SUB_TABLE: ({ value, column }) => {
1215
+ var _a, _b;
1216
+ 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" });
1217
+ const selected = value.filter((e) => e == null ? void 0 : e.isSelected);
1218
+ 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" });
1219
+ const displayFields = column.subTableDisplayFields || [];
1220
+ const isWhatsApp = ((_a = column.config) == null ? void 0 : _a.actionType) === "WHATSAPP";
1221
+ const actionPhoneCol = (_b = column.config) == null ? void 0 : _b.actionPhoneColumn;
1222
+ 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) => {
1223
+ var _a2, _b2;
1224
+ let label = "";
1225
+ if (entry._resolvedData) {
1226
+ if (displayFields.length > 0) {
1227
+ label = displayFields.map((f) => String(entry._resolvedData[f] || "")).filter(Boolean).join(" ");
1228
+ } else {
1229
+ const firstField = Object.keys(entry._resolvedData).find((k) => k !== "_id");
1230
+ if (firstField) label = String(entry._resolvedData[firstField] || "");
1231
+ }
1232
+ }
1233
+ if (!label) label = ((_a2 = entry.recordId) == null ? void 0 : _a2.slice(-6)) || "...";
1234
+ if (isWhatsApp) {
1235
+ const rawPhone = actionPhoneCol ? (_b2 = entry._resolvedData) == null ? void 0 : _b2[actionPhoneCol] : null;
1236
+ const phone = rawPhone ? String(rawPhone).trim() : null;
1237
+ if (phone) {
1238
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1239
+ "button",
1240
+ {
1241
+ type: "button",
1242
+ onClick: (e) => {
1243
+ e.stopPropagation();
1244
+ openWhatsAppChat(phone);
1245
+ },
1246
+ className: "inline-flex items-center gap-1 px-1.5 py-0.5 bg-emerald-50 hover:bg-emerald-100 text-emerald-800 border border-emerald-300 hover:border-emerald-400 rounded-full text-xs font-medium max-w-[150px] truncate cursor-pointer transition-colors shadow-xs",
1247
+ title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
1248
+ children: [
1249
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "w-3 h-3 text-emerald-600 shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) }),
1250
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "truncate", children: label })
1251
+ ]
1252
+ },
1253
+ entry.recordId || idx
1254
+ );
1255
+ }
1256
+ }
1257
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1258
+ "span",
1259
+ {
1260
+ 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",
1261
+ title: label,
1262
+ children: label
1263
+ },
1264
+ entry.recordId || idx
1265
+ );
1266
+ }) });
1267
+ }
905
1268
  };
906
1269
 
1270
+ // src/components/TableBlock/fields/SubTableViewer.tsx
1271
+ var import_react6 = require("react");
1272
+
1273
+ // src/utils/phone.ts
1274
+ function sanitizePhoneNumber(phone) {
1275
+ if (!phone) return "";
1276
+ const trimmed = phone.trim();
1277
+ const hasLeadingPlus = trimmed.startsWith("+");
1278
+ const digitsOnly = trimmed.replace(/\D/g, "");
1279
+ return hasLeadingPlus ? `+${digitsOnly}` : digitsOnly;
1280
+ }
1281
+ function isValidPhoneNumber(phone) {
1282
+ if (!phone) return false;
1283
+ const cleaned = sanitizePhoneNumber(phone);
1284
+ return /^\+?[0-9]{9,15}$/.test(cleaned);
1285
+ }
1286
+
1287
+ // src/components/TableBlock/fields/SubTableViewer.tsx
1288
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1289
+ function validateCellValue(val, col) {
1290
+ var _a;
1291
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
1292
+ const isEmpty = val === void 0 || val === null || typeof val === "string" && val.trim() === "";
1293
+ if (col.isRequired && isEmpty) {
1294
+ return {
1295
+ isValid: false,
1296
+ error: `\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA: \u05E9\u05D3\u05D4 '${col.name}' \u05D4\u05D9\u05E0\u05D5 \u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4 \u05D5\u05DC\u05D0 \u05D9\u05DB\u05D5\u05DC \u05DC\u05D4\u05D9\u05E9\u05D0\u05E8 \u05E8\u05D9\u05E7.`
1297
+ };
1298
+ }
1299
+ if (isEmpty) {
1300
+ return { isValid: true };
1301
+ }
1302
+ if (colType === "PHONE") {
1303
+ const strVal = String(val).trim();
1304
+ if (!isValidPhoneNumber(strVal)) {
1305
+ return {
1306
+ isValid: false,
1307
+ error: `\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 '${col.name}' \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA (\u05DC\u05D3\u05D5\u05D2\u05DE\u05D4 0501234567 \u05D0\u05D5 +972501234567).`
1308
+ };
1309
+ }
1310
+ }
1311
+ if (colType === "NUMBER" || colType === "CURRENCY") {
1312
+ if (typeof val === "string" && isNaN(Number(val))) {
1313
+ return {
1314
+ isValid: false,
1315
+ error: `\u05D4\u05E2\u05E8\u05DA \u05D1\u05E9\u05D3\u05D4 '${col.name}' \u05D7\u05D9\u05D9\u05D1 \u05DC\u05D4\u05D9\u05D5\u05EA \u05DE\u05E1\u05E4\u05E8 \u05EA\u05E7\u05D9\u05DF.`
1316
+ };
1317
+ }
1318
+ }
1319
+ return { isValid: true };
1320
+ }
1321
+ function SubTableCell({
1322
+ record,
1323
+ column,
1324
+ targetSchema,
1325
+ referencedTableId,
1326
+ context,
1327
+ relationOptions,
1328
+ setRelationOptions,
1329
+ refetchRelation,
1330
+ onCommit
1331
+ }) {
1332
+ var _a, _b;
1333
+ const colType = ((_a = column.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
1334
+ const isContact = colType === "GOOGLE_CONTACT";
1335
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
1336
+ const serverValue = (_b = record.data[column.name]) != null ? _b : colType === "BOOLEAN" ? false : "";
1337
+ const [draftValue, setDraftValue] = (0, import_react6.useState)(serverValue);
1338
+ const [isDirty, setIsDirty] = (0, import_react6.useState)(false);
1339
+ const [validationError, setValidationError] = (0, import_react6.useState)(null);
1340
+ const cellRef = (0, import_react6.useRef)(null);
1341
+ const draftRef = (0, import_react6.useRef)(draftValue);
1342
+ const isDirtyRef = (0, import_react6.useRef)(isDirty);
1343
+ const serverValueRef = (0, import_react6.useRef)(serverValue);
1344
+ const recordIdRef = (0, import_react6.useRef)(record.id);
1345
+ const columnRef = (0, import_react6.useRef)(column);
1346
+ const onCommitRef = (0, import_react6.useRef)(onCommit);
1347
+ const isCommittingRef = (0, import_react6.useRef)(false);
1348
+ const lastFailedValRef = (0, import_react6.useRef)(void 0);
1349
+ const { addToast } = useToast();
1350
+ draftRef.current = draftValue;
1351
+ isDirtyRef.current = isDirty;
1352
+ serverValueRef.current = serverValue;
1353
+ recordIdRef.current = record.id;
1354
+ columnRef.current = column;
1355
+ onCommitRef.current = onCommit;
1356
+ (0, import_react6.useEffect)(() => {
1357
+ if (!isDirtyRef.current) {
1358
+ setDraftValue(serverValue);
1359
+ draftRef.current = serverValue;
1360
+ setValidationError(null);
1361
+ lastFailedValRef.current = void 0;
1362
+ }
1363
+ }, [serverValue]);
1364
+ const commit = (0, import_react6.useCallback)(async (valToCommit) => {
1365
+ if (isCommittingRef.current) return false;
1366
+ if (!isDirtyRef.current) return true;
1367
+ if (valToCommit === serverValueRef.current) {
1368
+ setIsDirty(false);
1369
+ isDirtyRef.current = false;
1370
+ setValidationError(null);
1371
+ lastFailedValRef.current = void 0;
1372
+ return true;
1373
+ }
1374
+ const valRes = validateCellValue(valToCommit, columnRef.current);
1375
+ if (!valRes.isValid) {
1376
+ const errorMsg = valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA";
1377
+ setValidationError(errorMsg);
1378
+ if (lastFailedValRef.current !== valToCommit) {
1379
+ addToast({ type: "error", message: errorMsg });
1380
+ lastFailedValRef.current = valToCommit;
1381
+ }
1382
+ return false;
1383
+ }
1384
+ try {
1385
+ isCommittingRef.current = true;
1386
+ const success = await onCommitRef.current(recordIdRef.current, columnRef.current.name, valToCommit);
1387
+ if (success) {
1388
+ setIsDirty(false);
1389
+ isDirtyRef.current = false;
1390
+ serverValueRef.current = valToCommit;
1391
+ setValidationError(null);
1392
+ lastFailedValRef.current = void 0;
1393
+ return true;
1394
+ } else {
1395
+ setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
1396
+ return false;
1397
+ }
1398
+ } catch (e) {
1399
+ setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
1400
+ return false;
1401
+ } finally {
1402
+ isCommittingRef.current = false;
1403
+ }
1404
+ }, [addToast]);
1405
+ const discard = (0, import_react6.useCallback)(() => {
1406
+ setDraftValue(serverValueRef.current);
1407
+ draftRef.current = serverValueRef.current;
1408
+ setIsDirty(false);
1409
+ isDirtyRef.current = false;
1410
+ setValidationError(null);
1411
+ lastFailedValRef.current = void 0;
1412
+ }, []);
1413
+ (0, import_react6.useEffect)(() => {
1414
+ return () => {
1415
+ if (isDirtyRef.current && !isCommittingRef.current) {
1416
+ const val = draftRef.current;
1417
+ const orig = serverValueRef.current;
1418
+ if (val !== orig) {
1419
+ const valRes = validateCellValue(val, columnRef.current);
1420
+ if (valRes.isValid) {
1421
+ onCommitRef.current(recordIdRef.current, columnRef.current.name, val);
1422
+ }
1423
+ }
1424
+ }
1425
+ };
1426
+ }, []);
1427
+ const handleChange = (newVal) => {
1428
+ setDraftValue(newVal);
1429
+ draftRef.current = newVal;
1430
+ setIsDirty(true);
1431
+ isDirtyRef.current = true;
1432
+ if (validationError) {
1433
+ setValidationError(null);
1434
+ lastFailedValRef.current = void 0;
1435
+ }
1436
+ if (colType === "BOOLEAN" || colType === "GOOGLE_DRIVE_FILE") {
1437
+ commit(newVal);
1438
+ }
1439
+ };
1440
+ const handleBlur = (e) => {
1441
+ if (e.currentTarget.contains(e.relatedTarget)) {
1442
+ return;
1443
+ }
1444
+ if (isDirtyRef.current) {
1445
+ commit(draftRef.current);
1446
+ }
1447
+ };
1448
+ const handleKeyDown = (e) => {
1449
+ var _a2, _b2, _c, _d;
1450
+ if (e.key === "Enter") {
1451
+ e.preventDefault();
1452
+ if (isDirtyRef.current) {
1453
+ commit(draftRef.current);
1454
+ }
1455
+ (_b2 = (_a2 = e.target) == null ? void 0 : _a2.blur) == null ? void 0 : _b2.call(_a2);
1456
+ } else if (e.key === "Escape") {
1457
+ e.preventDefault();
1458
+ discard();
1459
+ (_d = (_c = e.target) == null ? void 0 : _c.blur) == null ? void 0 : _d.call(_c);
1460
+ }
1461
+ };
1462
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1463
+ "td",
1464
+ {
1465
+ ref: cellRef,
1466
+ onBlur: handleBlur,
1467
+ onKeyDown: handleKeyDown,
1468
+ title: validationError || void 0,
1469
+ className: `border border-slate-200 p-0 relative h-8 transition-colors ${isContact ? "min-w-[140px]" : ""} ${validationError ? "border-rose-400 ring-1 ring-rose-400 bg-rose-50/20" : ""}`,
1470
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1471
+ InputComponent,
1472
+ {
1473
+ value: draftValue,
1474
+ column,
1475
+ rowId: record.id,
1476
+ onChange: handleChange,
1477
+ context: __spreadProps(__spreadValues({}, context), {
1478
+ 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",
1479
+ relationOptions,
1480
+ updateRelationOptions: (name, opts) => setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [name]: opts })),
1481
+ refetchRelation,
1482
+ parentRecord: { tableId: (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId), data: context == null ? void 0 : context.rowData },
1483
+ rowData: record.data,
1484
+ tableId: (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId,
1485
+ updateQuietly: (rid, colName, val) => onCommitRef.current(rid, colName, val)
1486
+ })
1487
+ }
1488
+ )
1489
+ }
1490
+ );
1491
+ }
1492
+ function SubTableViewer({ rowId, column, value, onChange, context }) {
1493
+ var _a, _b;
1494
+ const { addToast } = useToast();
1495
+ const entries = Array.isArray(value) ? value : [];
1496
+ const [linkedRecords, setLinkedRecords] = (0, import_react6.useState)(() => {
1497
+ const initial = [];
1498
+ if (Array.isArray(value)) {
1499
+ for (const entry of value) {
1500
+ if (entry.recordId && entry._resolvedData) {
1501
+ initial.push({ id: entry.recordId, data: entry._resolvedData });
1502
+ }
1503
+ }
1504
+ }
1505
+ return initial;
1506
+ });
1507
+ const [targetSchema, setTargetSchema] = (0, import_react6.useState)(null);
1508
+ const [isLoading, setIsLoading] = (0, import_react6.useState)(true);
1509
+ const [isSearchOpen, setIsSearchOpen] = (0, import_react6.useState)(false);
1510
+ const [searchQuery, setSearchQuery] = (0, import_react6.useState)("");
1511
+ const [searchResults, setSearchResults] = (0, import_react6.useState)([]);
1512
+ const [isSearching, setIsSearching] = (0, import_react6.useState)(false);
1513
+ const [isCreating, setIsCreating] = (0, import_react6.useState)(false);
1514
+ const [newRecordData, setNewRecordData] = (0, import_react6.useState)({});
1515
+ const [conflictModalState, setConflictModalState] = (0, import_react6.useState)({
1516
+ isOpen: false,
1517
+ fieldName: "",
1518
+ matchingRecords: []
1519
+ });
1520
+ const searchRef = (0, import_react6.useRef)(null);
1521
+ const searchTimerRef = (0, import_react6.useRef)(null);
1522
+ const executeAction = context == null ? void 0 : context.executeAction;
1523
+ const referencedTableId = column.referencedTableId;
1524
+ const fetchedIdsRef = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
1525
+ (0, import_react6.useEffect)(() => {
1526
+ if (entries.length > 0) {
1527
+ setLinkedRecords((prev) => {
1528
+ const existingIds = new Set(prev.map((r) => r.id));
1529
+ const toAdd = [];
1530
+ for (const entry of entries) {
1531
+ if (entry.recordId && entry._resolvedData && !existingIds.has(entry.recordId)) {
1532
+ toAdd.push({ id: entry.recordId, data: entry._resolvedData });
1533
+ existingIds.add(entry.recordId);
1534
+ }
1535
+ }
1536
+ return toAdd.length > 0 ? [...prev, ...toAdd] : prev;
1537
+ });
1538
+ }
1539
+ }, [entries]);
1540
+ (0, import_react6.useEffect)(() => {
1541
+ if (!referencedTableId || !executeAction) {
1542
+ setIsLoading(false);
1543
+ return;
1544
+ }
1545
+ const recordIdsToFetch = entries.map((e) => e.recordId).filter((id) => !fetchedIdsRef.current.has(id));
1546
+ if (recordIdsToFetch.length === 0 && targetSchema) return;
1547
+ if (recordIdsToFetch.length > 0) {
1548
+ recordIdsToFetch.forEach((id) => fetchedIdsRef.current.add(id));
1549
+ }
1550
+ setIsLoading(true);
1551
+ executeAction("FETCH_SUB_TABLE_RECORDS", { referencedTableId, recordIds: recordIdsToFetch }).then((res) => {
1552
+ const payload = (res == null ? void 0 : res.data) || res;
1553
+ if (payload == null ? void 0 : payload.records) {
1554
+ setLinkedRecords((prev) => {
1555
+ const map = new Map(prev.map((r) => [r.id, r]));
1556
+ payload.records.forEach((r) => map.set(r.id, r));
1557
+ return Array.from(map.values());
1558
+ });
1559
+ }
1560
+ if (payload == null ? void 0 : payload.schema) {
1561
+ setTargetSchema(payload.schema);
1562
+ }
1563
+ }).catch(() => {
1564
+ recordIdsToFetch.forEach((id) => fetchedIdsRef.current.delete(id));
1565
+ }).finally(() => setIsLoading(false));
1566
+ }, [referencedTableId, executeAction, entries, targetSchema]);
1567
+ (0, import_react6.useEffect)(() => {
1568
+ const handleClick = (e) => {
1569
+ if (searchRef.current && !searchRef.current.contains(e.target)) {
1570
+ setIsSearchOpen(false);
1571
+ }
1572
+ };
1573
+ if (isSearchOpen) document.addEventListener("mousedown", handleClick);
1574
+ return () => document.removeEventListener("mousedown", handleClick);
1575
+ }, [isSearchOpen]);
1576
+ const handleSearch = (0, import_react6.useCallback)((query) => {
1577
+ setSearchQuery(query);
1578
+ if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
1579
+ if (!query.trim()) {
1580
+ setSearchResults([]);
1581
+ return;
1582
+ }
1583
+ searchTimerRef.current = setTimeout(async () => {
1584
+ if (!executeAction || !referencedTableId) return;
1585
+ setIsSearching(true);
1586
+ try {
1587
+ const excludeIds = entries.map((e) => e.recordId);
1588
+ const res = await executeAction("SEARCH_SUB_TABLE_RECORDS", {
1589
+ referencedTableId,
1590
+ query: query.trim(),
1591
+ excludeIds,
1592
+ limit: 15
1593
+ });
1594
+ setSearchResults(Array.isArray(res) ? res : []);
1595
+ } catch (e) {
1596
+ setSearchResults([]);
1597
+ } finally {
1598
+ setIsSearching(false);
1599
+ }
1600
+ }, 300);
1601
+ }, [executeAction, referencedTableId, entries]);
1602
+ const targetColumns = ((targetSchema == null ? void 0 : targetSchema.columns) || []).filter(
1603
+ (c) => {
1604
+ if (c.name === "_id" || c.type === "SUB_TABLE") return false;
1605
+ return true;
1606
+ }
1607
+ );
1608
+ const [relationOptions, setRelationOptions] = (0, import_react6.useState)({});
1609
+ (0, import_react6.useEffect)(() => {
1610
+ if (!executeAction || targetColumns.length === 0) return;
1611
+ const relationCols = targetColumns.filter((c) => {
1612
+ var _a2;
1613
+ return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION" && c.referencedTableId;
1614
+ });
1615
+ relationCols.forEach(async (col) => {
1616
+ try {
1617
+ const options = await executeAction("FETCH_RELATION", {
1618
+ referencedTableId: col.referencedTableId,
1619
+ displayField: col.displayField
1620
+ });
1621
+ if (options && Array.isArray(options)) {
1622
+ setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
1623
+ }
1624
+ } catch (err) {
1625
+ console.warn(`[SubTableViewer] Could not fetch relation options for column ${col.name}:`, err);
1626
+ }
1627
+ });
1628
+ }, [executeAction, targetColumns]);
1629
+ const refetchRelation = (0, import_react6.useCallback)(async (colName) => {
1630
+ var _a2;
1631
+ const col = targetColumns.find((c) => c.name === colName);
1632
+ if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !col.referencedTableId || !executeAction) return;
1633
+ try {
1634
+ const options = await executeAction("FETCH_RELATION", { referencedTableId: col.referencedTableId, displayField: col.displayField });
1635
+ if (options && Array.isArray(options)) {
1636
+ setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
1637
+ }
1638
+ } catch (err) {
1639
+ console.warn(`[SubTableViewer] Could not refetch relation options for column ${col.name}:`, err);
1640
+ }
1641
+ }, [targetColumns, executeAction]);
1642
+ const updateParentLinkage = async (updated) => {
1643
+ const isNewRow = rowId.startsWith("temp_");
1644
+ if (context == null ? void 0 : context.updateQuietly) {
1645
+ context.updateQuietly(rowId, column.name, updated);
1646
+ } else {
1647
+ onChange(updated);
1648
+ }
1649
+ if (executeAction && (context == null ? void 0 : context.parentTableId) && !isNewRow) {
1650
+ try {
1651
+ const payloadToSave = updated.map(({ recordId, isSelected }) => ({ recordId, isSelected }));
1652
+ await executeAction("UPDATE_RECORD", {
1653
+ tableId: context.parentTableId,
1654
+ recordId: rowId,
1655
+ data: { [column.name]: payloadToSave }
1656
+ });
1657
+ if (context == null ? void 0 : context.triggerSaveSuccess) {
1658
+ context.triggerSaveSuccess();
1659
+ }
1660
+ } catch (err) {
1661
+ console.error("Failed to auto-save parent linkage", err);
1662
+ }
1663
+ }
1664
+ };
1665
+ const handleLinkRecords = (recordsToLink) => {
1666
+ if (!recordsToLink || recordsToLink.length === 0) return;
1667
+ const existingEntryIds = new Set(entries.map((e) => e.recordId));
1668
+ const newEntries = [];
1669
+ const newRecordsToAdd = [];
1670
+ for (const record of recordsToLink) {
1671
+ fetchedIdsRef.current.add(record.id);
1672
+ const resolvedData = __spreadValues({}, record.data || {});
1673
+ targetColumns.forEach((col) => {
1674
+ if ((resolvedData[col.name] === void 0 || resolvedData[col.name] === null) && record[col.name] !== void 0) {
1675
+ resolvedData[col.name] = record[col.name];
1676
+ }
1677
+ });
1678
+ if (!existingEntryIds.has(record.id)) {
1679
+ newEntries.push({
1680
+ recordId: record.id,
1681
+ isSelected: true,
1682
+ _resolvedData: resolvedData
1683
+ });
1684
+ existingEntryIds.add(record.id);
1685
+ }
1686
+ newRecordsToAdd.push({
1687
+ id: record.id,
1688
+ data: resolvedData
1689
+ });
1690
+ }
1691
+ const updatedEntries = [...entries, ...newEntries];
1692
+ updateParentLinkage(updatedEntries);
1693
+ setLinkedRecords((prev) => {
1694
+ const map = new Map(prev.map((r) => [r.id, r]));
1695
+ newRecordsToAdd.forEach((r) => {
1696
+ const existing = map.get(r.id);
1697
+ if (existing) {
1698
+ map.set(r.id, __spreadProps(__spreadValues({}, existing), {
1699
+ data: __spreadValues(__spreadValues({}, existing.data), r.data)
1700
+ }));
1701
+ } else {
1702
+ map.set(r.id, r);
1703
+ }
1704
+ });
1705
+ return Array.from(map.values());
1706
+ });
1707
+ setSearchQuery("");
1708
+ setSearchResults([]);
1709
+ setIsSearchOpen(false);
1710
+ };
1711
+ const handleLinkRecord = (record) => {
1712
+ handleLinkRecords([record]);
1713
+ };
1714
+ const handleUniqueConflict = (conflictData) => {
1715
+ const rawMatching = Array.isArray(conflictData == null ? void 0 : conflictData.matchingRecords) ? conflictData.matchingRecords : [];
1716
+ const resolvedMatching = rawMatching.map((r) => {
1717
+ var _a2;
1718
+ const recordId = String(r.id || ((_a2 = r._id) == null ? void 0 : _a2.$oid) || r._id);
1719
+ let dataObj = {};
1720
+ if (r.data && typeof r.data === "object") {
1721
+ dataObj = __spreadValues({}, r.data);
1722
+ }
1723
+ targetColumns.forEach((col) => {
1724
+ if ((dataObj[col.name] === void 0 || dataObj[col.name] === null) && r[col.name] !== void 0) {
1725
+ dataObj[col.name] = r[col.name];
1726
+ }
1727
+ });
1728
+ return {
1729
+ id: recordId,
1730
+ data: dataObj
1731
+ };
1732
+ });
1733
+ setConflictModalState({
1734
+ isOpen: true,
1735
+ fieldName: (conflictData == null ? void 0 : conflictData.fieldName) || "",
1736
+ matchingRecords: resolvedMatching
1737
+ });
1738
+ };
1739
+ const handleCancelConflict = () => {
1740
+ setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
1741
+ };
1742
+ const handleConfirmLinkConflict = async () => {
1743
+ const { matchingRecords } = conflictModalState;
1744
+ if (matchingRecords && matchingRecords.length > 0) {
1745
+ handleLinkRecords(matchingRecords);
1746
+ setNewRecordData({});
1747
+ setIsCreating(false);
1748
+ setConflictModalState({
1749
+ isOpen: false,
1750
+ fieldName: "",
1751
+ matchingRecords: []
1752
+ });
1753
+ addToast({
1754
+ type: "success",
1755
+ message: "\u05D4\u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D5\u05E9\u05E8\u05D4 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
1756
+ });
1757
+ } else {
1758
+ setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
1759
+ }
1760
+ };
1761
+ const handleUnlinkRecord = (recordId) => {
1762
+ const updated = entries.filter((e) => e.recordId !== recordId);
1763
+ updateParentLinkage(updated);
1764
+ setLinkedRecords((prev) => prev.filter((r) => r.id !== recordId));
1765
+ };
1766
+ const handleToggleSelected = (recordId) => {
1767
+ const record = linkedRecords.find((r) => r.id === recordId);
1768
+ const updated = entries.map(
1769
+ (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { isSelected: !e.isSelected, _resolvedData: (record == null ? void 0 : record.data) || e._resolvedData }) : e
1770
+ );
1771
+ updateParentLinkage(updated);
1772
+ };
1773
+ const isMountedRef = (0, import_react6.useRef)(true);
1774
+ (0, import_react6.useEffect)(() => {
1775
+ isMountedRef.current = true;
1776
+ return () => {
1777
+ isMountedRef.current = false;
1778
+ };
1779
+ }, []);
1780
+ const handleCommitRecordCell = async (recordId, colName, value2) => {
1781
+ var _a2;
1782
+ const previousRecord = linkedRecords.find((r) => r.id === recordId);
1783
+ const previousValue = (_a2 = previousRecord == null ? void 0 : previousRecord.data) == null ? void 0 : _a2[colName];
1784
+ if (previousValue === value2) return true;
1785
+ const targetCol = targetColumns.find((c) => c.name === colName);
1786
+ const valRes = targetCol ? validateCellValue(value2, targetCol) : { isValid: true };
1787
+ if (!valRes.isValid) {
1788
+ addToast({
1789
+ type: "error",
1790
+ message: valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA"
1791
+ });
1792
+ return false;
1793
+ }
1794
+ if (executeAction && referencedTableId && !recordId.startsWith("temp_")) {
1795
+ try {
1796
+ const res = await executeAction("UPDATE_RECORD", {
1797
+ tableId: referencedTableId,
1798
+ recordId,
1799
+ data: { [colName]: value2 }
1800
+ });
1801
+ if (res && res.success === false) {
1802
+ const err = new Error(res.error || res.message || "Action execution failed");
1803
+ Object.assign(err, res);
1804
+ throw err;
1805
+ }
1806
+ if (isMountedRef.current) {
1807
+ const updatedRecords = linkedRecords.map(
1808
+ (r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
1809
+ );
1810
+ setLinkedRecords(updatedRecords);
1811
+ const targetRecord = updatedRecords.find((r) => r.id === recordId);
1812
+ const updatedEntries = entries.map(
1813
+ (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
1814
+ );
1815
+ if (context == null ? void 0 : context.updateQuietly) {
1816
+ context.updateQuietly(rowId, column.name, updatedEntries);
1817
+ } else {
1818
+ onChange(updatedEntries);
1819
+ }
1820
+ if (context == null ? void 0 : context.triggerSaveSuccess) {
1821
+ context.triggerSaveSuccess();
1822
+ }
1823
+ }
1824
+ return true;
1825
+ } catch (err) {
1826
+ console.error("[SubTableViewer] Failed to auto-save linked record field", err);
1827
+ let errorMsg = (err == null ? void 0 : err.message) || (err == null ? void 0 : err.error) || "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4";
1828
+ if ((err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" || (err == null ? void 0 : err.code) === "UNIQUE_CONSTRAINT_CONFLICT" || errorMsg.includes("must be unique") || errorMsg.includes("Duplicate value detected") || errorMsg.includes("\u05DB\u05D1\u05E8 \u05E7\u05D9\u05D9\u05DE\u05EA") || errorMsg.includes("UNIQUE_CONSTRAINT_CONFLICT")) {
1829
+ errorMsg = `\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA: \u05D4\u05E2\u05E8\u05DA '${value2}' \u05DB\u05D1\u05E8 \u05E7\u05D9\u05D9\u05DD \u05D1\u05E9\u05D3\u05D4 '${colName}' (\u05E9\u05D3\u05D4 \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9).`;
1830
+ } else if (errorMsg.includes("is required") || errorMsg.includes("\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4") || errorMsg.toLowerCase().includes("required")) {
1831
+ errorMsg = `\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA: \u05E9\u05D3\u05D4 '${colName}' \u05D4\u05D9\u05E0\u05D5 \u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4 \u05D5\u05DC\u05D0 \u05D9\u05DB\u05D5\u05DC \u05DC\u05D4\u05D9\u05E9\u05D0\u05E8 \u05E8\u05D9\u05E7.`;
1832
+ }
1833
+ addToast({
1834
+ type: "error",
1835
+ message: errorMsg
1836
+ });
1837
+ return false;
1838
+ }
1839
+ } else {
1840
+ if (isMountedRef.current) {
1841
+ const updatedRecords = linkedRecords.map(
1842
+ (r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
1843
+ );
1844
+ setLinkedRecords(updatedRecords);
1845
+ const targetRecord = updatedRecords.find((r) => r.id === recordId);
1846
+ const updatedEntries = entries.map(
1847
+ (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
1848
+ );
1849
+ if (context == null ? void 0 : context.updateQuietly) {
1850
+ context.updateQuietly(rowId, column.name, updatedEntries);
1851
+ } else {
1852
+ onChange(updatedEntries);
1853
+ }
1854
+ }
1855
+ return true;
1856
+ }
1857
+ };
1858
+ const handleRecordCellChange = handleCommitRecordCell;
1859
+ const handleCreateRecord = async () => {
1860
+ var _a2, _b2, _c, _d, _e;
1861
+ if (!executeAction || !referencedTableId) return;
1862
+ for (const col of targetColumns) {
1863
+ if (col.isRequired) {
1864
+ const val = newRecordData[col.name];
1865
+ if (val === void 0 || val === null || typeof val === "string" && val.trim() === "") {
1866
+ addToast({
1867
+ type: "error",
1868
+ message: `Validation Error: Field '${col.name}' is required but was not provided.`
1869
+ });
1870
+ return;
1871
+ }
1872
+ }
1873
+ if (((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE") {
1874
+ const val = newRecordData[col.name];
1875
+ if (val !== void 0 && val !== null && String(val).trim() !== "" && !isValidPhoneNumber(String(val))) {
1876
+ addToast({
1877
+ type: "error",
1878
+ message: `\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 '${col.name}' \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA.`
1879
+ });
1880
+ return;
1881
+ }
1882
+ }
1883
+ }
1884
+ try {
1885
+ const res = await executeAction("CREATE_RECORD", {
1886
+ tableId: referencedTableId,
1887
+ records: [newRecordData]
1888
+ });
1889
+ if (res && (res.error === "UNIQUE_CONSTRAINT_CONFLICT" || res.code === "UNIQUE_CONSTRAINT_CONFLICT")) {
1890
+ handleUniqueConflict(res);
1891
+ return;
1892
+ }
1893
+ if (res && res.success === false) {
1894
+ throw new Error(res.error || "Action execution failed");
1895
+ }
1896
+ const created = Array.isArray(res) ? res[0] : ((_b2 = res == null ? void 0 : res.data) == null ? void 0 : _b2[0]) || res;
1897
+ if (created) {
1898
+ const newRecord = {
1899
+ id: String(created.id || created._id),
1900
+ data: created.data || newRecordData
1901
+ };
1902
+ handleLinkRecord(newRecord);
1903
+ setIsCreating(false);
1904
+ setNewRecordData({});
1905
+ }
1906
+ } catch (err) {
1907
+ const isConflict = (err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" || (err == null ? void 0 : err.code) === "UNIQUE_CONSTRAINT_CONFLICT" || ((_c = err == null ? void 0 : err.data) == null ? void 0 : _c.error) === "UNIQUE_CONSTRAINT_CONFLICT" || ((_d = err == null ? void 0 : err.message) == null ? void 0 : _d.includes("UNIQUE_CONSTRAINT_CONFLICT"));
1908
+ if (isConflict) {
1909
+ const conflictPayload = (err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" ? err : ((_e = err == null ? void 0 : err.data) == null ? void 0 : _e.error) === "UNIQUE_CONSTRAINT_CONFLICT" ? err.data : err;
1910
+ handleUniqueConflict(conflictPayload);
1911
+ return;
1912
+ }
1913
+ const msg = (err == null ? void 0 : err.message) || String(err);
1914
+ addToast({
1915
+ type: "error",
1916
+ message: msg
1917
+ });
1918
+ }
1919
+ };
1920
+ const getDisplayLabel = (record) => {
1921
+ const fields = column.subTableDisplayFields || [];
1922
+ if (fields.length === 0) {
1923
+ const firstField = Object.keys(record.data).find((k) => k !== "_id");
1924
+ return firstField ? String(record.data[firstField] || "") : record.id;
1925
+ }
1926
+ return fields.map((f) => String(record.data[f] || "")).filter(Boolean).join(" ");
1927
+ };
1928
+ 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: [
1929
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-4 mb-2.5", children: [
1930
+ /* @__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 }) }),
1931
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1.5", children: [
1932
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative", ref: searchRef, children: [
1933
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1934
+ "button",
1935
+ {
1936
+ type: "button",
1937
+ onClick: () => setIsSearchOpen((prev) => !prev),
1938
+ 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",
1939
+ children: [
1940
+ /* @__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" }) }),
1941
+ "\u05E7\u05D9\u05E9\u05D5\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA"
1942
+ ]
1943
+ }
1944
+ ),
1945
+ 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: [
1946
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1947
+ "input",
1948
+ {
1949
+ type: "text",
1950
+ value: searchQuery,
1951
+ onChange: (e) => handleSearch(e.target.value),
1952
+ placeholder: "\u05D7\u05E4\u05E9 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
1953
+ 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",
1954
+ autoFocus: true
1955
+ }
1956
+ ),
1957
+ /* @__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)(
1958
+ "button",
1959
+ {
1960
+ type: "button",
1961
+ onClick: () => handleLinkRecord(r),
1962
+ className: "w-full text-right px-2 py-1.5 text-xs hover:bg-blue-50 rounded cursor-pointer transition-colors",
1963
+ children: getDisplayLabel(r)
1964
+ },
1965
+ r.id
1966
+ )) : 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..." }) })
1967
+ ] })
1968
+ ] }),
1969
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1970
+ "button",
1971
+ {
1972
+ type: "button",
1973
+ onClick: () => {
1974
+ setIsCreating(true);
1975
+ const initialData = {};
1976
+ targetColumns.forEach((c) => {
1977
+ if (c.defaultValue !== void 0 && c.defaultValue !== null) {
1978
+ initialData[c.name] = c.type === "NUMBER" || c.type === "CURRENCY" ? parseFloat(c.defaultValue) : c.type === "BOOLEAN" ? c.defaultValue === "true" || c.defaultValue === true : c.defaultValue;
1979
+ } else {
1980
+ if (c.type === "NUMBER" || c.type === "CURRENCY") initialData[c.name] = 0;
1981
+ else if (c.type === "BOOLEAN") initialData[c.name] = false;
1982
+ else initialData[c.name] = "";
1983
+ }
1984
+ });
1985
+ setNewRecordData(initialData);
1986
+ },
1987
+ 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",
1988
+ children: [
1989
+ /* @__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" }) }),
1990
+ "\u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4"
1991
+ ]
1992
+ }
1993
+ )
1994
+ ] })
1995
+ ] }),
1996
+ 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: [
1997
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "bg-slate-100/80", children: [
1998
+ /* @__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" }),
1999
+ targetColumns.map((col) => {
2000
+ var _a2;
2001
+ const isContact = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "GOOGLE_CONTACT";
2002
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2003
+ "th",
2004
+ {
2005
+ className: `border border-slate-200 px-2 py-1.5 text-right font-semibold text-slate-600 whitespace-nowrap ${isContact ? "min-w-[140px]" : ""}`,
2006
+ children: col.name
2007
+ },
2008
+ col.name
2009
+ );
2010
+ }),
2011
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "border border-slate-200 px-2 py-1.5 w-14" })
2012
+ ] }) }),
2013
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tbody", { children: [
2014
+ entries.map((entry) => {
2015
+ var _a2;
2016
+ const record = linkedRecords.find((r) => r.id === entry.recordId);
2017
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors", children: [
2018
+ /* @__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)(
2019
+ "input",
2020
+ {
2021
+ type: "checkbox",
2022
+ checked: entry.isSelected,
2023
+ onChange: () => handleToggleSelected(entry.recordId),
2024
+ className: "w-3.5 h-3.5 rounded border-slate-300 text-blue-600 cursor-pointer"
2025
+ }
2026
+ ) }),
2027
+ targetColumns.map((col) => {
2028
+ var _a3;
2029
+ const isContact = ((_a3 = col.type) == null ? void 0 : _a3.toUpperCase()) === "GOOGLE_CONTACT";
2030
+ if (!record) {
2031
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2032
+ "td",
2033
+ {
2034
+ className: `border border-slate-200 p-0 relative h-8 ${isContact ? "min-w-[140px]" : ""}`,
2035
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-slate-300 italic px-2", children: "\u05D8\u05D5\u05E2\u05DF..." })
2036
+ },
2037
+ col.name
2038
+ );
2039
+ }
2040
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2041
+ SubTableCell,
2042
+ {
2043
+ record,
2044
+ column: col,
2045
+ targetSchema,
2046
+ referencedTableId,
2047
+ context,
2048
+ relationOptions,
2049
+ setRelationOptions,
2050
+ refetchRelation,
2051
+ onCommit: handleCommitRecordCell
2052
+ },
2053
+ `${record.id}_${col.name}`
2054
+ );
2055
+ }),
2056
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-slate-200 px-1 py-1 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-center gap-1", children: [
2057
+ ((_a2 = column.config) == null ? void 0 : _a2.actionType) === "WHATSAPP" && (() => {
2058
+ var _a3, _b2, _c;
2059
+ const actionPhoneCol = (_a3 = column.config) == null ? void 0 : _a3.actionPhoneColumn;
2060
+ const phone = actionPhoneCol ? ((_b2 = record == null ? void 0 : record.data) == null ? void 0 : _b2[actionPhoneCol]) || ((_c = entry._resolvedData) == null ? void 0 : _c[actionPhoneCol]) : null;
2061
+ if (phone) {
2062
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2063
+ "button",
2064
+ {
2065
+ type: "button",
2066
+ onClick: (e) => {
2067
+ e.stopPropagation();
2068
+ openWhatsAppChat(String(phone));
2069
+ },
2070
+ className: "text-emerald-500 hover:text-emerald-600 p-0.5 rounded hover:bg-emerald-50 transition-colors cursor-pointer",
2071
+ title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
2072
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3.5 h-3.5", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) })
2073
+ }
2074
+ );
2075
+ }
2076
+ return null;
2077
+ })(),
2078
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2079
+ "button",
2080
+ {
2081
+ type: "button",
2082
+ onClick: (e) => {
2083
+ e.stopPropagation();
2084
+ handleUnlinkRecord(entry.recordId);
2085
+ },
2086
+ className: "text-slate-400 hover:text-rose-500 p-0.5 rounded transition-colors cursor-pointer inline-flex items-center justify-center",
2087
+ title: "\u05D4\u05E1\u05E8 \u05E7\u05D9\u05E9\u05D5\u05E8",
2088
+ 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" }) })
2089
+ }
2090
+ )
2091
+ ] }) })
2092
+ ] }, entry.recordId);
2093
+ }),
2094
+ isCreating && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "bg-emerald-50/40", children: [
2095
+ /* @__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" }) }),
2096
+ targetColumns.map((col) => {
2097
+ var _a2, _b2;
2098
+ const colType = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) || "DEFAULT";
2099
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
2100
+ const isContact = colType === "GOOGLE_CONTACT";
2101
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2102
+ "td",
2103
+ {
2104
+ className: `border border-emerald-200 p-0 relative h-8 ${isContact ? "min-w-[140px]" : ""}`,
2105
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2106
+ InputComponent,
2107
+ {
2108
+ value: (_b2 = newRecordData[col.name]) != null ? _b2 : colType === "BOOLEAN" ? false : "",
2109
+ column: col,
2110
+ rowId: "new_record",
2111
+ onChange: (v) => setNewRecordData((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: v })),
2112
+ context: __spreadProps(__spreadValues({}, context), {
2113
+ 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",
2114
+ relationOptions,
2115
+ refetchRelation,
2116
+ tableId: (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId
2117
+ })
2118
+ }
2119
+ )
2120
+ },
2121
+ `new_${col.name}`
2122
+ );
2123
+ }),
2124
+ /* @__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: [
2125
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2126
+ "button",
2127
+ {
2128
+ type: "button",
2129
+ onClick: handleCreateRecord,
2130
+ className: "p-1 text-emerald-600 hover:bg-emerald-100 rounded transition-colors",
2131
+ title: "\u05E9\u05DE\u05D5\u05E8",
2132
+ 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" }) })
2133
+ }
2134
+ ),
2135
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2136
+ "button",
2137
+ {
2138
+ type: "button",
2139
+ onClick: () => {
2140
+ setIsCreating(false);
2141
+ },
2142
+ className: "p-1 text-rose-500 hover:bg-rose-100 rounded transition-colors",
2143
+ title: "\u05D1\u05D9\u05D8\u05D5\u05DC",
2144
+ 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" }) })
2145
+ }
2146
+ )
2147
+ ] }) })
2148
+ ] })
2149
+ ] })
2150
+ ] }) }),
2151
+ conflictModalState.isOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2152
+ "div",
2153
+ {
2154
+ className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-slate-900/60 backdrop-blur-sm animate-in fade-in duration-200",
2155
+ dir: "rtl",
2156
+ onClick: handleCancelConflict,
2157
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2158
+ "div",
2159
+ {
2160
+ className: "bg-white rounded-xl shadow-2xl w-full max-w-lg sm:max-w-xl overflow-hidden border border-slate-200 animate-in fade-in zoom-in-95 duration-200",
2161
+ onClick: (e) => e.stopPropagation(),
2162
+ children: [
2163
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "p-5 border-b border-slate-100 flex items-center gap-3", children: [
2164
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-10 h-10 rounded-full bg-blue-50 border border-blue-200 flex items-center justify-center text-blue-600 flex-shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" }) }) }),
2165
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
2166
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { className: "text-base font-bold text-slate-800", children: conflictModalState.matchingRecords.length > 1 ? "\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA \u05D1\u05D8\u05D1\u05DC\u05D4" : "\u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D9\u05D9\u05DE\u05EA \u05D1\u05D8\u05D1\u05DC\u05D4" }),
2167
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-xs text-slate-500", children: "\u05E0\u05DE\u05E6\u05D0\u05D4 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D9\u05D9\u05DE\u05EA \u05E2\u05DD \u05D0\u05D5\u05EA\u05D5 \u05E2\u05E8\u05DA \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9" })
2168
+ ] })
2169
+ ] }),
2170
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "p-5 space-y-3", children: [
2171
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "text-sm text-slate-700 leading-relaxed", children: [
2172
+ "\u05E7\u05D9\u05D9\u05DE\u05EA \u05DB\u05D1\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05E2\u05DD \u05D4\u05E2\u05E8\u05DA \u05E9\u05E0\u05D1\u05D7\u05E8 \u05D1\u05E9\u05D3\u05D4",
2173
+ " ",
2174
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-bold text-slate-900 bg-slate-100 px-1.5 py-0.5 rounded border border-slate-200", children: conflictModalState.fieldName }),
2175
+ ". \u05D4\u05D0\u05DD \u05EA\u05E8\u05E6\u05D4 \u05DC\u05E7\u05E9\u05E8 \u05D0\u05D5\u05EA\u05D4 \u05DC\u05EA\u05EA-\u05D4\u05D8\u05D1\u05DC\u05D4 \u05D1\u05DE\u05E7\u05D5\u05DD \u05DC\u05D9\u05E6\u05D5\u05E8 \u05D7\u05D3\u05E9\u05D4?"
2176
+ ] }),
2177
+ conflictModalState.matchingRecords.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "p-3 bg-blue-50 border border-blue-200 rounded-lg text-xs font-semibold text-blue-800", children: [
2178
+ "\u05E0\u05DE\u05E6\u05D0\u05D5 ",
2179
+ conflictModalState.matchingRecords.length,
2180
+ " \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA. \u05D4\u05D0\u05DD \u05DC\u05E7\u05E9\u05E8 \u05D0\u05EA \u05DB\u05D5\u05DC\u05DF?"
2181
+ ] }),
2182
+ conflictModalState.matchingRecords.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "overflow-x-auto border border-slate-200 rounded-lg max-h-48 text-xs bg-white", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { className: "w-full text-right border-collapse", children: [
2183
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { className: "bg-slate-100 text-slate-700 font-semibold border-b whitespace-nowrap", children: (targetColumns.length > 0 ? targetColumns.filter((c) => c.name !== "_id" && c.name !== "id") : Object.keys(((_b = conflictModalState.matchingRecords[0]) == null ? void 0 : _b.data) || {}).filter((k) => k !== "_id" && k !== "id").map((name) => ({ name }))).map((col) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2184
+ "th",
2185
+ {
2186
+ className: "bg-slate-100 text-slate-700 font-semibold p-2 border-b whitespace-nowrap",
2187
+ children: col.name
2188
+ },
2189
+ col.name
2190
+ )) }) }),
2191
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tbody", { children: conflictModalState.matchingRecords.map((r, idx) => {
2192
+ const cols = targetColumns.length > 0 ? targetColumns.filter((c) => c.name !== "_id" && c.name !== "id") : Object.keys(r.data || {}).filter((k) => k !== "_id" && k !== "id").map((name) => ({ name }));
2193
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { className: "hover:bg-slate-50/80 transition-colors", children: cols.map((col) => {
2194
+ var _a2;
2195
+ const rawVal = (_a2 = r.data) == null ? void 0 : _a2[col.name];
2196
+ let displayVal = "-";
2197
+ if (rawVal !== void 0 && rawVal !== null && rawVal !== "") {
2198
+ if (typeof rawVal === "boolean") {
2199
+ displayVal = rawVal ? "\u05DB\u05DF" : "\u05DC\u05D0";
2200
+ } else if (typeof rawVal === "object") {
2201
+ displayVal = Array.isArray(rawVal) ? rawVal.join(", ") : JSON.stringify(rawVal);
2202
+ } else {
2203
+ displayVal = String(rawVal);
2204
+ }
2205
+ }
2206
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2207
+ "td",
2208
+ {
2209
+ className: "p-2 border-b border-slate-100 whitespace-nowrap text-slate-800",
2210
+ children: displayVal
2211
+ },
2212
+ col.name
2213
+ );
2214
+ }) }, r.id || idx);
2215
+ }) })
2216
+ ] }) })
2217
+ ] }),
2218
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "p-4 bg-slate-50 border-t border-slate-100 flex items-center justify-end gap-2.5", children: [
2219
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2220
+ "button",
2221
+ {
2222
+ type: "button",
2223
+ onClick: handleCancelConflict,
2224
+ className: "px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-200/70 rounded-lg border border-slate-300 transition-colors cursor-pointer",
2225
+ children: "\u05D1\u05D9\u05D8\u05D5\u05DC"
2226
+ }
2227
+ ),
2228
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2229
+ "button",
2230
+ {
2231
+ type: "button",
2232
+ onClick: handleConfirmLinkConflict,
2233
+ className: "px-4 py-2 text-sm font-semibold text-white bg-blue-600 hover:bg-blue-700 rounded-lg shadow transition-colors flex items-center gap-1.5 cursor-pointer",
2234
+ children: [
2235
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" }) }),
2236
+ conflictModalState.matchingRecords.length > 1 ? "\u05E7\u05E9\u05E8 \u05D0\u05EA \u05DB\u05D5\u05DC\u05DF" : "\u05E7\u05E9\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D4"
2237
+ ]
2238
+ }
2239
+ )
2240
+ ] })
2241
+ ]
2242
+ }
2243
+ )
2244
+ }
2245
+ )
2246
+ ] });
2247
+ }
2248
+
907
2249
  // src/components/TableBlock/TableBlockClient.tsx
908
2250
  var import_lucide_react4 = require("lucide-react");
909
- var import_jsx_runtime5 = require("react/jsx-runtime");
2251
+ var import_jsx_runtime6 = require("react/jsx-runtime");
910
2252
  function TableBlockClient({
911
2253
  data: initialRecords,
912
2254
  settings: schema,
@@ -923,14 +2265,14 @@ function TableBlockClient({
923
2265
  "data-testid": dataTestId
924
2266
  }) {
925
2267
  const { showError, addToast } = useToast();
926
- const [columnWidths, setColumnWidths] = (0, import_react6.useState)({});
927
- const [isMounted, setIsMounted] = (0, import_react6.useState)(false);
2268
+ const [columnWidths, setColumnWidths] = (0, import_react7.useState)({});
2269
+ const [isMounted, setIsMounted] = (0, import_react7.useState)(false);
928
2270
  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)(() => {
2271
+ const [page, setPage] = (0, import_react7.useState)(1);
2272
+ const [limit, setLimit] = (0, import_react7.useState)(50);
2273
+ const [totalRecords, setTotalRecords] = (0, import_react7.useState)(0);
2274
+ const [totalPages, setTotalPages] = (0, import_react7.useState)(1);
2275
+ (0, import_react7.useEffect)(() => {
934
2276
  if (typeof window !== "undefined") {
935
2277
  const savedWidths = localStorage.getItem(`table_widths_${tableKey}`);
936
2278
  if (savedWidths) {
@@ -953,7 +2295,7 @@ function TableBlockClient({
953
2295
  }
954
2296
  setIsMounted(true);
955
2297
  }, [tableKey]);
956
- const [showSummary, setShowSummary] = (0, import_react6.useState)(false);
2298
+ const [showSummary, setShowSummary] = (0, import_react7.useState)(false);
957
2299
  const toggleSummary = () => {
958
2300
  setShowSummary((prev) => {
959
2301
  const next = !prev;
@@ -962,8 +2304,8 @@ function TableBlockClient({
962
2304
  return next;
963
2305
  });
964
2306
  };
965
- const [resizingCol, setResizingCol] = (0, import_react6.useState)(null);
966
- (0, import_react6.useEffect)(() => {
2307
+ const [resizingCol, setResizingCol] = (0, import_react7.useState)(null);
2308
+ (0, import_react7.useEffect)(() => {
967
2309
  if (!resizingCol) return;
968
2310
  const handleMouseMove = (e) => {
969
2311
  const diffX = resizingCol.startX - e.clientX;
@@ -1010,7 +2352,7 @@ function TableBlockClient({
1010
2352
  return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
1011
2353
  });
1012
2354
  };
1013
- const mergeColumnDefs = (0, import_react6.useCallback)((existingCols, incomingCols) => {
2355
+ const mergeColumnDefs = (0, import_react7.useCallback)((existingCols, incomingCols) => {
1014
2356
  if (!incomingCols || incomingCols.length === 0) return existingCols || [];
1015
2357
  if (!existingCols || existingCols.length === 0) return incomingCols;
1016
2358
  const existingMap = new Map(existingCols.map((c) => [c.name, c]));
@@ -1030,18 +2372,18 @@ function TableBlockClient({
1030
2372
  return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
1031
2373
  });
1032
2374
  }, []);
1033
- const [localColumns, setLocalColumns] = (0, import_react6.useState)(() => (schema == null ? void 0 : schema.columns) || []);
1034
- (0, import_react6.useEffect)(() => {
2375
+ const [localColumns, setLocalColumns] = (0, import_react7.useState)(() => (schema == null ? void 0 : schema.columns) || []);
2376
+ (0, import_react7.useEffect)(() => {
1035
2377
  if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
1036
2378
  setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
1037
2379
  }
1038
2380
  }, [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)(() => {
2381
+ const [dirty, setDirty] = (0, import_react7.useState)({ added: [], modified: {}, deleted: [] });
2382
+ const dirtyRef = (0, import_react7.useRef)(dirty);
2383
+ (0, import_react7.useEffect)(() => {
1042
2384
  dirtyRef.current = dirty;
1043
2385
  }, [dirty]);
1044
- const mergeWithDirty = (0, import_react6.useCallback)((baseRecords) => {
2386
+ const mergeWithDirty = (0, import_react7.useCallback)((baseRecords) => {
1045
2387
  const { added, modified, deleted } = dirtyRef.current;
1046
2388
  const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
1047
2389
  const modifiedRecords = nonDeleted.map((r) => {
@@ -1054,8 +2396,8 @@ function TableBlockClient({
1054
2396
  const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
1055
2397
  return [...uniqueAdded, ...modifiedRecords];
1056
2398
  }, []);
1057
- const [data, setData] = (0, import_react6.useState)(() => normalizeRecords(initialRecords));
1058
- (0, import_react6.useEffect)(() => {
2399
+ const [data, setData] = (0, import_react7.useState)(() => normalizeRecords(initialRecords));
2400
+ (0, import_react7.useEffect)(() => {
1059
2401
  if (initialRecords) {
1060
2402
  setData(mergeWithDirty(normalizeRecords(initialRecords)));
1061
2403
  }
@@ -1070,19 +2412,19 @@ function TableBlockClient({
1070
2412
  }
1071
2413
  return false;
1072
2414
  };
1073
- const [baseRecordsMap, setBaseRecordsMap] = (0, import_react6.useState)(() => {
2415
+ const [baseRecordsMap, setBaseRecordsMap] = (0, import_react7.useState)(() => {
1074
2416
  const map = /* @__PURE__ */ new Map();
1075
2417
  (normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
1076
2418
  return map;
1077
2419
  });
1078
- (0, import_react6.useEffect)(() => {
2420
+ (0, import_react7.useEffect)(() => {
1079
2421
  if (initialRecords && initialRecords.length > 0) {
1080
2422
  const map = /* @__PURE__ */ new Map();
1081
2423
  (normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
1082
2424
  setBaseRecordsMap(map);
1083
2425
  }
1084
2426
  }, [initialRecords]);
1085
- const refetchTableData = (0, import_react6.useCallback)((targetPage) => {
2427
+ const refetchTableData = (0, import_react7.useCallback)((targetPage) => {
1086
2428
  const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
1087
2429
  if (!tableId || !executeAction) return Promise.resolve();
1088
2430
  const activePage = targetPage !== void 0 ? targetPage : page;
@@ -1116,8 +2458,8 @@ function TableBlockClient({
1116
2458
  }).catch((err) => {
1117
2459
  console.error("[TableBlock] Failed to auto-fetch table data:", err);
1118
2460
  });
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)(() => {
2461
+ }, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeColumnDefs]);
2462
+ (0, import_react7.useEffect)(() => {
1121
2463
  refetchTableData();
1122
2464
  }, [refetchTableData]);
1123
2465
  const handleLimitChange = (newLimit) => {
@@ -1133,19 +2475,20 @@ function TableBlockClient({
1133
2475
  const handleNextPage = () => {
1134
2476
  setPage((prev) => Math.min(totalPages, prev + 1));
1135
2477
  };
1136
- (0, import_react6.useEffect)(() => {
2478
+ (0, import_react7.useEffect)(() => {
1137
2479
  if (error) {
1138
2480
  showError(error, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E8\u05DB\u05D9\u05D1");
1139
2481
  }
1140
2482
  }, [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) => {
2483
+ const [searchQuery, setSearchQuery] = (0, import_react7.useState)("");
2484
+ const [selectedIds, setSelectedIds] = (0, import_react7.useState)(/* @__PURE__ */ new Set());
2485
+ const [pendingDeletions, setPendingDeletions] = (0, import_react7.useState)([]);
2486
+ const [isSaving, setIsSaving] = (0, import_react7.useState)(false);
2487
+ const [isSaveSuccess, setIsSaveSuccess] = (0, import_react7.useState)(false);
2488
+ const [relationOptions, setRelationOptions] = (0, import_react7.useState)({});
2489
+ const [expandedRowIds, setExpandedRowIds] = (0, import_react7.useState)(/* @__PURE__ */ new Set());
2490
+ const schemaColsString = (0, import_react7.useMemo)(() => JSON.stringify(localColumns || []), [localColumns]);
2491
+ const refetchRelation = (0, import_react7.useCallback)(async (colName) => {
1149
2492
  var _a;
1150
2493
  let parsedCols = [];
1151
2494
  try {
@@ -1165,7 +2508,7 @@ function TableBlockClient({
1165
2508
  console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
1166
2509
  }
1167
2510
  }, [schemaColsString, executeAction]);
1168
- (0, import_react6.useEffect)(() => {
2511
+ (0, import_react7.useEffect)(() => {
1169
2512
  let parsedCols = [];
1170
2513
  try {
1171
2514
  parsedCols = JSON.parse(schemaColsString);
@@ -1179,7 +2522,7 @@ function TableBlockClient({
1179
2522
  refetchRelation(col.name);
1180
2523
  });
1181
2524
  }, [schemaColsString, refetchRelation]);
1182
- const normalizedColumns = (0, import_react6.useMemo)(() => {
2525
+ const normalizedColumns = (0, import_react7.useMemo)(() => {
1183
2526
  return (localColumns || []).map((col, idx) => {
1184
2527
  const isRequired = col.isRequired === true || String(col.isRequired) === "true";
1185
2528
  const isUnique = col.isUnique === true || String(col.isUnique) === "true";
@@ -1193,17 +2536,17 @@ function TableBlockClient({
1193
2536
  return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
1194
2537
  });
1195
2538
  }, [localColumns]);
1196
- const filteredColumns = (0, import_react6.useMemo)(() => {
2539
+ const filteredColumns = (0, import_react7.useMemo)(() => {
1197
2540
  const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
1198
2541
  return normalizedColumns.filter((col) => !systemFields.includes(col.name) && !col.isHidden);
1199
2542
  }, [normalizedColumns]);
1200
- const customizableColumns = (0, import_react6.useMemo)(() => {
2543
+ const customizableColumns = (0, import_react7.useMemo)(() => {
1201
2544
  const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
1202
2545
  return normalizedColumns.filter((col) => !systemFields.includes(col.name));
1203
2546
  }, [normalizedColumns]);
1204
- const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = (0, import_react6.useState)(false);
1205
- const dropdownRef = (0, import_react6.useRef)(null);
1206
- (0, import_react6.useEffect)(() => {
2547
+ const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = (0, import_react7.useState)(false);
2548
+ const dropdownRef = (0, import_react7.useRef)(null);
2549
+ (0, import_react7.useEffect)(() => {
1207
2550
  const handleClickOutside = (e) => {
1208
2551
  if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
1209
2552
  setIsColumnsDropdownOpen(false);
@@ -1281,8 +2624,8 @@ function TableBlockClient({
1281
2624
  }
1282
2625
  }
1283
2626
  };
1284
- const [draggedColName, setDraggedColName] = (0, import_react6.useState)(null);
1285
- const [dragOverColName, setDragOverColName] = (0, import_react6.useState)(null);
2627
+ const [draggedColName, setDraggedColName] = (0, import_react7.useState)(null);
2628
+ const [dragOverColName, setDragOverColName] = (0, import_react7.useState)(null);
1286
2629
  const handleColumnReorder = async (draggedName, dropTargetName) => {
1287
2630
  var _a;
1288
2631
  if (draggedName === dropTargetName) return;
@@ -1324,6 +2667,10 @@ function TableBlockClient({
1324
2667
  var _a;
1325
2668
  const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
1326
2669
  let initialValue = col.defaultValue;
2670
+ if (typeUpper === "SUB_TABLE") {
2671
+ defaultData[col.name] = [];
2672
+ return;
2673
+ }
1327
2674
  if (initialValue !== void 0 && initialValue !== null && initialValue !== "") {
1328
2675
  if (typeUpper === "CURRENCY" || typeUpper === "NUMBER") {
1329
2676
  initialValue = parseFloat(initialValue);
@@ -1407,6 +2754,36 @@ function TableBlockClient({
1407
2754
  });
1408
2755
  }
1409
2756
  };
2757
+ const triggerSaveSuccess = (0, import_react7.useCallback)(() => {
2758
+ setIsSaveSuccess(true);
2759
+ setTimeout(() => {
2760
+ setIsSaveSuccess(false);
2761
+ }, 2500);
2762
+ }, []);
2763
+ const handleQuietCellChange = (0, import_react7.useCallback)((rowId, colName, value) => {
2764
+ setData((prev) => prev.map(
2765
+ (row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
2766
+ ));
2767
+ if (rowId.startsWith("temp_")) {
2768
+ setDirty((prev) => {
2769
+ if (!prev.added.some((r) => r.id === rowId)) return prev;
2770
+ return __spreadProps(__spreadValues({}, prev), {
2771
+ added: prev.added.map(
2772
+ (r) => r.id === rowId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value }) }) : r
2773
+ )
2774
+ });
2775
+ });
2776
+ } else {
2777
+ setBaseRecordsMap((prev) => {
2778
+ const next = new Map(prev);
2779
+ const rowData = next.get(rowId);
2780
+ if (rowData) {
2781
+ next.set(rowId, __spreadProps(__spreadValues({}, rowData), { [colName]: value }));
2782
+ }
2783
+ return next;
2784
+ });
2785
+ }
2786
+ }, []);
1410
2787
  const toggleSelectAll = (checked) => {
1411
2788
  const nextSelected = checked ? new Set(filteredData.map((r) => r.id)) : /* @__PURE__ */ new Set();
1412
2789
  setSelectedIds(nextSelected);
@@ -1436,9 +2813,15 @@ function TableBlockClient({
1436
2813
  const row = data.find((r) => r.id === id);
1437
2814
  if (row) {
1438
2815
  driveCols.forEach((col) => {
1439
- const fileObj = row.data[col.name];
1440
- if (fileObj && fileObj.fileId) {
1441
- filesToDelete.push(fileObj.fileId);
2816
+ const fileVal = row.data[col.name];
2817
+ if (Array.isArray(fileVal)) {
2818
+ fileVal.forEach((fileObj) => {
2819
+ if (fileObj && fileObj.fileId) {
2820
+ filesToDelete.push(fileObj.fileId);
2821
+ }
2822
+ });
2823
+ } else if (fileVal && fileVal.fileId) {
2824
+ filesToDelete.push(fileVal.fileId);
1442
2825
  }
1443
2826
  });
1444
2827
  }
@@ -1465,7 +2848,7 @@ function TableBlockClient({
1465
2848
  const formatPayload = (payload) => {
1466
2849
  const formatted = {};
1467
2850
  (localColumns || []).forEach((col) => {
1468
- var _a;
2851
+ var _a, _b, _c;
1469
2852
  if (["_id", "id", "createdAt", "updatedAt", "orgId", "tableId", "isSelected"].includes(col.name)) return;
1470
2853
  let val = payload[col.name];
1471
2854
  if (val !== void 0) {
@@ -1475,6 +2858,13 @@ function TableBlockClient({
1475
2858
  if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
1476
2859
  val = val === "" ? 0 : Number(val);
1477
2860
  if (isNaN(val)) val = 0;
2861
+ } else if (((_b = col.type) == null ? void 0 : _b.toUpperCase()) === "PHONE") {
2862
+ val = sanitizePhoneNumber(String(val));
2863
+ } else if (((_c = col.type) == null ? void 0 : _c.toUpperCase()) === "SUB_TABLE" && Array.isArray(val)) {
2864
+ val = val.map((item) => {
2865
+ const _a2 = item, { _resolvedData } = _a2, rest = __objRest(_a2, ["_resolvedData"]);
2866
+ return rest;
2867
+ });
1478
2868
  }
1479
2869
  formatted[col.name] = val;
1480
2870
  }
@@ -1484,7 +2874,7 @@ function TableBlockClient({
1484
2874
  };
1485
2875
  const hasChanges = dirty.added.length > 0 || Object.keys(dirty.modified).length > 0 || dirty.deleted.length > 0;
1486
2876
  const handleSave = async () => {
1487
- var _a;
2877
+ var _a, _b;
1488
2878
  if (!hasChanges) {
1489
2879
  return;
1490
2880
  }
@@ -1507,6 +2897,28 @@ function TableBlockClient({
1507
2897
  }
1508
2898
  }
1509
2899
  }
2900
+ const phoneCols = (localColumns || []).filter((c) => {
2901
+ var _a2;
2902
+ return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE";
2903
+ });
2904
+ for (const col of phoneCols) {
2905
+ for (const row of dirty.added) {
2906
+ const val = row.data[col.name];
2907
+ if (!isEmpty(val) && !isValidPhoneNumber(val)) {
2908
+ showError(`\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 "${col.name}" \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA (\u05DC\u05D3\u05D5\u05D2\u05DE\u05D4 0501234567 \u05D0\u05D5 +972501234567).`, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D5\u05D5\u05DC\u05D9\u05D3\u05E6\u05D9\u05D4");
2909
+ return;
2910
+ }
2911
+ }
2912
+ for (const [rowId, mods] of Object.entries(dirty.modified)) {
2913
+ const rowData = ((_b = data.find((r) => r.id === rowId)) == null ? void 0 : _b.data) || {};
2914
+ const mergedData = __spreadValues(__spreadValues({}, rowData), mods);
2915
+ const val = mergedData[col.name];
2916
+ if (!isEmpty(val) && !isValidPhoneNumber(val)) {
2917
+ showError(`\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 "${col.name}" \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA (\u05DC\u05D3\u05D5\u05D2\u05DE\u05D4 0501234567 \u05D0\u05D5 +972501234567).`, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D5\u05D5\u05DC\u05D9\u05D3\u05E6\u05D9\u05D4");
2918
+ return;
2919
+ }
2920
+ }
2921
+ }
1510
2922
  setIsSaving(true);
1511
2923
  try {
1512
2924
  if (!executeAction) {
@@ -1607,7 +3019,7 @@ function TableBlockClient({
1607
3019
  setIsSaving(false);
1608
3020
  }
1609
3021
  };
1610
- const filteredData = (0, import_react6.useMemo)(() => {
3022
+ const filteredData = (0, import_react7.useMemo)(() => {
1611
3023
  if (!searchQuery) return data;
1612
3024
  const lowerQuery = searchQuery.toLowerCase();
1613
3025
  return data.filter(
@@ -1618,7 +3030,7 @@ function TableBlockClient({
1618
3030
  }, [data, searchQuery]);
1619
3031
  const isUpdatingActive = Boolean(isUpdating || isSaving);
1620
3032
  const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
1621
- const columnTotals = (0, import_react6.useMemo)(() => {
3033
+ const columnTotals = (0, import_react7.useMemo)(() => {
1622
3034
  const totals = {};
1623
3035
  if (!showSummary) return totals;
1624
3036
  filteredColumns.forEach((col) => {
@@ -1636,7 +3048,7 @@ function TableBlockClient({
1636
3048
  });
1637
3049
  return totals;
1638
3050
  }, [filteredData, filteredColumns, showSummary]);
1639
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3051
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1640
3052
  "div",
1641
3053
  {
1642
3054
  id: componentId,
@@ -1644,34 +3056,34 @@ function TableBlockClient({
1644
3056
  className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs min-h-[350px] overflow-hidden ${className}`,
1645
3057
  dir: "rtl",
1646
3058
  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 })
3059
+ 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: [
3060
+ /* @__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" }) }),
3061
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: errorMessage })
1650
3062
  ] }) }),
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)(
3063
+ /* @__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: [
3064
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-center gap-2.5", children: [
3065
+ ((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 }) }),
3066
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1655
3067
  "button",
1656
3068
  {
1657
3069
  onClick: handleAddRow,
1658
3070
  disabled: isLoading || isUpdatingActive,
1659
3071
  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
3072
  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" }) })
3073
+ 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
3074
  }
1663
3075
  ),
1664
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3076
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1665
3077
  "button",
1666
3078
  {
1667
3079
  onClick: handleDuplicateRow,
1668
3080
  disabled: isLoading || isUpdatingActive || selectedIds.size !== 1,
1669
3081
  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
3082
  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" })
3083
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Copy, { className: "w-4 h-4 text-blue-600 shrink-0" })
1672
3084
  }
1673
3085
  ),
1674
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3086
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1675
3087
  "button",
1676
3088
  {
1677
3089
  onClick: handleDeleteSelected,
@@ -1679,12 +3091,12 @@ function TableBlockClient({
1679
3091
  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
3092
  title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
1681
3093
  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 })
3094
+ /* @__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" }) }),
3095
+ 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
3096
  ]
1685
3097
  }
1686
3098
  ),
1687
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3099
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1688
3100
  "button",
1689
3101
  {
1690
3102
  onClick: toggleSummary,
@@ -1692,13 +3104,13 @@ function TableBlockClient({
1692
3104
  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
3105
  title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
1694
3106
  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" })
3107
+ /* @__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" }) }),
3108
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
1697
3109
  ]
1698
3110
  }
1699
3111
  ),
1700
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
1701
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3112
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
3113
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1702
3114
  "button",
1703
3115
  {
1704
3116
  onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
@@ -1706,16 +3118,16 @@ function TableBlockClient({
1706
3118
  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
3119
  title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
1708
3120
  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" }) })
3121
+ /* @__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" }) }),
3122
+ /* @__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
3123
  ]
1712
3124
  }
1713
3125
  ),
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: [
3126
+ 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: [
3127
+ /* @__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: [
3128
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1.5", children: [
3129
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
3130
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-[10px] font-normal text-slate-400", children: [
1719
3131
  "(",
1720
3132
  customizableColumns.filter((c) => !c.isHidden).length,
1721
3133
  "/",
@@ -1723,7 +3135,7 @@ function TableBlockClient({
1723
3135
  ")"
1724
3136
  ] })
1725
3137
  ] }),
1726
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3138
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1727
3139
  "button",
1728
3140
  {
1729
3141
  type: "button",
@@ -1733,7 +3145,7 @@ function TableBlockClient({
1733
3145
  }
1734
3146
  )
1735
3147
  ] }),
1736
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
3148
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
1737
3149
  const isRequired = col.isRequired === true || String(col.isRequired) === "true";
1738
3150
  const isUnique = col.isUnique === true || String(col.isUnique) === "true";
1739
3151
  const isProtected = isRequired || isUnique;
@@ -1747,7 +3159,7 @@ function TableBlockClient({
1747
3159
  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
3160
  }
1749
3161
  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)(
3162
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1751
3163
  "div",
1752
3164
  {
1753
3165
  onClick: () => {
@@ -1758,8 +3170,8 @@ function TableBlockClient({
1758
3170
  title: isProtected ? protectedExplanation : void 0,
1759
3171
  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
3172
  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)(
3173
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
3174
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1763
3175
  "input",
1764
3176
  {
1765
3177
  type: "checkbox",
@@ -1770,16 +3182,16 @@ function TableBlockClient({
1770
3182
  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
3183
  }
1772
3184
  ),
1773
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
3185
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
1774
3186
  ] }),
1775
- isProtected && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3187
+ isProtected && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1776
3188
  "div",
1777
3189
  {
1778
3190
  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
3191
  title: protectedExplanation,
1780
3192
  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 })
3193
+ /* @__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" }) }),
3194
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: badgeLabel })
1783
3195
  ]
1784
3196
  }
1785
3197
  )
@@ -1790,9 +3202,9 @@ function TableBlockClient({
1790
3202
  }) })
1791
3203
  ] })
1792
3204
  ] }),
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)(
3205
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
3206
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
3207
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1796
3208
  "input",
1797
3209
  {
1798
3210
  placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
@@ -1802,45 +3214,45 @@ function TableBlockClient({
1802
3214
  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
3215
  }
1804
3216
  ),
1805
- searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3217
+ searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1806
3218
  "button",
1807
3219
  {
1808
3220
  type: "button",
1809
3221
  onClick: () => setSearchQuery(""),
1810
3222
  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
3223
  title: "Clear search",
1812
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.X, { className: "w-3.5 h-3.5" })
3224
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.X, { className: "w-3.5 h-3.5" })
1813
3225
  }
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" }) })
3226
+ ) : /* @__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
3227
  ] })
1816
3228
  ] }),
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" }),
3229
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-3", children: [
3230
+ 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: [
3231
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
1820
3232
  "\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" }) }),
3233
+ ] }) : 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: [
3234
+ /* @__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
3235
  "\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)(
3236
+ ] }) : 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,
3237
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1826
3238
  "button",
1827
3239
  {
1828
3240
  onClick: handleSave,
1829
3241
  disabled: isUpdatingActive || isLoading || !hasChanges,
1830
3242
  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" })
3243
+ 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
3244
  }
1833
3245
  )
1834
3246
  ] })
1835
3247
  ] }),
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..." })
3248
+ /* @__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: [
3249
+ 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: [
3250
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
3251
+ /* @__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
3252
  ] }),
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)(
3253
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
3254
+ /* @__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: [
3255
+ /* @__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
3256
  "input",
1845
3257
  {
1846
3258
  type: "checkbox",
@@ -1854,7 +3266,7 @@ function TableBlockClient({
1854
3266
  const isDragging = draggedColName === col.name;
1855
3267
  const isDragOver = dragOverColName === col.name;
1856
3268
  const currentWidth = columnWidths[col.name] || 200;
1857
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3269
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1858
3270
  "th",
1859
3271
  {
1860
3272
  style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
@@ -1890,7 +3302,7 @@ function TableBlockClient({
1890
3302
  },
1891
3303
  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
3304
  children: [
1893
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3305
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1894
3306
  "div",
1895
3307
  {
1896
3308
  onMouseDown: (e) => {
@@ -1902,16 +3314,16 @@ function TableBlockClient({
1902
3314
  title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
1903
3315
  }
1904
3316
  ),
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)(
3317
+ /* @__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: [
3318
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: col.name }),
3319
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1908
3320
  "svg",
1909
3321
  {
1910
3322
  className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
1911
3323
  fill: "none",
1912
3324
  viewBox: "0 0 24 24",
1913
3325
  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" })
3326
+ 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
3327
  }
1916
3328
  )
1917
3329
  ] })
@@ -1920,59 +3332,112 @@ function TableBlockClient({
1920
3332
  col.name
1921
3333
  );
1922
3334
  }),
1923
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none" })
3335
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none" })
1924
3336
  ] }) }),
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) => {
3337
+ /* @__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: [
3338
+ /* @__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" }) }),
3339
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
3340
+ ] }) }) }) : filteredData.map((row) => {
3341
+ const hasSubTableCols = filteredColumns.some((c) => {
1940
3342
  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,
3343
+ return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
3344
+ });
3345
+ const isExpanded = expandedRowIds.has(row.id);
3346
+ const subTableColumns = filteredColumns.filter((c) => {
3347
+ var _a;
3348
+ return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
3349
+ });
3350
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react7.default.Fragment, { children: [
3351
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
3352
+ /* @__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: [
3353
+ hasSubTableCols && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3354
+ "button",
3355
+ {
3356
+ type: "button",
3357
+ onClick: () => setExpandedRowIds((prev) => {
3358
+ const next = new Set(prev);
3359
+ if (next.has(row.id)) next.delete(row.id);
3360
+ else next.add(row.id);
3361
+ return next;
3362
+ }),
3363
+ className: "text-slate-400 hover:text-blue-600 p-0.5 rounded transition-colors cursor-pointer",
3364
+ title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
3365
+ 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" }) })
3366
+ }
3367
+ ),
3368
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3369
+ "input",
3370
+ {
3371
+ type: "checkbox",
3372
+ checked: selectedIds.has(row.id),
3373
+ onChange: (e) => toggleSelectRow(row.id, e.target.checked),
3374
+ disabled: isLoading || isUpdatingActive,
3375
+ className: "w-4 h-4 rounded border-slate-300 text-brand"
3376
+ }
3377
+ )
3378
+ ] }) }),
3379
+ filteredColumns.map((col) => {
3380
+ var _a;
3381
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
3382
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
3383
+ let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
3384
+ if (value === void 0 && col.defaultValue !== void 0) {
3385
+ value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
3386
+ if (colType === "CURRENCY" || colType === "NUMBER") {
3387
+ if (isNaN(value)) value = null;
3388
+ }
3389
+ }
3390
+ if (value === void 0) value = null;
3391
+ 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)(
3392
+ InputComponent,
3393
+ {
3394
+ value,
3395
+ column: col,
3396
+ rowId: row.id,
3397
+ onChange: (v) => handleCellChange(row.id, col.name, v),
3398
+ context: {
3399
+ 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",
3400
+ tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
3401
+ onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
3402
+ relationOptions,
3403
+ refetchRelation,
3404
+ executeAction,
3405
+ emitEvent,
3406
+ pageState,
3407
+ componentId,
3408
+ orgId,
3409
+ updateQuietly: handleQuietCellChange,
3410
+ triggerSaveSuccess,
3411
+ rowData: row.data
3412
+ }
3413
+ }
3414
+ ) }, col.name);
3415
+ }),
3416
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
3417
+ ] }),
3418
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3419
+ ExpandedSubTables,
1953
3420
  {
1954
- value,
1955
- column: col,
1956
3421
  rowId: row.id,
1957
- onChange: (v) => handleCellChange(row.id, col.name, v),
3422
+ rowData: row.data,
3423
+ subTableColumns,
3424
+ filteredColumnsLength: filteredColumns.length,
3425
+ handleCellChange,
1958
3426
  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
3427
  executeAction,
1964
- emitEvent,
1965
- pageState,
1966
- componentId,
1967
- orgId
3428
+ orgId,
3429
+ parentTableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
3430
+ tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
3431
+ rowData: row.data,
3432
+ updateQuietly: handleQuietCellChange,
3433
+ triggerSaveSuccess
1968
3434
  }
1969
3435
  }
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' }),
3436
+ )
3437
+ ] }, row.id);
3438
+ }) }),
3439
+ 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: [
3440
+ /* @__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
3441
  filteredColumns.map((col) => {
1977
3442
  var _a;
1978
3443
  const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
@@ -1986,16 +3451,16 @@ function TableBlockClient({
1986
3451
  displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
1987
3452
  }
1988
3453
  }
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);
3454
+ 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
3455
  }),
1991
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
3456
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
1992
3457
  ] }) })
1993
3458
  ] })
1994
3459
  ] }),
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)(
3460
+ /* @__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: [
3461
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
3462
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
3463
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1999
3464
  "select",
2000
3465
  {
2001
3466
  value: limit,
@@ -2003,27 +3468,27 @@ function TableBlockClient({
2003
3468
  disabled: isLoading || isUpdatingActive,
2004
3469
  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
3470
  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" })
3471
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: 20, children: "20" }),
3472
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: 50, children: "50" }),
3473
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: 100, children: "100" })
2009
3474
  ]
2010
3475
  }
2011
3476
  )
2012
3477
  ] }),
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: [
3478
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-4", children: [
3479
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-medium text-slate-600", children: [
2015
3480
  "\u05E2\u05DE\u05D5\u05D3 ",
2016
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { className: "text-slate-900", children: page }),
3481
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { className: "text-slate-900", children: page }),
2017
3482
  " \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: [
3483
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { className: "text-slate-900", children: totalPages || 1 }),
3484
+ totalRecords > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-slate-500 font-normal", children: [
2020
3485
  " (",
2021
3486
  totalRecords,
2022
3487
  ' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
2023
3488
  ] })
2024
3489
  ] }),
2025
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2026
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3490
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1.5", children: [
3491
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2027
3492
  "button",
2028
3493
  {
2029
3494
  onClick: handlePrevPage,
@@ -2033,7 +3498,7 @@ function TableBlockClient({
2033
3498
  children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
2034
3499
  }
2035
3500
  ),
2036
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3501
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2037
3502
  "button",
2038
3503
  {
2039
3504
  onClick: handleNextPage,
@@ -2050,11 +3515,60 @@ function TableBlockClient({
2050
3515
  }
2051
3516
  );
2052
3517
  }
3518
+ function ExpandedSubTables({
3519
+ rowId,
3520
+ rowData,
3521
+ subTableColumns,
3522
+ filteredColumnsLength,
3523
+ handleCellChange,
3524
+ context
3525
+ }) {
3526
+ var _a;
3527
+ const [activeTab, setActiveTab] = (0, import_react7.useState)((_a = subTableColumns[0]) == null ? void 0 : _a.name);
3528
+ if (subTableColumns.length === 0) return null;
3529
+ if (subTableColumns.length === 1) {
3530
+ const stCol = subTableColumns[0];
3531
+ 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)(
3532
+ SubTableViewer,
3533
+ {
3534
+ rowId,
3535
+ column: stCol,
3536
+ value: (rowData == null ? void 0 : rowData[stCol.name]) || [],
3537
+ onChange: (newVal) => handleCellChange(rowId, stCol.name, newVal),
3538
+ context
3539
+ }
3540
+ ) }) });
3541
+ }
3542
+ const activeCol = subTableColumns.find((c) => c.name === activeTab) || subTableColumns[0];
3543
+ 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: [
3544
+ /* @__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)(
3545
+ "button",
3546
+ {
3547
+ type: "button",
3548
+ onClick: () => setActiveTab(col.name),
3549
+ 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"}`,
3550
+ children: col.name
3551
+ },
3552
+ col.name
3553
+ )) }),
3554
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "bg-white", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3555
+ SubTableViewer,
3556
+ {
3557
+ rowId,
3558
+ column: activeCol,
3559
+ value: (rowData == null ? void 0 : rowData[activeCol.name]) || [],
3560
+ onChange: (newVal) => handleCellChange(rowId, activeCol.name, newVal),
3561
+ context
3562
+ },
3563
+ activeCol.name
3564
+ ) })
3565
+ ] }) });
3566
+ }
2053
3567
 
2054
3568
  // src/components/TableBlock/TableBlock.tsx
2055
- var import_jsx_runtime6 = require("react/jsx-runtime");
3569
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2056
3570
  function TableBlock(props) {
2057
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TableBlockClient, __spreadValues({}, props));
3571
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableBlockClient, __spreadValues({}, props));
2058
3572
  }
2059
3573
 
2060
3574
  // src/registry.ts
@@ -2068,5 +3582,7 @@ var UNIVERSE_COMPONENTS = {
2068
3582
  ToastProvider,
2069
3583
  UNIVERSE_COMPONENTS,
2070
3584
  cn,
3585
+ formatPhoneDisplay,
3586
+ openWhatsAppChat,
2071
3587
  useToast
2072
3588
  });