@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.mjs CHANGED
@@ -38,8 +38,38 @@ function cn(...inputs) {
38
38
  return twMerge(clsx(inputs));
39
39
  }
40
40
 
41
+ // src/utils/whatsapp.ts
42
+ function openWhatsAppChat(phone, defaultCountryCode = "972") {
43
+ if (!phone || typeof window === "undefined") return;
44
+ let cleaned = phone.replace(/\D/g, "");
45
+ if (cleaned.startsWith("0")) {
46
+ cleaned = defaultCountryCode + cleaned.substring(1);
47
+ }
48
+ const appUrl = `whatsapp://send?phone=${cleaned}`;
49
+ const webUrl = `https://web.whatsapp.com/send?phone=${cleaned}`;
50
+ const start = Date.now();
51
+ window.location.href = appUrl;
52
+ setTimeout(() => {
53
+ if (typeof document !== "undefined" && document.hasFocus() && Date.now() - start < 2e3) {
54
+ window.open(webUrl, "_blank", "noopener,noreferrer");
55
+ }
56
+ }, 1200);
57
+ }
58
+ function formatPhoneDisplay(phone) {
59
+ if (!phone) return "";
60
+ const digits = phone.replace(/\D/g, "");
61
+ if (digits.length === 10 && digits.startsWith("05")) {
62
+ return `${digits.slice(0, 3)}-${digits.slice(3, 6)}-${digits.slice(6)}`;
63
+ }
64
+ if (digits.length === 12 && digits.startsWith("9725")) {
65
+ const local = "0" + digits.slice(3);
66
+ return `${local.slice(0, 3)}-${local.slice(3, 6)}-${local.slice(6)}`;
67
+ }
68
+ return phone;
69
+ }
70
+
41
71
  // src/components/TableBlock/TableBlockClient.tsx
42
- import { useState as useState4, useMemo as useMemo2, useEffect as useEffect2, useCallback as useCallback3, useRef as useRef3 } from "react";
72
+ import React6, { useState as useState5, useMemo as useMemo2, useEffect as useEffect4, useCallback as useCallback4, useRef as useRef4 } from "react";
43
73
 
44
74
  // src/hooks/useToast.ts
45
75
  import { useContext as useContext2 } from "react";
@@ -242,12 +272,36 @@ function useToast() {
242
272
  import React4 from "react";
243
273
 
244
274
  // src/components/TableBlock/fields/DrivePickerCell.tsx
245
- import { useState as useState2 } from "react";
275
+ import React2, { useState as useState2, useEffect } from "react";
246
276
  import { FileText, Upload, X as X2 } from "lucide-react";
247
277
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
248
- function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, context }) {
278
+ function DrivePickerCell({ value, onChange, tableName, column, rowId, onMarkForDeletion, context }) {
249
279
  const [isOpening, setIsOpening] = useState2(false);
250
280
  const { showError } = useToast();
281
+ const cellContextId = React2.useMemo(() => {
282
+ const colName = (column == null ? void 0 : column.name) || "col";
283
+ const rId = rowId || "row";
284
+ return `${rId}-${colName}`;
285
+ }, [rowId, column == null ? void 0 : column.name]);
286
+ const fileList = React2.useMemo(() => {
287
+ if (!value) return [];
288
+ if (Array.isArray(value)) return value;
289
+ if (typeof value === "object" && (value.fileId || value.fileUrl || value.url)) {
290
+ return [value];
291
+ }
292
+ return [];
293
+ }, [value]);
294
+ useEffect(() => {
295
+ const handleMessage = (event) => {
296
+ var _a, _b, _c;
297
+ 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) {
298
+ const incoming = Array.isArray(event.data.payload) ? event.data.payload : [event.data.payload];
299
+ onChange([...fileList, ...incoming]);
300
+ }
301
+ };
302
+ window.addEventListener("message", handleMessage);
303
+ return () => window.removeEventListener("message", handleMessage);
304
+ }, [fileList, onChange, cellContextId]);
251
305
  const openUploadPopup = async () => {
252
306
  if (isOpening) return;
253
307
  setIsOpening(true);
@@ -276,34 +330,35 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
276
330
  } catch (e) {
277
331
  }
278
332
  }
279
- const actionResult = await context.executeAction("UPLOAD_DRIVE_FILE", { tableName });
333
+ const actionResult = await context.executeAction("UPLOAD_DRIVE_FILE", { tableName, cellContextId });
280
334
  const folderId = actionResult == null ? void 0 : actionResult.folderId;
281
- const pickerUrl = (actionResult == null ? void 0 : actionResult.pickerUrl) || (folderId ? `/embed/picker?folderId=${encodeURIComponent(folderId)}` : `/embed/picker`);
335
+ let pickerUrl = (actionResult == null ? void 0 : actionResult.pickerUrl) || (folderId ? `/embed/picker?folderId=${encodeURIComponent(folderId)}` : `/embed/picker`);
336
+ if (!pickerUrl.includes("cellContextId=")) {
337
+ const separator = pickerUrl.includes("?") ? "&" : "?";
338
+ pickerUrl = `${pickerUrl}${separator}cellContextId=${encodeURIComponent(cellContextId)}`;
339
+ }
282
340
  if (popup) {
283
341
  popup.location.href = pickerUrl;
284
342
  }
285
- const newFile = await new Promise((resolve) => {
343
+ await new Promise((resolve) => {
286
344
  let timer = null;
287
- const handleMessage = (event) => {
345
+ const handlePopupMessage = (event) => {
288
346
  var _a, _b;
289
- if (((_a = event.data) == null ? void 0 : _a.type) === "DRIVE_UPLOAD_SUCCESS" && ((_b = event.data) == null ? void 0 : _b.payload)) {
290
- window.removeEventListener("message", handleMessage);
347
+ if (((_a = event.data) == null ? void 0 : _a.type) === "DRIVE_UPLOAD_SUCCESS" && ((_b = event.data) == null ? void 0 : _b.cellContextId) === cellContextId) {
348
+ window.removeEventListener("message", handlePopupMessage);
291
349
  if (timer) clearInterval(timer);
292
- resolve(event.data.payload);
350
+ resolve();
293
351
  }
294
352
  };
295
353
  timer = setInterval(() => {
296
354
  if (!popup || popup.closed) {
297
355
  if (timer) clearInterval(timer);
298
- window.removeEventListener("message", handleMessage);
299
- resolve(null);
356
+ window.removeEventListener("message", handlePopupMessage);
357
+ resolve();
300
358
  }
301
359
  }, 800);
302
- window.addEventListener("message", handleMessage);
360
+ window.addEventListener("message", handlePopupMessage);
303
361
  });
304
- if (newFile) {
305
- onChange(newFile);
306
- }
307
362
  }
308
363
  } catch (error) {
309
364
  console.error("[DrivePickerCell] Error uploading file:", error);
@@ -313,40 +368,15 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
313
368
  setIsOpening(false);
314
369
  }
315
370
  };
316
- if (value == null ? void 0 : value.fileUrl) {
317
- return /* @__PURE__ */ jsxs2("div", { className: "flex items-center w-full h-8 px-2 gap-1", children: [
318
- /* @__PURE__ */ jsxs2(
319
- "a",
320
- {
321
- href: value.fileUrl,
322
- target: "_blank",
323
- rel: "noopener noreferrer",
324
- 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",
325
- title: value.fileName || "Open file",
326
- children: [
327
- /* @__PURE__ */ jsx2(FileText, { className: "w-3.5 h-3.5 shrink-0" }),
328
- /* @__PURE__ */ jsx2("span", { className: "truncate", children: value.fileName || "Unnamed file" })
329
- ]
330
- }
331
- ),
332
- /* @__PURE__ */ jsx2(
333
- "button",
334
- {
335
- type: "button",
336
- onClick: () => {
337
- if ((value == null ? void 0 : value.fileId) && onMarkForDeletion) {
338
- onMarkForDeletion(value.fileId);
339
- }
340
- onChange(null);
341
- },
342
- className: "shrink-0 p-0.5 rounded hover:bg-rose-100 text-slate-400 hover:text-rose-500 transition-colors",
343
- title: "Remove file",
344
- children: /* @__PURE__ */ jsx2(X2, { className: "w-3.5 h-3.5" })
345
- }
346
- )
347
- ] });
348
- }
349
- return /* @__PURE__ */ jsx2("div", { className: "flex items-center w-full h-8 px-2", children: /* @__PURE__ */ jsxs2(
371
+ const handleRemoveFile = (indexToRemove) => {
372
+ const fileToRemove = fileList[indexToRemove];
373
+ if ((fileToRemove == null ? void 0 : fileToRemove.fileId) && onMarkForDeletion) {
374
+ onMarkForDeletion(fileToRemove.fileId);
375
+ }
376
+ const updated = fileList.filter((_, idx) => idx !== indexToRemove);
377
+ onChange(updated);
378
+ };
379
+ const renderUploadButton = () => /* @__PURE__ */ jsx2("div", { className: "flex items-center w-full h-8 px-2", children: /* @__PURE__ */ jsxs2(
350
380
  "button",
351
381
  {
352
382
  type: "button",
@@ -359,10 +389,42 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
359
389
  ]
360
390
  }
361
391
  ) });
392
+ if (fileList.length > 0) {
393
+ return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col w-full py-1 gap-1", children: [
394
+ fileList.map((file, idx) => /* @__PURE__ */ jsxs2("div", { className: "flex items-center w-full h-8 px-2 gap-1", children: [
395
+ /* @__PURE__ */ jsxs2(
396
+ "a",
397
+ {
398
+ href: file.fileUrl || file.url,
399
+ target: "_blank",
400
+ rel: "noopener noreferrer",
401
+ 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",
402
+ title: file.fileName || "Open file",
403
+ children: [
404
+ /* @__PURE__ */ jsx2(FileText, { className: "w-3.5 h-3.5 shrink-0" }),
405
+ /* @__PURE__ */ jsx2("span", { className: "truncate", children: file.fileName || "Unnamed file" })
406
+ ]
407
+ }
408
+ ),
409
+ /* @__PURE__ */ jsx2(
410
+ "button",
411
+ {
412
+ type: "button",
413
+ onClick: () => handleRemoveFile(idx),
414
+ className: "shrink-0 p-0.5 rounded hover:bg-rose-100 text-slate-400 hover:text-rose-500 transition-colors",
415
+ title: "Remove file",
416
+ children: /* @__PURE__ */ jsx2(X2, { className: "w-3.5 h-3.5" })
417
+ }
418
+ )
419
+ ] }, file.fileId || idx)),
420
+ renderUploadButton()
421
+ ] });
422
+ }
423
+ return renderUploadButton();
362
424
  }
363
425
 
364
426
  // src/components/TableBlock/fields/DatePickerCell.tsx
365
- import { useState as useState3, useRef as useRef2, useEffect, useMemo, useCallback as useCallback2 } from "react";
427
+ import { useState as useState3, useRef as useRef2, useEffect as useEffect2, useMemo, useCallback as useCallback2 } from "react";
366
428
  import { Calendar as CalendarIcon, ChevronLeft, ChevronRight, X as X3 } from "lucide-react";
367
429
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
368
430
  function parseDateParts(val) {
@@ -447,13 +509,13 @@ function DatePickerCell({ value, onChange, readOnly = false }) {
447
509
  const parsedParts = useMemo(() => parseDateParts(value), [value]);
448
510
  const displayString = useMemo(() => formatDateDisplay(parsedParts), [parsedParts]);
449
511
  const [rawInput, setRawInput] = useState3(displayString);
450
- useEffect(() => {
512
+ useEffect2(() => {
451
513
  setRawInput(displayString);
452
514
  }, [displayString]);
453
515
  const now = /* @__PURE__ */ new Date();
454
516
  const [viewYear, setViewYear] = useState3((parsedParts == null ? void 0 : parsedParts.year) || now.getFullYear());
455
517
  const [viewMonth, setViewMonth] = useState3((parsedParts == null ? void 0 : parsedParts.month) || now.getMonth() + 1);
456
- useEffect(() => {
518
+ useEffect2(() => {
457
519
  if (parsedParts) {
458
520
  setViewYear(parsedParts.year);
459
521
  setViewMonth(parsedParts.month);
@@ -478,7 +540,7 @@ function DatePickerCell({ value, onChange, readOnly = false }) {
478
540
  }
479
541
  }
480
542
  }, []);
481
- useEffect(() => {
543
+ useEffect2(() => {
482
544
  if (!isOpen) return;
483
545
  updatePopoverPosition();
484
546
  function handleScrollOrResize() {
@@ -793,11 +855,13 @@ var FORM_INPUTS = {
793
855
  className: "w-4 h-4 rounded border-slate-300 text-brand"
794
856
  }
795
857
  ) }),
796
- GOOGLE_DRIVE_FILE: ({ value, onChange, context }) => /* @__PURE__ */ jsx4(
858
+ GOOGLE_DRIVE_FILE: ({ value, onChange, column, rowId, context }) => /* @__PURE__ */ jsx4(
797
859
  DrivePickerCell,
798
860
  {
799
- value: value || null,
861
+ value: value || [],
800
862
  onChange,
863
+ column,
864
+ rowId,
801
865
  tableName: context == null ? void 0 : context.tableName,
802
866
  onMarkForDeletion: context == null ? void 0 : context.onMarkForDeletion,
803
867
  context
@@ -855,6 +919,249 @@ var FORM_INPUTS = {
855
919
  }
856
920
  }
857
921
  ),
922
+ PHONE: ({ value, onChange, column }) => {
923
+ var _a;
924
+ const enableWhatsApp = (_a = column == null ? void 0 : column.config) == null ? void 0 : _a.enableWhatsApp;
925
+ return /* @__PURE__ */ jsxs4("div", { className: "flex items-center w-full h-full px-2 gap-1.5", children: [
926
+ /* @__PURE__ */ jsx4(
927
+ "input",
928
+ {
929
+ type: "tel",
930
+ className: "w-full h-8 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm flex-1",
931
+ value: value !== void 0 && value !== null ? String(value) : "",
932
+ onChange: (e) => onChange(e.target.value),
933
+ dir: "ltr"
934
+ }
935
+ ),
936
+ enableWhatsApp && value && /* @__PURE__ */ jsx4(
937
+ "button",
938
+ {
939
+ type: "button",
940
+ className: "text-emerald-500 cursor-pointer hover:opacity-80 transition-opacity shrink-0 p-1 rounded hover:bg-emerald-50",
941
+ title: "\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4",
942
+ onClick: (e) => {
943
+ e.stopPropagation();
944
+ openWhatsAppChat(String(value));
945
+ },
946
+ children: /* @__PURE__ */ jsx4("svg", { className: "w-4 h-4", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4("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" }) })
947
+ }
948
+ )
949
+ ] });
950
+ },
951
+ GOOGLE_CONTACT: ({ value, column, rowId, onChange, context }) => {
952
+ const [isSyncing, setIsSyncing] = React4.useState(false);
953
+ const { addToast } = useToast();
954
+ const googleClientIdRef = React4.useRef(null);
955
+ const ensureGisScript = React4.useCallback(() => {
956
+ return new Promise((resolve, reject) => {
957
+ var _a, _b, _c;
958
+ if ((_c = (_b = (_a = window.google) == null ? void 0 : _a.accounts) == null ? void 0 : _b.oauth2) == null ? void 0 : _c.initTokenClient) {
959
+ resolve();
960
+ return;
961
+ }
962
+ if (document.querySelector('script[src*="accounts.google.com/gsi/client"]')) {
963
+ const waitForLoad = setInterval(() => {
964
+ var _a2, _b2, _c2;
965
+ if ((_c2 = (_b2 = (_a2 = window.google) == null ? void 0 : _a2.accounts) == null ? void 0 : _b2.oauth2) == null ? void 0 : _c2.initTokenClient) {
966
+ clearInterval(waitForLoad);
967
+ resolve();
968
+ }
969
+ }, 100);
970
+ setTimeout(() => {
971
+ clearInterval(waitForLoad);
972
+ reject(new Error("GIS script load timeout"));
973
+ }, 1e4);
974
+ return;
975
+ }
976
+ const script = document.createElement("script");
977
+ script.src = "https://accounts.google.com/gsi/client";
978
+ script.async = true;
979
+ script.onload = () => resolve();
980
+ script.onerror = () => reject(new Error("Failed to load Google Identity Services"));
981
+ document.head.appendChild(script);
982
+ });
983
+ }, []);
984
+ const requestGisToken = React4.useCallback(async (hint) => {
985
+ await ensureGisScript();
986
+ if (!googleClientIdRef.current && (context == null ? void 0 : context.executeAction)) {
987
+ try {
988
+ const config = await context.executeAction("GET_GOOGLE_CONFIG", {});
989
+ googleClientIdRef.current = (config == null ? void 0 : config.clientId) || "";
990
+ } catch (e) {
991
+ throw new Error("Failed to fetch Google configuration");
992
+ }
993
+ }
994
+ const clientId = googleClientIdRef.current;
995
+ if (!clientId) {
996
+ throw new Error("Google Client ID is not configured");
997
+ }
998
+ const accessToken = await new Promise((resolve, reject) => {
999
+ const tokenClient = window.google.accounts.oauth2.initTokenClient({
1000
+ client_id: clientId,
1001
+ scope: "https://www.googleapis.com/auth/contacts https://www.googleapis.com/auth/userinfo.email",
1002
+ prompt: hint ? "" : "select_account",
1003
+ hint: hint || void 0,
1004
+ callback: (tokenResponse) => {
1005
+ if (tokenResponse == null ? void 0 : tokenResponse.access_token) {
1006
+ resolve(tokenResponse.access_token);
1007
+ } else {
1008
+ reject(new Error("Google authorization was cancelled or failed"));
1009
+ }
1010
+ },
1011
+ error_callback: (err) => {
1012
+ reject(new Error((err == null ? void 0 : err.message) || "Google authorization error"));
1013
+ }
1014
+ });
1015
+ tokenClient.requestAccessToken({ hint: hint || void 0 });
1016
+ });
1017
+ let email = "";
1018
+ try {
1019
+ const res = await fetch("https://www.googleapis.com/oauth2/v3/userinfo", {
1020
+ headers: { Authorization: `Bearer ${accessToken}` }
1021
+ });
1022
+ if (res.ok) {
1023
+ const info = await res.json();
1024
+ email = info.email || "";
1025
+ }
1026
+ } catch (e) {
1027
+ }
1028
+ return { accessToken, email };
1029
+ }, [ensureGisScript, context]);
1030
+ const handleSync = async () => {
1031
+ var _a, _b, _c;
1032
+ if (!(context == null ? void 0 : context.executeAction)) return;
1033
+ setIsSyncing(true);
1034
+ try {
1035
+ const mapping = column.contactMapping || {};
1036
+ const rowData = context.rowData || {};
1037
+ let hasPhone = false;
1038
+ if (mapping.phoneCol && rowData[mapping.phoneCol]) hasPhone = true;
1039
+ let hasName = false;
1040
+ if (mapping.nameParts && Array.isArray(mapping.nameParts)) {
1041
+ for (const part of mapping.nameParts) {
1042
+ if (part.type === "LOCAL" && rowData[part.columnId]) hasName = true;
1043
+ 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;
1044
+ }
1045
+ }
1046
+ if (!hasPhone) {
1047
+ 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" });
1048
+ setIsSyncing(false);
1049
+ return;
1050
+ }
1051
+ if (!hasName) {
1052
+ 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" });
1053
+ setIsSyncing(false);
1054
+ return;
1055
+ }
1056
+ let accessToken;
1057
+ let userEmail = "";
1058
+ try {
1059
+ const gisResult = await requestGisToken();
1060
+ accessToken = gisResult.accessToken;
1061
+ userEmail = gisResult.email;
1062
+ } catch (gisError) {
1063
+ addToast({ type: "warning", message: gisError.message || "\u05D4\u05D4\u05E8\u05E9\u05D0\u05D4 \u05DC\u05D2\u05D5\u05D2\u05DC \u05E0\u05DB\u05E9\u05DC\u05D4" });
1064
+ setIsSyncing(false);
1065
+ return;
1066
+ }
1067
+ const payload = {
1068
+ nameParts: mapping.nameParts || [],
1069
+ phoneCol: mapping.phoneCol,
1070
+ emailCol: mapping.emailCol,
1071
+ localRowData: rowData,
1072
+ parentRecord: context.parentRecord,
1073
+ accessToken,
1074
+ userEmail
1075
+ };
1076
+ const res = await context.executeAction("SYNC_GOOGLE_CONTACT", payload);
1077
+ if (res && res.synced) {
1078
+ if (context.updateQuietly) {
1079
+ context.updateQuietly(rowId, column.name, res);
1080
+ } else {
1081
+ onChange(res);
1082
+ }
1083
+ if (context.tableId && !rowId.startsWith("temp_")) {
1084
+ await context.executeAction("UPDATE_RECORD", {
1085
+ tableId: context.tableId,
1086
+ recordId: rowId,
1087
+ data: { [column.name]: res }
1088
+ });
1089
+ }
1090
+ }
1091
+ } catch (error) {
1092
+ console.error("Failed to sync contact:", error);
1093
+ addToast({ type: "warning", message: "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E1\u05E0\u05DB\u05E8\u05D5\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8: " + error.message });
1094
+ } finally {
1095
+ setIsSyncing(false);
1096
+ }
1097
+ };
1098
+ const handleUnlink = async () => {
1099
+ let accessToken;
1100
+ try {
1101
+ let emailHint = value == null ? void 0 : value.userEmail;
1102
+ if (!emailHint && (value == null ? void 0 : value.url)) {
1103
+ try {
1104
+ const parsed = new URL(value.url);
1105
+ emailHint = parsed.searchParams.get("authuser") || void 0;
1106
+ } catch (e) {
1107
+ }
1108
+ }
1109
+ const auth = await requestGisToken(emailHint);
1110
+ accessToken = auth.accessToken;
1111
+ } catch (err) {
1112
+ console.warn("[handleUnlink] Could not obtain token via GIS, falling back to server default token:", err);
1113
+ }
1114
+ if ((value == null ? void 0 : value.resourceName) && (context == null ? void 0 : context.executeAction)) {
1115
+ await context.executeAction("DELETE_GOOGLE_CONTACT", {
1116
+ resourceName: value.resourceName,
1117
+ accessToken
1118
+ });
1119
+ }
1120
+ if (context == null ? void 0 : context.updateQuietly) {
1121
+ context.updateQuietly(rowId, column.name, null);
1122
+ } else {
1123
+ onChange(null);
1124
+ }
1125
+ if ((context == null ? void 0 : context.tableId) && (context == null ? void 0 : context.executeAction) && !rowId.startsWith("temp_")) {
1126
+ await context.executeAction("UPDATE_RECORD", {
1127
+ tableId: context.tableId,
1128
+ recordId: rowId,
1129
+ data: { [column.name]: null }
1130
+ });
1131
+ }
1132
+ };
1133
+ if (value && value.synced && value.url) {
1134
+ return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5 h-8 px-2 group whitespace-nowrap", children: [
1135
+ /* @__PURE__ */ jsx4("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" }),
1136
+ /* @__PURE__ */ jsx4(
1137
+ "button",
1138
+ {
1139
+ type: "button",
1140
+ onClick: handleUnlink,
1141
+ className: "text-slate-400 hover:text-rose-500 opacity-0 group-hover:opacity-100 transition-opacity p-1 shrink-0",
1142
+ title: "\u05D1\u05D8\u05DC \u05E1\u05E0\u05DB\u05E8\u05D5\u05DF",
1143
+ children: /* @__PURE__ */ jsx4("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
1144
+ }
1145
+ )
1146
+ ] });
1147
+ }
1148
+ return /* @__PURE__ */ jsx4("div", { className: "flex items-center h-8 px-2 whitespace-nowrap", children: /* @__PURE__ */ jsxs4(
1149
+ "button",
1150
+ {
1151
+ type: "button",
1152
+ onClick: handleSync,
1153
+ disabled: isSyncing,
1154
+ 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",
1155
+ children: [
1156
+ isSyncing ? /* @__PURE__ */ jsxs4("svg", { className: "w-3.5 h-3.5 animate-spin shrink-0", viewBox: "0 0 24 24", fill: "none", children: [
1157
+ /* @__PURE__ */ jsx4("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
1158
+ /* @__PURE__ */ jsx4("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" })
1159
+ ] }) : /* @__PURE__ */ jsx4("svg", { className: "w-3.5 h-3.5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 4v16m8-8H4" }) }),
1160
+ /* @__PURE__ */ jsx4("span", { className: "whitespace-nowrap", children: "\u05E1\u05E0\u05DB\u05E8\u05DF \u05DC\u05D2\u05D5\u05D2\u05DC" })
1161
+ ]
1162
+ }
1163
+ ) });
1164
+ },
858
1165
  DEFAULT: ({ value, onChange }) => /* @__PURE__ */ jsx4(
859
1166
  "input",
860
1167
  {
@@ -863,12 +1170,1045 @@ var FORM_INPUTS = {
863
1170
  value: value !== void 0 && value !== null ? String(value) : "",
864
1171
  onChange: (e) => onChange(e.target.value)
865
1172
  }
866
- )
1173
+ ),
1174
+ SUB_TABLE: ({ value, column }) => {
1175
+ var _a, _b;
1176
+ if (!Array.isArray(value)) return /* @__PURE__ */ jsx4("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
1177
+ const selected = value.filter((e) => e == null ? void 0 : e.isSelected);
1178
+ if (selected.length === 0) return /* @__PURE__ */ jsx4("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
1179
+ const displayFields = column.subTableDisplayFields || [];
1180
+ const isWhatsApp = ((_a = column.config) == null ? void 0 : _a.actionType) === "WHATSAPP";
1181
+ const actionPhoneCol = (_b = column.config) == null ? void 0 : _b.actionPhoneColumn;
1182
+ return /* @__PURE__ */ jsx4("div", { className: "px-1.5 py-1 flex flex-wrap items-center gap-1 h-full", children: selected.map((entry, idx) => {
1183
+ var _a2, _b2;
1184
+ let label = "";
1185
+ if (entry._resolvedData) {
1186
+ if (displayFields.length > 0) {
1187
+ label = displayFields.map((f) => String(entry._resolvedData[f] || "")).filter(Boolean).join(" ");
1188
+ } else {
1189
+ const firstField = Object.keys(entry._resolvedData).find((k) => k !== "_id");
1190
+ if (firstField) label = String(entry._resolvedData[firstField] || "");
1191
+ }
1192
+ }
1193
+ if (!label) label = ((_a2 = entry.recordId) == null ? void 0 : _a2.slice(-6)) || "...";
1194
+ if (isWhatsApp) {
1195
+ const rawPhone = actionPhoneCol ? (_b2 = entry._resolvedData) == null ? void 0 : _b2[actionPhoneCol] : null;
1196
+ const phone = rawPhone ? String(rawPhone).trim() : null;
1197
+ if (phone) {
1198
+ return /* @__PURE__ */ jsxs4(
1199
+ "button",
1200
+ {
1201
+ type: "button",
1202
+ onClick: (e) => {
1203
+ e.stopPropagation();
1204
+ openWhatsAppChat(phone);
1205
+ },
1206
+ 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",
1207
+ title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
1208
+ children: [
1209
+ /* @__PURE__ */ jsx4("svg", { className: "w-3 h-3 text-emerald-600 shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4("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" }) }),
1210
+ /* @__PURE__ */ jsx4("span", { className: "truncate", children: label })
1211
+ ]
1212
+ },
1213
+ entry.recordId || idx
1214
+ );
1215
+ }
1216
+ }
1217
+ return /* @__PURE__ */ jsx4(
1218
+ "span",
1219
+ {
1220
+ 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",
1221
+ title: label,
1222
+ children: label
1223
+ },
1224
+ entry.recordId || idx
1225
+ );
1226
+ }) });
1227
+ }
867
1228
  };
868
1229
 
1230
+ // src/components/TableBlock/fields/SubTableViewer.tsx
1231
+ import { useState as useState4, useEffect as useEffect3, useRef as useRef3, useCallback as useCallback3 } from "react";
1232
+
1233
+ // src/utils/phone.ts
1234
+ function sanitizePhoneNumber(phone) {
1235
+ if (!phone) return "";
1236
+ const trimmed = phone.trim();
1237
+ const hasLeadingPlus = trimmed.startsWith("+");
1238
+ const digitsOnly = trimmed.replace(/\D/g, "");
1239
+ return hasLeadingPlus ? `+${digitsOnly}` : digitsOnly;
1240
+ }
1241
+ function isValidPhoneNumber(phone) {
1242
+ if (!phone) return false;
1243
+ const cleaned = sanitizePhoneNumber(phone);
1244
+ return /^\+?[0-9]{9,15}$/.test(cleaned);
1245
+ }
1246
+
1247
+ // src/components/TableBlock/fields/SubTableViewer.tsx
1248
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1249
+ function validateCellValue(val, col) {
1250
+ var _a;
1251
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
1252
+ const isEmpty = val === void 0 || val === null || typeof val === "string" && val.trim() === "";
1253
+ if (col.isRequired && isEmpty) {
1254
+ return {
1255
+ isValid: false,
1256
+ 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.`
1257
+ };
1258
+ }
1259
+ if (isEmpty) {
1260
+ return { isValid: true };
1261
+ }
1262
+ if (colType === "PHONE") {
1263
+ const strVal = String(val).trim();
1264
+ if (!isValidPhoneNumber(strVal)) {
1265
+ return {
1266
+ isValid: false,
1267
+ 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).`
1268
+ };
1269
+ }
1270
+ }
1271
+ if (colType === "NUMBER" || colType === "CURRENCY") {
1272
+ if (typeof val === "string" && isNaN(Number(val))) {
1273
+ return {
1274
+ isValid: false,
1275
+ 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.`
1276
+ };
1277
+ }
1278
+ }
1279
+ return { isValid: true };
1280
+ }
1281
+ function SubTableCell({
1282
+ record,
1283
+ column,
1284
+ targetSchema,
1285
+ referencedTableId,
1286
+ context,
1287
+ relationOptions,
1288
+ setRelationOptions,
1289
+ refetchRelation,
1290
+ onCommit
1291
+ }) {
1292
+ var _a, _b;
1293
+ const colType = ((_a = column.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
1294
+ const isContact = colType === "GOOGLE_CONTACT";
1295
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
1296
+ const serverValue = (_b = record.data[column.name]) != null ? _b : colType === "BOOLEAN" ? false : "";
1297
+ const [draftValue, setDraftValue] = useState4(serverValue);
1298
+ const [isDirty, setIsDirty] = useState4(false);
1299
+ const [validationError, setValidationError] = useState4(null);
1300
+ const cellRef = useRef3(null);
1301
+ const draftRef = useRef3(draftValue);
1302
+ const isDirtyRef = useRef3(isDirty);
1303
+ const serverValueRef = useRef3(serverValue);
1304
+ const recordIdRef = useRef3(record.id);
1305
+ const columnRef = useRef3(column);
1306
+ const onCommitRef = useRef3(onCommit);
1307
+ const isCommittingRef = useRef3(false);
1308
+ const lastFailedValRef = useRef3(void 0);
1309
+ const { addToast } = useToast();
1310
+ draftRef.current = draftValue;
1311
+ isDirtyRef.current = isDirty;
1312
+ serverValueRef.current = serverValue;
1313
+ recordIdRef.current = record.id;
1314
+ columnRef.current = column;
1315
+ onCommitRef.current = onCommit;
1316
+ useEffect3(() => {
1317
+ if (!isDirtyRef.current) {
1318
+ setDraftValue(serverValue);
1319
+ draftRef.current = serverValue;
1320
+ setValidationError(null);
1321
+ lastFailedValRef.current = void 0;
1322
+ }
1323
+ }, [serverValue]);
1324
+ const commit = useCallback3(async (valToCommit) => {
1325
+ if (isCommittingRef.current) return false;
1326
+ if (!isDirtyRef.current) return true;
1327
+ if (valToCommit === serverValueRef.current) {
1328
+ setIsDirty(false);
1329
+ isDirtyRef.current = false;
1330
+ setValidationError(null);
1331
+ lastFailedValRef.current = void 0;
1332
+ return true;
1333
+ }
1334
+ const valRes = validateCellValue(valToCommit, columnRef.current);
1335
+ if (!valRes.isValid) {
1336
+ const errorMsg = valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA";
1337
+ setValidationError(errorMsg);
1338
+ if (lastFailedValRef.current !== valToCommit) {
1339
+ addToast({ type: "error", message: errorMsg });
1340
+ lastFailedValRef.current = valToCommit;
1341
+ }
1342
+ return false;
1343
+ }
1344
+ try {
1345
+ isCommittingRef.current = true;
1346
+ const success = await onCommitRef.current(recordIdRef.current, columnRef.current.name, valToCommit);
1347
+ if (success) {
1348
+ setIsDirty(false);
1349
+ isDirtyRef.current = false;
1350
+ serverValueRef.current = valToCommit;
1351
+ setValidationError(null);
1352
+ lastFailedValRef.current = void 0;
1353
+ return true;
1354
+ } else {
1355
+ setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
1356
+ return false;
1357
+ }
1358
+ } catch (e) {
1359
+ setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
1360
+ return false;
1361
+ } finally {
1362
+ isCommittingRef.current = false;
1363
+ }
1364
+ }, [addToast]);
1365
+ const discard = useCallback3(() => {
1366
+ setDraftValue(serverValueRef.current);
1367
+ draftRef.current = serverValueRef.current;
1368
+ setIsDirty(false);
1369
+ isDirtyRef.current = false;
1370
+ setValidationError(null);
1371
+ lastFailedValRef.current = void 0;
1372
+ }, []);
1373
+ useEffect3(() => {
1374
+ return () => {
1375
+ if (isDirtyRef.current && !isCommittingRef.current) {
1376
+ const val = draftRef.current;
1377
+ const orig = serverValueRef.current;
1378
+ if (val !== orig) {
1379
+ const valRes = validateCellValue(val, columnRef.current);
1380
+ if (valRes.isValid) {
1381
+ onCommitRef.current(recordIdRef.current, columnRef.current.name, val);
1382
+ }
1383
+ }
1384
+ }
1385
+ };
1386
+ }, []);
1387
+ const handleChange = (newVal) => {
1388
+ setDraftValue(newVal);
1389
+ draftRef.current = newVal;
1390
+ setIsDirty(true);
1391
+ isDirtyRef.current = true;
1392
+ if (validationError) {
1393
+ setValidationError(null);
1394
+ lastFailedValRef.current = void 0;
1395
+ }
1396
+ if (colType === "BOOLEAN" || colType === "GOOGLE_DRIVE_FILE") {
1397
+ commit(newVal);
1398
+ }
1399
+ };
1400
+ const handleBlur = (e) => {
1401
+ if (e.currentTarget.contains(e.relatedTarget)) {
1402
+ return;
1403
+ }
1404
+ if (isDirtyRef.current) {
1405
+ commit(draftRef.current);
1406
+ }
1407
+ };
1408
+ const handleKeyDown = (e) => {
1409
+ var _a2, _b2, _c, _d;
1410
+ if (e.key === "Enter") {
1411
+ e.preventDefault();
1412
+ if (isDirtyRef.current) {
1413
+ commit(draftRef.current);
1414
+ }
1415
+ (_b2 = (_a2 = e.target) == null ? void 0 : _a2.blur) == null ? void 0 : _b2.call(_a2);
1416
+ } else if (e.key === "Escape") {
1417
+ e.preventDefault();
1418
+ discard();
1419
+ (_d = (_c = e.target) == null ? void 0 : _c.blur) == null ? void 0 : _d.call(_c);
1420
+ }
1421
+ };
1422
+ return /* @__PURE__ */ jsx5(
1423
+ "td",
1424
+ {
1425
+ ref: cellRef,
1426
+ onBlur: handleBlur,
1427
+ onKeyDown: handleKeyDown,
1428
+ title: validationError || void 0,
1429
+ 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" : ""}`,
1430
+ children: /* @__PURE__ */ jsx5(
1431
+ InputComponent,
1432
+ {
1433
+ value: draftValue,
1434
+ column,
1435
+ rowId: record.id,
1436
+ onChange: handleChange,
1437
+ context: __spreadProps(__spreadValues({}, context), {
1438
+ 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",
1439
+ relationOptions,
1440
+ updateRelationOptions: (name, opts) => setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [name]: opts })),
1441
+ refetchRelation,
1442
+ parentRecord: { tableId: (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId), data: context == null ? void 0 : context.rowData },
1443
+ rowData: record.data,
1444
+ tableId: (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId,
1445
+ updateQuietly: (rid, colName, val) => onCommitRef.current(rid, colName, val)
1446
+ })
1447
+ }
1448
+ )
1449
+ }
1450
+ );
1451
+ }
1452
+ function SubTableViewer({ rowId, column, value, onChange, context }) {
1453
+ var _a, _b;
1454
+ const { addToast } = useToast();
1455
+ const entries = Array.isArray(value) ? value : [];
1456
+ const [linkedRecords, setLinkedRecords] = useState4(() => {
1457
+ const initial = [];
1458
+ if (Array.isArray(value)) {
1459
+ for (const entry of value) {
1460
+ if (entry.recordId && entry._resolvedData) {
1461
+ initial.push({ id: entry.recordId, data: entry._resolvedData });
1462
+ }
1463
+ }
1464
+ }
1465
+ return initial;
1466
+ });
1467
+ const [targetSchema, setTargetSchema] = useState4(null);
1468
+ const [isLoading, setIsLoading] = useState4(true);
1469
+ const [isSearchOpen, setIsSearchOpen] = useState4(false);
1470
+ const [searchQuery, setSearchQuery] = useState4("");
1471
+ const [searchResults, setSearchResults] = useState4([]);
1472
+ const [isSearching, setIsSearching] = useState4(false);
1473
+ const [isCreating, setIsCreating] = useState4(false);
1474
+ const [newRecordData, setNewRecordData] = useState4({});
1475
+ const [conflictModalState, setConflictModalState] = useState4({
1476
+ isOpen: false,
1477
+ fieldName: "",
1478
+ matchingRecords: []
1479
+ });
1480
+ const searchRef = useRef3(null);
1481
+ const searchTimerRef = useRef3(null);
1482
+ const executeAction = context == null ? void 0 : context.executeAction;
1483
+ const referencedTableId = column.referencedTableId;
1484
+ const fetchedIdsRef = useRef3(/* @__PURE__ */ new Set());
1485
+ useEffect3(() => {
1486
+ if (entries.length > 0) {
1487
+ setLinkedRecords((prev) => {
1488
+ const existingIds = new Set(prev.map((r) => r.id));
1489
+ const toAdd = [];
1490
+ for (const entry of entries) {
1491
+ if (entry.recordId && entry._resolvedData && !existingIds.has(entry.recordId)) {
1492
+ toAdd.push({ id: entry.recordId, data: entry._resolvedData });
1493
+ existingIds.add(entry.recordId);
1494
+ }
1495
+ }
1496
+ return toAdd.length > 0 ? [...prev, ...toAdd] : prev;
1497
+ });
1498
+ }
1499
+ }, [entries]);
1500
+ useEffect3(() => {
1501
+ if (!referencedTableId || !executeAction) {
1502
+ setIsLoading(false);
1503
+ return;
1504
+ }
1505
+ const recordIdsToFetch = entries.map((e) => e.recordId).filter((id) => !fetchedIdsRef.current.has(id));
1506
+ if (recordIdsToFetch.length === 0 && targetSchema) return;
1507
+ if (recordIdsToFetch.length > 0) {
1508
+ recordIdsToFetch.forEach((id) => fetchedIdsRef.current.add(id));
1509
+ }
1510
+ setIsLoading(true);
1511
+ executeAction("FETCH_SUB_TABLE_RECORDS", { referencedTableId, recordIds: recordIdsToFetch }).then((res) => {
1512
+ const payload = (res == null ? void 0 : res.data) || res;
1513
+ if (payload == null ? void 0 : payload.records) {
1514
+ setLinkedRecords((prev) => {
1515
+ const map = new Map(prev.map((r) => [r.id, r]));
1516
+ payload.records.forEach((r) => map.set(r.id, r));
1517
+ return Array.from(map.values());
1518
+ });
1519
+ }
1520
+ if (payload == null ? void 0 : payload.schema) {
1521
+ setTargetSchema(payload.schema);
1522
+ }
1523
+ }).catch(() => {
1524
+ recordIdsToFetch.forEach((id) => fetchedIdsRef.current.delete(id));
1525
+ }).finally(() => setIsLoading(false));
1526
+ }, [referencedTableId, executeAction, entries, targetSchema]);
1527
+ useEffect3(() => {
1528
+ const handleClick = (e) => {
1529
+ if (searchRef.current && !searchRef.current.contains(e.target)) {
1530
+ setIsSearchOpen(false);
1531
+ }
1532
+ };
1533
+ if (isSearchOpen) document.addEventListener("mousedown", handleClick);
1534
+ return () => document.removeEventListener("mousedown", handleClick);
1535
+ }, [isSearchOpen]);
1536
+ const handleSearch = useCallback3((query) => {
1537
+ setSearchQuery(query);
1538
+ if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
1539
+ if (!query.trim()) {
1540
+ setSearchResults([]);
1541
+ return;
1542
+ }
1543
+ searchTimerRef.current = setTimeout(async () => {
1544
+ if (!executeAction || !referencedTableId) return;
1545
+ setIsSearching(true);
1546
+ try {
1547
+ const excludeIds = entries.map((e) => e.recordId);
1548
+ const res = await executeAction("SEARCH_SUB_TABLE_RECORDS", {
1549
+ referencedTableId,
1550
+ query: query.trim(),
1551
+ excludeIds,
1552
+ limit: 15
1553
+ });
1554
+ setSearchResults(Array.isArray(res) ? res : []);
1555
+ } catch (e) {
1556
+ setSearchResults([]);
1557
+ } finally {
1558
+ setIsSearching(false);
1559
+ }
1560
+ }, 300);
1561
+ }, [executeAction, referencedTableId, entries]);
1562
+ const targetColumns = ((targetSchema == null ? void 0 : targetSchema.columns) || []).filter(
1563
+ (c) => {
1564
+ if (c.name === "_id" || c.type === "SUB_TABLE") return false;
1565
+ return true;
1566
+ }
1567
+ );
1568
+ const [relationOptions, setRelationOptions] = useState4({});
1569
+ useEffect3(() => {
1570
+ if (!executeAction || targetColumns.length === 0) return;
1571
+ const relationCols = targetColumns.filter((c) => {
1572
+ var _a2;
1573
+ return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION" && c.referencedTableId;
1574
+ });
1575
+ relationCols.forEach(async (col) => {
1576
+ try {
1577
+ const options = await executeAction("FETCH_RELATION", {
1578
+ referencedTableId: col.referencedTableId,
1579
+ displayField: col.displayField
1580
+ });
1581
+ if (options && Array.isArray(options)) {
1582
+ setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
1583
+ }
1584
+ } catch (err) {
1585
+ console.warn(`[SubTableViewer] Could not fetch relation options for column ${col.name}:`, err);
1586
+ }
1587
+ });
1588
+ }, [executeAction, targetColumns]);
1589
+ const refetchRelation = useCallback3(async (colName) => {
1590
+ var _a2;
1591
+ const col = targetColumns.find((c) => c.name === colName);
1592
+ if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !col.referencedTableId || !executeAction) return;
1593
+ try {
1594
+ const options = await executeAction("FETCH_RELATION", { referencedTableId: col.referencedTableId, displayField: col.displayField });
1595
+ if (options && Array.isArray(options)) {
1596
+ setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
1597
+ }
1598
+ } catch (err) {
1599
+ console.warn(`[SubTableViewer] Could not refetch relation options for column ${col.name}:`, err);
1600
+ }
1601
+ }, [targetColumns, executeAction]);
1602
+ const updateParentLinkage = async (updated) => {
1603
+ const isNewRow = rowId.startsWith("temp_");
1604
+ if (context == null ? void 0 : context.updateQuietly) {
1605
+ context.updateQuietly(rowId, column.name, updated);
1606
+ } else {
1607
+ onChange(updated);
1608
+ }
1609
+ if (executeAction && (context == null ? void 0 : context.parentTableId) && !isNewRow) {
1610
+ try {
1611
+ const payloadToSave = updated.map(({ recordId, isSelected }) => ({ recordId, isSelected }));
1612
+ await executeAction("UPDATE_RECORD", {
1613
+ tableId: context.parentTableId,
1614
+ recordId: rowId,
1615
+ data: { [column.name]: payloadToSave }
1616
+ });
1617
+ if (context == null ? void 0 : context.triggerSaveSuccess) {
1618
+ context.triggerSaveSuccess();
1619
+ }
1620
+ } catch (err) {
1621
+ console.error("Failed to auto-save parent linkage", err);
1622
+ }
1623
+ }
1624
+ };
1625
+ const handleLinkRecords = (recordsToLink) => {
1626
+ if (!recordsToLink || recordsToLink.length === 0) return;
1627
+ const existingEntryIds = new Set(entries.map((e) => e.recordId));
1628
+ const newEntries = [];
1629
+ const newRecordsToAdd = [];
1630
+ for (const record of recordsToLink) {
1631
+ fetchedIdsRef.current.add(record.id);
1632
+ const resolvedData = __spreadValues({}, record.data || {});
1633
+ targetColumns.forEach((col) => {
1634
+ if ((resolvedData[col.name] === void 0 || resolvedData[col.name] === null) && record[col.name] !== void 0) {
1635
+ resolvedData[col.name] = record[col.name];
1636
+ }
1637
+ });
1638
+ if (!existingEntryIds.has(record.id)) {
1639
+ newEntries.push({
1640
+ recordId: record.id,
1641
+ isSelected: true,
1642
+ _resolvedData: resolvedData
1643
+ });
1644
+ existingEntryIds.add(record.id);
1645
+ }
1646
+ newRecordsToAdd.push({
1647
+ id: record.id,
1648
+ data: resolvedData
1649
+ });
1650
+ }
1651
+ const updatedEntries = [...entries, ...newEntries];
1652
+ updateParentLinkage(updatedEntries);
1653
+ setLinkedRecords((prev) => {
1654
+ const map = new Map(prev.map((r) => [r.id, r]));
1655
+ newRecordsToAdd.forEach((r) => {
1656
+ const existing = map.get(r.id);
1657
+ if (existing) {
1658
+ map.set(r.id, __spreadProps(__spreadValues({}, existing), {
1659
+ data: __spreadValues(__spreadValues({}, existing.data), r.data)
1660
+ }));
1661
+ } else {
1662
+ map.set(r.id, r);
1663
+ }
1664
+ });
1665
+ return Array.from(map.values());
1666
+ });
1667
+ setSearchQuery("");
1668
+ setSearchResults([]);
1669
+ setIsSearchOpen(false);
1670
+ };
1671
+ const handleLinkRecord = (record) => {
1672
+ handleLinkRecords([record]);
1673
+ };
1674
+ const handleUniqueConflict = (conflictData) => {
1675
+ const rawMatching = Array.isArray(conflictData == null ? void 0 : conflictData.matchingRecords) ? conflictData.matchingRecords : [];
1676
+ const resolvedMatching = rawMatching.map((r) => {
1677
+ var _a2;
1678
+ const recordId = String(r.id || ((_a2 = r._id) == null ? void 0 : _a2.$oid) || r._id);
1679
+ let dataObj = {};
1680
+ if (r.data && typeof r.data === "object") {
1681
+ dataObj = __spreadValues({}, r.data);
1682
+ }
1683
+ targetColumns.forEach((col) => {
1684
+ if ((dataObj[col.name] === void 0 || dataObj[col.name] === null) && r[col.name] !== void 0) {
1685
+ dataObj[col.name] = r[col.name];
1686
+ }
1687
+ });
1688
+ return {
1689
+ id: recordId,
1690
+ data: dataObj
1691
+ };
1692
+ });
1693
+ setConflictModalState({
1694
+ isOpen: true,
1695
+ fieldName: (conflictData == null ? void 0 : conflictData.fieldName) || "",
1696
+ matchingRecords: resolvedMatching
1697
+ });
1698
+ };
1699
+ const handleCancelConflict = () => {
1700
+ setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
1701
+ };
1702
+ const handleConfirmLinkConflict = async () => {
1703
+ const { matchingRecords } = conflictModalState;
1704
+ if (matchingRecords && matchingRecords.length > 0) {
1705
+ handleLinkRecords(matchingRecords);
1706
+ setNewRecordData({});
1707
+ setIsCreating(false);
1708
+ setConflictModalState({
1709
+ isOpen: false,
1710
+ fieldName: "",
1711
+ matchingRecords: []
1712
+ });
1713
+ addToast({
1714
+ type: "success",
1715
+ message: "\u05D4\u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D5\u05E9\u05E8\u05D4 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
1716
+ });
1717
+ } else {
1718
+ setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
1719
+ }
1720
+ };
1721
+ const handleUnlinkRecord = (recordId) => {
1722
+ const updated = entries.filter((e) => e.recordId !== recordId);
1723
+ updateParentLinkage(updated);
1724
+ setLinkedRecords((prev) => prev.filter((r) => r.id !== recordId));
1725
+ };
1726
+ const handleToggleSelected = (recordId) => {
1727
+ const record = linkedRecords.find((r) => r.id === recordId);
1728
+ const updated = entries.map(
1729
+ (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { isSelected: !e.isSelected, _resolvedData: (record == null ? void 0 : record.data) || e._resolvedData }) : e
1730
+ );
1731
+ updateParentLinkage(updated);
1732
+ };
1733
+ const isMountedRef = useRef3(true);
1734
+ useEffect3(() => {
1735
+ isMountedRef.current = true;
1736
+ return () => {
1737
+ isMountedRef.current = false;
1738
+ };
1739
+ }, []);
1740
+ const handleCommitRecordCell = async (recordId, colName, value2) => {
1741
+ var _a2;
1742
+ const previousRecord = linkedRecords.find((r) => r.id === recordId);
1743
+ const previousValue = (_a2 = previousRecord == null ? void 0 : previousRecord.data) == null ? void 0 : _a2[colName];
1744
+ if (previousValue === value2) return true;
1745
+ const targetCol = targetColumns.find((c) => c.name === colName);
1746
+ const valRes = targetCol ? validateCellValue(value2, targetCol) : { isValid: true };
1747
+ if (!valRes.isValid) {
1748
+ addToast({
1749
+ type: "error",
1750
+ message: valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA"
1751
+ });
1752
+ return false;
1753
+ }
1754
+ if (executeAction && referencedTableId && !recordId.startsWith("temp_")) {
1755
+ try {
1756
+ const res = await executeAction("UPDATE_RECORD", {
1757
+ tableId: referencedTableId,
1758
+ recordId,
1759
+ data: { [colName]: value2 }
1760
+ });
1761
+ if (res && res.success === false) {
1762
+ const err = new Error(res.error || res.message || "Action execution failed");
1763
+ Object.assign(err, res);
1764
+ throw err;
1765
+ }
1766
+ if (isMountedRef.current) {
1767
+ const updatedRecords = linkedRecords.map(
1768
+ (r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
1769
+ );
1770
+ setLinkedRecords(updatedRecords);
1771
+ const targetRecord = updatedRecords.find((r) => r.id === recordId);
1772
+ const updatedEntries = entries.map(
1773
+ (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
1774
+ );
1775
+ if (context == null ? void 0 : context.updateQuietly) {
1776
+ context.updateQuietly(rowId, column.name, updatedEntries);
1777
+ } else {
1778
+ onChange(updatedEntries);
1779
+ }
1780
+ if (context == null ? void 0 : context.triggerSaveSuccess) {
1781
+ context.triggerSaveSuccess();
1782
+ }
1783
+ }
1784
+ return true;
1785
+ } catch (err) {
1786
+ console.error("[SubTableViewer] Failed to auto-save linked record field", err);
1787
+ 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";
1788
+ 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")) {
1789
+ 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).`;
1790
+ } else if (errorMsg.includes("is required") || errorMsg.includes("\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4") || errorMsg.toLowerCase().includes("required")) {
1791
+ 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.`;
1792
+ }
1793
+ addToast({
1794
+ type: "error",
1795
+ message: errorMsg
1796
+ });
1797
+ return false;
1798
+ }
1799
+ } else {
1800
+ if (isMountedRef.current) {
1801
+ const updatedRecords = linkedRecords.map(
1802
+ (r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
1803
+ );
1804
+ setLinkedRecords(updatedRecords);
1805
+ const targetRecord = updatedRecords.find((r) => r.id === recordId);
1806
+ const updatedEntries = entries.map(
1807
+ (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
1808
+ );
1809
+ if (context == null ? void 0 : context.updateQuietly) {
1810
+ context.updateQuietly(rowId, column.name, updatedEntries);
1811
+ } else {
1812
+ onChange(updatedEntries);
1813
+ }
1814
+ }
1815
+ return true;
1816
+ }
1817
+ };
1818
+ const handleRecordCellChange = handleCommitRecordCell;
1819
+ const handleCreateRecord = async () => {
1820
+ var _a2, _b2, _c, _d, _e;
1821
+ if (!executeAction || !referencedTableId) return;
1822
+ for (const col of targetColumns) {
1823
+ if (col.isRequired) {
1824
+ const val = newRecordData[col.name];
1825
+ if (val === void 0 || val === null || typeof val === "string" && val.trim() === "") {
1826
+ addToast({
1827
+ type: "error",
1828
+ message: `Validation Error: Field '${col.name}' is required but was not provided.`
1829
+ });
1830
+ return;
1831
+ }
1832
+ }
1833
+ if (((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE") {
1834
+ const val = newRecordData[col.name];
1835
+ if (val !== void 0 && val !== null && String(val).trim() !== "" && !isValidPhoneNumber(String(val))) {
1836
+ addToast({
1837
+ type: "error",
1838
+ 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.`
1839
+ });
1840
+ return;
1841
+ }
1842
+ }
1843
+ }
1844
+ try {
1845
+ const res = await executeAction("CREATE_RECORD", {
1846
+ tableId: referencedTableId,
1847
+ records: [newRecordData]
1848
+ });
1849
+ if (res && (res.error === "UNIQUE_CONSTRAINT_CONFLICT" || res.code === "UNIQUE_CONSTRAINT_CONFLICT")) {
1850
+ handleUniqueConflict(res);
1851
+ return;
1852
+ }
1853
+ if (res && res.success === false) {
1854
+ throw new Error(res.error || "Action execution failed");
1855
+ }
1856
+ const created = Array.isArray(res) ? res[0] : ((_b2 = res == null ? void 0 : res.data) == null ? void 0 : _b2[0]) || res;
1857
+ if (created) {
1858
+ const newRecord = {
1859
+ id: String(created.id || created._id),
1860
+ data: created.data || newRecordData
1861
+ };
1862
+ handleLinkRecord(newRecord);
1863
+ setIsCreating(false);
1864
+ setNewRecordData({});
1865
+ }
1866
+ } catch (err) {
1867
+ 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"));
1868
+ if (isConflict) {
1869
+ 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;
1870
+ handleUniqueConflict(conflictPayload);
1871
+ return;
1872
+ }
1873
+ const msg = (err == null ? void 0 : err.message) || String(err);
1874
+ addToast({
1875
+ type: "error",
1876
+ message: msg
1877
+ });
1878
+ }
1879
+ };
1880
+ const getDisplayLabel = (record) => {
1881
+ const fields = column.subTableDisplayFields || [];
1882
+ if (fields.length === 0) {
1883
+ const firstField = Object.keys(record.data).find((k) => k !== "_id");
1884
+ return firstField ? String(record.data[firstField] || "") : record.id;
1885
+ }
1886
+ return fields.map((f) => String(record.data[f] || "")).filter(Boolean).join(" ");
1887
+ };
1888
+ return /* @__PURE__ */ jsxs5("div", { className: "p-3 animate-in fade-in slide-in-from-top-2 duration-200", dir: "rtl", children: [
1889
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-4 mb-2.5", children: [
1890
+ /* @__PURE__ */ jsx5("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx5("span", { className: "text-xs font-bold text-slate-600", children: (_a = targetSchema == null ? void 0 : targetSchema.name) != null ? _a : column.referencedTableName }) }),
1891
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5", children: [
1892
+ /* @__PURE__ */ jsxs5("div", { className: "relative", ref: searchRef, children: [
1893
+ /* @__PURE__ */ jsxs5(
1894
+ "button",
1895
+ {
1896
+ type: "button",
1897
+ onClick: () => setIsSearchOpen((prev) => !prev),
1898
+ 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",
1899
+ children: [
1900
+ /* @__PURE__ */ jsx5("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
1901
+ "\u05E7\u05D9\u05E9\u05D5\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA"
1902
+ ]
1903
+ }
1904
+ ),
1905
+ isSearchOpen && /* @__PURE__ */ jsxs5("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: [
1906
+ /* @__PURE__ */ jsx5(
1907
+ "input",
1908
+ {
1909
+ type: "text",
1910
+ value: searchQuery,
1911
+ onChange: (e) => handleSearch(e.target.value),
1912
+ placeholder: "\u05D7\u05E4\u05E9 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
1913
+ 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",
1914
+ autoFocus: true
1915
+ }
1916
+ ),
1917
+ /* @__PURE__ */ jsx5("div", { className: "max-h-48 overflow-y-auto", children: isSearching ? /* @__PURE__ */ jsx5("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ jsx5("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__ */ jsx5(
1918
+ "button",
1919
+ {
1920
+ type: "button",
1921
+ onClick: () => handleLinkRecord(r),
1922
+ className: "w-full text-right px-2 py-1.5 text-xs hover:bg-blue-50 rounded cursor-pointer transition-colors",
1923
+ children: getDisplayLabel(r)
1924
+ },
1925
+ r.id
1926
+ )) : searchQuery.trim() ? /* @__PURE__ */ jsx5("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__ */ jsx5("p", { className: "text-xs text-slate-400 text-center py-3", children: "\u05D4\u05E7\u05DC\u05D3 \u05DC\u05D7\u05D9\u05E4\u05D5\u05E9..." }) })
1927
+ ] })
1928
+ ] }),
1929
+ /* @__PURE__ */ jsxs5(
1930
+ "button",
1931
+ {
1932
+ type: "button",
1933
+ onClick: () => {
1934
+ setIsCreating(true);
1935
+ const initialData = {};
1936
+ targetColumns.forEach((c) => {
1937
+ if (c.defaultValue !== void 0 && c.defaultValue !== null) {
1938
+ initialData[c.name] = c.type === "NUMBER" || c.type === "CURRENCY" ? parseFloat(c.defaultValue) : c.type === "BOOLEAN" ? c.defaultValue === "true" || c.defaultValue === true : c.defaultValue;
1939
+ } else {
1940
+ if (c.type === "NUMBER" || c.type === "CURRENCY") initialData[c.name] = 0;
1941
+ else if (c.type === "BOOLEAN") initialData[c.name] = false;
1942
+ else initialData[c.name] = "";
1943
+ }
1944
+ });
1945
+ setNewRecordData(initialData);
1946
+ },
1947
+ 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",
1948
+ children: [
1949
+ /* @__PURE__ */ jsx5("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) }),
1950
+ "\u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4"
1951
+ ]
1952
+ }
1953
+ )
1954
+ ] })
1955
+ ] }),
1956
+ isLoading ? /* @__PURE__ */ jsx5("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx5("div", { className: "w-5 h-5 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : entries.length === 0 && !isCreating ? /* @__PURE__ */ jsx5("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__ */ jsx5("div", { className: "overflow-x-auto pb-1", children: /* @__PURE__ */ jsxs5("table", { className: "w-full text-xs border-collapse", children: [
1957
+ /* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsxs5("tr", { className: "bg-slate-100/80", children: [
1958
+ /* @__PURE__ */ jsx5("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" }),
1959
+ targetColumns.map((col) => {
1960
+ var _a2;
1961
+ const isContact = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "GOOGLE_CONTACT";
1962
+ return /* @__PURE__ */ jsx5(
1963
+ "th",
1964
+ {
1965
+ className: `border border-slate-200 px-2 py-1.5 text-right font-semibold text-slate-600 whitespace-nowrap ${isContact ? "min-w-[140px]" : ""}`,
1966
+ children: col.name
1967
+ },
1968
+ col.name
1969
+ );
1970
+ }),
1971
+ /* @__PURE__ */ jsx5("th", { className: "border border-slate-200 px-2 py-1.5 w-14" })
1972
+ ] }) }),
1973
+ /* @__PURE__ */ jsxs5("tbody", { children: [
1974
+ entries.map((entry) => {
1975
+ var _a2;
1976
+ const record = linkedRecords.find((r) => r.id === entry.recordId);
1977
+ return /* @__PURE__ */ jsxs5("tr", { className: "hover:bg-blue-50/30 transition-colors", children: [
1978
+ /* @__PURE__ */ jsx5("td", { className: "border border-slate-200 px-2 py-1 text-center", children: /* @__PURE__ */ jsx5(
1979
+ "input",
1980
+ {
1981
+ type: "checkbox",
1982
+ checked: entry.isSelected,
1983
+ onChange: () => handleToggleSelected(entry.recordId),
1984
+ className: "w-3.5 h-3.5 rounded border-slate-300 text-blue-600 cursor-pointer"
1985
+ }
1986
+ ) }),
1987
+ targetColumns.map((col) => {
1988
+ var _a3;
1989
+ const isContact = ((_a3 = col.type) == null ? void 0 : _a3.toUpperCase()) === "GOOGLE_CONTACT";
1990
+ if (!record) {
1991
+ return /* @__PURE__ */ jsx5(
1992
+ "td",
1993
+ {
1994
+ className: `border border-slate-200 p-0 relative h-8 ${isContact ? "min-w-[140px]" : ""}`,
1995
+ children: /* @__PURE__ */ jsx5("span", { className: "text-slate-300 italic px-2", children: "\u05D8\u05D5\u05E2\u05DF..." })
1996
+ },
1997
+ col.name
1998
+ );
1999
+ }
2000
+ return /* @__PURE__ */ jsx5(
2001
+ SubTableCell,
2002
+ {
2003
+ record,
2004
+ column: col,
2005
+ targetSchema,
2006
+ referencedTableId,
2007
+ context,
2008
+ relationOptions,
2009
+ setRelationOptions,
2010
+ refetchRelation,
2011
+ onCommit: handleCommitRecordCell
2012
+ },
2013
+ `${record.id}_${col.name}`
2014
+ );
2015
+ }),
2016
+ /* @__PURE__ */ jsx5("td", { className: "border border-slate-200 px-1 py-1 text-center", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-center gap-1", children: [
2017
+ ((_a2 = column.config) == null ? void 0 : _a2.actionType) === "WHATSAPP" && (() => {
2018
+ var _a3, _b2, _c;
2019
+ const actionPhoneCol = (_a3 = column.config) == null ? void 0 : _a3.actionPhoneColumn;
2020
+ const phone = actionPhoneCol ? ((_b2 = record == null ? void 0 : record.data) == null ? void 0 : _b2[actionPhoneCol]) || ((_c = entry._resolvedData) == null ? void 0 : _c[actionPhoneCol]) : null;
2021
+ if (phone) {
2022
+ return /* @__PURE__ */ jsx5(
2023
+ "button",
2024
+ {
2025
+ type: "button",
2026
+ onClick: (e) => {
2027
+ e.stopPropagation();
2028
+ openWhatsAppChat(String(phone));
2029
+ },
2030
+ className: "text-emerald-500 hover:text-emerald-600 p-0.5 rounded hover:bg-emerald-50 transition-colors cursor-pointer",
2031
+ title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
2032
+ children: /* @__PURE__ */ jsx5("svg", { className: "w-3.5 h-3.5", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("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" }) })
2033
+ }
2034
+ );
2035
+ }
2036
+ return null;
2037
+ })(),
2038
+ /* @__PURE__ */ jsx5(
2039
+ "button",
2040
+ {
2041
+ type: "button",
2042
+ onClick: (e) => {
2043
+ e.stopPropagation();
2044
+ handleUnlinkRecord(entry.recordId);
2045
+ },
2046
+ className: "text-slate-400 hover:text-rose-500 p-0.5 rounded transition-colors cursor-pointer inline-flex items-center justify-center",
2047
+ title: "\u05D4\u05E1\u05E8 \u05E7\u05D9\u05E9\u05D5\u05E8",
2048
+ children: /* @__PURE__ */ jsx5("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
2049
+ }
2050
+ )
2051
+ ] }) })
2052
+ ] }, entry.recordId);
2053
+ }),
2054
+ isCreating && /* @__PURE__ */ jsxs5("tr", { className: "bg-emerald-50/40", children: [
2055
+ /* @__PURE__ */ jsx5("td", { className: "border border-emerald-200 px-2 py-1 text-center", children: /* @__PURE__ */ jsx5("span", { className: "text-emerald-500 font-bold text-[10px]", children: "\u05D7\u05D3\u05E9" }) }),
2056
+ targetColumns.map((col) => {
2057
+ var _a2, _b2;
2058
+ const colType = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) || "DEFAULT";
2059
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
2060
+ const isContact = colType === "GOOGLE_CONTACT";
2061
+ return /* @__PURE__ */ jsx5(
2062
+ "td",
2063
+ {
2064
+ className: `border border-emerald-200 p-0 relative h-8 ${isContact ? "min-w-[140px]" : ""}`,
2065
+ children: /* @__PURE__ */ jsx5(
2066
+ InputComponent,
2067
+ {
2068
+ value: (_b2 = newRecordData[col.name]) != null ? _b2 : colType === "BOOLEAN" ? false : "",
2069
+ column: col,
2070
+ rowId: "new_record",
2071
+ onChange: (v) => setNewRecordData((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: v })),
2072
+ context: __spreadProps(__spreadValues({}, context), {
2073
+ 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",
2074
+ relationOptions,
2075
+ refetchRelation,
2076
+ tableId: (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId
2077
+ })
2078
+ }
2079
+ )
2080
+ },
2081
+ `new_${col.name}`
2082
+ );
2083
+ }),
2084
+ /* @__PURE__ */ jsx5("td", { className: "border border-emerald-200 px-1 py-1 text-center", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-center gap-1", children: [
2085
+ /* @__PURE__ */ jsx5(
2086
+ "button",
2087
+ {
2088
+ type: "button",
2089
+ onClick: handleCreateRecord,
2090
+ className: "p-1 text-emerald-600 hover:bg-emerald-100 rounded transition-colors",
2091
+ title: "\u05E9\u05DE\u05D5\u05E8",
2092
+ children: /* @__PURE__ */ jsx5("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) })
2093
+ }
2094
+ ),
2095
+ /* @__PURE__ */ jsx5(
2096
+ "button",
2097
+ {
2098
+ type: "button",
2099
+ onClick: () => {
2100
+ setIsCreating(false);
2101
+ },
2102
+ className: "p-1 text-rose-500 hover:bg-rose-100 rounded transition-colors",
2103
+ title: "\u05D1\u05D9\u05D8\u05D5\u05DC",
2104
+ children: /* @__PURE__ */ jsx5("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M6 18L18 6M6 6l12 12" }) })
2105
+ }
2106
+ )
2107
+ ] }) })
2108
+ ] })
2109
+ ] })
2110
+ ] }) }),
2111
+ conflictModalState.isOpen && /* @__PURE__ */ jsx5(
2112
+ "div",
2113
+ {
2114
+ 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",
2115
+ dir: "rtl",
2116
+ onClick: handleCancelConflict,
2117
+ children: /* @__PURE__ */ jsxs5(
2118
+ "div",
2119
+ {
2120
+ 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",
2121
+ onClick: (e) => e.stopPropagation(),
2122
+ children: [
2123
+ /* @__PURE__ */ jsxs5("div", { className: "p-5 border-b border-slate-100 flex items-center gap-3", children: [
2124
+ /* @__PURE__ */ jsx5("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__ */ jsx5("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("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" }) }) }),
2125
+ /* @__PURE__ */ jsxs5("div", { children: [
2126
+ /* @__PURE__ */ jsx5("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" }),
2127
+ /* @__PURE__ */ jsx5("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" })
2128
+ ] })
2129
+ ] }),
2130
+ /* @__PURE__ */ jsxs5("div", { className: "p-5 space-y-3", children: [
2131
+ /* @__PURE__ */ jsxs5("p", { className: "text-sm text-slate-700 leading-relaxed", children: [
2132
+ "\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",
2133
+ " ",
2134
+ /* @__PURE__ */ jsx5("span", { className: "font-bold text-slate-900 bg-slate-100 px-1.5 py-0.5 rounded border border-slate-200", children: conflictModalState.fieldName }),
2135
+ ". \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?"
2136
+ ] }),
2137
+ conflictModalState.matchingRecords.length > 1 && /* @__PURE__ */ jsxs5("div", { className: "p-3 bg-blue-50 border border-blue-200 rounded-lg text-xs font-semibold text-blue-800", children: [
2138
+ "\u05E0\u05DE\u05E6\u05D0\u05D5 ",
2139
+ conflictModalState.matchingRecords.length,
2140
+ " \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?"
2141
+ ] }),
2142
+ conflictModalState.matchingRecords.length > 0 && /* @__PURE__ */ jsx5("div", { className: "overflow-x-auto border border-slate-200 rounded-lg max-h-48 text-xs bg-white", children: /* @__PURE__ */ jsxs5("table", { className: "w-full text-right border-collapse", children: [
2143
+ /* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsx5("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__ */ jsx5(
2144
+ "th",
2145
+ {
2146
+ className: "bg-slate-100 text-slate-700 font-semibold p-2 border-b whitespace-nowrap",
2147
+ children: col.name
2148
+ },
2149
+ col.name
2150
+ )) }) }),
2151
+ /* @__PURE__ */ jsx5("tbody", { children: conflictModalState.matchingRecords.map((r, idx) => {
2152
+ 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 }));
2153
+ return /* @__PURE__ */ jsx5("tr", { className: "hover:bg-slate-50/80 transition-colors", children: cols.map((col) => {
2154
+ var _a2;
2155
+ const rawVal = (_a2 = r.data) == null ? void 0 : _a2[col.name];
2156
+ let displayVal = "-";
2157
+ if (rawVal !== void 0 && rawVal !== null && rawVal !== "") {
2158
+ if (typeof rawVal === "boolean") {
2159
+ displayVal = rawVal ? "\u05DB\u05DF" : "\u05DC\u05D0";
2160
+ } else if (typeof rawVal === "object") {
2161
+ displayVal = Array.isArray(rawVal) ? rawVal.join(", ") : JSON.stringify(rawVal);
2162
+ } else {
2163
+ displayVal = String(rawVal);
2164
+ }
2165
+ }
2166
+ return /* @__PURE__ */ jsx5(
2167
+ "td",
2168
+ {
2169
+ className: "p-2 border-b border-slate-100 whitespace-nowrap text-slate-800",
2170
+ children: displayVal
2171
+ },
2172
+ col.name
2173
+ );
2174
+ }) }, r.id || idx);
2175
+ }) })
2176
+ ] }) })
2177
+ ] }),
2178
+ /* @__PURE__ */ jsxs5("div", { className: "p-4 bg-slate-50 border-t border-slate-100 flex items-center justify-end gap-2.5", children: [
2179
+ /* @__PURE__ */ jsx5(
2180
+ "button",
2181
+ {
2182
+ type: "button",
2183
+ onClick: handleCancelConflict,
2184
+ 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",
2185
+ children: "\u05D1\u05D9\u05D8\u05D5\u05DC"
2186
+ }
2187
+ ),
2188
+ /* @__PURE__ */ jsxs5(
2189
+ "button",
2190
+ {
2191
+ type: "button",
2192
+ onClick: handleConfirmLinkConflict,
2193
+ 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",
2194
+ children: [
2195
+ /* @__PURE__ */ jsx5("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("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" }) }),
2196
+ conflictModalState.matchingRecords.length > 1 ? "\u05E7\u05E9\u05E8 \u05D0\u05EA \u05DB\u05D5\u05DC\u05DF" : "\u05E7\u05E9\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D4"
2197
+ ]
2198
+ }
2199
+ )
2200
+ ] })
2201
+ ]
2202
+ }
2203
+ )
2204
+ }
2205
+ )
2206
+ ] });
2207
+ }
2208
+
869
2209
  // src/components/TableBlock/TableBlockClient.tsx
870
2210
  import { X as X4, Copy as Copy2 } from "lucide-react";
871
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
2211
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
872
2212
  function TableBlockClient({
873
2213
  data: initialRecords,
874
2214
  settings: schema,
@@ -885,14 +2225,14 @@ function TableBlockClient({
885
2225
  "data-testid": dataTestId
886
2226
  }) {
887
2227
  const { showError, addToast } = useToast();
888
- const [columnWidths, setColumnWidths] = useState4({});
889
- const [isMounted, setIsMounted] = useState4(false);
2228
+ const [columnWidths, setColumnWidths] = useState5({});
2229
+ const [isMounted, setIsMounted] = useState5(false);
890
2230
  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";
891
- const [page, setPage] = useState4(1);
892
- const [limit, setLimit] = useState4(50);
893
- const [totalRecords, setTotalRecords] = useState4(0);
894
- const [totalPages, setTotalPages] = useState4(1);
895
- useEffect2(() => {
2231
+ const [page, setPage] = useState5(1);
2232
+ const [limit, setLimit] = useState5(50);
2233
+ const [totalRecords, setTotalRecords] = useState5(0);
2234
+ const [totalPages, setTotalPages] = useState5(1);
2235
+ useEffect4(() => {
896
2236
  if (typeof window !== "undefined") {
897
2237
  const savedWidths = localStorage.getItem(`table_widths_${tableKey}`);
898
2238
  if (savedWidths) {
@@ -915,7 +2255,7 @@ function TableBlockClient({
915
2255
  }
916
2256
  setIsMounted(true);
917
2257
  }, [tableKey]);
918
- const [showSummary, setShowSummary] = useState4(false);
2258
+ const [showSummary, setShowSummary] = useState5(false);
919
2259
  const toggleSummary = () => {
920
2260
  setShowSummary((prev) => {
921
2261
  const next = !prev;
@@ -924,8 +2264,8 @@ function TableBlockClient({
924
2264
  return next;
925
2265
  });
926
2266
  };
927
- const [resizingCol, setResizingCol] = useState4(null);
928
- useEffect2(() => {
2267
+ const [resizingCol, setResizingCol] = useState5(null);
2268
+ useEffect4(() => {
929
2269
  if (!resizingCol) return;
930
2270
  const handleMouseMove = (e) => {
931
2271
  const diffX = resizingCol.startX - e.clientX;
@@ -972,7 +2312,7 @@ function TableBlockClient({
972
2312
  return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
973
2313
  });
974
2314
  };
975
- const mergeColumnDefs = useCallback3((existingCols, incomingCols) => {
2315
+ const mergeColumnDefs = useCallback4((existingCols, incomingCols) => {
976
2316
  if (!incomingCols || incomingCols.length === 0) return existingCols || [];
977
2317
  if (!existingCols || existingCols.length === 0) return incomingCols;
978
2318
  const existingMap = new Map(existingCols.map((c) => [c.name, c]));
@@ -992,18 +2332,18 @@ function TableBlockClient({
992
2332
  return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
993
2333
  });
994
2334
  }, []);
995
- const [localColumns, setLocalColumns] = useState4(() => (schema == null ? void 0 : schema.columns) || []);
996
- useEffect2(() => {
2335
+ const [localColumns, setLocalColumns] = useState5(() => (schema == null ? void 0 : schema.columns) || []);
2336
+ useEffect4(() => {
997
2337
  if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
998
2338
  setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
999
2339
  }
1000
2340
  }, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
1001
- const [dirty, setDirty] = useState4({ added: [], modified: {}, deleted: [] });
1002
- const dirtyRef = useRef3(dirty);
1003
- useEffect2(() => {
2341
+ const [dirty, setDirty] = useState5({ added: [], modified: {}, deleted: [] });
2342
+ const dirtyRef = useRef4(dirty);
2343
+ useEffect4(() => {
1004
2344
  dirtyRef.current = dirty;
1005
2345
  }, [dirty]);
1006
- const mergeWithDirty = useCallback3((baseRecords) => {
2346
+ const mergeWithDirty = useCallback4((baseRecords) => {
1007
2347
  const { added, modified, deleted } = dirtyRef.current;
1008
2348
  const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
1009
2349
  const modifiedRecords = nonDeleted.map((r) => {
@@ -1016,8 +2356,8 @@ function TableBlockClient({
1016
2356
  const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
1017
2357
  return [...uniqueAdded, ...modifiedRecords];
1018
2358
  }, []);
1019
- const [data, setData] = useState4(() => normalizeRecords(initialRecords));
1020
- useEffect2(() => {
2359
+ const [data, setData] = useState5(() => normalizeRecords(initialRecords));
2360
+ useEffect4(() => {
1021
2361
  if (initialRecords) {
1022
2362
  setData(mergeWithDirty(normalizeRecords(initialRecords)));
1023
2363
  }
@@ -1032,19 +2372,19 @@ function TableBlockClient({
1032
2372
  }
1033
2373
  return false;
1034
2374
  };
1035
- const [baseRecordsMap, setBaseRecordsMap] = useState4(() => {
2375
+ const [baseRecordsMap, setBaseRecordsMap] = useState5(() => {
1036
2376
  const map = /* @__PURE__ */ new Map();
1037
2377
  (normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
1038
2378
  return map;
1039
2379
  });
1040
- useEffect2(() => {
2380
+ useEffect4(() => {
1041
2381
  if (initialRecords && initialRecords.length > 0) {
1042
2382
  const map = /* @__PURE__ */ new Map();
1043
2383
  (normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
1044
2384
  setBaseRecordsMap(map);
1045
2385
  }
1046
2386
  }, [initialRecords]);
1047
- const refetchTableData = useCallback3((targetPage) => {
2387
+ const refetchTableData = useCallback4((targetPage) => {
1048
2388
  const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
1049
2389
  if (!tableId || !executeAction) return Promise.resolve();
1050
2390
  const activePage = targetPage !== void 0 ? targetPage : page;
@@ -1078,8 +2418,8 @@ function TableBlockClient({
1078
2418
  }).catch((err) => {
1079
2419
  console.error("[TableBlock] Failed to auto-fetch table data:", err);
1080
2420
  });
1081
- }, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeWithDirty, mergeColumnDefs]);
1082
- useEffect2(() => {
2421
+ }, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeColumnDefs]);
2422
+ useEffect4(() => {
1083
2423
  refetchTableData();
1084
2424
  }, [refetchTableData]);
1085
2425
  const handleLimitChange = (newLimit) => {
@@ -1095,19 +2435,20 @@ function TableBlockClient({
1095
2435
  const handleNextPage = () => {
1096
2436
  setPage((prev) => Math.min(totalPages, prev + 1));
1097
2437
  };
1098
- useEffect2(() => {
2438
+ useEffect4(() => {
1099
2439
  if (error) {
1100
2440
  showError(error, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E8\u05DB\u05D9\u05D1");
1101
2441
  }
1102
2442
  }, [error, showError]);
1103
- const [searchQuery, setSearchQuery] = useState4("");
1104
- const [selectedIds, setSelectedIds] = useState4(/* @__PURE__ */ new Set());
1105
- const [pendingDeletions, setPendingDeletions] = useState4([]);
1106
- const [isSaving, setIsSaving] = useState4(false);
1107
- const [isSaveSuccess, setIsSaveSuccess] = useState4(false);
1108
- const [relationOptions, setRelationOptions] = useState4({});
2443
+ const [searchQuery, setSearchQuery] = useState5("");
2444
+ const [selectedIds, setSelectedIds] = useState5(/* @__PURE__ */ new Set());
2445
+ const [pendingDeletions, setPendingDeletions] = useState5([]);
2446
+ const [isSaving, setIsSaving] = useState5(false);
2447
+ const [isSaveSuccess, setIsSaveSuccess] = useState5(false);
2448
+ const [relationOptions, setRelationOptions] = useState5({});
2449
+ const [expandedRowIds, setExpandedRowIds] = useState5(/* @__PURE__ */ new Set());
1109
2450
  const schemaColsString = useMemo2(() => JSON.stringify(localColumns || []), [localColumns]);
1110
- const refetchRelation = useCallback3(async (colName) => {
2451
+ const refetchRelation = useCallback4(async (colName) => {
1111
2452
  var _a;
1112
2453
  let parsedCols = [];
1113
2454
  try {
@@ -1127,7 +2468,7 @@ function TableBlockClient({
1127
2468
  console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
1128
2469
  }
1129
2470
  }, [schemaColsString, executeAction]);
1130
- useEffect2(() => {
2471
+ useEffect4(() => {
1131
2472
  let parsedCols = [];
1132
2473
  try {
1133
2474
  parsedCols = JSON.parse(schemaColsString);
@@ -1163,9 +2504,9 @@ function TableBlockClient({
1163
2504
  const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
1164
2505
  return normalizedColumns.filter((col) => !systemFields.includes(col.name));
1165
2506
  }, [normalizedColumns]);
1166
- const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = useState4(false);
1167
- const dropdownRef = useRef3(null);
1168
- useEffect2(() => {
2507
+ const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = useState5(false);
2508
+ const dropdownRef = useRef4(null);
2509
+ useEffect4(() => {
1169
2510
  const handleClickOutside = (e) => {
1170
2511
  if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
1171
2512
  setIsColumnsDropdownOpen(false);
@@ -1243,8 +2584,8 @@ function TableBlockClient({
1243
2584
  }
1244
2585
  }
1245
2586
  };
1246
- const [draggedColName, setDraggedColName] = useState4(null);
1247
- const [dragOverColName, setDragOverColName] = useState4(null);
2587
+ const [draggedColName, setDraggedColName] = useState5(null);
2588
+ const [dragOverColName, setDragOverColName] = useState5(null);
1248
2589
  const handleColumnReorder = async (draggedName, dropTargetName) => {
1249
2590
  var _a;
1250
2591
  if (draggedName === dropTargetName) return;
@@ -1286,6 +2627,10 @@ function TableBlockClient({
1286
2627
  var _a;
1287
2628
  const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
1288
2629
  let initialValue = col.defaultValue;
2630
+ if (typeUpper === "SUB_TABLE") {
2631
+ defaultData[col.name] = [];
2632
+ return;
2633
+ }
1289
2634
  if (initialValue !== void 0 && initialValue !== null && initialValue !== "") {
1290
2635
  if (typeUpper === "CURRENCY" || typeUpper === "NUMBER") {
1291
2636
  initialValue = parseFloat(initialValue);
@@ -1369,6 +2714,36 @@ function TableBlockClient({
1369
2714
  });
1370
2715
  }
1371
2716
  };
2717
+ const triggerSaveSuccess = useCallback4(() => {
2718
+ setIsSaveSuccess(true);
2719
+ setTimeout(() => {
2720
+ setIsSaveSuccess(false);
2721
+ }, 2500);
2722
+ }, []);
2723
+ const handleQuietCellChange = useCallback4((rowId, colName, value) => {
2724
+ setData((prev) => prev.map(
2725
+ (row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
2726
+ ));
2727
+ if (rowId.startsWith("temp_")) {
2728
+ setDirty((prev) => {
2729
+ if (!prev.added.some((r) => r.id === rowId)) return prev;
2730
+ return __spreadProps(__spreadValues({}, prev), {
2731
+ added: prev.added.map(
2732
+ (r) => r.id === rowId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value }) }) : r
2733
+ )
2734
+ });
2735
+ });
2736
+ } else {
2737
+ setBaseRecordsMap((prev) => {
2738
+ const next = new Map(prev);
2739
+ const rowData = next.get(rowId);
2740
+ if (rowData) {
2741
+ next.set(rowId, __spreadProps(__spreadValues({}, rowData), { [colName]: value }));
2742
+ }
2743
+ return next;
2744
+ });
2745
+ }
2746
+ }, []);
1372
2747
  const toggleSelectAll = (checked) => {
1373
2748
  const nextSelected = checked ? new Set(filteredData.map((r) => r.id)) : /* @__PURE__ */ new Set();
1374
2749
  setSelectedIds(nextSelected);
@@ -1398,9 +2773,15 @@ function TableBlockClient({
1398
2773
  const row = data.find((r) => r.id === id);
1399
2774
  if (row) {
1400
2775
  driveCols.forEach((col) => {
1401
- const fileObj = row.data[col.name];
1402
- if (fileObj && fileObj.fileId) {
1403
- filesToDelete.push(fileObj.fileId);
2776
+ const fileVal = row.data[col.name];
2777
+ if (Array.isArray(fileVal)) {
2778
+ fileVal.forEach((fileObj) => {
2779
+ if (fileObj && fileObj.fileId) {
2780
+ filesToDelete.push(fileObj.fileId);
2781
+ }
2782
+ });
2783
+ } else if (fileVal && fileVal.fileId) {
2784
+ filesToDelete.push(fileVal.fileId);
1404
2785
  }
1405
2786
  });
1406
2787
  }
@@ -1427,7 +2808,7 @@ function TableBlockClient({
1427
2808
  const formatPayload = (payload) => {
1428
2809
  const formatted = {};
1429
2810
  (localColumns || []).forEach((col) => {
1430
- var _a;
2811
+ var _a, _b, _c;
1431
2812
  if (["_id", "id", "createdAt", "updatedAt", "orgId", "tableId", "isSelected"].includes(col.name)) return;
1432
2813
  let val = payload[col.name];
1433
2814
  if (val !== void 0) {
@@ -1437,6 +2818,13 @@ function TableBlockClient({
1437
2818
  if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
1438
2819
  val = val === "" ? 0 : Number(val);
1439
2820
  if (isNaN(val)) val = 0;
2821
+ } else if (((_b = col.type) == null ? void 0 : _b.toUpperCase()) === "PHONE") {
2822
+ val = sanitizePhoneNumber(String(val));
2823
+ } else if (((_c = col.type) == null ? void 0 : _c.toUpperCase()) === "SUB_TABLE" && Array.isArray(val)) {
2824
+ val = val.map((item) => {
2825
+ const _a2 = item, { _resolvedData } = _a2, rest = __objRest(_a2, ["_resolvedData"]);
2826
+ return rest;
2827
+ });
1440
2828
  }
1441
2829
  formatted[col.name] = val;
1442
2830
  }
@@ -1446,7 +2834,7 @@ function TableBlockClient({
1446
2834
  };
1447
2835
  const hasChanges = dirty.added.length > 0 || Object.keys(dirty.modified).length > 0 || dirty.deleted.length > 0;
1448
2836
  const handleSave = async () => {
1449
- var _a;
2837
+ var _a, _b;
1450
2838
  if (!hasChanges) {
1451
2839
  return;
1452
2840
  }
@@ -1469,6 +2857,28 @@ function TableBlockClient({
1469
2857
  }
1470
2858
  }
1471
2859
  }
2860
+ const phoneCols = (localColumns || []).filter((c) => {
2861
+ var _a2;
2862
+ return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE";
2863
+ });
2864
+ for (const col of phoneCols) {
2865
+ for (const row of dirty.added) {
2866
+ const val = row.data[col.name];
2867
+ if (!isEmpty(val) && !isValidPhoneNumber(val)) {
2868
+ 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");
2869
+ return;
2870
+ }
2871
+ }
2872
+ for (const [rowId, mods] of Object.entries(dirty.modified)) {
2873
+ const rowData = ((_b = data.find((r) => r.id === rowId)) == null ? void 0 : _b.data) || {};
2874
+ const mergedData = __spreadValues(__spreadValues({}, rowData), mods);
2875
+ const val = mergedData[col.name];
2876
+ if (!isEmpty(val) && !isValidPhoneNumber(val)) {
2877
+ 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");
2878
+ return;
2879
+ }
2880
+ }
2881
+ }
1472
2882
  setIsSaving(true);
1473
2883
  try {
1474
2884
  if (!executeAction) {
@@ -1598,7 +3008,7 @@ function TableBlockClient({
1598
3008
  });
1599
3009
  return totals;
1600
3010
  }, [filteredData, filteredColumns, showSummary]);
1601
- return /* @__PURE__ */ jsxs5(
3011
+ return /* @__PURE__ */ jsxs6(
1602
3012
  "div",
1603
3013
  {
1604
3014
  id: componentId,
@@ -1606,34 +3016,34 @@ function TableBlockClient({
1606
3016
  className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs min-h-[350px] overflow-hidden ${className}`,
1607
3017
  dir: "rtl",
1608
3018
  children: [
1609
- errorMessage && /* @__PURE__ */ jsx5("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
1610
- /* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
1611
- /* @__PURE__ */ jsx5("span", { children: errorMessage })
3019
+ errorMessage && /* @__PURE__ */ jsx6("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
3020
+ /* @__PURE__ */ jsx6("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
3021
+ /* @__PURE__ */ jsx6("span", { children: errorMessage })
1612
3022
  ] }) }),
1613
- /* @__PURE__ */ jsxs5("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: [
1614
- /* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap items-center gap-2.5", children: [
1615
- ((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ jsx5("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ jsx5("span", { children: schema.title || schema.name }) }),
1616
- /* @__PURE__ */ jsx5(
3023
+ /* @__PURE__ */ jsxs6("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: [
3024
+ /* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap items-center gap-2.5", children: [
3025
+ ((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ jsx6("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ jsx6("span", { children: schema.title || schema.name }) }),
3026
+ /* @__PURE__ */ jsx6(
1617
3027
  "button",
1618
3028
  {
1619
3029
  onClick: handleAddRow,
1620
3030
  disabled: isLoading || isUpdatingActive,
1621
3031
  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",
1622
3032
  title: "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
1623
- children: /* @__PURE__ */ jsx5("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
3033
+ children: /* @__PURE__ */ jsx6("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
1624
3034
  }
1625
3035
  ),
1626
- /* @__PURE__ */ jsx5(
3036
+ /* @__PURE__ */ jsx6(
1627
3037
  "button",
1628
3038
  {
1629
3039
  onClick: handleDuplicateRow,
1630
3040
  disabled: isLoading || isUpdatingActive || selectedIds.size !== 1,
1631
3041
  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",
1632
3042
  title: "\u05E9\u05DB\u05E4\u05DC \u05E9\u05D5\u05E8\u05D4 \u05E0\u05D1\u05D7\u05E8\u05EA",
1633
- children: /* @__PURE__ */ jsx5(Copy2, { className: "w-4 h-4 text-blue-600 shrink-0" })
3043
+ children: /* @__PURE__ */ jsx6(Copy2, { className: "w-4 h-4 text-blue-600 shrink-0" })
1634
3044
  }
1635
3045
  ),
1636
- /* @__PURE__ */ jsxs5(
3046
+ /* @__PURE__ */ jsxs6(
1637
3047
  "button",
1638
3048
  {
1639
3049
  onClick: handleDeleteSelected,
@@ -1641,12 +3051,12 @@ function TableBlockClient({
1641
3051
  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",
1642
3052
  title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
1643
3053
  children: [
1644
- /* @__PURE__ */ jsx5("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("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" }) }),
1645
- selectedIds.size > 0 && /* @__PURE__ */ jsx5("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 })
3054
+ /* @__PURE__ */ jsx6("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("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" }) }),
3055
+ selectedIds.size > 0 && /* @__PURE__ */ jsx6("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 })
1646
3056
  ]
1647
3057
  }
1648
3058
  ),
1649
- /* @__PURE__ */ jsxs5(
3059
+ /* @__PURE__ */ jsxs6(
1650
3060
  "button",
1651
3061
  {
1652
3062
  onClick: toggleSummary,
@@ -1654,13 +3064,13 @@ function TableBlockClient({
1654
3064
  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"}`,
1655
3065
  title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
1656
3066
  children: [
1657
- /* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
1658
- /* @__PURE__ */ jsx5("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
3067
+ /* @__PURE__ */ jsx6("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
3068
+ /* @__PURE__ */ jsx6("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
1659
3069
  ]
1660
3070
  }
1661
3071
  ),
1662
- /* @__PURE__ */ jsxs5("div", { className: "relative", ref: dropdownRef, children: [
1663
- /* @__PURE__ */ jsxs5(
3072
+ /* @__PURE__ */ jsxs6("div", { className: "relative", ref: dropdownRef, children: [
3073
+ /* @__PURE__ */ jsxs6(
1664
3074
  "button",
1665
3075
  {
1666
3076
  onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
@@ -1668,16 +3078,16 @@ function TableBlockClient({
1668
3078
  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",
1669
3079
  title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
1670
3080
  children: [
1671
- /* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("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" }) }),
1672
- /* @__PURE__ */ jsx5("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__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
3081
+ /* @__PURE__ */ jsx6("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("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" }) }),
3082
+ /* @__PURE__ */ jsx6("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__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
1673
3083
  ]
1674
3084
  }
1675
3085
  ),
1676
- isColumnsDropdownOpen && /* @__PURE__ */ jsxs5("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: [
1677
- /* @__PURE__ */ jsxs5("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: [
1678
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5", children: [
1679
- /* @__PURE__ */ jsx5("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
1680
- /* @__PURE__ */ jsxs5("span", { className: "text-[10px] font-normal text-slate-400", children: [
3086
+ isColumnsDropdownOpen && /* @__PURE__ */ jsxs6("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: [
3087
+ /* @__PURE__ */ jsxs6("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: [
3088
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5", children: [
3089
+ /* @__PURE__ */ jsx6("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
3090
+ /* @__PURE__ */ jsxs6("span", { className: "text-[10px] font-normal text-slate-400", children: [
1681
3091
  "(",
1682
3092
  customizableColumns.filter((c) => !c.isHidden).length,
1683
3093
  "/",
@@ -1685,7 +3095,7 @@ function TableBlockClient({
1685
3095
  ")"
1686
3096
  ] })
1687
3097
  ] }),
1688
- /* @__PURE__ */ jsx5(
3098
+ /* @__PURE__ */ jsx6(
1689
3099
  "button",
1690
3100
  {
1691
3101
  type: "button",
@@ -1695,7 +3105,7 @@ function TableBlockClient({
1695
3105
  }
1696
3106
  )
1697
3107
  ] }),
1698
- /* @__PURE__ */ jsx5("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
3108
+ /* @__PURE__ */ jsx6("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
1699
3109
  const isRequired = col.isRequired === true || String(col.isRequired) === "true";
1700
3110
  const isUnique = col.isUnique === true || String(col.isUnique) === "true";
1701
3111
  const isProtected = isRequired || isUnique;
@@ -1709,7 +3119,7 @@ function TableBlockClient({
1709
3119
  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";
1710
3120
  }
1711
3121
  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";
1712
- return /* @__PURE__ */ jsxs5(
3122
+ return /* @__PURE__ */ jsxs6(
1713
3123
  "div",
1714
3124
  {
1715
3125
  onClick: () => {
@@ -1720,8 +3130,8 @@ function TableBlockClient({
1720
3130
  title: isProtected ? protectedExplanation : void 0,
1721
3131
  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"}`,
1722
3132
  children: [
1723
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 min-w-0", children: [
1724
- /* @__PURE__ */ jsx5(
3133
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 min-w-0", children: [
3134
+ /* @__PURE__ */ jsx6(
1725
3135
  "input",
1726
3136
  {
1727
3137
  type: "checkbox",
@@ -1732,16 +3142,16 @@ function TableBlockClient({
1732
3142
  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"
1733
3143
  }
1734
3144
  ),
1735
- /* @__PURE__ */ jsx5("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
3145
+ /* @__PURE__ */ jsx6("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
1736
3146
  ] }),
1737
- isProtected && /* @__PURE__ */ jsxs5(
3147
+ isProtected && /* @__PURE__ */ jsxs6(
1738
3148
  "div",
1739
3149
  {
1740
3150
  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",
1741
3151
  title: protectedExplanation,
1742
3152
  children: [
1743
- /* @__PURE__ */ jsx5("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__ */ jsx5("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" }) }),
1744
- /* @__PURE__ */ jsx5("span", { children: badgeLabel })
3153
+ /* @__PURE__ */ jsx6("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__ */ jsx6("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" }) }),
3154
+ /* @__PURE__ */ jsx6("span", { children: badgeLabel })
1745
3155
  ]
1746
3156
  }
1747
3157
  )
@@ -1752,9 +3162,9 @@ function TableBlockClient({
1752
3162
  }) })
1753
3163
  ] })
1754
3164
  ] }),
1755
- /* @__PURE__ */ jsx5("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
1756
- /* @__PURE__ */ jsxs5("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
1757
- /* @__PURE__ */ jsx5(
3165
+ /* @__PURE__ */ jsx6("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
3166
+ /* @__PURE__ */ jsxs6("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
3167
+ /* @__PURE__ */ jsx6(
1758
3168
  "input",
1759
3169
  {
1760
3170
  placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
@@ -1764,45 +3174,45 @@ function TableBlockClient({
1764
3174
  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"
1765
3175
  }
1766
3176
  ),
1767
- searchQuery ? /* @__PURE__ */ jsx5(
3177
+ searchQuery ? /* @__PURE__ */ jsx6(
1768
3178
  "button",
1769
3179
  {
1770
3180
  type: "button",
1771
3181
  onClick: () => setSearchQuery(""),
1772
3182
  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",
1773
3183
  title: "Clear search",
1774
- children: /* @__PURE__ */ jsx5(X4, { className: "w-3.5 h-3.5" })
3184
+ children: /* @__PURE__ */ jsx6(X4, { className: "w-3.5 h-3.5" })
1775
3185
  }
1776
- ) : /* @__PURE__ */ jsx5("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__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
3186
+ ) : /* @__PURE__ */ jsx6("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__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
1777
3187
  ] })
1778
3188
  ] }),
1779
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
1780
- isUpdatingActive ? /* @__PURE__ */ jsxs5("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: [
1781
- /* @__PURE__ */ jsx5("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
3189
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
3190
+ isUpdatingActive ? /* @__PURE__ */ jsxs6("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: [
3191
+ /* @__PURE__ */ jsx6("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
1782
3192
  "\u05DE\u05E2\u05D3\u05DB\u05DF..."
1783
- ] }) : isSaveSuccess ? /* @__PURE__ */ jsxs5("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: [
1784
- /* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
3193
+ ] }) : isSaveSuccess ? /* @__PURE__ */ jsxs6("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: [
3194
+ /* @__PURE__ */ jsx6("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
1785
3195
  "\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
1786
- ] }) : hasChanges ? /* @__PURE__ */ jsx5("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,
1787
- /* @__PURE__ */ jsx5(
3196
+ ] }) : hasChanges ? /* @__PURE__ */ jsx6("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,
3197
+ /* @__PURE__ */ jsx6(
1788
3198
  "button",
1789
3199
  {
1790
3200
  onClick: handleSave,
1791
3201
  disabled: isUpdatingActive || isLoading || !hasChanges,
1792
3202
  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"}`,
1793
- children: /* @__PURE__ */ jsx5("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
3203
+ children: /* @__PURE__ */ jsx6("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
1794
3204
  }
1795
3205
  )
1796
3206
  ] })
1797
3207
  ] }),
1798
- /* @__PURE__ */ jsxs5("div", { className: `overflow-x-auto relative min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
1799
- isLoading && /* @__PURE__ */ jsxs5("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
1800
- /* @__PURE__ */ jsx5("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
1801
- /* @__PURE__ */ jsx5("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
3208
+ /* @__PURE__ */ jsxs6("div", { className: `overflow-x-auto relative min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
3209
+ isLoading && /* @__PURE__ */ jsxs6("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
3210
+ /* @__PURE__ */ jsx6("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
3211
+ /* @__PURE__ */ jsx6("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
1802
3212
  ] }),
1803
- /* @__PURE__ */ jsxs5("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
1804
- /* @__PURE__ */ jsx5("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ jsxs5("tr", { children: [
1805
- /* @__PURE__ */ jsx5("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__ */ jsx5(
3213
+ /* @__PURE__ */ jsxs6("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
3214
+ /* @__PURE__ */ jsx6("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ jsxs6("tr", { children: [
3215
+ /* @__PURE__ */ jsx6("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__ */ jsx6(
1806
3216
  "input",
1807
3217
  {
1808
3218
  type: "checkbox",
@@ -1816,7 +3226,7 @@ function TableBlockClient({
1816
3226
  const isDragging = draggedColName === col.name;
1817
3227
  const isDragOver = dragOverColName === col.name;
1818
3228
  const currentWidth = columnWidths[col.name] || 200;
1819
- return /* @__PURE__ */ jsxs5(
3229
+ return /* @__PURE__ */ jsxs6(
1820
3230
  "th",
1821
3231
  {
1822
3232
  style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
@@ -1852,7 +3262,7 @@ function TableBlockClient({
1852
3262
  },
1853
3263
  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"}`,
1854
3264
  children: [
1855
- /* @__PURE__ */ jsx5(
3265
+ /* @__PURE__ */ jsx6(
1856
3266
  "div",
1857
3267
  {
1858
3268
  onMouseDown: (e) => {
@@ -1864,16 +3274,16 @@ function TableBlockClient({
1864
3274
  title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
1865
3275
  }
1866
3276
  ),
1867
- /* @__PURE__ */ jsxs5("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: [
1868
- /* @__PURE__ */ jsx5("span", { className: "truncate", children: col.name }),
1869
- /* @__PURE__ */ jsx5(
3277
+ /* @__PURE__ */ jsxs6("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: [
3278
+ /* @__PURE__ */ jsx6("span", { className: "truncate", children: col.name }),
3279
+ /* @__PURE__ */ jsx6(
1870
3280
  "svg",
1871
3281
  {
1872
3282
  className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
1873
3283
  fill: "none",
1874
3284
  viewBox: "0 0 24 24",
1875
3285
  stroke: "currentColor",
1876
- children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
3286
+ children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
1877
3287
  }
1878
3288
  )
1879
3289
  ] })
@@ -1882,59 +3292,112 @@ function TableBlockClient({
1882
3292
  col.name
1883
3293
  );
1884
3294
  }),
1885
- /* @__PURE__ */ jsx5("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none" })
3295
+ /* @__PURE__ */ jsx6("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none" })
1886
3296
  ] }) }),
1887
- /* @__PURE__ */ jsx5("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ jsx5("tr", { children: /* @__PURE__ */ jsx5("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center justify-center gap-2", children: [
1888
- /* @__PURE__ */ jsx5("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("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" }) }),
1889
- /* @__PURE__ */ jsx5("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
1890
- ] }) }) }) : filteredData.map((row) => /* @__PURE__ */ jsxs5("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
1891
- /* @__PURE__ */ jsx5("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", children: /* @__PURE__ */ jsx5(
1892
- "input",
1893
- {
1894
- type: "checkbox",
1895
- checked: selectedIds.has(row.id),
1896
- onChange: (e) => toggleSelectRow(row.id, e.target.checked),
1897
- disabled: isLoading || isUpdatingActive,
1898
- className: "w-4 h-4 rounded border-slate-300 text-brand"
1899
- }
1900
- ) }),
1901
- filteredColumns.map((col) => {
3297
+ /* @__PURE__ */ jsx6("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ jsx6("tr", { children: /* @__PURE__ */ jsx6("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center justify-center gap-2", children: [
3298
+ /* @__PURE__ */ jsx6("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx6("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" }) }),
3299
+ /* @__PURE__ */ jsx6("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
3300
+ ] }) }) }) : filteredData.map((row) => {
3301
+ const hasSubTableCols = filteredColumns.some((c) => {
1902
3302
  var _a;
1903
- const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
1904
- const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
1905
- let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
1906
- if (value === void 0 && col.defaultValue !== void 0) {
1907
- value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
1908
- if (colType === "CURRENCY" || colType === "NUMBER") {
1909
- if (isNaN(value)) value = null;
1910
- }
1911
- }
1912
- if (value === void 0) value = null;
1913
- return /* @__PURE__ */ jsx5("td", { className: "border-b border-l border-slate-200 p-0 relative", children: /* @__PURE__ */ jsx5(
1914
- InputComponent,
3303
+ return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
3304
+ });
3305
+ const isExpanded = expandedRowIds.has(row.id);
3306
+ const subTableColumns = filteredColumns.filter((c) => {
3307
+ var _a;
3308
+ return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
3309
+ });
3310
+ return /* @__PURE__ */ jsxs6(React6.Fragment, { children: [
3311
+ /* @__PURE__ */ jsxs6("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
3312
+ /* @__PURE__ */ jsx6("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-center gap-1", children: [
3313
+ hasSubTableCols && /* @__PURE__ */ jsx6(
3314
+ "button",
3315
+ {
3316
+ type: "button",
3317
+ onClick: () => setExpandedRowIds((prev) => {
3318
+ const next = new Set(prev);
3319
+ if (next.has(row.id)) next.delete(row.id);
3320
+ else next.add(row.id);
3321
+ return next;
3322
+ }),
3323
+ className: "text-slate-400 hover:text-blue-600 p-0.5 rounded transition-colors cursor-pointer",
3324
+ title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
3325
+ children: /* @__PURE__ */ jsx6("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__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 5l7 7-7 7" }) })
3326
+ }
3327
+ ),
3328
+ /* @__PURE__ */ jsx6(
3329
+ "input",
3330
+ {
3331
+ type: "checkbox",
3332
+ checked: selectedIds.has(row.id),
3333
+ onChange: (e) => toggleSelectRow(row.id, e.target.checked),
3334
+ disabled: isLoading || isUpdatingActive,
3335
+ className: "w-4 h-4 rounded border-slate-300 text-brand"
3336
+ }
3337
+ )
3338
+ ] }) }),
3339
+ filteredColumns.map((col) => {
3340
+ var _a;
3341
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
3342
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
3343
+ let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
3344
+ if (value === void 0 && col.defaultValue !== void 0) {
3345
+ value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
3346
+ if (colType === "CURRENCY" || colType === "NUMBER") {
3347
+ if (isNaN(value)) value = null;
3348
+ }
3349
+ }
3350
+ if (value === void 0) value = null;
3351
+ return /* @__PURE__ */ jsx6("td", { className: "border-b border-l border-slate-200 p-0 relative", children: /* @__PURE__ */ jsx6(
3352
+ InputComponent,
3353
+ {
3354
+ value,
3355
+ column: col,
3356
+ rowId: row.id,
3357
+ onChange: (v) => handleCellChange(row.id, col.name, v),
3358
+ context: {
3359
+ 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",
3360
+ tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
3361
+ onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
3362
+ relationOptions,
3363
+ refetchRelation,
3364
+ executeAction,
3365
+ emitEvent,
3366
+ pageState,
3367
+ componentId,
3368
+ orgId,
3369
+ updateQuietly: handleQuietCellChange,
3370
+ triggerSaveSuccess,
3371
+ rowData: row.data
3372
+ }
3373
+ }
3374
+ ) }, col.name);
3375
+ }),
3376
+ /* @__PURE__ */ jsx6("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
3377
+ ] }),
3378
+ isExpanded && /* @__PURE__ */ jsx6(
3379
+ ExpandedSubTables,
1915
3380
  {
1916
- value,
1917
- column: col,
1918
3381
  rowId: row.id,
1919
- onChange: (v) => handleCellChange(row.id, col.name, v),
3382
+ rowData: row.data,
3383
+ subTableColumns,
3384
+ filteredColumnsLength: filteredColumns.length,
3385
+ handleCellChange,
1920
3386
  context: {
1921
- 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",
1922
- onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
1923
- relationOptions,
1924
- refetchRelation,
1925
3387
  executeAction,
1926
- emitEvent,
1927
- pageState,
1928
- componentId,
1929
- orgId
3388
+ orgId,
3389
+ parentTableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
3390
+ tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
3391
+ rowData: row.data,
3392
+ updateQuietly: handleQuietCellChange,
3393
+ triggerSaveSuccess
1930
3394
  }
1931
3395
  }
1932
- ) }, col.name);
1933
- }),
1934
- /* @__PURE__ */ jsx5("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
1935
- ] }, row.id)) }),
1936
- showSummary && filteredData.length > 0 && /* @__PURE__ */ jsx5("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__ */ jsxs5("tr", { children: [
1937
- /* @__PURE__ */ jsx5("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' }),
3396
+ )
3397
+ ] }, row.id);
3398
+ }) }),
3399
+ showSummary && filteredData.length > 0 && /* @__PURE__ */ jsx6("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__ */ jsxs6("tr", { children: [
3400
+ /* @__PURE__ */ jsx6("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' }),
1938
3401
  filteredColumns.map((col) => {
1939
3402
  var _a;
1940
3403
  const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
@@ -1948,16 +3411,16 @@ function TableBlockClient({
1948
3411
  displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
1949
3412
  }
1950
3413
  }
1951
- return /* @__PURE__ */ jsx5("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__ */ jsx5("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ jsx5("span", { className: "truncate", children: displayVal }) }) }, col.name);
3414
+ return /* @__PURE__ */ jsx6("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__ */ jsx6("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ jsx6("span", { className: "truncate", children: displayVal }) }) }, col.name);
1952
3415
  }),
1953
- /* @__PURE__ */ jsx5("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
3416
+ /* @__PURE__ */ jsx6("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
1954
3417
  ] }) })
1955
3418
  ] })
1956
3419
  ] }),
1957
- /* @__PURE__ */ jsxs5("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: [
1958
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
1959
- /* @__PURE__ */ jsx5("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
1960
- /* @__PURE__ */ jsxs5(
3420
+ /* @__PURE__ */ jsxs6("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: [
3421
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
3422
+ /* @__PURE__ */ jsx6("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
3423
+ /* @__PURE__ */ jsxs6(
1961
3424
  "select",
1962
3425
  {
1963
3426
  value: limit,
@@ -1965,27 +3428,27 @@ function TableBlockClient({
1965
3428
  disabled: isLoading || isUpdatingActive,
1966
3429
  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",
1967
3430
  children: [
1968
- /* @__PURE__ */ jsx5("option", { value: 20, children: "20" }),
1969
- /* @__PURE__ */ jsx5("option", { value: 50, children: "50" }),
1970
- /* @__PURE__ */ jsx5("option", { value: 100, children: "100" })
3431
+ /* @__PURE__ */ jsx6("option", { value: 20, children: "20" }),
3432
+ /* @__PURE__ */ jsx6("option", { value: 50, children: "50" }),
3433
+ /* @__PURE__ */ jsx6("option", { value: 100, children: "100" })
1971
3434
  ]
1972
3435
  }
1973
3436
  )
1974
3437
  ] }),
1975
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-4", children: [
1976
- /* @__PURE__ */ jsxs5("span", { className: "font-medium text-slate-600", children: [
3438
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-4", children: [
3439
+ /* @__PURE__ */ jsxs6("span", { className: "font-medium text-slate-600", children: [
1977
3440
  "\u05E2\u05DE\u05D5\u05D3 ",
1978
- /* @__PURE__ */ jsx5("strong", { className: "text-slate-900", children: page }),
3441
+ /* @__PURE__ */ jsx6("strong", { className: "text-slate-900", children: page }),
1979
3442
  " \u05DE\u05EA\u05D5\u05DA ",
1980
- /* @__PURE__ */ jsx5("strong", { className: "text-slate-900", children: totalPages || 1 }),
1981
- totalRecords > 0 && /* @__PURE__ */ jsxs5("span", { className: "text-slate-500 font-normal", children: [
3443
+ /* @__PURE__ */ jsx6("strong", { className: "text-slate-900", children: totalPages || 1 }),
3444
+ totalRecords > 0 && /* @__PURE__ */ jsxs6("span", { className: "text-slate-500 font-normal", children: [
1982
3445
  " (",
1983
3446
  totalRecords,
1984
3447
  ' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
1985
3448
  ] })
1986
3449
  ] }),
1987
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5", children: [
1988
- /* @__PURE__ */ jsx5(
3450
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5", children: [
3451
+ /* @__PURE__ */ jsx6(
1989
3452
  "button",
1990
3453
  {
1991
3454
  onClick: handlePrevPage,
@@ -1995,7 +3458,7 @@ function TableBlockClient({
1995
3458
  children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
1996
3459
  }
1997
3460
  ),
1998
- /* @__PURE__ */ jsx5(
3461
+ /* @__PURE__ */ jsx6(
1999
3462
  "button",
2000
3463
  {
2001
3464
  onClick: handleNextPage,
@@ -2012,11 +3475,60 @@ function TableBlockClient({
2012
3475
  }
2013
3476
  );
2014
3477
  }
3478
+ function ExpandedSubTables({
3479
+ rowId,
3480
+ rowData,
3481
+ subTableColumns,
3482
+ filteredColumnsLength,
3483
+ handleCellChange,
3484
+ context
3485
+ }) {
3486
+ var _a;
3487
+ const [activeTab, setActiveTab] = useState5((_a = subTableColumns[0]) == null ? void 0 : _a.name);
3488
+ if (subTableColumns.length === 0) return null;
3489
+ if (subTableColumns.length === 1) {
3490
+ const stCol = subTableColumns[0];
3491
+ return /* @__PURE__ */ jsx6("tr", { children: /* @__PURE__ */ jsx6("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50", children: /* @__PURE__ */ jsx6(
3492
+ SubTableViewer,
3493
+ {
3494
+ rowId,
3495
+ column: stCol,
3496
+ value: (rowData == null ? void 0 : rowData[stCol.name]) || [],
3497
+ onChange: (newVal) => handleCellChange(rowId, stCol.name, newVal),
3498
+ context
3499
+ }
3500
+ ) }) });
3501
+ }
3502
+ const activeCol = subTableColumns.find((c) => c.name === activeTab) || subTableColumns[0];
3503
+ return /* @__PURE__ */ jsx6("tr", { children: /* @__PURE__ */ jsxs6("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50 overflow-hidden", children: [
3504
+ /* @__PURE__ */ jsx6("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__ */ jsx6(
3505
+ "button",
3506
+ {
3507
+ type: "button",
3508
+ onClick: () => setActiveTab(col.name),
3509
+ 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"}`,
3510
+ children: col.name
3511
+ },
3512
+ col.name
3513
+ )) }),
3514
+ /* @__PURE__ */ jsx6("div", { className: "bg-white", children: /* @__PURE__ */ jsx6(
3515
+ SubTableViewer,
3516
+ {
3517
+ rowId,
3518
+ column: activeCol,
3519
+ value: (rowData == null ? void 0 : rowData[activeCol.name]) || [],
3520
+ onChange: (newVal) => handleCellChange(rowId, activeCol.name, newVal),
3521
+ context
3522
+ },
3523
+ activeCol.name
3524
+ ) })
3525
+ ] }) });
3526
+ }
2015
3527
 
2016
3528
  // src/components/TableBlock/TableBlock.tsx
2017
- import { jsx as jsx6 } from "react/jsx-runtime";
3529
+ import { jsx as jsx7 } from "react/jsx-runtime";
2018
3530
  function TableBlock(props) {
2019
- return /* @__PURE__ */ jsx6(TableBlockClient, __spreadValues({}, props));
3531
+ return /* @__PURE__ */ jsx7(TableBlockClient, __spreadValues({}, props));
2020
3532
  }
2021
3533
 
2022
3534
  // src/registry.ts
@@ -2029,5 +3541,7 @@ export {
2029
3541
  ToastProvider,
2030
3542
  UNIVERSE_COMPONENTS,
2031
3543
  cn,
3544
+ formatPhoneDisplay,
3545
+ openWhatsAppChat,
2032
3546
  useToast
2033
3547
  };