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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -47,6 +47,7 @@ var __copyProps = (to, from, except, desc) => {
47
47
  }
48
48
  return to;
49
49
  };
50
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
50
51
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
51
52
  // If the importer is in node compatibility mode or this is not an ESM
52
53
  // file that has been converted to a CommonJS file using a Babel-
@@ -58,16 +59,37 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
58
59
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
59
60
 
60
61
  // src/index.ts
61
- var index_exports = {};
62
- __export(index_exports, {
62
+ var src_exports = {};
63
+ __export(src_exports, {
64
+ ColumnHeaderTitle: () => ColumnHeaderTitle,
65
+ DatePickerCell: () => DatePickerCell,
66
+ LinkPickerCell: () => LinkPickerCell,
67
+ PASTEL_PALETTES: () => PASTEL_PALETTES,
68
+ RelationPickerCell: () => RelationPickerCell,
63
69
  TableBlock: () => TableBlock,
70
+ TimePickerCell: () => TimePickerCell,
64
71
  ToastContext: () => ToastContext,
65
72
  ToastProvider: () => ToastProvider,
66
73
  UNIVERSE_COMPONENTS: () => UNIVERSE_COMPONENTS,
74
+ calculateMinColumnWidth: () => calculateMinColumnWidth,
67
75
  cn: () => cn,
76
+ formatConflictCellValue: () => formatConflictCellValue,
77
+ formatPhoneDisplay: () => formatPhoneDisplay,
78
+ formatTimeInput: () => formatTimeInput,
79
+ formatTimeIso: () => formatTimeIso,
80
+ getDeterministicPastelBadge: () => getDeterministicPastelBadge,
81
+ measureTextWidth: () => measureTextWidth,
82
+ normalizeRelationValue: () => normalizeRelationValue,
83
+ openWhatsAppChat: () => openWhatsAppChat,
84
+ parseLinkValue: () => parseLinkValue,
85
+ parseTimeParts: () => parseTimeParts,
86
+ resolveProtocol: () => resolveProtocol,
87
+ splitHeaderTitle: () => splitHeaderTitle,
88
+ useColumnReorder: () => useColumnReorder,
89
+ useColumnResize: () => useColumnResize,
68
90
  useToast: () => useToast
69
91
  });
70
- module.exports = __toCommonJS(index_exports);
92
+ module.exports = __toCommonJS(src_exports);
71
93
 
72
94
  // src/utils/cn.ts
73
95
  var import_clsx = require("clsx");
@@ -76,8 +98,76 @@ function cn(...inputs) {
76
98
  return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
77
99
  }
78
100
 
101
+ // src/utils/whatsapp.ts
102
+ function openWhatsAppChat(phone, defaultCountryCode = "972") {
103
+ if (!phone || typeof window === "undefined") return;
104
+ let cleaned = phone.replace(/\D/g, "");
105
+ if (cleaned.startsWith("0")) {
106
+ cleaned = defaultCountryCode + cleaned.substring(1);
107
+ }
108
+ const appUrl = `whatsapp://send?phone=${cleaned}`;
109
+ const webUrl = `https://web.whatsapp.com/send?phone=${cleaned}`;
110
+ const start = Date.now();
111
+ window.location.href = appUrl;
112
+ setTimeout(() => {
113
+ if (typeof document !== "undefined" && document.hasFocus() && Date.now() - start < 2e3) {
114
+ window.open(webUrl, "_blank", "noopener,noreferrer");
115
+ }
116
+ }, 1200);
117
+ }
118
+ function formatPhoneDisplay(phone) {
119
+ if (!phone) return "";
120
+ const digits = phone.replace(/\D/g, "");
121
+ if (digits.length === 10 && digits.startsWith("05")) {
122
+ return `${digits.slice(0, 3)}-${digits.slice(3, 6)}-${digits.slice(6)}`;
123
+ }
124
+ if (digits.length === 12 && digits.startsWith("9725")) {
125
+ const local = "0" + digits.slice(3);
126
+ return `${local.slice(0, 3)}-${local.slice(3, 6)}-${local.slice(6)}`;
127
+ }
128
+ return phone;
129
+ }
130
+
131
+ // src/utils/colors.ts
132
+ var PASTEL_PALETTES = [
133
+ { bg: "bg-blue-50", text: "text-blue-700", border: "border-blue-200" },
134
+ { bg: "bg-emerald-50", text: "text-emerald-700", border: "border-emerald-200" },
135
+ { bg: "bg-violet-50", text: "text-violet-700", border: "border-violet-200" },
136
+ { bg: "bg-amber-50", text: "text-amber-700", border: "border-amber-200" },
137
+ { bg: "bg-rose-50", text: "text-rose-700", border: "border-rose-200" },
138
+ { bg: "bg-cyan-50", text: "text-cyan-700", border: "border-cyan-200" },
139
+ { bg: "bg-indigo-50", text: "text-indigo-700", border: "border-indigo-200" },
140
+ { bg: "bg-teal-50", text: "text-teal-700", border: "border-teal-200" },
141
+ { bg: "bg-sky-50", text: "text-sky-700", border: "border-sky-200" },
142
+ { bg: "bg-fuchsia-50", text: "text-fuchsia-700", border: "border-fuchsia-200" },
143
+ { bg: "bg-pink-50", text: "text-pink-700", border: "border-pink-200" },
144
+ { bg: "bg-purple-50", text: "text-purple-700", border: "border-purple-200" },
145
+ { bg: "bg-orange-50", text: "text-orange-700", border: "border-orange-200" },
146
+ { bg: "bg-red-50", text: "text-red-700", border: "border-red-200" },
147
+ { bg: "bg-lime-50", text: "text-lime-700", border: "border-lime-200" },
148
+ { bg: "bg-green-50", text: "text-green-700", border: "border-green-200" },
149
+ { bg: "bg-yellow-50", text: "text-yellow-700", border: "border-yellow-200" }
150
+ ];
151
+ function getDeterministicPastelBadge(key) {
152
+ if (!key) return PASTEL_PALETTES[0];
153
+ let hash = 2166136261;
154
+ for (let i = 0; i < key.length; i++) {
155
+ hash ^= key.charCodeAt(i);
156
+ hash = Math.imul(hash, 16777619);
157
+ }
158
+ const index = Math.abs(hash) % PASTEL_PALETTES.length;
159
+ return PASTEL_PALETTES[index];
160
+ }
161
+
162
+ // src/types/data.types.ts
163
+ var data_types_exports = {};
164
+ __reExport(data_types_exports, require("@universe-platform/shared"));
165
+
166
+ // src/index.ts
167
+ __reExport(src_exports, data_types_exports, module.exports);
168
+
79
169
  // src/components/TableBlock/TableBlockClient.tsx
80
- var import_react7 = __toESM(require("react"));
170
+ var import_react12 = __toESM(require("react"));
81
171
 
82
172
  // src/hooks/useToast.ts
83
173
  var import_react2 = require("react");
@@ -277,7 +367,7 @@ function useToast() {
277
367
  }
278
368
 
279
369
  // src/components/TableBlock/fields/fieldRegistry.tsx
280
- var import_react5 = __toESM(require("react"));
370
+ var import_react8 = __toESM(require("react"));
281
371
 
282
372
  // src/components/TableBlock/fields/DrivePickerCell.tsx
283
373
  var import_react3 = __toESM(require("react"));
@@ -734,214 +824,1086 @@ function DatePickerCell({ value, onChange, readOnly = false }) {
734
824
  ] });
735
825
  }
736
826
 
737
- // src/components/TableBlock/fields/fieldRegistry.tsx
827
+ // src/components/TableBlock/fields/TimePickerCell.tsx
828
+ var import_react5 = require("react");
829
+ var import_lucide_react4 = require("lucide-react");
738
830
  var import_jsx_runtime4 = require("react/jsx-runtime");
739
- var CURRENCY_SYMBOLS = {
740
- USD: "$",
741
- EUR: "\u20AC",
742
- ILS: "\u20AA",
743
- GBP: "\xA3"
744
- };
745
- function getCurrencySymbol(code) {
746
- if (!code) return "";
747
- return CURRENCY_SYMBOLS[code.toUpperCase()] || code;
748
- }
749
- function getRelationDisplayLabel(opt, column) {
750
- if (!opt) return "\u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05E1\u05E8\u05D4";
751
- const val = column.displayField && opt.data ? opt.data[column.displayField] : void 0;
752
- if (val !== void 0 && val !== null && val !== "") {
753
- return String(val);
831
+ function parseTimeParts(val) {
832
+ if (val === void 0 || val === null || val === "") return null;
833
+ if (typeof val === "string") {
834
+ const trimmed = val.trim();
835
+ if (!trimmed) return null;
836
+ const match = trimmed.match(/^(\d{1,2})[:.](\d{1,2})(?:[:.]\d{1,2})?$/);
837
+ if (match) {
838
+ const hour = parseInt(match[1], 10);
839
+ const minute = parseInt(match[2], 10);
840
+ if (hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59) {
841
+ return { hour, minute };
842
+ }
843
+ return null;
844
+ }
845
+ if (trimmed.includes("T")) {
846
+ const d = new Date(trimmed);
847
+ if (!isNaN(d.getTime())) {
848
+ return { hour: d.getHours(), minute: d.getMinutes() };
849
+ }
850
+ }
851
+ } else if (val instanceof Date && !isNaN(val.getTime())) {
852
+ return { hour: val.getHours(), minute: val.getMinutes() };
754
853
  }
755
- if (opt.label && opt.label !== opt.id) {
756
- return String(opt.label);
854
+ return null;
855
+ }
856
+ function formatTimeIso(hour, minute) {
857
+ const hh = String(hour).padStart(2, "0");
858
+ const mm = String(minute).padStart(2, "0");
859
+ return `${hh}:${mm}`;
860
+ }
861
+ function formatTimeInput(input) {
862
+ if (!input) return "";
863
+ const digits = String(input).replace(/\D/g, "");
864
+ if (!digits) return "";
865
+ if (digits.length === 1) {
866
+ const d = parseInt(digits, 10);
867
+ if (d > 2) {
868
+ return `0${d}:`;
869
+ }
870
+ return `${digits}:`;
757
871
  }
758
- if (opt.data) {
759
- const fallbackField = Object.keys(opt.data).find((k) => {
760
- if (k === "_id" || k === "id") return false;
761
- const v = opt.data[k];
762
- if (typeof v === "string" && v.trim() !== "") return true;
763
- if (typeof v === "number" && !isNaN(v)) return true;
764
- return false;
765
- });
766
- if (fallbackField) return String(opt.data[fallbackField]);
872
+ const h = parseInt(digits.slice(0, 2), 10);
873
+ const hh = h > 23 ? "23" : digits.slice(0, 2);
874
+ if (digits.length === 2) {
875
+ return `${hh}:`;
767
876
  }
768
- if (opt.label) {
769
- return String(opt.label);
877
+ if (digits.length === 3) {
878
+ return `${hh}:${digits[2]}`;
770
879
  }
771
- return "\u05E2\u05E8\u05DA \u05E8\u05D9\u05E7";
880
+ const m = parseInt(digits.slice(2, 4), 10);
881
+ const mm = m > 59 ? "59" : digits.slice(2, 4);
882
+ return `${hh}:${mm}`;
772
883
  }
773
- var FORM_INPUTS = {
774
- DATE: ({ value, onChange, column }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DatePickerCell, { value, onChange, column }),
775
- CURRENCY: ({ value, column, onChange }) => {
776
- const symbol = getCurrencySymbol(column.currencySymbol);
777
- const [isFocused, setIsFocused] = import_react5.default.useState(false);
778
- const displayValue = !isFocused && value !== void 0 && value !== null && value !== "" && !isNaN(Number(value)) ? new Intl.NumberFormat("en-US").format(Number(value)) : value !== void 0 && value !== null ? value : "";
779
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "relative w-full h-full", children: [
780
- symbol && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "absolute left-2 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none text-sm", children: symbol }),
781
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
782
- "input",
783
- {
784
- type: isFocused ? "number" : "text",
785
- step: "any",
786
- className: `w-full h-8 ${symbol ? "pl-6 pr-2" : "px-2"} bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm`,
787
- value: displayValue,
788
- onFocus: () => setIsFocused(true),
789
- onBlur: () => setIsFocused(false),
790
- onChange: (e) => {
791
- const val = e.target.value;
792
- onChange(val === "" ? "" : Number(val));
793
- }
884
+ var ALL_MINUTES = Array.from({ length: 60 }, (_, i) => i);
885
+ function TimePickerCell({ value, onChange, readOnly = false }) {
886
+ var _a, _b;
887
+ const [isOpen, setIsOpen] = (0, import_react5.useState)(false);
888
+ const containerRef = (0, import_react5.useRef)(null);
889
+ const hoursListRef = (0, import_react5.useRef)(null);
890
+ const minutesListRef = (0, import_react5.useRef)(null);
891
+ const [popoverPos, setPopoverPos] = (0, import_react5.useState)({ top: 0, right: 0 });
892
+ const parsedParts = (0, import_react5.useMemo)(() => parseTimeParts(value), [value]);
893
+ const displayString = (0, import_react5.useMemo)(() => {
894
+ return parsedParts ? formatTimeIso(parsedParts.hour, parsedParts.minute) : "";
895
+ }, [parsedParts]);
896
+ const [rawInput, setRawInput] = (0, import_react5.useState)(displayString);
897
+ (0, import_react5.useEffect)(() => {
898
+ setRawInput(displayString);
899
+ }, [displayString]);
900
+ const selectedHour = (_a = parsedParts == null ? void 0 : parsedParts.hour) != null ? _a : null;
901
+ const selectedMinute = (_b = parsedParts == null ? void 0 : parsedParts.minute) != null ? _b : null;
902
+ const updatePopoverPosition = (0, import_react5.useCallback)(() => {
903
+ if (containerRef.current) {
904
+ const rect = containerRef.current.getBoundingClientRect();
905
+ const right = window.innerWidth - rect.right;
906
+ const popoverHeight = 260;
907
+ const spaceBelow = window.innerHeight - rect.bottom;
908
+ if (spaceBelow < popoverHeight && rect.top > popoverHeight) {
909
+ setPopoverPos({
910
+ top: Math.max(10, rect.top - popoverHeight - 4),
911
+ right: Math.max(10, right)
912
+ });
913
+ } else {
914
+ setPopoverPos({
915
+ top: Math.min(window.innerHeight - popoverHeight - 10, rect.bottom + 4),
916
+ right: Math.max(10, right)
917
+ });
918
+ }
919
+ }
920
+ }, []);
921
+ (0, import_react5.useEffect)(() => {
922
+ if (!isOpen) return;
923
+ updatePopoverPosition();
924
+ function handleScrollOrResize() {
925
+ updatePopoverPosition();
926
+ }
927
+ function handleClickOutside(event) {
928
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
929
+ const popoverEl = document.getElementById("time-picker-popover");
930
+ if (popoverEl && popoverEl.contains(event.target)) {
931
+ return;
794
932
  }
795
- )
796
- ] });
797
- },
798
- TIME: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
799
- "input",
800
- {
801
- type: "time",
802
- className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
803
- value: value || "",
804
- onChange: (e) => onChange(e.target.value)
933
+ setIsOpen(false);
934
+ }
805
935
  }
806
- ),
807
- LINK: ({ value, onChange }) => {
808
- const [isEditing, setIsEditing] = import_react5.default.useState(false);
809
- const label = (value == null ? void 0 : value.label) || "";
810
- const url = (value == null ? void 0 : value.url) || "";
811
- if (!isEditing) {
812
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2 px-2 py-1 h-full w-full", children: [
813
- url ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline flex-1 truncate", children: label || url }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-slate-400 italic flex-1 text-sm", children: "\u05E8\u05D9\u05E7" }),
814
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
815
- "button",
816
- {
817
- onClick: () => setIsEditing(true),
818
- className: "text-xs font-medium text-slate-400 hover:text-blue-500 p-1 rounded transition-colors",
819
- title: "\u05E2\u05E8\u05D5\u05DA \u05E7\u05D9\u05E9\u05D5\u05E8",
820
- children: "\u05E2\u05E8\u05D9\u05DB\u05D4"
821
- }
822
- )
823
- ] });
936
+ window.addEventListener("scroll", handleScrollOrResize, true);
937
+ window.addEventListener("resize", handleScrollOrResize);
938
+ document.addEventListener("mousedown", handleClickOutside);
939
+ return () => {
940
+ window.removeEventListener("scroll", handleScrollOrResize, true);
941
+ window.removeEventListener("resize", handleScrollOrResize);
942
+ document.removeEventListener("mousedown", handleClickOutside);
943
+ };
944
+ }, [isOpen, updatePopoverPosition]);
945
+ (0, import_react5.useEffect)(() => {
946
+ if (isOpen) {
947
+ if (selectedHour !== null && hoursListRef.current) {
948
+ const activeHourBtn = hoursListRef.current.querySelector('[data-selected="true"]');
949
+ if (activeHourBtn) {
950
+ activeHourBtn.scrollIntoView({ block: "center" });
951
+ }
952
+ }
953
+ if (selectedMinute !== null && minutesListRef.current) {
954
+ const activeMinBtn = minutesListRef.current.querySelector('[data-selected="true"]');
955
+ if (activeMinBtn) {
956
+ activeMinBtn.scrollIntoView({ block: "center" });
957
+ }
958
+ }
959
+ }
960
+ }, [isOpen, selectedHour, selectedMinute]);
961
+ const handleInputChange = (e) => {
962
+ let val = e.target.value;
963
+ if (val.length === 2 && !val.includes(":") && rawInput.length === 1) {
964
+ val += ":";
965
+ }
966
+ if (val.length > 5) return;
967
+ setRawInput(val);
968
+ if (val.length === 5 && /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/.test(val)) {
969
+ onChange(val);
970
+ }
971
+ };
972
+ const handleKeyDown = (e) => {
973
+ if (e.key === "Enter") {
974
+ handleInputBlur();
975
+ setIsOpen(false);
976
+ return;
977
+ }
978
+ if (e.key === "Backspace" || e.key === "Delete" || e.key === "ArrowLeft" || e.key === "ArrowRight" || e.key === "Tab" || e.key === "Escape" || (e.ctrlKey || e.metaKey)) {
979
+ return;
980
+ }
981
+ if (e.key === ":") return;
982
+ if (!/^\d$/.test(e.key)) {
983
+ e.preventDefault();
984
+ }
985
+ };
986
+ const handleInputBlur = () => {
987
+ let text = rawInput.trim();
988
+ if (!text) {
989
+ onChange(null);
990
+ return;
991
+ }
992
+ if (!text.includes(":")) {
993
+ if (text.length === 1 || text.length === 2) {
994
+ text = `${text}:00`;
995
+ } else if (text.length === 3) {
996
+ text = `0${text[0]}:${text.slice(1)}`;
997
+ } else if (text.length === 4) {
998
+ text = `${text.slice(0, 2)}:${text.slice(2)}`;
999
+ }
1000
+ } else if (text.endsWith(":")) {
1001
+ text = `${text}00`;
824
1002
  }
825
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex gap-2 p-1 w-full min-w-[250px] items-center bg-white border border-blue-200 rounded shadow-sm z-10", children: [
1003
+ const parts = parseTimeParts(text);
1004
+ if (parts) {
1005
+ const iso = formatTimeIso(parts.hour, parts.minute);
1006
+ setRawInput(iso);
1007
+ onChange(iso);
1008
+ } else {
1009
+ setRawInput(displayString);
1010
+ }
1011
+ };
1012
+ const handleSelectHour = (h) => {
1013
+ const m = selectedMinute != null ? selectedMinute : 0;
1014
+ const iso = formatTimeIso(h, m);
1015
+ onChange(iso);
1016
+ setRawInput(iso);
1017
+ };
1018
+ const handleSelectMinute = (m) => {
1019
+ const h = selectedHour != null ? selectedHour : (/* @__PURE__ */ new Date()).getHours();
1020
+ const iso = formatTimeIso(h, m);
1021
+ onChange(iso);
1022
+ setRawInput(iso);
1023
+ };
1024
+ const handleSetNow = () => {
1025
+ const now = /* @__PURE__ */ new Date();
1026
+ const iso = formatTimeIso(now.getHours(), now.getMinutes());
1027
+ onChange(iso);
1028
+ setRawInput(iso);
1029
+ };
1030
+ const handleClear = () => {
1031
+ onChange(null);
1032
+ setRawInput("");
1033
+ setIsOpen(false);
1034
+ };
1035
+ if (readOnly) {
1036
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1.5 px-2 h-full", children: [
1037
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react4.Clock, { className: "w-3.5 h-3.5 text-slate-400 shrink-0" }),
1038
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-sm font-normal text-slate-800 tracking-wider", dir: "ltr", children: displayString || "-" })
1039
+ ] });
1040
+ }
1041
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { ref: containerRef, className: "relative w-full h-full flex items-center px-2", children: [
1042
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1.5", children: [
826
1043
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
827
- "input",
1044
+ "button",
828
1045
  {
829
- type: "text",
830
- placeholder: "Label",
831
- className: "flex-1 h-8 px-2 bg-transparent focus:outline-none text-sm border-r",
832
- value: label,
833
- onChange: (e) => onChange({ label: e.target.value, url })
1046
+ type: "button",
1047
+ onClick: () => {
1048
+ setIsOpen((prev) => {
1049
+ const next = !prev;
1050
+ if (next) updatePopoverPosition();
1051
+ return next;
1052
+ });
1053
+ },
1054
+ className: "p-1 text-slate-400 hover:text-blue-600 rounded transition-colors cursor-pointer shrink-0",
1055
+ title: "\u05D1\u05D7\u05E8 \u05E9\u05E2\u05D4",
1056
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react4.Clock, { className: "w-4 h-4" })
834
1057
  }
835
1058
  ),
836
1059
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
837
1060
  "input",
838
1061
  {
839
- type: "url",
840
- placeholder: "URL",
841
- className: "flex-1 h-8 px-2 bg-transparent focus:outline-none text-sm",
842
- value: url,
843
- onChange: (e) => onChange({ label, url: e.target.value })
844
- }
845
- ),
846
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
847
- "button",
848
- {
849
- onClick: () => setIsEditing(false),
850
- className: "text-xs font-medium text-green-600 hover:text-green-700 p-1 mx-1 rounded transition-colors",
851
- title: "\u05E9\u05DE\u05D5\u05E8",
852
- children: "\u05E9\u05DE\u05D5\u05E8"
1062
+ type: "text",
1063
+ dir: "ltr",
1064
+ placeholder: "--:--",
1065
+ className: "w-14 h-7 px-1 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm font-normal text-slate-800 tracking-wider rounded text-center",
1066
+ value: rawInput,
1067
+ onChange: handleInputChange,
1068
+ onKeyDown: handleKeyDown,
1069
+ onBlur: handleInputBlur
853
1070
  }
854
1071
  )
855
- ] });
856
- },
857
- BOOLEAN: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex items-center justify-center w-full h-full p-2", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
858
- "input",
859
- {
860
- type: "checkbox",
861
- checked: !!value,
862
- onChange: (e) => onChange(e.target.checked),
863
- className: "w-4 h-4 rounded border-slate-300 text-brand"
864
- }
865
- ) }),
866
- GOOGLE_DRIVE_FILE: ({ value, onChange, column, rowId, context }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
867
- DrivePickerCell,
868
- {
869
- value: value || [],
870
- onChange,
871
- column,
872
- rowId,
873
- tableName: context == null ? void 0 : context.tableName,
874
- onMarkForDeletion: context == null ? void 0 : context.onMarkForDeletion,
875
- context
876
- }
877
- ),
878
- RELATION: ({ value, onChange, column, context }) => {
879
- var _a;
880
- const options = ((_a = context == null ? void 0 : context.relationOptions) == null ? void 0 : _a[column.name]) || [];
881
- import_react5.default.useEffect(() => {
882
- if (typeof value === "string" && value !== "" && options.length > 0) {
883
- const isValidId = options.some((o) => String(o.id) === String(value));
884
- if (!isValidId) {
885
- const match = options.find(
886
- (o) => String(getRelationDisplayLabel(o, column)).trim() === String(value).trim()
887
- );
888
- if (match) {
889
- onChange(match.id);
890
- } else {
891
- onChange("");
892
- }
893
- }
894
- }
895
- }, [value, options, column, onChange]);
896
- const processedOptions = options.map((opt) => __spreadProps(__spreadValues({}, opt), {
897
- _displayLabel: getRelationDisplayLabel(opt, column)
898
- }));
899
- const validOptions = processedOptions.filter((o) => o._displayLabel !== "\u05D4\u05E2\u05E8\u05DA \u05E9\u05D1\u05E8\u05E9\u05D5\u05DE\u05D4 \u05D4\u05DE\u05E7\u05D5\u05E9\u05E8\u05EA \u05E0\u05E9\u05D0\u05E8 \u05E8\u05D9\u05E7");
900
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
901
- "select",
1072
+ ] }),
1073
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1074
+ "div",
902
1075
  {
903
- className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
904
- value: value !== void 0 && value !== null ? String(value) : "",
905
- onChange: (e) => onChange(e.target.value),
906
- onFocus: () => {
907
- if (context == null ? void 0 : context.refetchRelation) {
908
- context.refetchRelation(column.name);
909
- }
910
- },
1076
+ id: "time-picker-popover",
1077
+ dir: "rtl",
1078
+ style: { top: `${popoverPos.top}px`, right: `${popoverPos.right}px` },
1079
+ className: "fixed z-[99999] w-64 bg-white rounded-xl shadow-2xl border border-slate-200 p-3.5 animate-in fade-in zoom-in-95 duration-150",
911
1080
  children: [
912
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: "\u05D1\u05D7\u05E8..." }),
913
- validOptions.length > 0 ? validOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: opt.id, children: opt._displayLabel }, opt.id)) : options.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "empty_all", disabled: true, children: "\u05DB\u05DC \u05D4\u05E2\u05E8\u05DB\u05D9\u05DD \u05D1\u05D8\u05D1\u05DC\u05D4 \u05D4\u05DE\u05E7\u05D5\u05E9\u05E8\u05EA \u05E8\u05D9\u05E7\u05D9\u05DD" }) : null
1081
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center justify-between pb-2 mb-2 border-b border-slate-100", children: [
1082
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1.5 text-xs font-semibold text-slate-700", children: [
1083
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react4.Clock, { className: "w-3.5 h-3.5 text-blue-600" }),
1084
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u05D1\u05D7\u05D9\u05E8\u05EA \u05E9\u05E2\u05D4" })
1085
+ ] }),
1086
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1", children: [
1087
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1088
+ "button",
1089
+ {
1090
+ type: "button",
1091
+ onClick: handleSetNow,
1092
+ className: "text-[11px] px-1.5 py-0.5 font-medium text-blue-600 hover:bg-blue-50 rounded transition-colors cursor-pointer",
1093
+ children: "\u05E2\u05DB\u05E9\u05D9\u05D5"
1094
+ }
1095
+ ),
1096
+ displayString && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1097
+ "button",
1098
+ {
1099
+ type: "button",
1100
+ onClick: handleClear,
1101
+ className: "text-[11px] px-1.5 py-0.5 font-medium text-slate-500 hover:text-rose-600 hover:bg-rose-50 rounded transition-colors cursor-pointer",
1102
+ children: "\u05E0\u05E7\u05D4"
1103
+ }
1104
+ ),
1105
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1106
+ "button",
1107
+ {
1108
+ type: "button",
1109
+ onClick: () => setIsOpen(false),
1110
+ className: "p-0.5 text-slate-400 hover:text-slate-600 rounded transition-colors cursor-pointer mr-0.5",
1111
+ title: "\u05E1\u05D2\u05D5\u05E8",
1112
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react4.X, { className: "w-3.5 h-3.5" })
1113
+ }
1114
+ )
1115
+ ] })
1116
+ ] }),
1117
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex items-center justify-center py-1 mb-2 bg-slate-50 border border-slate-100 rounded-lg", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-base font-semibold text-slate-800 tracking-wider", dir: "ltr", children: displayString || "--:--" }) }),
1118
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
1119
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
1120
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "text-[11px] font-medium text-slate-400 text-center mb-1", children: "\u05D3\u05E7\u05D5\u05EA" }),
1121
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1122
+ "div",
1123
+ {
1124
+ ref: minutesListRef,
1125
+ className: "h-44 overflow-y-auto border border-slate-100 rounded-lg p-1 space-y-0.5 bg-slate-50/50",
1126
+ children: ALL_MINUTES.map((m) => {
1127
+ const isSelected = selectedMinute === m;
1128
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1129
+ "button",
1130
+ {
1131
+ type: "button",
1132
+ "data-selected": isSelected,
1133
+ onClick: () => handleSelectMinute(m),
1134
+ className: `w-full py-1 text-xs text-center rounded transition-colors cursor-pointer ${isSelected ? "bg-blue-600 text-white font-medium shadow-xs" : "text-slate-700 hover:bg-slate-200/70"}`,
1135
+ children: String(m).padStart(2, "0")
1136
+ },
1137
+ m
1138
+ );
1139
+ })
1140
+ }
1141
+ )
1142
+ ] }),
1143
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
1144
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "text-[11px] font-medium text-slate-400 text-center mb-1", children: "\u05E9\u05E2\u05D5\u05EA" }),
1145
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1146
+ "div",
1147
+ {
1148
+ ref: hoursListRef,
1149
+ className: "h-44 overflow-y-auto border border-slate-100 rounded-lg p-1 space-y-0.5 bg-slate-50/50",
1150
+ children: Array.from({ length: 24 }, (_, i) => {
1151
+ const isSelected = selectedHour === i;
1152
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1153
+ "button",
1154
+ {
1155
+ type: "button",
1156
+ "data-selected": isSelected,
1157
+ onClick: () => handleSelectHour(i),
1158
+ className: `w-full py-1 text-xs text-center rounded transition-colors cursor-pointer ${isSelected ? "bg-blue-600 text-white font-medium shadow-xs" : "text-slate-700 hover:bg-slate-200/70"}`,
1159
+ children: String(i).padStart(2, "0")
1160
+ },
1161
+ i
1162
+ );
1163
+ })
1164
+ }
1165
+ )
1166
+ ] })
1167
+ ] })
914
1168
  ]
915
1169
  }
916
- );
917
- },
918
- NUMBER: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
919
- "input",
920
- {
921
- type: "number",
922
- className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
923
- value: value !== void 0 && value !== null ? value : "",
924
- onChange: (e) => {
925
- const val = e.target.value;
926
- onChange(val === "" ? "" : Number(val));
927
- }
1170
+ )
1171
+ ] });
1172
+ }
1173
+
1174
+ // src/components/TableBlock/fields/LinkPickerCell.tsx
1175
+ var import_react6 = require("react");
1176
+ var import_lucide_react5 = require("lucide-react");
1177
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1178
+ function parseLinkValue(val) {
1179
+ if (!val) return { url: "", label: "" };
1180
+ if (typeof val === "string") {
1181
+ return { url: val.trim(), label: "" };
1182
+ }
1183
+ if (typeof val === "object") {
1184
+ return {
1185
+ url: typeof val.url === "string" ? val.url.trim() : "",
1186
+ label: typeof val.label === "string" ? val.label.trim() : ""
1187
+ };
1188
+ }
1189
+ return { url: "", label: "" };
1190
+ }
1191
+ function resolveProtocol(url) {
1192
+ const trimmed = url.trim();
1193
+ if (!trimmed) return "";
1194
+ if (/^https?:\/\//i.test(trimmed)) {
1195
+ return trimmed;
1196
+ }
1197
+ return `https://${trimmed}`;
1198
+ }
1199
+ function LinkPickerCell({ value, onChange, readOnly = false }) {
1200
+ const [isOpen, setIsOpen] = (0, import_react6.useState)(false);
1201
+ const containerRef = (0, import_react6.useRef)(null);
1202
+ const urlInputRef = (0, import_react6.useRef)(null);
1203
+ const [popoverPos, setPopoverPos] = (0, import_react6.useState)({ top: 0, right: 0 });
1204
+ const currentLink = parseLinkValue(value);
1205
+ const [draftUrl, setDraftUrl] = (0, import_react6.useState)(currentLink.url);
1206
+ const [draftLabel, setDraftLabel] = (0, import_react6.useState)(currentLink.label);
1207
+ const draftUrlRef = (0, import_react6.useRef)(draftUrl);
1208
+ const draftLabelRef = (0, import_react6.useRef)(draftLabel);
1209
+ (0, import_react6.useEffect)(() => {
1210
+ draftUrlRef.current = draftUrl;
1211
+ }, [draftUrl]);
1212
+ (0, import_react6.useEffect)(() => {
1213
+ draftLabelRef.current = draftLabel;
1214
+ }, [draftLabel]);
1215
+ (0, import_react6.useEffect)(() => {
1216
+ if (!isOpen) {
1217
+ setDraftUrl(currentLink.url);
1218
+ setDraftLabel(currentLink.label);
928
1219
  }
929
- ),
930
- PHONE: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
931
- "input",
932
- {
933
- type: "tel",
1220
+ }, [value, isOpen]);
1221
+ const updatePopoverPosition = (0, import_react6.useCallback)(() => {
1222
+ if (containerRef.current) {
1223
+ const rect = containerRef.current.getBoundingClientRect();
1224
+ const right = window.innerWidth - rect.right;
1225
+ const popoverHeight = 220;
1226
+ const spaceBelow = window.innerHeight - rect.bottom;
1227
+ if (spaceBelow < popoverHeight && rect.top > popoverHeight) {
1228
+ setPopoverPos({
1229
+ top: Math.max(10, rect.top - popoverHeight - 4),
1230
+ right: Math.max(10, right)
1231
+ });
1232
+ } else {
1233
+ setPopoverPos({
1234
+ top: Math.min(window.innerHeight - popoverHeight - 10, rect.bottom + 4),
1235
+ right: Math.max(10, right)
1236
+ });
1237
+ }
1238
+ }
1239
+ }, []);
1240
+ const handleSaveAndClose = (0, import_react6.useCallback)(() => {
1241
+ const rawUrl = draftUrlRef.current.trim();
1242
+ const rawLabel = draftLabelRef.current.trim();
1243
+ if (!rawUrl) {
1244
+ onChange(null);
1245
+ } else {
1246
+ const resolved = resolveProtocol(rawUrl);
1247
+ onChange({
1248
+ url: resolved,
1249
+ label: rawLabel
1250
+ });
1251
+ }
1252
+ setIsOpen(false);
1253
+ }, [onChange]);
1254
+ const handleOpen = () => {
1255
+ setDraftUrl(currentLink.url);
1256
+ setDraftLabel(currentLink.label);
1257
+ updatePopoverPosition();
1258
+ setIsOpen(true);
1259
+ setTimeout(() => {
1260
+ var _a;
1261
+ (_a = urlInputRef.current) == null ? void 0 : _a.focus();
1262
+ }, 50);
1263
+ };
1264
+ (0, import_react6.useEffect)(() => {
1265
+ if (!isOpen) return;
1266
+ updatePopoverPosition();
1267
+ function handleScrollOrResize() {
1268
+ updatePopoverPosition();
1269
+ }
1270
+ function handleClickOutside(event) {
1271
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
1272
+ const popoverEl = document.getElementById("link-picker-popover");
1273
+ if (popoverEl && popoverEl.contains(event.target)) {
1274
+ return;
1275
+ }
1276
+ handleSaveAndClose();
1277
+ }
1278
+ }
1279
+ window.addEventListener("scroll", handleScrollOrResize, true);
1280
+ window.addEventListener("resize", handleScrollOrResize);
1281
+ document.addEventListener("mousedown", handleClickOutside);
1282
+ return () => {
1283
+ window.removeEventListener("scroll", handleScrollOrResize, true);
1284
+ window.removeEventListener("resize", handleScrollOrResize);
1285
+ document.removeEventListener("mousedown", handleClickOutside);
1286
+ };
1287
+ }, [isOpen, updatePopoverPosition, handleSaveAndClose]);
1288
+ const handleClear = () => {
1289
+ onChange(null);
1290
+ setDraftUrl("");
1291
+ setDraftLabel("");
1292
+ setIsOpen(false);
1293
+ };
1294
+ if (readOnly) {
1295
+ if (!currentLink.url) {
1296
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-400 text-xs italic", children: "-" });
1297
+ }
1298
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "px-2 py-1 flex items-center h-full w-full", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1299
+ "a",
1300
+ {
1301
+ href: currentLink.url,
1302
+ target: "_blank",
1303
+ rel: "noopener noreferrer",
1304
+ className: "text-blue-600 hover:underline truncate text-sm flex items-center gap-1.5",
1305
+ onClick: (e) => e.stopPropagation(),
1306
+ children: [
1307
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.ExternalLink, { className: "w-3.5 h-3.5 shrink-0 text-blue-500" }),
1308
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate", children: currentLink.label || currentLink.url })
1309
+ ]
1310
+ }
1311
+ ) });
1312
+ }
1313
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: containerRef, className: "relative w-full h-full flex items-center justify-between px-2 py-1 group", children: [
1314
+ currentLink.url ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1315
+ "a",
1316
+ {
1317
+ href: currentLink.url,
1318
+ target: "_blank",
1319
+ rel: "noopener noreferrer",
1320
+ className: "text-blue-600 hover:underline truncate text-sm flex items-center gap-1.5 flex-1 min-w-0",
1321
+ onClick: (e) => e.stopPropagation(),
1322
+ title: currentLink.url,
1323
+ children: [
1324
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.ExternalLink, { className: "w-3.5 h-3.5 shrink-0 text-blue-500" }),
1325
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate", children: currentLink.label || currentLink.url })
1326
+ ]
1327
+ }
1328
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1329
+ "span",
1330
+ {
1331
+ className: "text-slate-400 italic text-sm flex-1 cursor-pointer select-none",
1332
+ onClick: handleOpen,
1333
+ children: "\u05E8\u05D9\u05E7"
1334
+ }
1335
+ ),
1336
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1337
+ "button",
1338
+ {
1339
+ type: "button",
1340
+ onClick: (e) => {
1341
+ e.stopPropagation();
1342
+ if (isOpen) {
1343
+ handleSaveAndClose();
1344
+ } else {
1345
+ handleOpen();
1346
+ }
1347
+ },
1348
+ className: "p-1 text-slate-400 hover:text-blue-600 hover:bg-slate-100 rounded transition-colors cursor-pointer shrink-0 ml-1",
1349
+ title: "\u05E2\u05E8\u05D9\u05DB\u05EA \u05E7\u05D9\u05E9\u05D5\u05E8",
1350
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Link2, { className: "w-3.5 h-3.5" })
1351
+ }
1352
+ ),
1353
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1354
+ "div",
1355
+ {
1356
+ id: "link-picker-popover",
1357
+ dir: "rtl",
1358
+ style: { top: `${popoverPos.top}px`, right: `${popoverPos.right}px` },
1359
+ className: "fixed z-[99999] w-[280px] bg-white rounded-xl shadow-2xl border border-slate-200 p-3.5 animate-in fade-in zoom-in-95 duration-150",
1360
+ onClick: (e) => e.stopPropagation(),
1361
+ children: [
1362
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between pb-2 mb-3 border-b border-slate-100", children: [
1363
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1.5 text-xs font-semibold text-slate-700", children: [
1364
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Link2, { className: "w-3.5 h-3.5 text-blue-600" }),
1365
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u05E2\u05E8\u05D9\u05DB\u05EA \u05E7\u05D9\u05E9\u05D5\u05E8" })
1366
+ ] }),
1367
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1368
+ "button",
1369
+ {
1370
+ type: "button",
1371
+ onClick: handleSaveAndClose,
1372
+ className: "p-0.5 text-slate-400 hover:text-slate-600 rounded transition-colors cursor-pointer",
1373
+ title: "\u05E1\u05D2\u05D5\u05E8 \u05D5\u05E9\u05DE\u05D5\u05E8",
1374
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.X, { className: "w-3.5 h-3.5" })
1375
+ }
1376
+ )
1377
+ ] }),
1378
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "space-y-2.5 mb-3.5", children: [
1379
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
1380
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "block text-xs font-medium text-slate-700 mb-1", children: [
1381
+ "\u05DB\u05EA\u05D5\u05D1\u05EA URL ",
1382
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-rose-500", children: "*" })
1383
+ ] }),
1384
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1385
+ "input",
1386
+ {
1387
+ ref: urlInputRef,
1388
+ type: "text",
1389
+ dir: "ltr",
1390
+ placeholder: "https://...",
1391
+ className: "w-full h-8 px-2.5 bg-slate-50 border border-slate-200 rounded-lg text-sm text-slate-800 placeholder-slate-400 focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 transition-colors",
1392
+ value: draftUrl,
1393
+ onChange: (e) => setDraftUrl(e.target.value),
1394
+ onKeyDown: (e) => {
1395
+ if (e.key === "Enter") {
1396
+ e.preventDefault();
1397
+ handleSaveAndClose();
1398
+ }
1399
+ }
1400
+ }
1401
+ )
1402
+ ] }),
1403
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
1404
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "block text-xs font-medium text-slate-700 mb-1", children: [
1405
+ "\u05D8\u05E7\u05E1\u05D8 \u05DC\u05EA\u05E6\u05D5\u05D2\u05D4 ",
1406
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-slate-400 font-normal", children: "(\u05D0\u05D5\u05E4\u05E6\u05D9\u05D5\u05E0\u05DC\u05D9)" })
1407
+ ] }),
1408
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1409
+ "input",
1410
+ {
1411
+ type: "text",
1412
+ placeholder: "\u05E9\u05DD \u05D4\u05E7\u05D9\u05E9\u05D5\u05E8",
1413
+ className: "w-full h-8 px-2.5 bg-slate-50 border border-slate-200 rounded-lg text-sm text-slate-800 placeholder-slate-400 focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 transition-colors",
1414
+ value: draftLabel,
1415
+ onChange: (e) => setDraftLabel(e.target.value),
1416
+ onKeyDown: (e) => {
1417
+ if (e.key === "Enter") {
1418
+ e.preventDefault();
1419
+ handleSaveAndClose();
1420
+ }
1421
+ }
1422
+ }
1423
+ )
1424
+ ] })
1425
+ ] }),
1426
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between pt-2 border-t border-slate-100", children: [
1427
+ currentLink.url ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1428
+ "button",
1429
+ {
1430
+ type: "button",
1431
+ onClick: handleClear,
1432
+ className: "inline-flex items-center gap-1 text-xs text-rose-600 hover:text-rose-700 hover:bg-rose-50 px-2 py-1 rounded transition-colors cursor-pointer",
1433
+ title: "\u05DE\u05D7\u05E7 \u05E7\u05D9\u05E9\u05D5\u05E8",
1434
+ children: [
1435
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Trash2, { className: "w-3 h-3" }),
1436
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u05E0\u05E7\u05D4" })
1437
+ ]
1438
+ }
1439
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", {}),
1440
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1441
+ "button",
1442
+ {
1443
+ type: "button",
1444
+ onClick: handleSaveAndClose,
1445
+ className: "inline-flex items-center gap-1 text-xs font-medium text-white bg-blue-600 hover:bg-blue-700 px-3 py-1.5 rounded-lg shadow-xs transition-colors cursor-pointer",
1446
+ children: [
1447
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Check, { className: "w-3.5 h-3.5" }),
1448
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u05E9\u05DE\u05D5\u05E8" })
1449
+ ]
1450
+ }
1451
+ )
1452
+ ] })
1453
+ ]
1454
+ }
1455
+ )
1456
+ ] });
1457
+ }
1458
+
1459
+ // src/components/TableBlock/fields/RelationPickerCell.tsx
1460
+ var import_react7 = require("react");
1461
+ var import_lucide_react6 = require("lucide-react");
1462
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1463
+ function isRawObjectId(str) {
1464
+ if (typeof str !== "string") return false;
1465
+ const trimmed = str.trim();
1466
+ return /^[0-9a-fA-F]{24}$/.test(trimmed) || trimmed.startsWith("temp_");
1467
+ }
1468
+ function normalizeRelationValue(val) {
1469
+ if (val === null || val === void 0 || val === "") return [];
1470
+ if (Array.isArray(val)) {
1471
+ return val.map((item) => {
1472
+ if (typeof item === "string") return item.trim();
1473
+ if (typeof item === "object" && item !== null) {
1474
+ return String(item.id || item._id || item.value || "").trim();
1475
+ }
1476
+ return String(item).trim();
1477
+ }).filter((id) => Boolean(id) && id !== "");
1478
+ }
1479
+ if (typeof val === "string") {
1480
+ const trimmed = val.trim();
1481
+ return trimmed ? [trimmed] : [];
1482
+ }
1483
+ if (typeof val === "object" && val !== null) {
1484
+ const id = String(val.id || val._id || val.value || "").trim();
1485
+ return id ? [id] : [];
1486
+ }
1487
+ return [];
1488
+ }
1489
+ function resolveRelationLabel(opt, column) {
1490
+ var _a;
1491
+ if (!opt) return "";
1492
+ const displayField = (_a = column.config) == null ? void 0 : _a.displayField;
1493
+ if (displayField && opt.data) {
1494
+ const val = opt.data[displayField];
1495
+ if (val !== void 0 && val !== null) {
1496
+ const s = String(val).trim();
1497
+ if (s !== "" && !isRawObjectId(s)) {
1498
+ return s;
1499
+ }
1500
+ }
1501
+ }
1502
+ if (opt.label && typeof opt.label === "string") {
1503
+ const s = opt.label.trim();
1504
+ if (s !== "" && !isRawObjectId(s) && s !== opt.id) {
1505
+ return s;
1506
+ }
1507
+ }
1508
+ if (opt.data) {
1509
+ const defaultLabel = opt.data.name || opt.data.title || opt.data.fullName;
1510
+ if (defaultLabel !== void 0 && defaultLabel !== null) {
1511
+ const s = String(defaultLabel).trim();
1512
+ if (s !== "" && !isRawObjectId(s)) {
1513
+ return s;
1514
+ }
1515
+ }
1516
+ }
1517
+ return "";
1518
+ }
1519
+ function RelationPickerCell({
1520
+ value,
1521
+ onChange,
1522
+ column,
1523
+ context,
1524
+ rowId,
1525
+ readOnly = false
1526
+ }) {
1527
+ var _a;
1528
+ const [isOpen, setIsOpen] = (0, import_react7.useState)(false);
1529
+ const [searchQuery, setSearchQuery] = (0, import_react7.useState)("");
1530
+ const containerRef = (0, import_react7.useRef)(null);
1531
+ const searchInputRef = (0, import_react7.useRef)(null);
1532
+ const allowMultiple = Boolean((_a = column.config) == null ? void 0 : _a.allowMultiple);
1533
+ const selectedIds = (0, import_react7.useMemo)(() => normalizeRelationValue(value), [value]);
1534
+ const isStandalone = !context || context.relationOptions === void 0;
1535
+ const optionsLoaded = isStandalone || context.relationOptions[column.name] !== void 0;
1536
+ const rawOptions = (0, import_react7.useMemo)(() => {
1537
+ var _a2;
1538
+ return ((_a2 = context == null ? void 0 : context.relationOptions) == null ? void 0 : _a2[column.name]) || [];
1539
+ }, [context == null ? void 0 : context.relationOptions, column.name]);
1540
+ const processedOptions = (0, import_react7.useMemo)(() => {
1541
+ return rawOptions.map((opt) => {
1542
+ const label = resolveRelationLabel(opt, column);
1543
+ return {
1544
+ id: String(opt.id),
1545
+ _displayLabel: label
1546
+ };
1547
+ }).filter((opt) => opt._displayLabel && opt._displayLabel.trim() !== "" && !isRawObjectId(opt._displayLabel));
1548
+ }, [rawOptions, column]);
1549
+ const getDisplayForId = (0, import_react7.useCallback)((id) => {
1550
+ const found = processedOptions.find((o) => String(o.id) === String(id));
1551
+ if (found && found._displayLabel && !isRawObjectId(found._displayLabel)) {
1552
+ return found._displayLabel;
1553
+ }
1554
+ return "-";
1555
+ }, [processedOptions]);
1556
+ const handleOpen = (e) => {
1557
+ if (readOnly) return;
1558
+ e == null ? void 0 : e.stopPropagation();
1559
+ setIsOpen((prev) => !prev);
1560
+ setSearchQuery("");
1561
+ if (context == null ? void 0 : context.refetchRelation) {
1562
+ context.refetchRelation(column.name);
1563
+ }
1564
+ };
1565
+ (0, import_react7.useEffect)(() => {
1566
+ if (isOpen) {
1567
+ setTimeout(() => {
1568
+ var _a2;
1569
+ (_a2 = searchInputRef.current) == null ? void 0 : _a2.focus();
1570
+ }, 50);
1571
+ }
1572
+ }, [isOpen]);
1573
+ const handleSelectOption = (optId) => {
1574
+ if (!allowMultiple) {
1575
+ onChange([optId]);
1576
+ setIsOpen(false);
1577
+ } else {
1578
+ if (selectedIds.includes(optId)) {
1579
+ onChange(selectedIds.filter((id) => id !== optId));
1580
+ } else {
1581
+ onChange([...selectedIds, optId]);
1582
+ }
1583
+ }
1584
+ };
1585
+ const handleRemove = (idToRemove) => {
1586
+ onChange(selectedIds.filter((id) => id !== idToRemove));
1587
+ };
1588
+ const handleClearSingle = (e) => {
1589
+ e.stopPropagation();
1590
+ onChange([]);
1591
+ };
1592
+ (0, import_react7.useEffect)(() => {
1593
+ if (!isOpen) return;
1594
+ function handleClickOutside(event) {
1595
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
1596
+ setIsOpen(false);
1597
+ }
1598
+ }
1599
+ function handleKeyDown(event) {
1600
+ if (event.key === "Escape") {
1601
+ setIsOpen(false);
1602
+ }
1603
+ }
1604
+ document.addEventListener("mousedown", handleClickOutside);
1605
+ document.addEventListener("keydown", handleKeyDown);
1606
+ return () => {
1607
+ document.removeEventListener("mousedown", handleClickOutside);
1608
+ document.removeEventListener("keydown", handleKeyDown);
1609
+ };
1610
+ }, [isOpen]);
1611
+ const filteredOptions = (0, import_react7.useMemo)(() => {
1612
+ const query = searchQuery.trim().toLowerCase();
1613
+ if (!query) return processedOptions;
1614
+ return processedOptions.filter((opt) => {
1615
+ return (opt._displayLabel || "").toLowerCase().includes(query);
1616
+ });
1617
+ }, [processedOptions, searchQuery]);
1618
+ if (!optionsLoaded && selectedIds.length > 0) {
1619
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "px-2 py-1 flex items-center h-full w-full", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "inline-block w-16 h-4 bg-slate-100 animate-pulse rounded" }) });
1620
+ }
1621
+ if (readOnly) {
1622
+ if (selectedIds.length === 0) {
1623
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "-" });
1624
+ }
1625
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "px-1.5 py-1 flex flex-wrap items-center gap-1 h-full max-w-full overflow-hidden", dir: "rtl", children: selectedIds.map((id) => {
1626
+ const displayText = getDisplayForId(id);
1627
+ if (displayText === "-") {
1628
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-slate-400 text-xs", children: "-" }, id);
1629
+ }
1630
+ const palette = getDeterministicPastelBadge(displayText);
1631
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1632
+ "span",
1633
+ {
1634
+ className: `inline-flex items-center px-2 py-0.5 rounded text-xs font-medium border shadow-xs max-w-full truncate ${palette.bg} ${palette.text} ${palette.border}`,
1635
+ title: displayText,
1636
+ children: displayText
1637
+ },
1638
+ id
1639
+ );
1640
+ }) });
1641
+ }
1642
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1643
+ "div",
1644
+ {
1645
+ ref: containerRef,
1646
+ className: `relative w-full h-full flex items-center justify-between px-1.5 py-1 ${isOpen ? "z-50" : ""}`,
1647
+ dir: "rtl",
1648
+ children: [
1649
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1650
+ "div",
1651
+ {
1652
+ className: "flex items-center justify-between w-full h-full overflow-hidden cursor-pointer gap-1",
1653
+ onClick: handleOpen,
1654
+ children: !allowMultiple ? (
1655
+ // Single Select Mode
1656
+ (() => {
1657
+ const singleId = selectedIds[0];
1658
+ const displayText = singleId ? getDisplayForId(singleId) : "";
1659
+ const hasValidSelection = singleId && displayText !== "-" && displayText !== "";
1660
+ if (hasValidSelection) {
1661
+ const palette = getDeterministicPastelBadge(displayText);
1662
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between w-full overflow-hidden", children: [
1663
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1664
+ "span",
1665
+ {
1666
+ className: `inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium border shadow-xs max-w-full truncate group/tag ${palette.bg} ${palette.text} ${palette.border}`,
1667
+ title: displayText,
1668
+ children: [
1669
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: displayText }),
1670
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1671
+ "button",
1672
+ {
1673
+ type: "button",
1674
+ onClick: handleClearSingle,
1675
+ className: "opacity-0 group-hover/tag:opacity-100 hover:opacity-100 focus:opacity-100 focus:outline-none p-0.5 rounded-full hover:bg-black/10 transition-opacity cursor-pointer shrink-0",
1676
+ title: "\u05E0\u05E7\u05D4",
1677
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.X, { className: "w-3 h-3" })
1678
+ }
1679
+ )
1680
+ ]
1681
+ }
1682
+ ),
1683
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.ChevronDown, { className: "w-3.5 h-3.5 text-slate-400 opacity-0 hover:opacity-60 transition-opacity shrink-0 ml-1" })
1684
+ ] });
1685
+ }
1686
+ if (singleId && displayText === "-") {
1687
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between w-full text-slate-400 text-xs", children: [
1688
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "-" }),
1689
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.ChevronDown, { className: "w-3.5 h-3.5 text-slate-400 opacity-0 hover:opacity-60 transition-opacity shrink-0 ml-1" })
1690
+ ] });
1691
+ }
1692
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between w-full text-slate-400 italic text-xs select-none", children: [
1693
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05D1\u05D7\u05E8..." }),
1694
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.ChevronDown, { className: "w-3.5 h-3.5 text-slate-400 opacity-60 shrink-0 ml-1" })
1695
+ ] });
1696
+ })()
1697
+ ) : (
1698
+ // Multi Select Mode
1699
+ selectedIds.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between w-full text-slate-400 italic text-xs select-none", children: [
1700
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05D1\u05D7\u05E8..." }),
1701
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.ChevronDown, { className: "w-3.5 h-3.5 text-slate-400 opacity-60 shrink-0 ml-1" })
1702
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between w-full overflow-hidden", children: [
1703
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex flex-wrap items-center gap-1 overflow-hidden max-h-full flex-1 py-0.5", children: selectedIds.map((id) => {
1704
+ const displayText = getDisplayForId(id);
1705
+ if (displayText === "-") {
1706
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-slate-400 text-xs px-1", children: "-" }, id);
1707
+ }
1708
+ const palette = getDeterministicPastelBadge(displayText);
1709
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1710
+ "span",
1711
+ {
1712
+ className: `inline-flex items-center gap-1 px-2 py-0.5 rounded text-xs font-medium border shadow-xs max-w-[160px] truncate group/tag ${palette.bg} ${palette.text} ${palette.border}`,
1713
+ title: displayText,
1714
+ children: [
1715
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: displayText }),
1716
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1717
+ "button",
1718
+ {
1719
+ type: "button",
1720
+ onClick: (e) => {
1721
+ e.stopPropagation();
1722
+ handleRemove(id);
1723
+ },
1724
+ className: "opacity-0 group-hover/tag:opacity-100 hover:opacity-100 focus:opacity-100 focus:outline-none p-0.5 rounded-full hover:bg-black/10 transition-opacity cursor-pointer shrink-0",
1725
+ title: "\u05D4\u05E1\u05E8",
1726
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.X, { className: "w-3 h-3" })
1727
+ }
1728
+ )
1729
+ ]
1730
+ },
1731
+ id
1732
+ );
1733
+ }) }),
1734
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.ChevronDown, { className: "w-3.5 h-3.5 text-slate-400 opacity-0 hover:opacity-60 transition-opacity shrink-0 ml-1" })
1735
+ ] })
1736
+ )
1737
+ }
1738
+ ),
1739
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1740
+ "div",
1741
+ {
1742
+ id: `relation-dropdown-${column.name}-${rowId || "cell"}`,
1743
+ dir: "rtl",
1744
+ className: "absolute top-full right-0 mt-1 z-[100] bg-white rounded-md shadow-lg border border-slate-200 p-1 min-w-[200px] w-full max-w-[300px] animate-in fade-in duration-100 flex flex-col",
1745
+ onClick: (e) => e.stopPropagation(),
1746
+ children: [
1747
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative mb-1", children: [
1748
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.Search, { className: "w-3.5 h-3.5 text-slate-400 absolute right-2 top-2 pointer-events-none" }),
1749
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1750
+ "input",
1751
+ {
1752
+ ref: searchInputRef,
1753
+ type: "text",
1754
+ placeholder: "\u05D7\u05E4\u05E9...",
1755
+ value: searchQuery,
1756
+ onChange: (e) => setSearchQuery(e.target.value),
1757
+ onKeyDown: (e) => {
1758
+ if (e.key === "Escape") {
1759
+ e.stopPropagation();
1760
+ setIsOpen(false);
1761
+ }
1762
+ },
1763
+ className: "w-full h-7 pr-7 pl-2 bg-slate-50 border border-slate-200 rounded text-xs text-slate-800 placeholder-slate-400 focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500 transition-colors"
1764
+ }
1765
+ )
1766
+ ] }),
1767
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "overflow-y-auto max-h-[180px] space-y-0.5", children: filteredOptions.length > 0 ? filteredOptions.map((opt) => {
1768
+ const isSelected = selectedIds.includes(opt.id);
1769
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1770
+ "div",
1771
+ {
1772
+ onClick: () => handleSelectOption(opt.id),
1773
+ className: `flex items-center justify-between px-2.5 py-1.5 rounded cursor-pointer text-xs transition-colors ${isSelected ? "bg-blue-50 text-blue-900 font-medium" : "hover:bg-slate-50 text-slate-700"}`,
1774
+ children: [
1775
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate flex-1", children: opt._displayLabel }),
1776
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react6.Check, { className: "w-3.5 h-3.5 text-blue-600 shrink-0 mr-1" })
1777
+ ]
1778
+ },
1779
+ opt.id
1780
+ );
1781
+ }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "py-2.5 px-2 text-center text-xs text-slate-400 select-none", children: processedOptions.length === 0 ? "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D6\u05DE\u05D9\u05E0\u05D5\u05EA" : "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA" }) })
1782
+ ]
1783
+ }
1784
+ )
1785
+ ]
1786
+ }
1787
+ );
1788
+ }
1789
+
1790
+ // src/components/TableBlock/fields/fieldRegistry.tsx
1791
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1792
+ var CURRENCY_SYMBOLS = {
1793
+ USD: "$",
1794
+ EUR: "\u20AC",
1795
+ ILS: "\u20AA",
1796
+ GBP: "\xA3"
1797
+ };
1798
+ function getCurrencySymbol(code) {
1799
+ if (!code) return "";
1800
+ return CURRENCY_SYMBOLS[code.toUpperCase()] || code;
1801
+ }
1802
+ var FORM_INPUTS = {
1803
+ DATE: ({ value, onChange, column }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DatePickerCell, { value, onChange, column }),
1804
+ CURRENCY: ({ value, column, onChange }) => {
1805
+ var _a;
1806
+ const symbol = getCurrencySymbol((_a = column.config) == null ? void 0 : _a.currencySymbol);
1807
+ const [isFocused, setIsFocused] = import_react8.default.useState(false);
1808
+ const displayValue = !isFocused && value !== void 0 && value !== null && !isNaN(Number(value)) ? new Intl.NumberFormat("en-US").format(Number(value)) : value !== void 0 && value !== null ? value : "";
1809
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "relative w-full h-full", children: [
1810
+ symbol && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "absolute left-2 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none text-sm", children: symbol }),
1811
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1812
+ "input",
1813
+ {
1814
+ type: isFocused ? "number" : "text",
1815
+ step: "any",
1816
+ className: `w-full h-8 ${symbol ? "pl-6 pr-2" : "px-2"} bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm`,
1817
+ value: displayValue,
1818
+ onFocus: () => setIsFocused(true),
1819
+ onBlur: () => setIsFocused(false),
1820
+ onChange: (e) => {
1821
+ const val = e.target.value;
1822
+ onChange(val === "" ? null : Number(val));
1823
+ }
1824
+ }
1825
+ )
1826
+ ] });
1827
+ },
1828
+ TIME: ({ value, onChange, column }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TimePickerCell, { value, onChange, column }),
1829
+ LINK: ({ value, onChange, column }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LinkPickerCell, { value, onChange, column }),
1830
+ BOOLEAN: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex items-center justify-center w-full h-full p-2", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1831
+ "input",
1832
+ {
1833
+ type: "checkbox",
1834
+ checked: !!value,
1835
+ onChange: (e) => onChange(e.target.checked),
1836
+ className: "w-4 h-4 rounded border-slate-300 text-brand"
1837
+ }
1838
+ ) }),
1839
+ GOOGLE_DRIVE_FILE: ({ value, onChange, column, rowId, context }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1840
+ DrivePickerCell,
1841
+ {
1842
+ value: value || [],
1843
+ onChange,
1844
+ column,
1845
+ rowId,
1846
+ tableName: context == null ? void 0 : context.tableName,
1847
+ onMarkForDeletion: context == null ? void 0 : context.onMarkForDeletion,
1848
+ context
1849
+ }
1850
+ ),
1851
+ RELATION: ({ value, onChange, column, context, rowId }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1852
+ RelationPickerCell,
1853
+ {
1854
+ value,
1855
+ onChange,
1856
+ column,
1857
+ context,
1858
+ rowId
1859
+ }
1860
+ ),
1861
+ NUMBER: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1862
+ "input",
1863
+ {
1864
+ type: "number",
934
1865
  className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
935
- value: value !== void 0 && value !== null ? String(value) : "",
936
- onChange: (e) => onChange(e.target.value),
937
- dir: "ltr"
1866
+ value: value !== void 0 && value !== null ? value : "",
1867
+ onChange: (e) => {
1868
+ const val = e.target.value;
1869
+ onChange(val === "" ? null : Number(val));
1870
+ }
938
1871
  }
939
1872
  ),
1873
+ PHONE: ({ value, onChange, column }) => {
1874
+ var _a;
1875
+ const enableWhatsApp = (_a = column == null ? void 0 : column.config) == null ? void 0 : _a.enableWhatsApp;
1876
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center w-full h-full px-2 gap-1.5 overflow-hidden", children: [
1877
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1878
+ "input",
1879
+ {
1880
+ type: "tel",
1881
+ className: "w-full h-8 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm flex-1 min-w-0",
1882
+ value: value !== void 0 && value !== null ? String(value) : "",
1883
+ onChange: (e) => onChange(e.target.value || null),
1884
+ dir: "ltr"
1885
+ }
1886
+ ),
1887
+ enableWhatsApp && value && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1888
+ "button",
1889
+ {
1890
+ type: "button",
1891
+ className: "text-emerald-500 cursor-pointer hover:opacity-80 transition-opacity shrink-0 p-1 rounded hover:bg-emerald-50",
1892
+ title: "\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4",
1893
+ onClick: (e) => {
1894
+ e.stopPropagation();
1895
+ openWhatsAppChat(String(value));
1896
+ },
1897
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "w-4 h-4", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) })
1898
+ }
1899
+ )
1900
+ ] });
1901
+ },
940
1902
  GOOGLE_CONTACT: ({ value, column, rowId, onChange, context }) => {
941
- const [isSyncing, setIsSyncing] = import_react5.default.useState(false);
1903
+ const [isSyncing, setIsSyncing] = import_react8.default.useState(false);
942
1904
  const { addToast } = useToast();
943
- const googleClientIdRef = import_react5.default.useRef(null);
944
- const ensureGisScript = import_react5.default.useCallback(() => {
1905
+ const googleClientIdRef = import_react8.default.useRef(null);
1906
+ const ensureGisScript = import_react8.default.useCallback(() => {
945
1907
  return new Promise((resolve, reject) => {
946
1908
  var _a, _b, _c;
947
1909
  if ((_c = (_b = (_a = window.google) == null ? void 0 : _a.accounts) == null ? void 0 : _b.oauth2) == null ? void 0 : _c.initTokenClient) {
@@ -970,7 +1932,7 @@ var FORM_INPUTS = {
970
1932
  document.head.appendChild(script);
971
1933
  });
972
1934
  }, []);
973
- const requestGisToken = import_react5.default.useCallback(async (hint) => {
1935
+ const requestGisToken = import_react8.default.useCallback(async (hint) => {
974
1936
  await ensureGisScript();
975
1937
  if (!googleClientIdRef.current && (context == null ? void 0 : context.executeAction)) {
976
1938
  try {
@@ -1017,19 +1979,27 @@ var FORM_INPUTS = {
1017
1979
  return { accessToken, email };
1018
1980
  }, [ensureGisScript, context]);
1019
1981
  const handleSync = async () => {
1020
- var _a, _b, _c;
1982
+ var _a, _b, _c, _d, _e, _f;
1021
1983
  if (!(context == null ? void 0 : context.executeAction)) return;
1022
1984
  setIsSyncing(true);
1023
1985
  try {
1024
- const mapping = column.contactMapping || {};
1986
+ const mapping = ((_a = column.config) == null ? void 0 : _a.contactMapping) || {};
1025
1987
  const rowData = context.rowData || {};
1988
+ const targetTableMetaId = (context == null ? void 0 : context.tableMetaId) || (context == null ? void 0 : context.tableId);
1989
+ const targetOrgId = context == null ? void 0 : context.orgId;
1026
1990
  let hasPhone = false;
1027
1991
  if (mapping.phoneCol && rowData[mapping.phoneCol]) hasPhone = true;
1992
+ const activeParentTableId = ((_b = context.parentRecord) == null ? void 0 : _b.tableId) || (context == null ? void 0 : context.parentTableId);
1028
1993
  let hasName = false;
1029
1994
  if (mapping.nameParts && Array.isArray(mapping.nameParts)) {
1030
1995
  for (const part of mapping.nameParts) {
1031
1996
  if (part.type === "LOCAL" && rowData[part.columnId]) hasName = true;
1032
- if (part.type === "PARENT" && ((_a = context.parentRecord) == null ? void 0 : _a.tableId) === part.parentTableId && ((_c = (_b = context.parentRecord) == null ? void 0 : _b.data) == null ? void 0 : _c[part.columnId])) hasName = true;
1997
+ if (part.type === "PARENT") {
1998
+ if (!activeParentTableId) continue;
1999
+ if (part.parentTableId && part.parentTableId !== activeParentTableId) continue;
2000
+ if ((_d = (_c = context.parentRecord) == null ? void 0 : _c.data) == null ? void 0 : _d[part.columnId]) hasName = true;
2001
+ else if (((_e = context.parentRecord) == null ? void 0 : _e.recordId) || ((_f = context.parentRecord) == null ? void 0 : _f.id)) hasName = true;
2002
+ }
1033
2003
  }
1034
2004
  }
1035
2005
  if (!hasPhone) {
@@ -1059,6 +2029,10 @@ var FORM_INPUTS = {
1059
2029
  emailCol: mapping.emailCol,
1060
2030
  localRowData: rowData,
1061
2031
  parentRecord: context.parentRecord,
2032
+ tableMetaId: targetTableMetaId,
2033
+ tableId: targetTableMetaId,
2034
+ recordId: rowId,
2035
+ orgId: targetOrgId,
1062
2036
  accessToken,
1063
2037
  userEmail
1064
2038
  };
@@ -1069,142 +2043,740 @@ var FORM_INPUTS = {
1069
2043
  } else {
1070
2044
  onChange(res);
1071
2045
  }
1072
- if (context.tableId && !rowId.startsWith("temp_")) {
2046
+ if (targetTableMetaId && !rowId.startsWith("temp_")) {
1073
2047
  await context.executeAction("UPDATE_RECORD", {
1074
- tableId: context.tableId,
2048
+ tableId: targetTableMetaId,
2049
+ tableMetaId: targetTableMetaId,
1075
2050
  recordId: rowId,
2051
+ orgId: targetOrgId,
1076
2052
  data: { [column.name]: res }
1077
2053
  });
1078
2054
  }
1079
2055
  }
1080
- } catch (error) {
1081
- console.error("Failed to sync contact:", error);
1082
- addToast({ type: "warning", message: "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E1\u05E0\u05DB\u05E8\u05D5\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8: " + error.message });
1083
- } finally {
1084
- setIsSyncing(false);
2056
+ } catch (error) {
2057
+ console.error("Failed to sync contact:", error);
2058
+ addToast({ type: "warning", message: "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E1\u05E0\u05DB\u05E8\u05D5\u05DF \u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8: " + error.message });
2059
+ } finally {
2060
+ setIsSyncing(false);
2061
+ }
2062
+ };
2063
+ const handleUnlink = async () => {
2064
+ let accessToken;
2065
+ const targetTableMetaId = (context == null ? void 0 : context.tableMetaId) || (context == null ? void 0 : context.tableId);
2066
+ const targetOrgId = context == null ? void 0 : context.orgId;
2067
+ try {
2068
+ let emailHint = value == null ? void 0 : value.userEmail;
2069
+ if (!emailHint && (value == null ? void 0 : value.url)) {
2070
+ try {
2071
+ const parsed = new URL(value.url);
2072
+ emailHint = parsed.searchParams.get("authuser") || void 0;
2073
+ } catch (e) {
2074
+ }
2075
+ }
2076
+ const auth = await requestGisToken(emailHint);
2077
+ accessToken = auth.accessToken;
2078
+ } catch (err) {
2079
+ console.warn("[handleUnlink] Could not obtain token via GIS, falling back to server default token:", err);
2080
+ }
2081
+ if ((value == null ? void 0 : value.resourceName) && (context == null ? void 0 : context.executeAction)) {
2082
+ await context.executeAction("DELETE_GOOGLE_CONTACT", {
2083
+ resourceName: value.resourceName,
2084
+ accessToken,
2085
+ tableMetaId: targetTableMetaId,
2086
+ tableId: targetTableMetaId,
2087
+ recordId: rowId,
2088
+ orgId: targetOrgId
2089
+ });
2090
+ }
2091
+ if (context == null ? void 0 : context.updateQuietly) {
2092
+ context.updateQuietly(rowId, column.name, null);
2093
+ } else {
2094
+ onChange(null);
2095
+ }
2096
+ if (targetTableMetaId && (context == null ? void 0 : context.executeAction) && !rowId.startsWith("temp_")) {
2097
+ await context.executeAction("UPDATE_RECORD", {
2098
+ tableId: targetTableMetaId,
2099
+ tableMetaId: targetTableMetaId,
2100
+ recordId: rowId,
2101
+ orgId: targetOrgId,
2102
+ data: { [column.name]: null }
2103
+ });
2104
+ }
2105
+ };
2106
+ if (value && value.synced && value.url) {
2107
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-1.5 h-8 px-2 group whitespace-nowrap overflow-hidden max-w-full", children: [
2108
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("a", { href: value.url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline flex-1 truncate text-xs whitespace-nowrap", children: "\u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05D2\u05D5\u05D2\u05DC" }),
2109
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2110
+ "button",
2111
+ {
2112
+ type: "button",
2113
+ onClick: handleUnlink,
2114
+ className: "text-slate-400 hover:text-rose-500 opacity-0 group-hover:opacity-100 transition-opacity p-1 shrink-0",
2115
+ title: "\u05D1\u05D8\u05DC \u05E1\u05E0\u05DB\u05E8\u05D5\u05DF",
2116
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
2117
+ }
2118
+ )
2119
+ ] });
2120
+ }
2121
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex items-center h-8 px-2 whitespace-nowrap overflow-hidden max-w-full", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2122
+ "button",
2123
+ {
2124
+ type: "button",
2125
+ onClick: handleSync,
2126
+ disabled: isSyncing,
2127
+ 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 max-w-full overflow-hidden",
2128
+ children: [
2129
+ isSyncing ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { className: "w-3.5 h-3.5 animate-spin shrink-0", viewBox: "0 0 24 24", fill: "none", children: [
2130
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
2131
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
2132
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "w-3.5 h-3.5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 4v16m8-8H4" }) }),
2133
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "whitespace-nowrap truncate", children: "\u05E1\u05E0\u05DB\u05E8\u05DF \u05DC\u05D2\u05D5\u05D2\u05DC" })
2134
+ ]
2135
+ }
2136
+ ) });
2137
+ },
2138
+ DEFAULT: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2139
+ "input",
2140
+ {
2141
+ type: "text",
2142
+ className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
2143
+ value: value !== void 0 && value !== null ? String(value) : "",
2144
+ onChange: (e) => onChange(e.target.value)
2145
+ }
2146
+ ),
2147
+ SUB_TABLE: ({ value, column }) => {
2148
+ var _a, _b, _c;
2149
+ if (!Array.isArray(value)) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
2150
+ const selected = value.filter((e) => e == null ? void 0 : e.isSelected);
2151
+ if (selected.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
2152
+ const displayFields = ((_a = column.config) == null ? void 0 : _a.subTableDisplayFields) || [];
2153
+ const isWhatsApp = ((_b = column.config) == null ? void 0 : _b.actionType) === "WHATSAPP";
2154
+ const actionPhoneCol = (_c = column.config) == null ? void 0 : _c.actionPhoneColumn;
2155
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "px-1.5 py-1 flex flex-nowrap items-center gap-1 h-full overflow-hidden max-w-full", children: selected.map((entry, idx) => {
2156
+ var _a2, _b2;
2157
+ let label = "";
2158
+ if (entry._resolvedData) {
2159
+ if (displayFields.length > 0) {
2160
+ label = displayFields.map((f) => String(entry._resolvedData[f] || "")).filter(Boolean).join(" ");
2161
+ } else {
2162
+ const firstField = Object.keys(entry._resolvedData).find((k) => k !== "_id");
2163
+ if (firstField) label = String(entry._resolvedData[firstField] || "");
2164
+ }
2165
+ }
2166
+ if (!label) label = ((_a2 = entry.recordId) == null ? void 0 : _a2.slice(-6)) || "...";
2167
+ if (isWhatsApp) {
2168
+ const rawPhone = actionPhoneCol ? (_b2 = entry._resolvedData) == null ? void 0 : _b2[actionPhoneCol] : null;
2169
+ const phone = rawPhone ? String(rawPhone).trim() : null;
2170
+ if (phone) {
2171
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2172
+ "button",
2173
+ {
2174
+ type: "button",
2175
+ onClick: (e) => {
2176
+ e.stopPropagation();
2177
+ openWhatsAppChat(phone);
2178
+ },
2179
+ 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-full truncate cursor-pointer transition-colors shadow-xs shrink",
2180
+ title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
2181
+ children: [
2182
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { className: "w-3 h-3 text-emerald-600 shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) }),
2183
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate", children: label })
2184
+ ]
2185
+ },
2186
+ entry.recordId || idx
2187
+ );
2188
+ }
2189
+ }
2190
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2191
+ "span",
2192
+ {
2193
+ 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-full truncate shrink",
2194
+ title: label,
2195
+ children: label
2196
+ },
2197
+ entry.recordId || idx
2198
+ );
2199
+ }) });
2200
+ }
2201
+ };
2202
+
2203
+ // src/components/TableBlock/fields/SubTableViewer.tsx
2204
+ var import_react11 = require("react");
2205
+ var import_shared = require("@universe-platform/shared");
2206
+
2207
+ // src/utils/phone.ts
2208
+ function sanitizePhoneNumber(phone) {
2209
+ if (!phone) return "";
2210
+ const trimmed = phone.trim();
2211
+ const hasLeadingPlus = trimmed.startsWith("+");
2212
+ const digitsOnly = trimmed.replace(/\D/g, "");
2213
+ return hasLeadingPlus ? `+${digitsOnly}` : digitsOnly;
2214
+ }
2215
+ function isValidPhoneNumber(phone) {
2216
+ if (!phone) return false;
2217
+ const cleaned = sanitizePhoneNumber(phone);
2218
+ return /^\+?[0-9]{9,15}$/.test(cleaned);
2219
+ }
2220
+
2221
+ // src/components/TableBlock/useColumnResize.ts
2222
+ var import_react9 = require("react");
2223
+ function useColumnResize({
2224
+ storageKey,
2225
+ defaultWidth = 200,
2226
+ minWidth = 60,
2227
+ maxWidth = 500,
2228
+ getMinColWidth
2229
+ }) {
2230
+ const [columnWidths, setColumnWidths] = (0, import_react9.useState)({});
2231
+ const [resizingCol, setResizingCol] = (0, import_react9.useState)(null);
2232
+ (0, import_react9.useEffect)(() => {
2233
+ if (typeof window === "undefined" || !storageKey) return;
2234
+ try {
2235
+ const saved = localStorage.getItem(storageKey);
2236
+ if (saved) {
2237
+ setColumnWidths(JSON.parse(saved));
2238
+ }
2239
+ } catch (e) {
2240
+ console.error(`Failed to load column widths for key "${storageKey}":`, e);
2241
+ }
2242
+ }, [storageKey]);
2243
+ (0, import_react9.useEffect)(() => {
2244
+ if (!resizingCol) return;
2245
+ const handleMouseMove = (e) => {
2246
+ const diffX = resizingCol.startX - e.clientX;
2247
+ const colMin = resizingCol.minWidth || minWidth;
2248
+ const newWidth = Math.max(colMin, Math.min(maxWidth, resizingCol.startWidth + diffX));
2249
+ setColumnWidths((prev) => __spreadProps(__spreadValues({}, prev), { [resizingCol.name]: newWidth }));
2250
+ };
2251
+ const handleMouseUp = () => {
2252
+ setResizingCol(null);
2253
+ setColumnWidths((prev) => {
2254
+ if (typeof window !== "undefined" && storageKey) {
2255
+ try {
2256
+ localStorage.setItem(storageKey, JSON.stringify(prev));
2257
+ } catch (e) {
2258
+ console.error(`Failed to save column widths for key "${storageKey}":`, e);
2259
+ }
2260
+ }
2261
+ return prev;
2262
+ });
2263
+ };
2264
+ document.addEventListener("mousemove", handleMouseMove);
2265
+ document.addEventListener("mouseup", handleMouseUp);
2266
+ return () => {
2267
+ document.removeEventListener("mousemove", handleMouseMove);
2268
+ document.removeEventListener("mouseup", handleMouseUp);
2269
+ };
2270
+ }, [resizingCol, storageKey, minWidth, maxWidth]);
2271
+ const startResize = (0, import_react9.useCallback)(
2272
+ (colName, currentWidth, clientX, customMinWidth) => {
2273
+ const colMin = customMinWidth != null ? customMinWidth : getMinColWidth ? getMinColWidth(colName) : minWidth;
2274
+ setResizingCol({
2275
+ name: colName,
2276
+ startWidth: currentWidth,
2277
+ startX: clientX,
2278
+ minWidth: colMin
2279
+ });
2280
+ },
2281
+ [getMinColWidth, minWidth]
2282
+ );
2283
+ const getWidth = (0, import_react9.useCallback)(
2284
+ (colName, fallback) => {
2285
+ const colMin = getMinColWidth ? getMinColWidth(colName) : minWidth;
2286
+ const saved = columnWidths[colName] || fallback || defaultWidth;
2287
+ return Math.max(colMin, saved);
2288
+ },
2289
+ [columnWidths, defaultWidth, getMinColWidth, minWidth]
2290
+ );
2291
+ return {
2292
+ columnWidths,
2293
+ setColumnWidths,
2294
+ resizingCol,
2295
+ startResize,
2296
+ getWidth,
2297
+ minWidth
2298
+ };
2299
+ }
2300
+
2301
+ // src/components/TableBlock/useColumnReorder.ts
2302
+ var import_react10 = require("react");
2303
+ function useColumnReorder({
2304
+ onReorder,
2305
+ disabled = false
2306
+ }) {
2307
+ const [draggedColName, setDraggedColName] = (0, import_react10.useState)(null);
2308
+ const [dragOverColName, setDragOverColName] = (0, import_react10.useState)(null);
2309
+ const getHeaderDragProps = (0, import_react10.useCallback)(
2310
+ (colName) => {
2311
+ if (disabled) {
2312
+ return {
2313
+ draggable: false
2314
+ };
2315
+ }
2316
+ return {
2317
+ draggable: true,
2318
+ onDragStart: (e) => {
2319
+ e.dataTransfer.setData("text/plain", colName);
2320
+ e.dataTransfer.effectAllowed = "move";
2321
+ setDraggedColName(colName);
2322
+ },
2323
+ onDragOver: (e) => {
2324
+ e.preventDefault();
2325
+ e.dataTransfer.dropEffect = "move";
2326
+ if (dragOverColName !== colName) {
2327
+ setDragOverColName(colName);
2328
+ }
2329
+ },
2330
+ onDragLeave: () => {
2331
+ if (dragOverColName === colName) {
2332
+ setDragOverColName(null);
2333
+ }
2334
+ },
2335
+ onDrop: (e) => {
2336
+ e.preventDefault();
2337
+ if (draggedColName && draggedColName !== colName) {
2338
+ onReorder(draggedColName, colName);
2339
+ }
2340
+ setDraggedColName(null);
2341
+ setDragOverColName(null);
2342
+ },
2343
+ onDragEnd: () => {
2344
+ setDraggedColName(null);
2345
+ setDragOverColName(null);
2346
+ }
2347
+ };
2348
+ },
2349
+ [disabled, draggedColName, dragOverColName, onReorder]
2350
+ );
2351
+ const isDragging = (0, import_react10.useCallback)((colName) => draggedColName === colName, [draggedColName]);
2352
+ const isDragOver = (0, import_react10.useCallback)((colName) => dragOverColName === colName, [dragOverColName]);
2353
+ return {
2354
+ draggedColName,
2355
+ dragOverColName,
2356
+ isDragging,
2357
+ isDragOver,
2358
+ getHeaderDragProps
2359
+ };
2360
+ }
2361
+
2362
+ // src/components/TableBlock/columnTitleUtils.tsx
2363
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2364
+ var canvas = null;
2365
+ function measureTextWidth(text, font = '600 14px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif') {
2366
+ if (typeof document === "undefined") return text.length * 9;
2367
+ if (!canvas) {
2368
+ canvas = document.createElement("canvas");
2369
+ }
2370
+ const ctx = canvas.getContext("2d");
2371
+ if (!ctx) return text.length * 9;
2372
+ ctx.font = font;
2373
+ return ctx.measureText(text).width;
2374
+ }
2375
+ function splitHeaderTitle(name) {
2376
+ if (!name) return { isSingleWord: true, line1: "" };
2377
+ const words = name.trim().split(/\s+/).filter(Boolean);
2378
+ if (words.length <= 1) {
2379
+ return { isSingleWord: true, line1: words[0] || "" };
2380
+ }
2381
+ if (words.length === 2) {
2382
+ return { isSingleWord: false, line1: words[0], line2: words[1] };
2383
+ }
2384
+ let bestSplit = 1;
2385
+ let minDiff = Infinity;
2386
+ for (let i = 1; i < words.length; i++) {
2387
+ const l1 = words.slice(0, i).join(" ");
2388
+ const l2 = words.slice(i).join(" ");
2389
+ const diff = Math.abs(l1.length - l2.length);
2390
+ if (diff < minDiff) {
2391
+ minDiff = diff;
2392
+ bestSplit = i;
2393
+ }
2394
+ }
2395
+ return {
2396
+ isSingleWord: false,
2397
+ line1: words.slice(0, bestSplit).join(" "),
2398
+ line2: words.slice(bestSplit).join(" ")
2399
+ };
2400
+ }
2401
+ function calculateMinColumnWidth(name, isSubTable = false, colType) {
2402
+ const font = isSubTable ? '600 12px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' : '600 14px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
2403
+ const chromeWidth = isSubTable ? 44 : 52;
2404
+ let baseMin = isSubTable ? 50 : 60;
2405
+ if ((colType == null ? void 0 : colType.toUpperCase()) === "GOOGLE_CONTACT") {
2406
+ baseMin = isSubTable ? 110 : 120;
2407
+ }
2408
+ if (!name) return baseMin;
2409
+ const { isSingleWord, line1, line2 } = splitHeaderTitle(name);
2410
+ if (isSingleWord) {
2411
+ const wordWidth = measureTextWidth(line1, font);
2412
+ return Math.max(baseMin, Math.ceil(wordWidth + chromeWidth));
2413
+ }
2414
+ const w1 = measureTextWidth(line1, font);
2415
+ const w2 = line2 ? measureTextWidth(line2, font) : 0;
2416
+ const maxLine = Math.max(w1, w2);
2417
+ return Math.max(baseMin, Math.ceil(maxLine + chromeWidth));
2418
+ }
2419
+ function ColumnHeaderTitle({ name, width, isSubTable = false }) {
2420
+ const { isSingleWord, line1, line2 } = splitHeaderTitle(name);
2421
+ if (isSingleWord || !line2) {
2422
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-nowrap select-none overflow-hidden text-right flex-1", title: name, children: line1 });
2423
+ }
2424
+ const font = isSubTable ? '600 12px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif' : '600 14px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
2425
+ const chromeWidth = isSubTable ? 44 : 52;
2426
+ const fullTitleWidth = measureTextWidth(name, font) + chromeWidth;
2427
+ if (width !== void 0 && width >= fullTitleWidth) {
2428
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-nowrap select-none overflow-hidden text-right flex-1", title: name, children: name });
2429
+ }
2430
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex flex-col justify-center leading-tight select-none overflow-hidden text-right flex-1", title: name, children: [
2431
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-nowrap block", children: line1 }),
2432
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-nowrap block", children: line2 })
2433
+ ] });
2434
+ }
2435
+
2436
+ // src/components/TableBlock/fields/SubTableViewer.tsx
2437
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2438
+ function formatConflictCellValue(rawVal, colDef, relationOptionsMap) {
2439
+ var _a, _b, _c;
2440
+ if (rawVal === void 0 || rawVal === null || rawVal === "") {
2441
+ return "-";
2442
+ }
2443
+ const colType = (_a = colDef == null ? void 0 : colDef.type) == null ? void 0 : _a.toUpperCase();
2444
+ if (typeof rawVal === "boolean" || colType === "BOOLEAN") {
2445
+ return rawVal ? "\u05DB\u05DF" : "\u05DC\u05D0";
2446
+ }
2447
+ if (colType === "GOOGLE_CONTACT" || typeof rawVal === "object" && rawVal !== null && ("resourceName" in rawVal || "synced" in rawVal)) {
2448
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-violet-50 text-violet-700 border border-violet-200", children: "\u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05D2\u05D5\u05D2\u05DC" });
2449
+ }
2450
+ if (colType === "GOOGLE_DRIVE_FILE" || typeof rawVal === "object" && rawVal !== null && ("fileId" in rawVal || "fileUrl" in rawVal || "fileName" in rawVal)) {
2451
+ const fileName = rawVal == null ? void 0 : rawVal.fileName;
2452
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-rose-50 text-rose-700 border border-rose-200 truncate max-w-[150px]", title: fileName || "\u05E7\u05D5\u05D1\u05E5 \u05DE\u05E6\u05D5\u05E8\u05E3", children: fileName ? String(fileName) : "\u05E7\u05D5\u05D1\u05E5 \u05DE\u05E6\u05D5\u05E8\u05E3" });
2453
+ }
2454
+ if (colType === "LINK" || typeof rawVal === "object" && rawVal !== null && ("url" in rawVal || "label" in rawVal)) {
2455
+ const text = (rawVal == null ? void 0 : rawVal.label) || (rawVal == null ? void 0 : rawVal.url);
2456
+ return text ? String(text) : "-";
2457
+ }
2458
+ if (colType === "SUB_TABLE" || Array.isArray(rawVal) && rawVal.length > 0 && typeof rawVal[0] === "object" && ("recordId" in rawVal[0] || "id" in rawVal[0])) {
2459
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-amber-50 text-amber-700 border border-amber-200", children: [
2460
+ rawVal.length,
2461
+ " \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA"
2462
+ ] });
2463
+ }
2464
+ if (colType === "RELATION") {
2465
+ if (Array.isArray(rawVal)) {
2466
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-indigo-50 text-indigo-700 border border-indigo-200", children: [
2467
+ rawVal.length,
2468
+ " \u05DE\u05E7\u05D5\u05E9\u05E8\u05D9\u05DD"
2469
+ ] });
2470
+ }
2471
+ const colOpts = (colDef == null ? void 0 : colDef.name) && relationOptionsMap ? relationOptionsMap[colDef.name] : void 0;
2472
+ if (Array.isArray(colOpts)) {
2473
+ const opt = colOpts.find((o) => String(o.id) === String(rawVal));
2474
+ if (opt) {
2475
+ const displayField = (_b = colDef == null ? void 0 : colDef.config) == null ? void 0 : _b.displayField;
2476
+ const disp = opt._displayLabel || displayField && ((_c = opt.data) == null ? void 0 : _c[displayField]) || (opt.label !== opt.id ? opt.label : "");
2477
+ if (disp && String(disp).trim() !== "" && !/^[a-f\d]{24}$/i.test(String(disp))) {
2478
+ return String(disp);
2479
+ }
1085
2480
  }
1086
- };
1087
- const handleUnlink = async () => {
1088
- let accessToken;
1089
- try {
1090
- let emailHint = value == null ? void 0 : value.userEmail;
1091
- if (!emailHint && (value == null ? void 0 : value.url)) {
1092
- try {
1093
- const parsed = new URL(value.url);
1094
- emailHint = parsed.searchParams.get("authuser") || void 0;
1095
- } catch (e) {
1096
- }
1097
- }
1098
- const auth = await requestGisToken(emailHint);
1099
- accessToken = auth.accessToken;
1100
- } catch (err) {
1101
- console.warn("[handleUnlink] Could not obtain token via GIS, falling back to server default token:", err);
2481
+ }
2482
+ if (typeof rawVal === "object" && rawVal !== null) {
2483
+ const relDisplay = rawVal.title || rawVal.name || rawVal.label;
2484
+ if (relDisplay && !/^[a-f\d]{24}$/i.test(String(relDisplay))) {
2485
+ return String(relDisplay);
1102
2486
  }
1103
- if ((value == null ? void 0 : value.resourceName) && (context == null ? void 0 : context.executeAction)) {
1104
- await context.executeAction("DELETE_GOOGLE_CONTACT", {
1105
- resourceName: value.resourceName,
1106
- accessToken
1107
- });
2487
+ }
2488
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-indigo-50 text-indigo-700 border border-indigo-200", children: "\u05E8\u05E9\u05D5\u05DE\u05D4 \u05DE\u05E7\u05D5\u05E9\u05E8\u05EA" });
2489
+ }
2490
+ if (Array.isArray(rawVal)) {
2491
+ const allPrimitives = rawVal.every((v) => typeof v !== "object");
2492
+ if (allPrimitives) {
2493
+ return rawVal.join(", ") || "-";
2494
+ }
2495
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[11px] font-medium bg-slate-100 text-slate-700 border border-slate-200", children: [
2496
+ rawVal.length,
2497
+ " \u05E4\u05E8\u05D9\u05D8\u05D9\u05DD"
2498
+ ] });
2499
+ }
2500
+ if (typeof rawVal === "object" && rawVal !== null) {
2501
+ return "-";
2502
+ }
2503
+ if ((colDef == null ? void 0 : colDef.type) && !(0, import_shared.isTextRepresentable)(colDef.type)) {
2504
+ return "-";
2505
+ }
2506
+ return String(rawVal);
2507
+ }
2508
+ function validateCellValue(val, col) {
2509
+ var _a;
2510
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
2511
+ const isEmpty = val === void 0 || val === null || typeof val === "string" && val.trim() === "";
2512
+ if (col.isRequired && isEmpty) {
2513
+ return {
2514
+ isValid: false,
2515
+ 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.`
2516
+ };
2517
+ }
2518
+ if (isEmpty) {
2519
+ return { isValid: true };
2520
+ }
2521
+ if (colType === "PHONE") {
2522
+ const strVal = String(val).trim();
2523
+ if (!isValidPhoneNumber(strVal)) {
2524
+ return {
2525
+ isValid: false,
2526
+ 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).`
2527
+ };
2528
+ }
2529
+ }
2530
+ if (colType === "NUMBER" || colType === "CURRENCY") {
2531
+ if (typeof val === "string" && isNaN(Number(val))) {
2532
+ return {
2533
+ isValid: false,
2534
+ 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.`
2535
+ };
2536
+ }
2537
+ }
2538
+ return { isValid: true };
2539
+ }
2540
+ function SubTableCell({
2541
+ record,
2542
+ column,
2543
+ targetSchema,
2544
+ referencedTableId,
2545
+ parentRowId,
2546
+ context,
2547
+ relationOptions,
2548
+ setRelationOptions,
2549
+ refetchRelation,
2550
+ onCommit,
2551
+ onQuietUpdate,
2552
+ width
2553
+ }) {
2554
+ var _a, _b, _c, _d, _e;
2555
+ const colType = ((_a = column.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
2556
+ const isContact = colType === "GOOGLE_CONTACT";
2557
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
2558
+ const serverValue = (_b = record.data[column.name]) != null ? _b : colType === "BOOLEAN" ? false : "";
2559
+ const [draftValue, setDraftValue] = (0, import_react11.useState)(serverValue);
2560
+ const [isDirty, setIsDirty] = (0, import_react11.useState)(false);
2561
+ const [validationError, setValidationError] = (0, import_react11.useState)(null);
2562
+ const cellRef = (0, import_react11.useRef)(null);
2563
+ const draftRef = (0, import_react11.useRef)(draftValue);
2564
+ const isDirtyRef = (0, import_react11.useRef)(isDirty);
2565
+ const serverValueRef = (0, import_react11.useRef)(serverValue);
2566
+ const recordIdRef = (0, import_react11.useRef)(record.id);
2567
+ const columnRef = (0, import_react11.useRef)(column);
2568
+ const onCommitRef = (0, import_react11.useRef)(onCommit);
2569
+ const isCommittingRef = (0, import_react11.useRef)(false);
2570
+ const lastFailedValRef = (0, import_react11.useRef)(void 0);
2571
+ const { addToast } = useToast();
2572
+ draftRef.current = draftValue;
2573
+ isDirtyRef.current = isDirty;
2574
+ serverValueRef.current = serverValue;
2575
+ recordIdRef.current = record.id;
2576
+ columnRef.current = column;
2577
+ onCommitRef.current = onCommit;
2578
+ (0, import_react11.useEffect)(() => {
2579
+ if (!isDirtyRef.current) {
2580
+ setDraftValue(serverValue);
2581
+ draftRef.current = serverValue;
2582
+ setValidationError(null);
2583
+ lastFailedValRef.current = void 0;
2584
+ }
2585
+ }, [serverValue]);
2586
+ const commit = (0, import_react11.useCallback)(async (valToCommit) => {
2587
+ if (isCommittingRef.current) return false;
2588
+ if (!isDirtyRef.current) return true;
2589
+ if (valToCommit === serverValueRef.current) {
2590
+ setIsDirty(false);
2591
+ isDirtyRef.current = false;
2592
+ setValidationError(null);
2593
+ lastFailedValRef.current = void 0;
2594
+ return true;
2595
+ }
2596
+ const valRes = validateCellValue(valToCommit, columnRef.current);
2597
+ if (!valRes.isValid) {
2598
+ const errorMsg = valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA";
2599
+ setValidationError(errorMsg);
2600
+ if (lastFailedValRef.current !== valToCommit) {
2601
+ addToast({ type: "error", message: errorMsg });
2602
+ lastFailedValRef.current = valToCommit;
1108
2603
  }
1109
- if (context == null ? void 0 : context.updateQuietly) {
1110
- context.updateQuietly(rowId, column.name, null);
2604
+ return false;
2605
+ }
2606
+ try {
2607
+ isCommittingRef.current = true;
2608
+ const success = await onCommitRef.current(recordIdRef.current, columnRef.current.name, valToCommit);
2609
+ if (success) {
2610
+ setIsDirty(false);
2611
+ isDirtyRef.current = false;
2612
+ serverValueRef.current = valToCommit;
2613
+ setValidationError(null);
2614
+ lastFailedValRef.current = void 0;
2615
+ return true;
1111
2616
  } else {
1112
- onChange(null);
2617
+ setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
2618
+ return false;
1113
2619
  }
1114
- if ((context == null ? void 0 : context.tableId) && (context == null ? void 0 : context.executeAction) && !rowId.startsWith("temp_")) {
1115
- await context.executeAction("UPDATE_RECORD", {
1116
- tableId: context.tableId,
1117
- recordId: rowId,
1118
- data: { [column.name]: null }
1119
- });
2620
+ } catch (e) {
2621
+ setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
2622
+ return false;
2623
+ } finally {
2624
+ isCommittingRef.current = false;
2625
+ }
2626
+ }, [addToast]);
2627
+ const discard = (0, import_react11.useCallback)(() => {
2628
+ setDraftValue(serverValueRef.current);
2629
+ draftRef.current = serverValueRef.current;
2630
+ setIsDirty(false);
2631
+ isDirtyRef.current = false;
2632
+ setValidationError(null);
2633
+ lastFailedValRef.current = void 0;
2634
+ }, []);
2635
+ (0, import_react11.useEffect)(() => {
2636
+ return () => {
2637
+ if (isDirtyRef.current && !isCommittingRef.current) {
2638
+ const val = draftRef.current;
2639
+ const orig = serverValueRef.current;
2640
+ if (val !== orig) {
2641
+ const valRes = validateCellValue(val, columnRef.current);
2642
+ if (valRes.isValid) {
2643
+ onCommitRef.current(recordIdRef.current, columnRef.current.name, val);
2644
+ }
2645
+ }
1120
2646
  }
1121
2647
  };
1122
- if (value && value.synced && value.url) {
1123
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2 h-8 px-2 group", children: [
1124
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { href: value.url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline flex-1 truncate text-sm", children: "\u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05D2\u05D5\u05D2\u05DC" }),
1125
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1126
- "button",
1127
- {
1128
- onClick: handleUnlink,
1129
- className: "text-slate-400 hover:text-rose-500 opacity-0 group-hover:opacity-100 transition-opacity p-1",
1130
- title: "\u05D1\u05D8\u05DC \u05E1\u05E0\u05DB\u05E8\u05D5\u05DF",
1131
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
1132
- }
1133
- )
1134
- ] });
2648
+ }, []);
2649
+ const handleChange = (newVal) => {
2650
+ setDraftValue(newVal);
2651
+ draftRef.current = newVal;
2652
+ setIsDirty(true);
2653
+ isDirtyRef.current = true;
2654
+ if (validationError) {
2655
+ setValidationError(null);
2656
+ lastFailedValRef.current = void 0;
1135
2657
  }
1136
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex items-center h-8 px-2", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1137
- "button",
1138
- {
1139
- onClick: handleSync,
1140
- disabled: isSyncing,
1141
- className: "flex items-center gap-1.5 px-3 py-1 bg-blue-50 text-blue-600 hover:bg-blue-100 border border-blue-200 rounded-md text-xs font-medium transition-colors disabled:opacity-50",
1142
- children: [
1143
- isSyncing ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { className: "w-3.5 h-3.5 animate-spin", viewBox: "0 0 24 24", fill: "none", children: [
1144
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
1145
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
1146
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 4v16m8-8H4" }) }),
1147
- "\u05E1\u05E0\u05DB\u05E8\u05DF \u05DC\u05D2\u05D5\u05D2\u05DC"
1148
- ]
1149
- }
1150
- ) });
1151
- },
1152
- DEFAULT: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1153
- "input",
1154
- {
1155
- type: "text",
1156
- className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
1157
- value: value !== void 0 && value !== null ? String(value) : "",
1158
- onChange: (e) => onChange(e.target.value)
2658
+ if (colType === "BOOLEAN" || colType === "GOOGLE_DRIVE_FILE") {
2659
+ commit(newVal);
1159
2660
  }
1160
- ),
1161
- SUB_TABLE: ({ value, column }) => {
1162
- if (!Array.isArray(value)) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
1163
- const selected = value.filter((e) => e == null ? void 0 : e.isSelected);
1164
- if (selected.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
1165
- const displayFields = column.subTableDisplayFields || [];
1166
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "px-1.5 py-1 flex flex-wrap items-center gap-1 h-full", children: selected.map((entry, idx) => {
1167
- var _a;
1168
- let label = "";
1169
- if (entry._resolvedData && displayFields.length > 0) {
1170
- label = displayFields.map((f) => String(entry._resolvedData[f] || "")).filter(Boolean).join(" ");
2661
+ };
2662
+ const handleBlur = (e) => {
2663
+ if (e.currentTarget.contains(e.relatedTarget)) {
2664
+ return;
2665
+ }
2666
+ if (isDirtyRef.current) {
2667
+ commit(draftRef.current);
2668
+ }
2669
+ };
2670
+ const handleKeyDown = (e) => {
2671
+ var _a2, _b2, _c2, _d2;
2672
+ if (e.key === "Enter") {
2673
+ e.preventDefault();
2674
+ if (isDirtyRef.current) {
2675
+ commit(draftRef.current);
1171
2676
  }
1172
- if (!label) label = ((_a = entry.recordId) == null ? void 0 : _a.slice(-6)) || "...";
1173
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1174
- "span",
2677
+ (_b2 = (_a2 = e.target) == null ? void 0 : _a2.blur) == null ? void 0 : _b2.call(_a2);
2678
+ } else if (e.key === "Escape") {
2679
+ e.preventDefault();
2680
+ discard();
2681
+ (_d2 = (_c2 = e.target) == null ? void 0 : _c2.blur) == null ? void 0 : _d2.call(_c2);
2682
+ }
2683
+ };
2684
+ const subTableMetaId = (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId;
2685
+ const parentTableId = (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId);
2686
+ const effectiveParentRecordId = parentRowId || ((_c = context == null ? void 0 : context.parentRecord) == null ? void 0 : _c.recordId) || ((_d = context == null ? void 0 : context.parentRecord) == null ? void 0 : _d.id) || (context == null ? void 0 : context.rowId);
2687
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2688
+ "td",
2689
+ {
2690
+ ref: cellRef,
2691
+ onBlur: handleBlur,
2692
+ onKeyDown: handleKeyDown,
2693
+ title: validationError || void 0,
2694
+ style: width ? { width, minWidth: width, maxWidth: width } : void 0,
2695
+ className: `border border-slate-200 p-0 relative h-8 transition-colors ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"} ${validationError ? "border-rose-400 ring-1 ring-rose-400 bg-rose-50/20" : ""}`,
2696
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2697
+ InputComponent,
1175
2698
  {
1176
- className: "inline-flex items-center px-1.5 py-0.5 bg-amber-50 text-amber-800 border border-amber-200 rounded-full text-xs font-medium max-w-[140px] truncate",
1177
- title: label,
1178
- children: label
1179
- },
1180
- entry.recordId || idx
1181
- );
1182
- }) });
1183
- }
1184
- };
1185
-
1186
- // src/components/TableBlock/fields/SubTableViewer.tsx
1187
- var import_react6 = require("react");
1188
- var import_jsx_runtime5 = require("react/jsx-runtime");
2699
+ value: draftValue,
2700
+ column,
2701
+ rowId: record.id,
2702
+ onChange: handleChange,
2703
+ context: __spreadProps(__spreadValues({}, context), {
2704
+ 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",
2705
+ relationOptions,
2706
+ updateRelationOptions: (name, opts) => setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [name]: opts })),
2707
+ refetchRelation,
2708
+ parentTableId,
2709
+ parentRecord: {
2710
+ tableId: parentTableId,
2711
+ recordId: effectiveParentRecordId,
2712
+ id: effectiveParentRecordId,
2713
+ data: (context == null ? void 0 : context.rowData) || ((_e = context == null ? void 0 : context.parentRecord) == null ? void 0 : _e.data)
2714
+ },
2715
+ rowData: record.data,
2716
+ tableId: subTableMetaId,
2717
+ tableMetaId: subTableMetaId,
2718
+ recordId: record.id,
2719
+ orgId: context == null ? void 0 : context.orgId,
2720
+ updateQuietly: (rid, colName, val) => {
2721
+ if (onQuietUpdate) {
2722
+ onQuietUpdate(rid, colName, val);
2723
+ } else {
2724
+ onCommitRef.current(rid, colName, val);
2725
+ }
2726
+ }
2727
+ })
2728
+ }
2729
+ )
2730
+ }
2731
+ );
2732
+ }
1189
2733
  function SubTableViewer({ rowId, column, value, onChange, context }) {
1190
- var _a;
2734
+ var _a, _b, _c, _d, _e, _f;
1191
2735
  const { addToast } = useToast();
1192
2736
  const entries = Array.isArray(value) ? value : [];
1193
- const [linkedRecords, setLinkedRecords] = (0, import_react6.useState)([]);
1194
- const [targetSchema, setTargetSchema] = (0, import_react6.useState)(null);
1195
- const [isLoading, setIsLoading] = (0, import_react6.useState)(true);
1196
- const [isSearchOpen, setIsSearchOpen] = (0, import_react6.useState)(false);
1197
- const [searchQuery, setSearchQuery] = (0, import_react6.useState)("");
1198
- const [searchResults, setSearchResults] = (0, import_react6.useState)([]);
1199
- const [isSearching, setIsSearching] = (0, import_react6.useState)(false);
1200
- const [isCreating, setIsCreating] = (0, import_react6.useState)(false);
1201
- const [newRecordData, setNewRecordData] = (0, import_react6.useState)({});
1202
- const searchRef = (0, import_react6.useRef)(null);
1203
- const searchTimerRef = (0, import_react6.useRef)(null);
2737
+ const [linkedRecords, setLinkedRecords] = (0, import_react11.useState)(() => {
2738
+ const initial = [];
2739
+ for (const entry of entries) {
2740
+ if (entry.recordId && entry._resolvedData) {
2741
+ initial.push({ id: entry.recordId, data: entry._resolvedData });
2742
+ }
2743
+ }
2744
+ return initial;
2745
+ });
2746
+ const [targetSchema, setTargetSchema] = (0, import_react11.useState)(null);
2747
+ const [isLoading, setIsLoading] = (0, import_react11.useState)(true);
2748
+ const [isSearchOpen, setIsSearchOpen] = (0, import_react11.useState)(false);
2749
+ const [searchQuery, setSearchQuery] = (0, import_react11.useState)("");
2750
+ const [searchResults, setSearchResults] = (0, import_react11.useState)([]);
2751
+ const [isSearching, setIsSearching] = (0, import_react11.useState)(false);
2752
+ const [isCreating, setIsCreating] = (0, import_react11.useState)(false);
2753
+ const [newRecordData, setNewRecordData] = (0, import_react11.useState)({});
2754
+ const [conflictModalState, setConflictModalState] = (0, import_react11.useState)({
2755
+ isOpen: false,
2756
+ fieldName: "",
2757
+ matchingRecords: []
2758
+ });
2759
+ const searchRef = (0, import_react11.useRef)(null);
2760
+ const searchTimerRef = (0, import_react11.useRef)(null);
1204
2761
  const executeAction = context == null ? void 0 : context.executeAction;
1205
- const referencedTableId = column.referencedTableId;
1206
- const fetchedIdsRef = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
1207
- (0, import_react6.useEffect)(() => {
2762
+ const referencedTableId = ((_a = column.config) == null ? void 0 : _a.referencedTableId) || column.referencedTableId;
2763
+ const fetchedIdsRef = (0, import_react11.useRef)(/* @__PURE__ */ new Set());
2764
+ (0, import_react11.useEffect)(() => {
2765
+ if (entries.length > 0) {
2766
+ setLinkedRecords((prev) => {
2767
+ const existingIds = new Set(prev.map((r) => r.id));
2768
+ const toAdd = [];
2769
+ for (const entry of entries) {
2770
+ if (entry.recordId && entry._resolvedData && !existingIds.has(entry.recordId)) {
2771
+ toAdd.push({ id: entry.recordId, data: entry._resolvedData });
2772
+ existingIds.add(entry.recordId);
2773
+ }
2774
+ }
2775
+ return toAdd.length > 0 ? [...prev, ...toAdd] : prev;
2776
+ });
2777
+ }
2778
+ }, [entries]);
2779
+ (0, import_react11.useEffect)(() => {
1208
2780
  if (!referencedTableId || !executeAction) {
1209
2781
  setIsLoading(false);
1210
2782
  return;
@@ -1231,7 +2803,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1231
2803
  recordIdsToFetch.forEach((id) => fetchedIdsRef.current.delete(id));
1232
2804
  }).finally(() => setIsLoading(false));
1233
2805
  }, [referencedTableId, executeAction, entries, targetSchema]);
1234
- (0, import_react6.useEffect)(() => {
2806
+ (0, import_react11.useEffect)(() => {
1235
2807
  const handleClick = (e) => {
1236
2808
  if (searchRef.current && !searchRef.current.contains(e.target)) {
1237
2809
  setIsSearchOpen(false);
@@ -1240,7 +2812,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1240
2812
  if (isSearchOpen) document.addEventListener("mousedown", handleClick);
1241
2813
  return () => document.removeEventListener("mousedown", handleClick);
1242
2814
  }, [isSearchOpen]);
1243
- const handleSearch = (0, import_react6.useCallback)((query) => {
2815
+ const handleSearch = (0, import_react11.useCallback)((query) => {
1244
2816
  setSearchQuery(query);
1245
2817
  if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
1246
2818
  if (!query.trim()) {
@@ -1266,24 +2838,79 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1266
2838
  }
1267
2839
  }, 300);
1268
2840
  }, [executeAction, referencedTableId, entries]);
1269
- const targetColumns = ((targetSchema == null ? void 0 : targetSchema.columns) || []).filter(
1270
- (c) => {
1271
- if (c.name === "_id" || c.type === "SUB_TABLE") return false;
1272
- return true;
2841
+ const [localColumnOrder, setLocalColumnOrder] = (0, import_react11.useState)(null);
2842
+ (0, import_react11.useEffect)(() => {
2843
+ setLocalColumnOrder(null);
2844
+ }, [column.name, (_b = column.config) == null ? void 0 : _b.subTableColumnOrder]);
2845
+ const rawTargetColumns = (0, import_react11.useMemo)(() => {
2846
+ return ((targetSchema == null ? void 0 : targetSchema.columns) || []).filter(
2847
+ (c) => c.name !== "_id" && c.type !== "SUB_TABLE"
2848
+ );
2849
+ }, [targetSchema == null ? void 0 : targetSchema.columns]);
2850
+ const targetColumns = (0, import_react11.useMemo)(() => {
2851
+ var _a2;
2852
+ const activeOrder = localColumnOrder || ((_a2 = column.config) == null ? void 0 : _a2.subTableColumnOrder);
2853
+ if (!activeOrder || !Array.isArray(activeOrder) || activeOrder.length === 0) {
2854
+ return rawTargetColumns;
1273
2855
  }
1274
- );
1275
- const [relationOptions, setRelationOptions] = (0, import_react6.useState)({});
1276
- (0, import_react6.useEffect)(() => {
1277
- if (!executeAction || targetColumns.length === 0) return;
1278
- const relationCols = targetColumns.filter((c) => {
1279
- var _a2;
1280
- return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION" && c.referencedTableId;
2856
+ const sorted = [...rawTargetColumns];
2857
+ sorted.sort((a, b) => {
2858
+ const idxA = activeOrder.indexOf(a.name);
2859
+ const idxB = activeOrder.indexOf(b.name);
2860
+ if (idxA === -1 && idxB === -1) return 0;
2861
+ if (idxA === -1) return 1;
2862
+ if (idxB === -1) return -1;
2863
+ return idxA - idxB;
2864
+ });
2865
+ return sorted;
2866
+ }, [rawTargetColumns, localColumnOrder, (_c = column.config) == null ? void 0 : _c.subTableColumnOrder]);
2867
+ const handleSubTableColumnReorder = async (draggedName, dropTargetName) => {
2868
+ if (draggedName === dropTargetName) return;
2869
+ const currentNames = targetColumns.map((c) => c.name);
2870
+ const fromIdx = currentNames.indexOf(draggedName);
2871
+ const toIdx = currentNames.indexOf(dropTargetName);
2872
+ if (fromIdx === -1 || toIdx === -1 || fromIdx === toIdx) return;
2873
+ const newOrder = [...currentNames];
2874
+ const [moved] = newOrder.splice(fromIdx, 1);
2875
+ newOrder.splice(toIdx, 0, moved);
2876
+ setLocalColumnOrder(newOrder);
2877
+ if (context == null ? void 0 : context.onUpdateColumnConfig) {
2878
+ try {
2879
+ await context.onUpdateColumnConfig(column.name, {
2880
+ subTableColumnOrder: newOrder
2881
+ });
2882
+ } catch (err) {
2883
+ console.error("[SubTableViewer] Failed to save sub-table column order:", err);
2884
+ }
2885
+ }
2886
+ };
2887
+ const { draggedColName, dragOverColName, getHeaderDragProps } = useColumnReorder({
2888
+ onReorder: handleSubTableColumnReorder,
2889
+ disabled: isLoading
2890
+ });
2891
+ const targetTableId = (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId || column.name;
2892
+ const { columnWidths, startResize } = useColumnResize({
2893
+ storageKey: `table_sub_${targetTableId}_widths`,
2894
+ minWidth: 60,
2895
+ defaultWidth: 150,
2896
+ getMinColWidth: (colName) => {
2897
+ const col = targetColumns.find((c) => c.name === colName);
2898
+ return calculateMinColumnWidth(colName, true, col == null ? void 0 : col.type);
2899
+ }
2900
+ });
2901
+ const [relationOptions, setRelationOptions] = (0, import_react11.useState)({});
2902
+ (0, import_react11.useEffect)(() => {
2903
+ if (!executeAction || !(targetSchema == null ? void 0 : targetSchema.columns) || targetSchema.columns.length === 0) return;
2904
+ const relationCols = targetSchema.columns.filter((c) => {
2905
+ var _a2, _b2;
2906
+ return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION" && ((_b2 = c.config) == null ? void 0 : _b2.referencedTableId);
1281
2907
  });
1282
2908
  relationCols.forEach(async (col) => {
2909
+ var _a2, _b2;
1283
2910
  try {
1284
2911
  const options = await executeAction("FETCH_RELATION", {
1285
- referencedTableId: col.referencedTableId,
1286
- displayField: col.displayField
2912
+ referencedTableId: (_a2 = col.config) == null ? void 0 : _a2.referencedTableId,
2913
+ displayField: (_b2 = col.config) == null ? void 0 : _b2.displayField
1287
2914
  });
1288
2915
  if (options && Array.isArray(options)) {
1289
2916
  setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
@@ -1293,12 +2920,12 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1293
2920
  }
1294
2921
  });
1295
2922
  }, [executeAction, targetColumns]);
1296
- const refetchRelation = (0, import_react6.useCallback)(async (colName) => {
1297
- var _a2;
2923
+ const refetchRelation = (0, import_react11.useCallback)(async (colName) => {
2924
+ var _a2, _b2, _c2;
1298
2925
  const col = targetColumns.find((c) => c.name === colName);
1299
- if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !col.referencedTableId || !executeAction) return;
2926
+ if (!col || ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) !== "RELATION" || !((_b2 = col.config) == null ? void 0 : _b2.referencedTableId) || !executeAction) return;
1300
2927
  try {
1301
- const options = await executeAction("FETCH_RELATION", { referencedTableId: col.referencedTableId, displayField: col.displayField });
2928
+ const options = await executeAction("FETCH_RELATION", { referencedTableId: col.config.referencedTableId, displayField: (_c2 = col.config) == null ? void 0 : _c2.displayField });
1302
2929
  if (options && Array.isArray(options)) {
1303
2930
  setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: options }));
1304
2931
  }
@@ -1329,20 +2956,102 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1329
2956
  }
1330
2957
  }
1331
2958
  };
1332
- const handleLinkRecord = (record) => {
1333
- fetchedIdsRef.current.add(record.id);
1334
- const newEntry = { recordId: record.id, isSelected: true, _resolvedData: record.data };
1335
- const updated = [...entries, newEntry];
1336
- updateParentLinkage(updated);
2959
+ const handleLinkRecords = (recordsToLink) => {
2960
+ if (!recordsToLink || recordsToLink.length === 0) return;
2961
+ const existingEntryIds = new Set(entries.map((e) => e.recordId));
2962
+ const newEntries = [];
2963
+ const newRecordsToAdd = [];
2964
+ for (const record of recordsToLink) {
2965
+ fetchedIdsRef.current.add(record.id);
2966
+ const resolvedData = __spreadValues({}, record.data || {});
2967
+ targetColumns.forEach((col) => {
2968
+ if ((resolvedData[col.name] === void 0 || resolvedData[col.name] === null) && record[col.name] !== void 0) {
2969
+ resolvedData[col.name] = record[col.name];
2970
+ }
2971
+ });
2972
+ if (!existingEntryIds.has(record.id)) {
2973
+ newEntries.push({
2974
+ recordId: record.id,
2975
+ isSelected: true,
2976
+ _resolvedData: resolvedData
2977
+ });
2978
+ existingEntryIds.add(record.id);
2979
+ }
2980
+ newRecordsToAdd.push({
2981
+ id: record.id,
2982
+ data: resolvedData
2983
+ });
2984
+ }
2985
+ const updatedEntries = [...entries, ...newEntries];
2986
+ updateParentLinkage(updatedEntries);
1337
2987
  setLinkedRecords((prev) => {
1338
- const exists = prev.find((r) => r.id === record.id);
1339
- if (exists) return prev;
1340
- return [...prev, record];
2988
+ const map = new Map(prev.map((r) => [r.id, r]));
2989
+ newRecordsToAdd.forEach((r) => {
2990
+ const existing = map.get(r.id);
2991
+ if (existing) {
2992
+ map.set(r.id, __spreadProps(__spreadValues({}, existing), {
2993
+ data: __spreadValues(__spreadValues({}, existing.data), r.data)
2994
+ }));
2995
+ } else {
2996
+ map.set(r.id, r);
2997
+ }
2998
+ });
2999
+ return Array.from(map.values());
1341
3000
  });
1342
3001
  setSearchQuery("");
1343
3002
  setSearchResults([]);
1344
3003
  setIsSearchOpen(false);
1345
3004
  };
3005
+ const handleLinkRecord = (record) => {
3006
+ handleLinkRecords([record]);
3007
+ };
3008
+ const handleUniqueConflict = (conflictData) => {
3009
+ const rawMatching = Array.isArray(conflictData == null ? void 0 : conflictData.matchingRecords) ? conflictData.matchingRecords : [];
3010
+ const resolvedMatching = rawMatching.map((r) => {
3011
+ var _a2;
3012
+ const recordId = String(r.id || ((_a2 = r._id) == null ? void 0 : _a2.$oid) || r._id);
3013
+ let dataObj = {};
3014
+ if (r.data && typeof r.data === "object") {
3015
+ dataObj = __spreadValues({}, r.data);
3016
+ }
3017
+ targetColumns.forEach((col) => {
3018
+ if ((dataObj[col.name] === void 0 || dataObj[col.name] === null) && r[col.name] !== void 0) {
3019
+ dataObj[col.name] = r[col.name];
3020
+ }
3021
+ });
3022
+ return {
3023
+ id: recordId,
3024
+ data: dataObj
3025
+ };
3026
+ });
3027
+ setConflictModalState({
3028
+ isOpen: true,
3029
+ fieldName: (conflictData == null ? void 0 : conflictData.fieldName) || "",
3030
+ matchingRecords: resolvedMatching
3031
+ });
3032
+ };
3033
+ const handleCancelConflict = () => {
3034
+ setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
3035
+ };
3036
+ const handleConfirmLinkConflict = async () => {
3037
+ const { matchingRecords } = conflictModalState;
3038
+ if (matchingRecords && matchingRecords.length > 0) {
3039
+ handleLinkRecords(matchingRecords);
3040
+ setNewRecordData({});
3041
+ setIsCreating(false);
3042
+ setConflictModalState({
3043
+ isOpen: false,
3044
+ fieldName: "",
3045
+ matchingRecords: []
3046
+ });
3047
+ addToast({
3048
+ type: "success",
3049
+ message: "\u05D4\u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D5\u05E9\u05E8\u05D4 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
3050
+ });
3051
+ } else {
3052
+ setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
3053
+ }
3054
+ };
1346
3055
  const handleUnlinkRecord = (recordId) => {
1347
3056
  const updated = entries.filter((e) => e.recordId !== recordId);
1348
3057
  updateParentLinkage(updated);
@@ -1355,37 +3064,109 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1355
3064
  );
1356
3065
  updateParentLinkage(updated);
1357
3066
  };
1358
- const handleRecordCellChange = async (recordId, colName, value2) => {
1359
- const updatedRecords = linkedRecords.map(
1360
- (r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
1361
- );
1362
- setLinkedRecords(updatedRecords);
1363
- const targetRecord = updatedRecords.find((r) => r.id === recordId);
1364
- const updatedEntries = entries.map(
1365
- (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
1366
- );
1367
- if (context == null ? void 0 : context.updateQuietly) {
1368
- context.updateQuietly(rowId, column.name, updatedEntries);
1369
- } else {
1370
- onChange(updatedEntries);
3067
+ const isMountedRef = (0, import_react11.useRef)(true);
3068
+ (0, import_react11.useEffect)(() => {
3069
+ isMountedRef.current = true;
3070
+ return () => {
3071
+ isMountedRef.current = false;
3072
+ };
3073
+ }, []);
3074
+ const handleCommitRecordCell = async (recordId, colName, value2) => {
3075
+ var _a2;
3076
+ const previousRecord = linkedRecords.find((r) => r.id === recordId);
3077
+ const previousValue = (_a2 = previousRecord == null ? void 0 : previousRecord.data) == null ? void 0 : _a2[colName];
3078
+ if (previousValue === value2) return true;
3079
+ const targetCol = targetColumns.find((c) => c.name === colName);
3080
+ const valRes = targetCol ? validateCellValue(value2, targetCol) : { isValid: true };
3081
+ if (!valRes.isValid) {
3082
+ addToast({
3083
+ type: "error",
3084
+ message: valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA"
3085
+ });
3086
+ return false;
1371
3087
  }
1372
3088
  if (executeAction && referencedTableId && !recordId.startsWith("temp_")) {
1373
3089
  try {
1374
- await executeAction("UPDATE_RECORD", {
3090
+ const res = await executeAction("UPDATE_RECORD", {
1375
3091
  tableId: referencedTableId,
3092
+ tableMetaId: referencedTableId,
1376
3093
  recordId,
3094
+ orgId: context == null ? void 0 : context.orgId,
1377
3095
  data: { [colName]: value2 }
1378
3096
  });
1379
- if (context == null ? void 0 : context.triggerSaveSuccess) {
1380
- context.triggerSaveSuccess();
3097
+ if (res && res.success === false) {
3098
+ const err = new Error(res.error || res.message || "Action execution failed");
3099
+ Object.assign(err, res);
3100
+ throw err;
3101
+ }
3102
+ if (isMountedRef.current) {
3103
+ const updatedRecords = linkedRecords.map(
3104
+ (r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
3105
+ );
3106
+ setLinkedRecords(updatedRecords);
3107
+ const targetRecord = updatedRecords.find((r) => r.id === recordId);
3108
+ const updatedEntries = entries.map(
3109
+ (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
3110
+ );
3111
+ if (context == null ? void 0 : context.updateQuietly) {
3112
+ context.updateQuietly(rowId, column.name, updatedEntries);
3113
+ } else {
3114
+ onChange(updatedEntries);
3115
+ }
3116
+ if (context == null ? void 0 : context.triggerSaveSuccess) {
3117
+ context.triggerSaveSuccess();
3118
+ }
1381
3119
  }
3120
+ return true;
1382
3121
  } catch (err) {
1383
3122
  console.error("[SubTableViewer] Failed to auto-save linked record field", err);
3123
+ 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";
3124
+ 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")) {
3125
+ 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).`;
3126
+ } else if (errorMsg.includes("is required") || errorMsg.includes("\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4") || errorMsg.toLowerCase().includes("required")) {
3127
+ 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.`;
3128
+ }
3129
+ addToast({
3130
+ type: "error",
3131
+ message: errorMsg
3132
+ });
3133
+ return false;
3134
+ }
3135
+ } else {
3136
+ if (isMountedRef.current) {
3137
+ const updatedRecords = linkedRecords.map(
3138
+ (r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
3139
+ );
3140
+ setLinkedRecords(updatedRecords);
3141
+ const targetRecord = updatedRecords.find((r) => r.id === recordId);
3142
+ const updatedEntries = entries.map(
3143
+ (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
3144
+ );
3145
+ if (context == null ? void 0 : context.updateQuietly) {
3146
+ context.updateQuietly(rowId, column.name, updatedEntries);
3147
+ } else {
3148
+ onChange(updatedEntries);
3149
+ }
1384
3150
  }
3151
+ return true;
1385
3152
  }
1386
3153
  };
3154
+ const handleRecordCellChange = handleCommitRecordCell;
3155
+ const handleQuietSubTableCellChange = (0, import_react11.useCallback)((recordId, colName, value2) => {
3156
+ setLinkedRecords(
3157
+ (prev) => prev.map((r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r)
3158
+ );
3159
+ const updatedEntries = entries.map(
3160
+ (e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: __spreadProps(__spreadValues({}, e._resolvedData || {}), { [colName]: value2 }) }) : e
3161
+ );
3162
+ if (context == null ? void 0 : context.updateQuietly) {
3163
+ context.updateQuietly(rowId, column.name, updatedEntries);
3164
+ } else {
3165
+ onChange(updatedEntries);
3166
+ }
3167
+ }, [entries, context, rowId, column.name, onChange]);
1387
3168
  const handleCreateRecord = async () => {
1388
- var _a2;
3169
+ var _a2, _b2, _c2, _d2, _e2;
1389
3170
  if (!executeAction || !referencedTableId) return;
1390
3171
  for (const col of targetColumns) {
1391
3172
  if (col.isRequired) {
@@ -1398,16 +3179,32 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1398
3179
  return;
1399
3180
  }
1400
3181
  }
3182
+ if (((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE") {
3183
+ const val = newRecordData[col.name];
3184
+ if (val !== void 0 && val !== null && String(val).trim() !== "" && !isValidPhoneNumber(String(val))) {
3185
+ addToast({
3186
+ type: "error",
3187
+ 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.`
3188
+ });
3189
+ return;
3190
+ }
3191
+ }
1401
3192
  }
1402
3193
  try {
1403
3194
  const res = await executeAction("CREATE_RECORD", {
1404
3195
  tableId: referencedTableId,
3196
+ tableMetaId: referencedTableId,
3197
+ orgId: context == null ? void 0 : context.orgId,
1405
3198
  records: [newRecordData]
1406
3199
  });
3200
+ if (res && (res.error === "UNIQUE_CONSTRAINT_CONFLICT" || res.code === "UNIQUE_CONSTRAINT_CONFLICT")) {
3201
+ handleUniqueConflict(res);
3202
+ return;
3203
+ }
1407
3204
  if (res && res.success === false) {
1408
3205
  throw new Error(res.error || "Action execution failed");
1409
3206
  }
1410
- const created = Array.isArray(res) ? res[0] : ((_a2 = res == null ? void 0 : res.data) == null ? void 0 : _a2[0]) || res;
3207
+ const created = Array.isArray(res) ? res[0] : ((_b2 = res == null ? void 0 : res.data) == null ? void 0 : _b2[0]) || res;
1411
3208
  if (created) {
1412
3209
  const newRecord = {
1413
3210
  id: String(created.id || created._id),
@@ -1418,6 +3215,12 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1418
3215
  setNewRecordData({});
1419
3216
  }
1420
3217
  } catch (err) {
3218
+ const isConflict = (err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" || (err == null ? void 0 : err.code) === "UNIQUE_CONSTRAINT_CONFLICT" || ((_c2 = err == null ? void 0 : err.data) == null ? void 0 : _c2.error) === "UNIQUE_CONSTRAINT_CONFLICT" || ((_d2 = err == null ? void 0 : err.message) == null ? void 0 : _d2.includes("UNIQUE_CONSTRAINT_CONFLICT"));
3219
+ if (isConflict) {
3220
+ const conflictPayload = (err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" ? err : ((_e2 = err == null ? void 0 : err.data) == null ? void 0 : _e2.error) === "UNIQUE_CONSTRAINT_CONFLICT" ? err.data : err;
3221
+ handleUniqueConflict(conflictPayload);
3222
+ return;
3223
+ }
1421
3224
  const msg = (err == null ? void 0 : err.message) || String(err);
1422
3225
  addToast({
1423
3226
  type: "error",
@@ -1426,32 +3229,33 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1426
3229
  }
1427
3230
  };
1428
3231
  const getDisplayLabel = (record) => {
1429
- const fields = column.subTableDisplayFields || [];
3232
+ var _a2;
3233
+ const fields = ((_a2 = column.config) == null ? void 0 : _a2.subTableDisplayFields) || [];
1430
3234
  if (fields.length === 0) {
1431
3235
  const firstField = Object.keys(record.data).find((k) => k !== "_id");
1432
3236
  return firstField ? String(record.data[firstField] || "") : record.id;
1433
3237
  }
1434
3238
  return fields.map((f) => String(record.data[f] || "")).filter(Boolean).join(" ");
1435
3239
  };
1436
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "p-3 animate-in fade-in slide-in-from-top-2 duration-200", dir: "rtl", children: [
1437
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-4 mb-2.5", children: [
1438
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-xs font-bold text-slate-600", children: (_a = targetSchema == null ? void 0 : targetSchema.name) != null ? _a : column.referencedTableName }) }),
1439
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1.5", children: [
1440
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative", ref: searchRef, children: [
1441
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3240
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "p-3 animate-in fade-in slide-in-from-top-2 duration-200", dir: "rtl", children: [
3241
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-4 mb-2.5", children: [
3242
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-xs font-bold text-slate-600", children: (_e = targetSchema == null ? void 0 : targetSchema.name) != null ? _e : (_d = column.config) == null ? void 0 : _d.referencedTableName }) }),
3243
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-1.5", children: [
3244
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "relative", ref: searchRef, children: [
3245
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1442
3246
  "button",
1443
3247
  {
1444
3248
  type: "button",
1445
3249
  onClick: () => setIsSearchOpen((prev) => !prev),
1446
3250
  className: "h-7 px-2.5 text-[11px] font-semibold bg-blue-50 hover:bg-blue-100 text-blue-700 border border-blue-200 rounded-md transition-colors cursor-pointer flex items-center gap-1",
1447
3251
  children: [
1448
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
3252
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }),
1449
3253
  "\u05E7\u05D9\u05E9\u05D5\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA"
1450
3254
  ]
1451
3255
  }
1452
3256
  ),
1453
- isSearchOpen && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "absolute right-0 top-full mt-1 w-72 bg-white border border-slate-200 rounded-lg shadow-xl z-50 p-2", children: [
1454
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3257
+ isSearchOpen && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "absolute right-0 top-full mt-1 w-72 bg-white border border-slate-200 rounded-lg shadow-xl z-50 p-2", children: [
3258
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1455
3259
  "input",
1456
3260
  {
1457
3261
  type: "text",
@@ -1462,7 +3266,7 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1462
3266
  autoFocus: true
1463
3267
  }
1464
3268
  ),
1465
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "max-h-48 overflow-y-auto", children: isSearching ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-4 h-4 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : searchResults.length > 0 ? searchResults.map((r) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3269
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "max-h-48 overflow-y-auto", children: isSearching ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "w-4 h-4 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : searchResults.length > 0 ? searchResults.map((r) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1466
3270
  "button",
1467
3271
  {
1468
3272
  type: "button",
@@ -1471,10 +3275,10 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1471
3275
  children: getDisplayLabel(r)
1472
3276
  },
1473
3277
  r.id
1474
- )) : searchQuery.trim() ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-xs text-slate-400 text-center py-3", children: "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-xs text-slate-400 text-center py-3", children: "\u05D4\u05E7\u05DC\u05D3 \u05DC\u05D7\u05D9\u05E4\u05D5\u05E9..." }) })
3278
+ )) : searchQuery.trim() ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-xs text-slate-400 text-center py-3", children: "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05EA\u05D5\u05E6\u05D0\u05D5\u05EA" }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-xs text-slate-400 text-center py-3", children: "\u05D4\u05E7\u05DC\u05D3 \u05DC\u05D7\u05D9\u05E4\u05D5\u05E9..." }) })
1475
3279
  ] })
1476
3280
  ] }),
1477
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3281
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1478
3282
  "button",
1479
3283
  {
1480
3284
  type: "button",
@@ -1494,24 +3298,69 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1494
3298
  },
1495
3299
  className: "h-7 px-2.5 text-[11px] font-semibold bg-emerald-50 hover:bg-emerald-100 text-emerald-700 border border-emerald-200 rounded-md transition-colors cursor-pointer flex items-center gap-1",
1496
3300
  children: [
1497
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) }),
3301
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3 h-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) }),
1498
3302
  "\u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4"
1499
3303
  ]
1500
3304
  }
1501
3305
  )
1502
3306
  ] })
1503
3307
  ] }),
1504
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-5 h-5 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : entries.length === 0 && !isCreating ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-center py-6 text-xs text-slate-400", children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA. \u05D4\u05E9\u05EA\u05DE\u05E9 \u05D1\u05D7\u05D9\u05E4\u05D5\u05E9 \u05DB\u05D3\u05D9 \u05DC\u05E7\u05E9\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA, \u05D0\u05D5 \u05D4\u05D5\u05E1\u05E3 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4." }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "overflow-x-auto pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { className: "w-full text-xs border-collapse", children: [
1505
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "bg-slate-100/80", children: [
1506
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "border border-slate-200 px-2 py-1.5 text-center w-10 font-semibold text-slate-500", children: "\u05E0\u05D1\u05D7\u05E8" }),
1507
- targetColumns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "border border-slate-200 px-2 py-1.5 text-right font-semibold text-slate-600 whitespace-nowrap", children: col.name }, col.name)),
1508
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "border border-slate-200 px-2 py-1.5 w-14" })
3308
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "w-5 h-5 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : entries.length === 0 && !isCreating ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "text-center py-6 text-xs text-slate-400", children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA. \u05D4\u05E9\u05EA\u05DE\u05E9 \u05D1\u05D7\u05D9\u05E4\u05D5\u05E9 \u05DB\u05D3\u05D9 \u05DC\u05E7\u05E9\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA, \u05D0\u05D5 \u05D4\u05D5\u05E1\u05E3 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4." }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "overflow-x-auto pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("table", { className: "w-full text-xs border-collapse table-auto", children: [
3309
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tr", { className: "bg-slate-100/80 h-12 min-h-[48px]", children: [
3310
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { className: "border border-slate-200 px-2 py-1.5 text-center w-10 font-semibold text-slate-500 h-12 min-h-[48px] align-middle", style: { width: 40, minWidth: 40, maxWidth: 40 }, children: "\u05E0\u05D1\u05D7\u05E8" }),
3311
+ targetColumns.map((col) => {
3312
+ const dragProps = getHeaderDragProps(col.name);
3313
+ const isDragging = draggedColName === col.name;
3314
+ const isDragOver = dragOverColName === col.name;
3315
+ const colMinWidth = calculateMinColumnWidth(col.name, true, col.type);
3316
+ const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 150);
3317
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
3318
+ "th",
3319
+ __spreadProps(__spreadValues({
3320
+ style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
3321
+ title: col.name
3322
+ }, dragProps), {
3323
+ className: `relative border border-slate-200 px-3 py-1.5 font-semibold text-slate-600 select-none cursor-grab active:cursor-grabbing transition-colors h-12 min-h-[48px] align-middle ${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"}`,
3324
+ children: [
3325
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3326
+ "div",
3327
+ {
3328
+ onMouseDown: (e) => {
3329
+ e.preventDefault();
3330
+ e.stopPropagation();
3331
+ startResize(col.name, currentWidth, e.clientX, colMinWidth);
3332
+ },
3333
+ className: "absolute left-0 top-0 bottom-0 w-1.5 cursor-col-resize hover:bg-brand active:bg-brand-hover z-20",
3334
+ title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
3335
+ }
3336
+ ),
3337
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center justify-between gap-1.5 group overflow-hidden w-full", title: col.name, children: [
3338
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ColumnHeaderTitle, { name: col.name, width: currentWidth, isSubTable: true }),
3339
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3340
+ "svg",
3341
+ {
3342
+ className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
3343
+ fill: "none",
3344
+ viewBox: "0 0 24 24",
3345
+ stroke: "currentColor",
3346
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
3347
+ }
3348
+ )
3349
+ ] })
3350
+ ]
3351
+ }),
3352
+ col.name
3353
+ );
3354
+ }),
3355
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { className: "border border-slate-200 px-2 py-1.5 w-14 h-12 min-h-[48px]", style: { width: 56, minWidth: 56, maxWidth: 56 } }),
3356
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("th", { className: "w-full min-w-[50px] border border-slate-200 pointer-events-none h-12 min-h-[48px]" })
1509
3357
  ] }) }),
1510
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tbody", { children: [
3358
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tbody", { children: [
1511
3359
  entries.map((entry) => {
3360
+ var _a2;
1512
3361
  const record = linkedRecords.find((r) => r.id === entry.recordId);
1513
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors", children: [
1514
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-slate-200 px-2 py-1 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3362
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors", children: [
3363
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-slate-200 px-2 py-1 text-center", style: { width: 40, minWidth: 40, maxWidth: 40 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1515
3364
  "input",
1516
3365
  {
1517
3366
  type: "checkbox",
@@ -1521,74 +3370,129 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1521
3370
  }
1522
3371
  ) }),
1523
3372
  targetColumns.map((col) => {
1524
- var _a2, _b;
1525
- const colType = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) || "DEFAULT";
1526
- const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
1527
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-slate-200 p-0 relative h-8", children: record ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1528
- InputComponent,
3373
+ const currentWidth = columnWidths[col.name] || 150;
3374
+ if (!record) {
3375
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3376
+ "td",
3377
+ {
3378
+ style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
3379
+ className: "border border-slate-200 p-0 relative h-8 overflow-hidden",
3380
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-slate-300 italic px-2", children: "\u05D8\u05D5\u05E2\u05DF..." })
3381
+ },
3382
+ col.name
3383
+ );
3384
+ }
3385
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3386
+ SubTableCell,
1529
3387
  {
1530
- value: (_b = record.data[col.name]) != null ? _b : colType === "BOOLEAN" ? false : "",
3388
+ record,
1531
3389
  column: col,
1532
- rowId: record.id,
1533
- onChange: (v) => handleRecordCellChange(record.id, col.name, v),
1534
- context: __spreadProps(__spreadValues({}, context), {
1535
- tableName: (targetSchema == null ? void 0 : targetSchema.name) || (targetSchema == null ? void 0 : targetSchema.tableName) || (targetSchema == null ? void 0 : targetSchema.title) || (targetSchema == null ? void 0 : targetSchema.id) || "Table",
1536
- relationOptions,
1537
- updateRelationOptions: (name, opts) => setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [name]: opts })),
1538
- refetchRelation,
1539
- parentRecord: { tableId: (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId), data: context == null ? void 0 : context.rowData },
1540
- rowData: record.data,
1541
- tableId: targetSchema == null ? void 0 : targetSchema.id,
1542
- updateQuietly: (rid, colName, val) => handleRecordCellChange(rid, colName, val)
1543
- })
1544
- }
1545
- ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-slate-300 italic px-2", children: "\u05D8\u05D5\u05E2\u05DF..." }) }, col.name);
3390
+ targetSchema,
3391
+ referencedTableId,
3392
+ parentRowId: rowId,
3393
+ context,
3394
+ relationOptions,
3395
+ setRelationOptions,
3396
+ refetchRelation,
3397
+ onCommit: handleCommitRecordCell,
3398
+ onQuietUpdate: handleQuietSubTableCellChange,
3399
+ width: currentWidth
3400
+ },
3401
+ `${record.id}_${col.name}`
3402
+ );
1546
3403
  }),
1547
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-slate-200 px-1 py-1 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1548
- "button",
1549
- {
1550
- type: "button",
1551
- onClick: () => handleUnlinkRecord(entry.recordId),
1552
- className: "text-slate-400 hover:text-rose-500 p-0.5 rounded transition-colors cursor-pointer inline-flex items-center justify-center w-full",
1553
- title: "\u05D4\u05E1\u05E8 \u05E7\u05D9\u05E9\u05D5\u05E8",
1554
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
1555
- }
1556
- ) })
3404
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-slate-200 px-1 py-1 text-center", style: { width: 56, minWidth: 56, maxWidth: 56 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center justify-center gap-1", children: [
3405
+ ((_a2 = column.config) == null ? void 0 : _a2.actionType) === "WHATSAPP" && (() => {
3406
+ var _a3, _b2, _c2;
3407
+ const actionPhoneCol = (_a3 = column.config) == null ? void 0 : _a3.actionPhoneColumn;
3408
+ const phone = actionPhoneCol ? ((_b2 = record == null ? void 0 : record.data) == null ? void 0 : _b2[actionPhoneCol]) || ((_c2 = entry._resolvedData) == null ? void 0 : _c2[actionPhoneCol]) : null;
3409
+ if (phone) {
3410
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3411
+ "button",
3412
+ {
3413
+ type: "button",
3414
+ onClick: (e) => {
3415
+ e.stopPropagation();
3416
+ openWhatsAppChat(String(phone));
3417
+ },
3418
+ className: "text-emerald-500 hover:text-emerald-600 p-0.5 rounded hover:bg-emerald-50 transition-colors cursor-pointer",
3419
+ title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
3420
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3.5 h-3.5", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) })
3421
+ }
3422
+ );
3423
+ }
3424
+ return null;
3425
+ })(),
3426
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3427
+ "button",
3428
+ {
3429
+ type: "button",
3430
+ onClick: (e) => {
3431
+ e.stopPropagation();
3432
+ handleUnlinkRecord(entry.recordId);
3433
+ },
3434
+ className: "text-slate-400 hover:text-rose-500 p-0.5 rounded transition-colors cursor-pointer inline-flex items-center justify-center",
3435
+ title: "\u05D4\u05E1\u05E8 \u05E7\u05D9\u05E9\u05D5\u05E8",
3436
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
3437
+ }
3438
+ )
3439
+ ] }) }),
3440
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-slate-200 bg-white pointer-events-none" })
1557
3441
  ] }, entry.recordId);
1558
3442
  }),
1559
- isCreating && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "bg-emerald-50/40", children: [
1560
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-emerald-200 px-2 py-1 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-emerald-500 font-bold text-[10px]", children: "\u05D7\u05D3\u05E9" }) }),
3443
+ isCreating && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("tr", { className: "bg-emerald-50/40", children: [
3444
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-emerald-200 px-2 py-1 text-center", style: { width: 40, minWidth: 40, maxWidth: 40 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-emerald-500 font-bold text-[10px]", children: "\u05D7\u05D3\u05E9" }) }),
1561
3445
  targetColumns.map((col) => {
1562
- var _a2, _b;
3446
+ var _a2, _b2, _c2, _d2, _e2;
1563
3447
  const colType = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) || "DEFAULT";
1564
3448
  const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
1565
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-emerald-200 p-0 relative h-8", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1566
- InputComponent,
3449
+ const currentWidth = columnWidths[col.name] || 150;
3450
+ const effectiveParentId = rowId || ((_b2 = context == null ? void 0 : context.parentRecord) == null ? void 0 : _b2.recordId) || ((_c2 = context == null ? void 0 : context.parentRecord) == null ? void 0 : _c2.id) || (context == null ? void 0 : context.rowId);
3451
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3452
+ "td",
1567
3453
  {
1568
- value: (_b = newRecordData[col.name]) != null ? _b : colType === "BOOLEAN" ? false : "",
1569
- column: col,
1570
- rowId: "new_record",
1571
- onChange: (v) => setNewRecordData((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: v })),
1572
- context: __spreadProps(__spreadValues({}, context), {
1573
- tableName: (targetSchema == null ? void 0 : targetSchema.name) || (targetSchema == null ? void 0 : targetSchema.tableName) || (targetSchema == null ? void 0 : targetSchema.title) || (targetSchema == null ? void 0 : targetSchema.id) || "Table",
1574
- relationOptions,
1575
- refetchRelation
1576
- })
1577
- }
1578
- ) }, `new_${col.name}`);
3454
+ style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
3455
+ className: `border border-emerald-200 p-0 relative h-8 ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
3456
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3457
+ InputComponent,
3458
+ {
3459
+ value: (_d2 = newRecordData[col.name]) != null ? _d2 : colType === "BOOLEAN" ? false : "",
3460
+ column: col,
3461
+ rowId: "new_record",
3462
+ onChange: (v) => setNewRecordData((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: v })),
3463
+ context: __spreadProps(__spreadValues({}, context), {
3464
+ 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",
3465
+ relationOptions,
3466
+ refetchRelation,
3467
+ parentTableId: (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId),
3468
+ parentRecord: {
3469
+ tableId: (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId),
3470
+ recordId: effectiveParentId,
3471
+ id: effectiveParentId,
3472
+ data: (context == null ? void 0 : context.rowData) || ((_e2 = context == null ? void 0 : context.parentRecord) == null ? void 0 : _e2.data)
3473
+ },
3474
+ tableId: targetTableId,
3475
+ tableMetaId: targetTableId,
3476
+ orgId: context == null ? void 0 : context.orgId
3477
+ })
3478
+ }
3479
+ )
3480
+ },
3481
+ `new_${col.name}`
3482
+ );
1579
3483
  }),
1580
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border border-emerald-200 px-1 py-1 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-center gap-1", children: [
1581
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3484
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-emerald-200 px-1 py-1 text-center", style: { width: 56, minWidth: 56, maxWidth: 56 }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center justify-center gap-1", children: [
3485
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1582
3486
  "button",
1583
3487
  {
1584
3488
  type: "button",
1585
3489
  onClick: handleCreateRecord,
1586
3490
  className: "p-1 text-emerald-600 hover:bg-emerald-100 rounded transition-colors",
1587
3491
  title: "\u05E9\u05DE\u05D5\u05E8",
1588
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) })
3492
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) })
1589
3493
  }
1590
3494
  ),
1591
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
3495
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1592
3496
  "button",
1593
3497
  {
1594
3498
  type: "button",
@@ -1597,19 +3501,107 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
1597
3501
  },
1598
3502
  className: "p-1 text-rose-500 hover:bg-rose-100 rounded transition-colors",
1599
3503
  title: "\u05D1\u05D9\u05D8\u05D5\u05DC",
1600
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M6 18L18 6M6 6l12 12" }) })
3504
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M6 18L18 6M6 6l12 12" }) })
1601
3505
  }
1602
3506
  )
1603
- ] }) })
3507
+ ] }) }),
3508
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("td", { className: "border border-emerald-200 bg-emerald-50/40 pointer-events-none" })
1604
3509
  ] })
1605
3510
  ] })
1606
- ] }) })
3511
+ ] }) }),
3512
+ conflictModalState.isOpen && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3513
+ "div",
3514
+ {
3515
+ 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",
3516
+ dir: "rtl",
3517
+ onClick: handleCancelConflict,
3518
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
3519
+ "div",
3520
+ {
3521
+ 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",
3522
+ onClick: (e) => e.stopPropagation(),
3523
+ children: [
3524
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "p-5 border-b border-slate-100 flex items-center gap-3", children: [
3525
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "w-10 h-10 rounded-full bg-blue-50 border border-blue-200 flex items-center justify-center text-blue-600 flex-shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" }) }) }),
3526
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
3527
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h3", { className: "text-base font-bold text-slate-800", children: conflictModalState.matchingRecords.length > 1 ? "\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA \u05D1\u05D8\u05D1\u05DC\u05D4" : "\u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D9\u05D9\u05DE\u05EA \u05D1\u05D8\u05D1\u05DC\u05D4" }),
3528
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-xs text-slate-500", children: "\u05E0\u05DE\u05E6\u05D0\u05D4 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D9\u05D9\u05DE\u05EA \u05E2\u05DD \u05D0\u05D5\u05EA\u05D5 \u05E2\u05E8\u05DA \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9" })
3529
+ ] })
3530
+ ] }),
3531
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "p-5 space-y-3", children: [
3532
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("p", { className: "text-sm text-slate-700 leading-relaxed", children: [
3533
+ "\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",
3534
+ " ",
3535
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "font-bold text-slate-900 bg-slate-100 px-1.5 py-0.5 rounded border border-slate-200", children: conflictModalState.fieldName }),
3536
+ ". \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?"
3537
+ ] }),
3538
+ conflictModalState.matchingRecords.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "p-3 bg-blue-50 border border-blue-200 rounded-lg text-xs font-semibold text-blue-800", children: [
3539
+ "\u05E0\u05DE\u05E6\u05D0\u05D5 ",
3540
+ conflictModalState.matchingRecords.length,
3541
+ " \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?"
3542
+ ] }),
3543
+ conflictModalState.matchingRecords.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "overflow-x-auto border border-slate-200 rounded-lg max-h-48 text-xs bg-white", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("table", { className: "w-full text-right border-collapse", children: [
3544
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tr", { className: "bg-slate-100 text-slate-700 font-semibold border-b whitespace-nowrap", children: (targetColumns.length > 0 ? targetColumns.filter((c) => c.name !== "_id" && c.name !== "id") : Object.keys(((_f = conflictModalState.matchingRecords[0]) == null ? void 0 : _f.data) || {}).filter((k) => k !== "_id" && k !== "id").map((name) => ({ name }))).map((col) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3545
+ "th",
3546
+ {
3547
+ className: "bg-slate-100 text-slate-700 font-semibold p-2 border-b whitespace-nowrap",
3548
+ children: col.name
3549
+ },
3550
+ col.name
3551
+ )) }) }),
3552
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tbody", { children: conflictModalState.matchingRecords.map((r, idx) => {
3553
+ 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 }));
3554
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("tr", { className: "hover:bg-slate-50/80 transition-colors", children: cols.map((col) => {
3555
+ var _a2;
3556
+ const rawVal = (_a2 = r.data) == null ? void 0 : _a2[col.name];
3557
+ const colDef = targetColumns.find((c) => c.name === col.name) || col;
3558
+ const displayVal = formatConflictCellValue(rawVal, colDef, relationOptions || (context == null ? void 0 : context.relationOptions));
3559
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3560
+ "td",
3561
+ {
3562
+ className: "p-2 border-b border-slate-100 whitespace-nowrap text-slate-800",
3563
+ children: displayVal
3564
+ },
3565
+ col.name
3566
+ );
3567
+ }) }, r.id || idx);
3568
+ }) })
3569
+ ] }) })
3570
+ ] }),
3571
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "p-4 bg-slate-50 border-t border-slate-100 flex items-center justify-end gap-2.5", children: [
3572
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3573
+ "button",
3574
+ {
3575
+ type: "button",
3576
+ onClick: handleCancelConflict,
3577
+ 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",
3578
+ children: "\u05D1\u05D9\u05D8\u05D5\u05DC"
3579
+ }
3580
+ ),
3581
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
3582
+ "button",
3583
+ {
3584
+ type: "button",
3585
+ onClick: handleConfirmLinkConflict,
3586
+ 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",
3587
+ children: [
3588
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" }) }),
3589
+ conflictModalState.matchingRecords.length > 1 ? "\u05E7\u05E9\u05E8 \u05D0\u05EA \u05DB\u05D5\u05DC\u05DF" : "\u05E7\u05E9\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D4"
3590
+ ]
3591
+ }
3592
+ )
3593
+ ] })
3594
+ ]
3595
+ }
3596
+ )
3597
+ }
3598
+ )
1607
3599
  ] });
1608
3600
  }
1609
3601
 
1610
3602
  // src/components/TableBlock/TableBlockClient.tsx
1611
- var import_lucide_react4 = require("lucide-react");
1612
- var import_jsx_runtime6 = require("react/jsx-runtime");
3603
+ var import_lucide_react7 = require("lucide-react");
3604
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1613
3605
  function TableBlockClient({
1614
3606
  data: initialRecords,
1615
3607
  settings: schema,
@@ -1626,22 +3618,25 @@ function TableBlockClient({
1626
3618
  "data-testid": dataTestId
1627
3619
  }) {
1628
3620
  const { showError, addToast } = useToast();
1629
- const [columnWidths, setColumnWidths] = (0, import_react7.useState)({});
1630
- const [isMounted, setIsMounted] = (0, import_react7.useState)(false);
1631
3621
  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";
1632
- const [page, setPage] = (0, import_react7.useState)(1);
1633
- const [limit, setLimit] = (0, import_react7.useState)(50);
1634
- const [totalRecords, setTotalRecords] = (0, import_react7.useState)(0);
1635
- const [totalPages, setTotalPages] = (0, import_react7.useState)(1);
1636
- (0, import_react7.useEffect)(() => {
3622
+ const { columnWidths, startResize } = useColumnResize({
3623
+ storageKey: `table_widths_${tableKey}`,
3624
+ minWidth: 60,
3625
+ defaultWidth: 200,
3626
+ getMinColWidth: (colName) => {
3627
+ const col = (localColumns || []).find((c) => c.name === colName);
3628
+ return calculateMinColumnWidth(colName, false, col == null ? void 0 : col.type);
3629
+ }
3630
+ });
3631
+ const [isMounted, setIsMounted] = (0, import_react12.useState)(false);
3632
+ const [isInitialLoading, setIsInitialLoading] = (0, import_react12.useState)(true);
3633
+ const [page, setPage] = (0, import_react12.useState)(1);
3634
+ const [limit, setLimit] = (0, import_react12.useState)(50);
3635
+ const [totalRecords, setTotalRecords] = (0, import_react12.useState)(0);
3636
+ const [totalPages, setTotalPages] = (0, import_react12.useState)(1);
3637
+ const [showSummary, setShowSummary] = (0, import_react12.useState)(false);
3638
+ (0, import_react12.useEffect)(() => {
1637
3639
  if (typeof window !== "undefined") {
1638
- const savedWidths = localStorage.getItem(`table_widths_${tableKey}`);
1639
- if (savedWidths) {
1640
- try {
1641
- setColumnWidths(JSON.parse(savedWidths));
1642
- } catch (e) {
1643
- }
1644
- }
1645
3640
  const savedSummary = localStorage.getItem(`table_summary_${tableKey}`);
1646
3641
  if (savedSummary !== null) {
1647
3642
  setShowSummary(savedSummary === "true");
@@ -1656,7 +3651,6 @@ function TableBlockClient({
1656
3651
  }
1657
3652
  setIsMounted(true);
1658
3653
  }, [tableKey]);
1659
- const [showSummary, setShowSummary] = (0, import_react7.useState)(false);
1660
3654
  const toggleSummary = () => {
1661
3655
  setShowSummary((prev) => {
1662
3656
  const next = !prev;
@@ -1665,29 +3659,6 @@ function TableBlockClient({
1665
3659
  return next;
1666
3660
  });
1667
3661
  };
1668
- const [resizingCol, setResizingCol] = (0, import_react7.useState)(null);
1669
- (0, import_react7.useEffect)(() => {
1670
- if (!resizingCol) return;
1671
- const handleMouseMove = (e) => {
1672
- const diffX = resizingCol.startX - e.clientX;
1673
- const newWidth = Math.max(100, Math.min(500, resizingCol.startWidth + diffX));
1674
- setColumnWidths((prev) => __spreadProps(__spreadValues({}, prev), { [resizingCol.name]: newWidth }));
1675
- };
1676
- const handleMouseUp = () => {
1677
- setResizingCol(null);
1678
- setColumnWidths((prev) => {
1679
- const tableKey2 = (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";
1680
- localStorage.setItem(`table_widths_${tableKey2}`, JSON.stringify(prev));
1681
- return prev;
1682
- });
1683
- };
1684
- document.addEventListener("mousemove", handleMouseMove);
1685
- document.addEventListener("mouseup", handleMouseUp);
1686
- return () => {
1687
- document.removeEventListener("mousemove", handleMouseMove);
1688
- document.removeEventListener("mouseup", handleMouseUp);
1689
- };
1690
- }, [resizingCol, schema]);
1691
3662
  const normalizeRecords = (records) => {
1692
3663
  return (records || []).map((row) => {
1693
3664
  var _c;
@@ -1713,7 +3684,7 @@ function TableBlockClient({
1713
3684
  return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
1714
3685
  });
1715
3686
  };
1716
- const mergeColumnDefs = (0, import_react7.useCallback)((existingCols, incomingCols) => {
3687
+ const mergeColumnDefs = (0, import_react12.useCallback)((existingCols, incomingCols) => {
1717
3688
  if (!incomingCols || incomingCols.length === 0) return existingCols || [];
1718
3689
  if (!existingCols || existingCols.length === 0) return incomingCols;
1719
3690
  const existingMap = new Map(existingCols.map((c) => [c.name, c]));
@@ -1733,18 +3704,18 @@ function TableBlockClient({
1733
3704
  return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
1734
3705
  });
1735
3706
  }, []);
1736
- const [localColumns, setLocalColumns] = (0, import_react7.useState)(() => (schema == null ? void 0 : schema.columns) || []);
1737
- (0, import_react7.useEffect)(() => {
3707
+ const [localColumns, setLocalColumns] = (0, import_react12.useState)(() => (schema == null ? void 0 : schema.columns) || []);
3708
+ (0, import_react12.useEffect)(() => {
1738
3709
  if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
1739
3710
  setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
1740
3711
  }
1741
3712
  }, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
1742
- const [dirty, setDirty] = (0, import_react7.useState)({ added: [], modified: {}, deleted: [] });
1743
- const dirtyRef = (0, import_react7.useRef)(dirty);
1744
- (0, import_react7.useEffect)(() => {
3713
+ const [dirty, setDirty] = (0, import_react12.useState)({ added: [], modified: {}, deleted: [] });
3714
+ const dirtyRef = (0, import_react12.useRef)(dirty);
3715
+ (0, import_react12.useEffect)(() => {
1745
3716
  dirtyRef.current = dirty;
1746
3717
  }, [dirty]);
1747
- const mergeWithDirty = (0, import_react7.useCallback)((baseRecords) => {
3718
+ const mergeWithDirty = (0, import_react12.useCallback)((baseRecords) => {
1748
3719
  const { added, modified, deleted } = dirtyRef.current;
1749
3720
  const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
1750
3721
  const modifiedRecords = nonDeleted.map((r) => {
@@ -1757,10 +3728,13 @@ function TableBlockClient({
1757
3728
  const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
1758
3729
  return [...uniqueAdded, ...modifiedRecords];
1759
3730
  }, []);
1760
- const [data, setData] = (0, import_react7.useState)(() => normalizeRecords(initialRecords));
1761
- (0, import_react7.useEffect)(() => {
3731
+ const [data, setData] = (0, import_react12.useState)(() => normalizeRecords(initialRecords));
3732
+ const [serverRecords, setServerRecords] = (0, import_react12.useState)(() => normalizeRecords(initialRecords));
3733
+ (0, import_react12.useEffect)(() => {
1762
3734
  if (initialRecords) {
1763
- setData(mergeWithDirty(normalizeRecords(initialRecords)));
3735
+ const norm = normalizeRecords(initialRecords);
3736
+ setServerRecords(norm);
3737
+ setData(mergeWithDirty(norm));
1764
3738
  }
1765
3739
  }, [initialRecords, mergeWithDirty]);
1766
3740
  const isEqualValues = (a, b) => {
@@ -1773,19 +3747,19 @@ function TableBlockClient({
1773
3747
  }
1774
3748
  return false;
1775
3749
  };
1776
- const [baseRecordsMap, setBaseRecordsMap] = (0, import_react7.useState)(() => {
3750
+ const [baseRecordsMap, setBaseRecordsMap] = (0, import_react12.useState)(() => {
1777
3751
  const map = /* @__PURE__ */ new Map();
1778
3752
  (normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
1779
3753
  return map;
1780
3754
  });
1781
- (0, import_react7.useEffect)(() => {
3755
+ (0, import_react12.useEffect)(() => {
1782
3756
  if (initialRecords && initialRecords.length > 0) {
1783
3757
  const map = /* @__PURE__ */ new Map();
1784
3758
  (normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
1785
3759
  setBaseRecordsMap(map);
1786
3760
  }
1787
3761
  }, [initialRecords]);
1788
- const refetchTableData = (0, import_react7.useCallback)((targetPage) => {
3762
+ const refetchTableData = (0, import_react12.useCallback)((targetPage) => {
1789
3763
  const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
1790
3764
  if (!tableId || !executeAction) return Promise.resolve();
1791
3765
  const activePage = targetPage !== void 0 ? targetPage : page;
@@ -1801,7 +3775,8 @@ function TableBlockClient({
1801
3775
  const map = /* @__PURE__ */ new Map();
1802
3776
  norm.forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
1803
3777
  setBaseRecordsMap(map);
1804
- setData(norm);
3778
+ setServerRecords(norm);
3779
+ setData(mergeWithDirty(norm));
1805
3780
  }
1806
3781
  if (res.meta) {
1807
3782
  const total = typeof res.meta.totalRecords === "number" ? res.meta.totalRecords : 0;
@@ -1819,9 +3794,22 @@ function TableBlockClient({
1819
3794
  }).catch((err) => {
1820
3795
  console.error("[TableBlock] Failed to auto-fetch table data:", err);
1821
3796
  });
1822
- }, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeColumnDefs]);
1823
- (0, import_react7.useEffect)(() => {
1824
- refetchTableData();
3797
+ }, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeColumnDefs, mergeWithDirty]);
3798
+ (0, import_react12.useEffect)(() => {
3799
+ let isMounted2 = true;
3800
+ const fetchPromise = refetchTableData();
3801
+ if (fetchPromise && typeof fetchPromise.finally === "function") {
3802
+ fetchPromise.finally(() => {
3803
+ if (isMounted2) {
3804
+ setIsInitialLoading(false);
3805
+ }
3806
+ });
3807
+ } else {
3808
+ setIsInitialLoading(false);
3809
+ }
3810
+ return () => {
3811
+ isMounted2 = false;
3812
+ };
1825
3813
  }, [refetchTableData]);
1826
3814
  const handleLimitChange = (newLimit) => {
1827
3815
  setLimit(newLimit);
@@ -1836,31 +3824,50 @@ function TableBlockClient({
1836
3824
  const handleNextPage = () => {
1837
3825
  setPage((prev) => Math.min(totalPages, prev + 1));
1838
3826
  };
1839
- (0, import_react7.useEffect)(() => {
3827
+ (0, import_react12.useEffect)(() => {
1840
3828
  if (error) {
1841
3829
  showError(error, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E8\u05DB\u05D9\u05D1");
1842
3830
  }
1843
3831
  }, [error, showError]);
1844
- const [searchQuery, setSearchQuery] = (0, import_react7.useState)("");
1845
- const [selectedIds, setSelectedIds] = (0, import_react7.useState)(/* @__PURE__ */ new Set());
1846
- const [pendingDeletions, setPendingDeletions] = (0, import_react7.useState)([]);
1847
- const [isSaving, setIsSaving] = (0, import_react7.useState)(false);
1848
- const [isSaveSuccess, setIsSaveSuccess] = (0, import_react7.useState)(false);
1849
- const [relationOptions, setRelationOptions] = (0, import_react7.useState)({});
1850
- const [expandedRowIds, setExpandedRowIds] = (0, import_react7.useState)(/* @__PURE__ */ new Set());
1851
- const schemaColsString = (0, import_react7.useMemo)(() => JSON.stringify(localColumns || []), [localColumns]);
1852
- const refetchRelation = (0, import_react7.useCallback)(async (colName) => {
1853
- var _a;
3832
+ const [searchQuery, setSearchQuery] = (0, import_react12.useState)("");
3833
+ const [columnFilters, setColumnFilters] = (0, import_react12.useState)({});
3834
+ const [activeSearchCol, setActiveSearchCol] = (0, import_react12.useState)(null);
3835
+ const activeSearchRef = (0, import_react12.useRef)(null);
3836
+ (0, import_react12.useEffect)(() => {
3837
+ if (!activeSearchCol) return;
3838
+ const handleMouseDown = (e) => {
3839
+ if (activeSearchRef.current && !activeSearchRef.current.contains(e.target)) {
3840
+ setActiveSearchCol(null);
3841
+ }
3842
+ };
3843
+ document.addEventListener("mousedown", handleMouseDown);
3844
+ return () => {
3845
+ document.removeEventListener("mousedown", handleMouseDown);
3846
+ };
3847
+ }, [activeSearchCol]);
3848
+ const [selectedIds, setSelectedIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
3849
+ const [pendingDeletions, setPendingDeletions] = (0, import_react12.useState)([]);
3850
+ const [isSaving, setIsSaving] = (0, import_react12.useState)(false);
3851
+ const isUpdatingActive = Boolean(isUpdating || isSaving);
3852
+ const [isSaveSuccess, setIsSaveSuccess] = (0, import_react12.useState)(false);
3853
+ const [relationOptions, setRelationOptions] = (0, import_react12.useState)({});
3854
+ const [expandedRowIds, setExpandedRowIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
3855
+ const schemaColsString = (0, import_react12.useMemo)(() => JSON.stringify(localColumns || []), [localColumns]);
3856
+ const refetchRelation = (0, import_react12.useCallback)(async (colName) => {
3857
+ var _a, _b, _c;
1854
3858
  let parsedCols = [];
1855
3859
  try {
1856
3860
  parsedCols = JSON.parse(schemaColsString);
1857
3861
  } catch (e) {
1858
3862
  }
1859
- const col = parsedCols.find((c) => c.name === colName);
1860
- if (!col || ((_a = col.type) == null ? void 0 : _a.toUpperCase()) !== "RELATION" || !col.referencedTableId) return;
3863
+ const col = parsedCols.find((c) => {
3864
+ var _a2;
3865
+ return c.name === colName && ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION";
3866
+ });
3867
+ if (!col || !((_a = col.config) == null ? void 0 : _a.referencedTableId)) return;
1861
3868
  try {
1862
3869
  if (executeAction) {
1863
- const options = await executeAction("FETCH_RELATION", { referencedTableId: col.referencedTableId, displayField: col.displayField });
3870
+ const options = await executeAction("FETCH_RELATION", { referencedTableId: (_b = col.config) == null ? void 0 : _b.referencedTableId, displayField: (_c = col.config) == null ? void 0 : _c.displayField });
1864
3871
  if (options && Array.isArray(options)) {
1865
3872
  setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [colName]: options }));
1866
3873
  }
@@ -1869,7 +3876,7 @@ function TableBlockClient({
1869
3876
  console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
1870
3877
  }
1871
3878
  }, [schemaColsString, executeAction]);
1872
- (0, import_react7.useEffect)(() => {
3879
+ (0, import_react12.useEffect)(() => {
1873
3880
  let parsedCols = [];
1874
3881
  try {
1875
3882
  parsedCols = JSON.parse(schemaColsString);
@@ -1883,7 +3890,7 @@ function TableBlockClient({
1883
3890
  refetchRelation(col.name);
1884
3891
  });
1885
3892
  }, [schemaColsString, refetchRelation]);
1886
- const normalizedColumns = (0, import_react7.useMemo)(() => {
3893
+ const normalizedColumns = (0, import_react12.useMemo)(() => {
1887
3894
  return (localColumns || []).map((col, idx) => {
1888
3895
  const isRequired = col.isRequired === true || String(col.isRequired) === "true";
1889
3896
  const isUnique = col.isUnique === true || String(col.isUnique) === "true";
@@ -1897,17 +3904,17 @@ function TableBlockClient({
1897
3904
  return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
1898
3905
  });
1899
3906
  }, [localColumns]);
1900
- const filteredColumns = (0, import_react7.useMemo)(() => {
3907
+ const filteredColumns = (0, import_react12.useMemo)(() => {
1901
3908
  const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
1902
3909
  return normalizedColumns.filter((col) => !systemFields.includes(col.name) && !col.isHidden);
1903
3910
  }, [normalizedColumns]);
1904
- const customizableColumns = (0, import_react7.useMemo)(() => {
3911
+ const customizableColumns = (0, import_react12.useMemo)(() => {
1905
3912
  const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
1906
3913
  return normalizedColumns.filter((col) => !systemFields.includes(col.name));
1907
3914
  }, [normalizedColumns]);
1908
- const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = (0, import_react7.useState)(false);
1909
- const dropdownRef = (0, import_react7.useRef)(null);
1910
- (0, import_react7.useEffect)(() => {
3915
+ const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = (0, import_react12.useState)(false);
3916
+ const dropdownRef = (0, import_react12.useRef)(null);
3917
+ (0, import_react12.useEffect)(() => {
1911
3918
  const handleClickOutside = (e) => {
1912
3919
  if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
1913
3920
  setIsColumnsDropdownOpen(false);
@@ -1985,8 +3992,6 @@ function TableBlockClient({
1985
3992
  }
1986
3993
  }
1987
3994
  };
1988
- const [draggedColName, setDraggedColName] = (0, import_react7.useState)(null);
1989
- const [dragOverColName, setDragOverColName] = (0, import_react7.useState)(null);
1990
3995
  const handleColumnReorder = async (draggedName, dropTargetName) => {
1991
3996
  var _a;
1992
3997
  if (draggedName === dropTargetName) return;
@@ -2021,6 +4026,43 @@ function TableBlockClient({
2021
4026
  }
2022
4027
  }
2023
4028
  };
4029
+ const { draggedColName, dragOverColName, getHeaderDragProps } = useColumnReorder({
4030
+ onReorder: handleColumnReorder,
4031
+ disabled: isLoading || isUpdatingActive
4032
+ });
4033
+ const handleUpdateColumnConfig = async (columnName, partialConfig) => {
4034
+ var _a;
4035
+ let updatedColumns = [];
4036
+ setLocalColumns((prevCols) => {
4037
+ const nextCols = (prevCols || []).map((col) => {
4038
+ if (col.name === columnName) {
4039
+ return __spreadProps(__spreadValues({}, col), {
4040
+ config: __spreadValues(__spreadValues({}, col.config || {}), partialConfig)
4041
+ });
4042
+ }
4043
+ return col;
4044
+ });
4045
+ updatedColumns = nextCols;
4046
+ return nextCols;
4047
+ });
4048
+ const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
4049
+ if (targetTableId && executeAction && updatedColumns.length > 0) {
4050
+ try {
4051
+ const res = await executeAction("UPDATE_TABLE_COLUMNS", {
4052
+ tableId: targetTableId,
4053
+ tableMetaId: targetTableId,
4054
+ columns: updatedColumns
4055
+ });
4056
+ const returnedCols = (res == null ? void 0 : res.columns) || ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.columns);
4057
+ if (returnedCols && Array.isArray(returnedCols)) {
4058
+ setLocalColumns((prev) => mergeColumnDefs(prev, returnedCols));
4059
+ }
4060
+ } catch (err) {
4061
+ console.error("[TableBlock] Failed to save column config:", err);
4062
+ showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E2\u05D3\u05DB\u05D5\u05DF \u05D4\u05D2\u05D3\u05E8\u05D5\u05EA \u05E2\u05DE\u05D5\u05D3\u05D4");
4063
+ }
4064
+ }
4065
+ };
2024
4066
  const generateTempId = () => `temp_${Math.random().toString(36).substr(2, 9)}`;
2025
4067
  const handleAddRow = () => {
2026
4068
  const defaultData = {};
@@ -2115,13 +4157,13 @@ function TableBlockClient({
2115
4157
  });
2116
4158
  }
2117
4159
  };
2118
- const triggerSaveSuccess = (0, import_react7.useCallback)(() => {
4160
+ const triggerSaveSuccess = (0, import_react12.useCallback)(() => {
2119
4161
  setIsSaveSuccess(true);
2120
4162
  setTimeout(() => {
2121
4163
  setIsSaveSuccess(false);
2122
4164
  }, 2500);
2123
4165
  }, []);
2124
- const handleQuietCellChange = (0, import_react7.useCallback)((rowId, colName, value) => {
4166
+ const handleQuietCellChange = (0, import_react12.useCallback)((rowId, colName, value) => {
2125
4167
  setData((prev) => prev.map(
2126
4168
  (row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
2127
4169
  ));
@@ -2209,7 +4251,7 @@ function TableBlockClient({
2209
4251
  const formatPayload = (payload) => {
2210
4252
  const formatted = {};
2211
4253
  (localColumns || []).forEach((col) => {
2212
- var _a, _b;
4254
+ var _a, _b, _c;
2213
4255
  if (["_id", "id", "createdAt", "updatedAt", "orgId", "tableId", "isSelected"].includes(col.name)) return;
2214
4256
  let val = payload[col.name];
2215
4257
  if (val !== void 0) {
@@ -2219,7 +4261,9 @@ function TableBlockClient({
2219
4261
  if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
2220
4262
  val = val === "" ? 0 : Number(val);
2221
4263
  if (isNaN(val)) val = 0;
2222
- } else if (((_b = col.type) == null ? void 0 : _b.toUpperCase()) === "SUB_TABLE" && Array.isArray(val)) {
4264
+ } else if (((_b = col.type) == null ? void 0 : _b.toUpperCase()) === "PHONE") {
4265
+ val = sanitizePhoneNumber(String(val));
4266
+ } else if (((_c = col.type) == null ? void 0 : _c.toUpperCase()) === "SUB_TABLE" && Array.isArray(val)) {
2223
4267
  val = val.map((item) => {
2224
4268
  const _a2 = item, { _resolvedData } = _a2, rest = __objRest(_a2, ["_resolvedData"]);
2225
4269
  return rest;
@@ -2232,8 +4276,17 @@ function TableBlockClient({
2232
4276
  return formatted;
2233
4277
  };
2234
4278
  const hasChanges = dirty.added.length > 0 || Object.keys(dirty.modified).length > 0 || dirty.deleted.length > 0;
4279
+ const handleRevertChanges = () => {
4280
+ setDirty({ added: [], modified: {}, deleted: [] });
4281
+ setData(serverRecords.map((r) => __spreadProps(__spreadValues({}, r), { data: __spreadValues({}, r.data) })));
4282
+ setSelectedIds(/* @__PURE__ */ new Set());
4283
+ setPendingDeletions([]);
4284
+ if (emitEvent) {
4285
+ emitEvent("SELECTION_CHANGE", { selectedIds: [], componentId });
4286
+ }
4287
+ };
2235
4288
  const handleSave = async () => {
2236
- var _a;
4289
+ var _a, _b;
2237
4290
  if (!hasChanges) {
2238
4291
  return;
2239
4292
  }
@@ -2256,6 +4309,28 @@ function TableBlockClient({
2256
4309
  }
2257
4310
  }
2258
4311
  }
4312
+ const phoneCols = (localColumns || []).filter((c) => {
4313
+ var _a2;
4314
+ return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE";
4315
+ });
4316
+ for (const col of phoneCols) {
4317
+ for (const row of dirty.added) {
4318
+ const val = row.data[col.name];
4319
+ if (!isEmpty(val) && !isValidPhoneNumber(val)) {
4320
+ 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");
4321
+ return;
4322
+ }
4323
+ }
4324
+ for (const [rowId, mods] of Object.entries(dirty.modified)) {
4325
+ const rowData = ((_b = data.find((r) => r.id === rowId)) == null ? void 0 : _b.data) || {};
4326
+ const mergedData = __spreadValues(__spreadValues({}, rowData), mods);
4327
+ const val = mergedData[col.name];
4328
+ if (!isEmpty(val) && !isValidPhoneNumber(val)) {
4329
+ 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");
4330
+ return;
4331
+ }
4332
+ }
4333
+ }
2259
4334
  setIsSaving(true);
2260
4335
  try {
2261
4336
  if (!executeAction) {
@@ -2356,18 +4431,89 @@ function TableBlockClient({
2356
4431
  setIsSaving(false);
2357
4432
  }
2358
4433
  };
2359
- const filteredData = (0, import_react7.useMemo)(() => {
2360
- if (!searchQuery) return data;
2361
- const lowerQuery = searchQuery.toLowerCase();
2362
- return data.filter(
2363
- (row) => (row == null ? void 0 : row.data) && Object.values(row.data).some(
2364
- (val) => String(val != null ? val : "").toLowerCase().includes(lowerQuery)
2365
- )
2366
- );
2367
- }, [data, searchQuery]);
2368
- const isUpdatingActive = Boolean(isUpdating || isSaving);
4434
+ const getRowRelationLabels = (0, import_react12.useCallback)((rowVal, col) => {
4435
+ const ids = normalizeRelationValue(rowVal);
4436
+ if (ids.length === 0) return [];
4437
+ const options = relationOptions[col.name] || [];
4438
+ return ids.map((id) => {
4439
+ const opt = options.find((o) => o.id === id || o._id === id);
4440
+ if (opt) {
4441
+ const resolved = resolveRelationLabel(opt, col);
4442
+ if (resolved) return resolved;
4443
+ if (opt.label) return String(opt.label);
4444
+ if (opt.name) return String(opt.name);
4445
+ }
4446
+ if (typeof rowVal === "object" && rowVal !== null) {
4447
+ if (rowVal._displayLabel) return String(rowVal._displayLabel);
4448
+ if (rowVal.label) return String(rowVal.label);
4449
+ }
4450
+ return id;
4451
+ });
4452
+ }, [relationOptions]);
4453
+ const getUniqueRelationOptions = (0, import_react12.useCallback)((col) => {
4454
+ const seenIds = /* @__PURE__ */ new Set();
4455
+ const results = [];
4456
+ const options = relationOptions[col.name] || [];
4457
+ data.forEach((row) => {
4458
+ if (!(row == null ? void 0 : row.data)) return;
4459
+ const ids = normalizeRelationValue(row.data[col.name]);
4460
+ ids.forEach((id) => {
4461
+ if (!seenIds.has(id)) {
4462
+ seenIds.add(id);
4463
+ const opt = options.find((o) => o.id === id || o._id === id);
4464
+ let label = opt ? resolveRelationLabel(opt, col) : "";
4465
+ if (!label && opt) label = opt.label || opt.name || opt.title || id;
4466
+ if (!label) label = id;
4467
+ results.push({ id, label });
4468
+ }
4469
+ });
4470
+ });
4471
+ return results.sort((a, b) => a.label.localeCompare(b.label));
4472
+ }, [data, relationOptions]);
4473
+ const filteredData = (0, import_react12.useMemo)(() => {
4474
+ const hasGlobalSearch = Boolean(searchQuery && searchQuery.trim() !== "");
4475
+ const activeFilters = Object.entries(columnFilters).filter(([, val]) => Boolean(val && val.trim() !== ""));
4476
+ const hasColumnFilters = activeFilters.length > 0;
4477
+ if (!hasGlobalSearch && !hasColumnFilters) return data;
4478
+ const lowerGlobal = hasGlobalSearch ? searchQuery.trim().toLowerCase() : "";
4479
+ return data.filter((row) => {
4480
+ var _a;
4481
+ if (!row || !row.data) return false;
4482
+ if (hasGlobalSearch) {
4483
+ const matchesGlobal = (localColumns || []).some((col) => {
4484
+ var _a2;
4485
+ const rawVal = row.data[col.name];
4486
+ if (rawVal === void 0 || rawVal === null) return false;
4487
+ if (((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "RELATION") {
4488
+ const labels = getRowRelationLabels(rawVal, col);
4489
+ return labels.some((l) => l.toLowerCase().includes(lowerGlobal));
4490
+ }
4491
+ if (typeof rawVal === "object") {
4492
+ return JSON.stringify(rawVal).toLowerCase().includes(lowerGlobal);
4493
+ }
4494
+ return String(rawVal).toLowerCase().includes(lowerGlobal);
4495
+ });
4496
+ if (!matchesGlobal) return false;
4497
+ }
4498
+ for (const [colName, filterVal] of activeFilters) {
4499
+ const lowerFilter = filterVal.trim().toLowerCase();
4500
+ const col = (localColumns || []).find((c) => c.name === colName);
4501
+ const rawVal = row.data[colName];
4502
+ if (((_a = col == null ? void 0 : col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION") {
4503
+ const labels = getRowRelationLabels(rawVal, col);
4504
+ const matches = labels.some((l) => l.toLowerCase().includes(lowerFilter));
4505
+ if (!matches) return false;
4506
+ } else {
4507
+ if (rawVal === void 0 || rawVal === null) return false;
4508
+ const strVal = typeof rawVal === "object" ? JSON.stringify(rawVal).toLowerCase() : String(rawVal).toLowerCase();
4509
+ if (!strVal.includes(lowerFilter)) return false;
4510
+ }
4511
+ }
4512
+ return true;
4513
+ });
4514
+ }, [data, searchQuery, columnFilters, localColumns, getRowRelationLabels]);
2369
4515
  const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
2370
- const columnTotals = (0, import_react7.useMemo)(() => {
4516
+ const columnTotals = (0, import_react12.useMemo)(() => {
2371
4517
  const totals = {};
2372
4518
  if (!showSummary) return totals;
2373
4519
  filteredColumns.forEach((col) => {
@@ -2385,7 +4531,7 @@ function TableBlockClient({
2385
4531
  });
2386
4532
  return totals;
2387
4533
  }, [filteredData, filteredColumns, showSummary]);
2388
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4534
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2389
4535
  "div",
2390
4536
  {
2391
4537
  id: componentId,
@@ -2393,34 +4539,34 @@ function TableBlockClient({
2393
4539
  className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs min-h-[350px] overflow-hidden ${className}`,
2394
4540
  dir: "rtl",
2395
4541
  children: [
2396
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
2397
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
2398
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: errorMessage })
4542
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2", children: [
4543
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
4544
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: errorMessage })
2399
4545
  ] }) }),
2400
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-3 p-3.5 sm:p-4 bg-slate-50 border-b border-slate-200", children: [
2401
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-center gap-2.5", children: [
2402
- ((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: schema.title || schema.name }) }),
2403
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4546
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-3 p-3.5 sm:p-4 bg-slate-50 border-b border-slate-200", children: [
4547
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-wrap items-center gap-2.5", children: [
4548
+ ((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: schema.title || schema.name }) }),
4549
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2404
4550
  "button",
2405
4551
  {
2406
4552
  onClick: handleAddRow,
2407
- disabled: isLoading || isUpdatingActive,
2408
- className: "w-9 h-9 bg-emerald-600 hover:bg-emerald-700 active:bg-emerald-800 text-white rounded-lg shadow-xs flex items-center justify-center transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
2409
- title: "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
2410
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
4553
+ disabled: isInitialLoading || isLoading || isUpdatingActive,
4554
+ className: `w-9 h-9 text-white rounded-lg shadow-xs flex items-center justify-center transition-all ${isInitialLoading || isLoading || isUpdatingActive ? "bg-emerald-950/80 text-emerald-400/60 pointer-events-none cursor-not-allowed" : "bg-emerald-600 hover:bg-emerald-700 active:bg-emerald-800 cursor-pointer"}`,
4555
+ title: isInitialLoading ? "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." : "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
4556
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
2411
4557
  }
2412
4558
  ),
2413
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4559
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2414
4560
  "button",
2415
4561
  {
2416
4562
  onClick: handleDuplicateRow,
2417
- disabled: isLoading || isUpdatingActive || selectedIds.size !== 1,
4563
+ disabled: isInitialLoading || isLoading || isUpdatingActive || selectedIds.size !== 1,
2418
4564
  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",
2419
4565
  title: "\u05E9\u05DB\u05E4\u05DC \u05E9\u05D5\u05E8\u05D4 \u05E0\u05D1\u05D7\u05E8\u05EA",
2420
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Copy, { className: "w-4 h-4 text-blue-600 shrink-0" })
4566
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.Copy, { className: "w-4 h-4 text-blue-600 shrink-0" })
2421
4567
  }
2422
4568
  ),
2423
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4569
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2424
4570
  "button",
2425
4571
  {
2426
4572
  onClick: handleDeleteSelected,
@@ -2428,12 +4574,12 @@ function TableBlockClient({
2428
4574
  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",
2429
4575
  title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
2430
4576
  children: [
2431
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
2432
- selectedIds.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "absolute -top-1.5 -right-1.5 bg-rose-600 text-white min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs", children: selectedIds.size })
4577
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
4578
+ selectedIds.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "absolute -top-1.5 -right-1.5 bg-rose-600 text-white min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs", children: selectedIds.size })
2433
4579
  ]
2434
4580
  }
2435
4581
  ),
2436
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4582
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2437
4583
  "button",
2438
4584
  {
2439
4585
  onClick: toggleSummary,
@@ -2441,13 +4587,13 @@ function TableBlockClient({
2441
4587
  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"}`,
2442
4588
  title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
2443
4589
  children: [
2444
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
2445
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
4590
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
4591
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
2446
4592
  ]
2447
4593
  }
2448
4594
  ),
2449
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
2450
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4595
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "relative", ref: dropdownRef, children: [
4596
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2451
4597
  "button",
2452
4598
  {
2453
4599
  onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
@@ -2455,16 +4601,16 @@ function TableBlockClient({
2455
4601
  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",
2456
4602
  title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
2457
4603
  children: [
2458
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" }) }),
2459
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: `w-3.5 h-3.5 text-slate-500 transition-transform ${isColumnsDropdownOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
4604
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" }) }),
4605
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: `w-3.5 h-3.5 text-slate-500 transition-transform ${isColumnsDropdownOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
2460
4606
  ]
2461
4607
  }
2462
4608
  ),
2463
- isColumnsDropdownOpen && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "absolute right-0 top-full mt-1.5 w-56 bg-white border border-slate-200 rounded-xl shadow-xl z-50 p-1.5 dir-rtl animate-in fade-in slide-in-from-top-2 duration-150", children: [
2464
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "px-2 py-1.5 text-xs font-bold text-slate-500 border-b border-slate-100 mb-1 flex items-center justify-between", children: [
2465
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2466
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
2467
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-[10px] font-normal text-slate-400", children: [
4609
+ isColumnsDropdownOpen && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "absolute right-0 top-full mt-1.5 w-56 bg-white border border-slate-200 rounded-xl shadow-xl z-50 p-1.5 dir-rtl animate-in fade-in slide-in-from-top-2 duration-150", children: [
4610
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "px-2 py-1.5 text-xs font-bold text-slate-500 border-b border-slate-100 mb-1 flex items-center justify-between", children: [
4611
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1.5", children: [
4612
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
4613
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-[10px] font-normal text-slate-400", children: [
2468
4614
  "(",
2469
4615
  customizableColumns.filter((c) => !c.isHidden).length,
2470
4616
  "/",
@@ -2472,7 +4618,7 @@ function TableBlockClient({
2472
4618
  ")"
2473
4619
  ] })
2474
4620
  ] }),
2475
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4621
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2476
4622
  "button",
2477
4623
  {
2478
4624
  type: "button",
@@ -2482,7 +4628,7 @@ function TableBlockClient({
2482
4628
  }
2483
4629
  )
2484
4630
  ] }),
2485
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
4631
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
2486
4632
  const isRequired = col.isRequired === true || String(col.isRequired) === "true";
2487
4633
  const isUnique = col.isUnique === true || String(col.isUnique) === "true";
2488
4634
  const isProtected = isRequired || isUnique;
@@ -2496,7 +4642,7 @@ function TableBlockClient({
2496
4642
  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";
2497
4643
  }
2498
4644
  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";
2499
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4645
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2500
4646
  "div",
2501
4647
  {
2502
4648
  onClick: () => {
@@ -2507,8 +4653,8 @@ function TableBlockClient({
2507
4653
  title: isProtected ? protectedExplanation : void 0,
2508
4654
  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"}`,
2509
4655
  children: [
2510
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
2511
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4656
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
4657
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2512
4658
  "input",
2513
4659
  {
2514
4660
  type: "checkbox",
@@ -2519,16 +4665,16 @@ function TableBlockClient({
2519
4665
  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"
2520
4666
  }
2521
4667
  ),
2522
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
4668
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
2523
4669
  ] }),
2524
- isProtected && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4670
+ isProtected && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2525
4671
  "div",
2526
4672
  {
2527
4673
  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",
2528
4674
  title: protectedExplanation,
2529
4675
  children: [
2530
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-3 h-3 text-amber-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: "2.2", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }),
2531
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: badgeLabel })
4676
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-3 h-3 text-amber-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: "2.2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }),
4677
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: badgeLabel })
2532
4678
  ]
2533
4679
  }
2534
4680
  )
@@ -2539,9 +4685,9 @@ function TableBlockClient({
2539
4685
  }) })
2540
4686
  ] })
2541
4687
  ] }),
2542
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
2543
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
2544
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4688
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
4689
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
4690
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2545
4691
  "input",
2546
4692
  {
2547
4693
  placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
@@ -2551,129 +4697,224 @@ function TableBlockClient({
2551
4697
  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"
2552
4698
  }
2553
4699
  ),
2554
- searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4700
+ searchQuery ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2555
4701
  "button",
2556
4702
  {
2557
4703
  type: "button",
2558
4704
  onClick: () => setSearchQuery(""),
2559
4705
  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",
2560
4706
  title: "Clear search",
2561
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.X, { className: "w-3.5 h-3.5" })
4707
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.X, { className: "w-3.5 h-3.5" })
2562
4708
  }
2563
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4 h-4 text-slate-400 absolute right-2.5 top-2.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
4709
+ ) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4 h-4 text-slate-400 absolute right-2.5 top-2.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
2564
4710
  ] })
2565
4711
  ] }),
2566
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-3", children: [
2567
- isUpdatingActive ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-xs text-blue-600 font-semibold flex items-center gap-1.5 bg-blue-50 border border-blue-200 px-3 py-1.5 rounded-lg animate-pulse", children: [
2568
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
4712
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-3", children: [
4713
+ isUpdatingActive ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-xs text-blue-600 font-semibold flex items-center gap-1.5 bg-blue-50 border border-blue-200 px-3 py-1.5 rounded-lg animate-pulse", children: [
4714
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
2569
4715
  "\u05DE\u05E2\u05D3\u05DB\u05DF..."
2570
- ] }) : isSaveSuccess ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-xs text-emerald-700 font-semibold flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 px-3 py-1.5 rounded-lg animate-in fade-in duration-200", children: [
2571
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
4716
+ ] }) : isSaveSuccess ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-xs text-emerald-700 font-semibold flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 px-3 py-1.5 rounded-lg animate-in fade-in duration-200", children: [
4717
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
2572
4718
  "\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
2573
- ] }) : hasChanges ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-xs font-semibold text-amber-700 animate-in fade-in", children: "\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5" }) : null,
2574
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4719
+ ] }) : hasChanges ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1.5 animate-in fade-in", children: [
4720
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-xs font-semibold text-amber-700", children: "\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5" }),
4721
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4722
+ "button",
4723
+ {
4724
+ type: "button",
4725
+ onClick: handleRevertChanges,
4726
+ disabled: isUpdatingActive,
4727
+ className: "p-1 text-amber-700 hover:text-amber-900 hover:bg-amber-100/80 active:bg-amber-200/80 rounded-md transition-colors cursor-pointer disabled:opacity-50 disabled:pointer-events-none",
4728
+ title: "\u05D1\u05D8\u05DC \u05D0\u05EA \u05DB\u05DC \u05D4\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5",
4729
+ "aria-label": "\u05D1\u05D8\u05DC \u05D0\u05EA \u05DB\u05DC \u05D4\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5",
4730
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.RotateCcw, { className: "w-3.5 h-3.5" })
4731
+ }
4732
+ )
4733
+ ] }) : null,
4734
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2575
4735
  "button",
2576
4736
  {
2577
4737
  onClick: handleSave,
2578
4738
  disabled: isUpdatingActive || isLoading || !hasChanges,
2579
4739
  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"}`,
2580
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
4740
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
2581
4741
  }
2582
4742
  )
2583
4743
  ] })
2584
4744
  ] }),
2585
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `overflow-x-auto relative min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
2586
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
2587
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
2588
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
4745
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: `overflow-x-auto relative min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
4746
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
4747
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
4748
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
2589
4749
  ] }),
2590
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
2591
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { children: [
2592
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("th", { className: "border-b border-l border-slate-200 p-2.5 w-10 text-center shrink-0", style: { width: 50, minWidth: 50, maxWidth: 50 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2593
- "input",
2594
- {
2595
- type: "checkbox",
2596
- checked: filteredData.length > 0 && selectedIds.size === filteredData.length,
2597
- onChange: (e) => toggleSelectAll(e.target.checked),
2598
- disabled: isLoading || isUpdatingActive,
2599
- className: "w-4 h-4 rounded border-slate-300 text-brand"
2600
- }
2601
- ) }),
4750
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
4751
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tr", { className: "h-12 min-h-[48px]", children: [
4752
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { className: "border-b border-l border-slate-200 p-1.5 text-center shrink-0 h-12 min-h-[48px] align-middle", style: { width: 72, minWidth: 72, maxWidth: 72 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-center gap-1.5", children: [
4753
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4754
+ "input",
4755
+ {
4756
+ type: "checkbox",
4757
+ checked: filteredData.length > 0 && selectedIds.size === filteredData.length,
4758
+ onChange: (e) => toggleSelectAll(e.target.checked),
4759
+ disabled: isLoading || isUpdatingActive,
4760
+ className: "w-4 h-4 rounded border-slate-300 text-brand"
4761
+ }
4762
+ ),
4763
+ filteredColumns.some((c) => {
4764
+ var _a;
4765
+ return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
4766
+ }) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "w-5 h-5 shrink-0" })
4767
+ ] }) }),
2602
4768
  filteredColumns.map((col) => {
2603
- const isDragging = draggedColName === col.name;
2604
- const isDragOver = dragOverColName === col.name;
2605
- const currentWidth = columnWidths[col.name] || 200;
2606
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
4769
+ var _a, _b;
4770
+ const isSearching = activeSearchCol === col.name;
4771
+ const dragProps = isSearching ? {} : getHeaderDragProps(col.name);
4772
+ const isDragging = !isSearching && draggedColName === col.name;
4773
+ const isDragOver = !isSearching && dragOverColName === col.name;
4774
+ const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
4775
+ const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
4776
+ const isRelation = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION";
4777
+ const filterVal = columnFilters[col.name] || "";
4778
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2607
4779
  "th",
2608
- {
4780
+ __spreadProps(__spreadValues({
2609
4781
  style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
2610
- draggable: !isLoading && !isUpdatingActive,
2611
- onDragStart: (e) => {
2612
- e.dataTransfer.setData("text/plain", col.name);
2613
- e.dataTransfer.effectAllowed = "move";
2614
- setDraggedColName(col.name);
2615
- },
2616
- onDragOver: (e) => {
2617
- e.preventDefault();
2618
- e.dataTransfer.dropEffect = "move";
2619
- if (dragOverColName !== col.name) {
2620
- setDragOverColName(col.name);
2621
- }
2622
- },
2623
- onDragLeave: () => {
2624
- if (dragOverColName === col.name) {
2625
- setDragOverColName(null);
2626
- }
2627
- },
2628
- onDrop: (e) => {
2629
- e.preventDefault();
2630
- if (draggedColName && draggedColName !== col.name) {
2631
- handleColumnReorder(draggedColName, col.name);
2632
- }
2633
- setDraggedColName(null);
2634
- setDragOverColName(null);
2635
- },
2636
- onDragEnd: () => {
2637
- setDraggedColName(null);
2638
- setDragOverColName(null);
2639
- },
2640
- className: `relative border-b border-l border-slate-200 px-4 py-2.5 font-semibold text-slate-700 whitespace-nowrap select-none cursor-grab active:cursor-grabbing transition-colors ${isDragging ? "opacity-40 bg-slate-200 border-dashed border-2 border-brand" : ""} ${isDragOver ? "bg-blue-50 border-r-4 border-r-brand text-brand font-bold" : "hover:bg-slate-200/60"}`,
4782
+ title: isSearching ? void 0 : col.name
4783
+ }, dragProps), {
4784
+ className: `relative border-b border-l border-slate-200 px-2.5 py-1.5 font-semibold text-slate-700 select-none transition-colors h-12 min-h-[48px] align-middle ${isSearching ? "cursor-default bg-blue-50/40" : "cursor-grab active:cursor-grabbing hover:bg-slate-200/60"} ${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" : ""}`,
2641
4785
  children: [
2642
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4786
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2643
4787
  "div",
2644
4788
  {
2645
4789
  onMouseDown: (e) => {
2646
4790
  e.preventDefault();
2647
4791
  e.stopPropagation();
2648
- setResizingCol({ name: col.name, startWidth: currentWidth, startX: e.clientX });
4792
+ startResize(col.name, currentWidth, e.clientX, colMinWidth);
2649
4793
  },
2650
4794
  className: "absolute left-0 top-0 bottom-0 w-1.5 cursor-col-resize hover:bg-brand active:bg-brand-hover z-20",
2651
4795
  title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
2652
4796
  }
2653
4797
  ),
2654
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between gap-2 group overflow-hidden", title: "\u05D2\u05E8\u05D5\u05E8 \u05DC\u05E9\u05D9\u05E0\u05D5\u05D9 \u05E1\u05D3\u05E8 \u05D4\u05E2\u05DE\u05D5\u05D3\u05D4", children: [
2655
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: col.name }),
2656
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2657
- "svg",
2658
- {
2659
- className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
2660
- fill: "none",
2661
- viewBox: "0 0 24 24",
2662
- stroke: "currentColor",
2663
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
2664
- }
2665
- )
4798
+ isSearching ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
4799
+ "div",
4800
+ {
4801
+ ref: activeSearchRef,
4802
+ className: "flex items-center gap-1 w-full",
4803
+ onClick: (e) => e.stopPropagation(),
4804
+ onMouseDown: (e) => e.stopPropagation(),
4805
+ children: [
4806
+ isRelation ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative flex items-center w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
4807
+ "select",
4808
+ {
4809
+ autoFocus: true,
4810
+ value: filterVal,
4811
+ onChange: (e) => {
4812
+ const val = e.target.value;
4813
+ setColumnFilters((prev) => {
4814
+ const next = __spreadValues({}, prev);
4815
+ if (val) next[col.name] = val;
4816
+ else delete next[col.name];
4817
+ return next;
4818
+ });
4819
+ },
4820
+ onKeyDown: (e) => {
4821
+ if (e.key === "Escape" || e.key === "Enter") {
4822
+ setActiveSearchCol(null);
4823
+ }
4824
+ },
4825
+ className: "h-7 text-xs px-1.5 w-full rounded border border-blue-400 bg-white text-slate-800 focus:outline-none focus:ring-1 focus:ring-blue-400 cursor-pointer truncate",
4826
+ children: [
4827
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "", children: "\u05D4\u05DB\u05DC" }),
4828
+ getUniqueRelationOptions(col).map((opt) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: opt.label, children: opt.label }, opt.id))
4829
+ ]
4830
+ }
4831
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "relative flex items-center w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4832
+ "input",
4833
+ {
4834
+ autoFocus: true,
4835
+ type: "text",
4836
+ placeholder: `\u05D7\u05E4\u05E9 \u05D1-${col.name}...`,
4837
+ value: filterVal,
4838
+ onChange: (e) => {
4839
+ const val = e.target.value;
4840
+ setColumnFilters((prev) => {
4841
+ const next = __spreadValues({}, prev);
4842
+ if (val) next[col.name] = val;
4843
+ else delete next[col.name];
4844
+ return next;
4845
+ });
4846
+ },
4847
+ onKeyDown: (e) => {
4848
+ if (e.key === "Escape" || e.key === "Enter") {
4849
+ setActiveSearchCol(null);
4850
+ }
4851
+ },
4852
+ className: "h-7 text-xs px-2 w-full rounded border border-blue-400 bg-white text-slate-800 focus:outline-none focus:ring-1 focus:ring-blue-400"
4853
+ }
4854
+ ) }),
4855
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4856
+ "button",
4857
+ {
4858
+ type: "button",
4859
+ onMouseDown: (e) => {
4860
+ e.preventDefault();
4861
+ e.stopPropagation();
4862
+ },
4863
+ onClick: (e) => {
4864
+ e.stopPropagation();
4865
+ setColumnFilters((prev) => {
4866
+ const next = __spreadValues({}, prev);
4867
+ delete next[col.name];
4868
+ return next;
4869
+ });
4870
+ setActiveSearchCol(null);
4871
+ },
4872
+ className: "p-1 text-slate-400 hover:text-slate-700 hover:bg-slate-200/70 rounded transition-colors cursor-pointer shrink-0",
4873
+ title: "\u05E0\u05E7\u05D4 \u05D5\u05E1\u05D2\u05D5\u05E8 \u05D7\u05D9\u05E4\u05D5\u05E9",
4874
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.X, { className: "w-3.5 h-3.5" })
4875
+ }
4876
+ )
4877
+ ]
4878
+ }
4879
+ ) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between gap-1.5 group overflow-hidden w-full", title: col.name, children: [
4880
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex items-center gap-1.5 min-w-0 flex-1 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ColumnHeaderTitle, { name: col.name, width: currentWidth, isSubTable: false }) }),
4881
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1 shrink-0", children: [
4882
+ ((_b = col.type) == null ? void 0 : _b.toUpperCase()) !== "SUB_TABLE" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4883
+ "button",
4884
+ {
4885
+ type: "button",
4886
+ onClick: (e) => {
4887
+ e.stopPropagation();
4888
+ e.preventDefault();
4889
+ setActiveSearchCol(col.name);
4890
+ },
4891
+ className: `p-1 rounded transition-all cursor-pointer ${filterVal ? "opacity-100 text-blue-600 bg-blue-100 hover:bg-blue-200" : "opacity-0 group-hover:opacity-100 text-slate-400 hover:text-slate-600 hover:bg-slate-200/60"}`,
4892
+ title: filterVal ? `\u05DE\u05E1\u05D5\u05E0\u05DF \u05DC\u05E4\u05D9: "${filterVal}" (\u05DC\u05D7\u05E5 \u05DC\u05E2\u05E8\u05D9\u05DB\u05D4)` : "\u05D7\u05E4\u05E9 \u05D5\u05E1\u05E0\u05DF \u05D1\u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5",
4893
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react7.Search, { className: "w-3.5 h-3.5" })
4894
+ }
4895
+ ),
4896
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4897
+ "svg",
4898
+ {
4899
+ className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
4900
+ fill: "none",
4901
+ viewBox: "0 0 24 24",
4902
+ stroke: "currentColor",
4903
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
4904
+ }
4905
+ )
4906
+ ] })
2666
4907
  ] })
2667
4908
  ]
2668
- },
4909
+ }),
2669
4910
  col.name
2670
4911
  );
2671
4912
  }),
2672
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none" })
4913
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none h-12 min-h-[48px]" })
2673
4914
  ] }) }),
2674
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col items-center justify-center gap-2", children: [
2675
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }),
2676
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
4915
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col items-center justify-center gap-2", children: [
4916
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }),
4917
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
2677
4918
  ] }) }) }) : filteredData.map((row) => {
2678
4919
  const hasSubTableCols = filteredColumns.some((c) => {
2679
4920
  var _a;
@@ -2684,10 +4925,20 @@ function TableBlockClient({
2684
4925
  var _a;
2685
4926
  return ((_a = c.type) == null ? void 0 : _a.toUpperCase()) === "SUB_TABLE";
2686
4927
  });
2687
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react7.default.Fragment, { children: [
2688
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
2689
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-center gap-1", children: [
2690
- hasSubTableCols && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
4928
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react12.default.Fragment, { children: [
4929
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
4930
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", style: { width: 72, minWidth: 72, maxWidth: 72 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-center gap-1.5", children: [
4931
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4932
+ "input",
4933
+ {
4934
+ type: "checkbox",
4935
+ checked: selectedIds.has(row.id),
4936
+ onChange: (e) => toggleSelectRow(row.id, e.target.checked),
4937
+ disabled: isLoading || isUpdatingActive,
4938
+ className: "w-4 h-4 rounded border-slate-300 text-brand"
4939
+ }
4940
+ ),
4941
+ hasSubTableCols && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2691
4942
  "button",
2692
4943
  {
2693
4944
  type: "button",
@@ -2697,19 +4948,9 @@ function TableBlockClient({
2697
4948
  else next.add(row.id);
2698
4949
  return next;
2699
4950
  }),
2700
- className: "text-slate-400 hover:text-blue-600 p-0.5 rounded transition-colors cursor-pointer",
4951
+ className: "w-5 h-5 rounded-full bg-slate-500 hover:bg-slate-600 text-white flex items-center justify-center transition-colors cursor-pointer shrink-0 shadow-sm",
2701
4952
  title: isExpanded ? "\u05E1\u05D2\u05D5\u05E8 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4" : "\u05E4\u05EA\u05D7 \u05EA\u05EA-\u05D8\u05D1\u05DC\u05D4",
2702
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { className: `w-3.5 h-3.5 transition-transform duration-150 ${isExpanded ? "rotate-90" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 5l7 7-7 7" }) })
2703
- }
2704
- ),
2705
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2706
- "input",
2707
- {
2708
- type: "checkbox",
2709
- checked: selectedIds.has(row.id),
2710
- onChange: (e) => toggleSelectRow(row.id, e.target.checked),
2711
- disabled: isLoading || isUpdatingActive,
2712
- className: "w-4 h-4 rounded border-slate-300 text-brand"
4953
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: `w-3 h-3 transition-transform duration-150 ${isExpanded ? "rotate-90" : "rotate-180"}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "3", d: "M9 5l7 7-7 7" }) })
2713
4954
  }
2714
4955
  )
2715
4956
  ] }) }),
@@ -2717,6 +4958,8 @@ function TableBlockClient({
2717
4958
  var _a;
2718
4959
  const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
2719
4960
  const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
4961
+ const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
4962
+ const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
2720
4963
  let value = (row == null ? void 0 : row.data) ? row.data[col.name] : void 0;
2721
4964
  if (value === void 0 && col.defaultValue !== void 0) {
2722
4965
  value = colType === "CURRENCY" || colType === "NUMBER" ? parseFloat(col.defaultValue) : col.defaultValue;
@@ -2725,34 +4968,42 @@ function TableBlockClient({
2725
4968
  }
2726
4969
  }
2727
4970
  if (value === void 0) value = null;
2728
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-l border-slate-200 p-0 relative", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2729
- InputComponent,
4971
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4972
+ "td",
2730
4973
  {
2731
- value,
2732
- column: col,
2733
- rowId: row.id,
2734
- onChange: (v) => handleCellChange(row.id, col.name, v),
2735
- context: {
2736
- tableName: (schema == null ? void 0 : schema.name) || (schema == null ? void 0 : schema.tableName) || (schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.id) || "Table",
2737
- tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
2738
- onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
2739
- relationOptions,
2740
- refetchRelation,
2741
- executeAction,
2742
- emitEvent,
2743
- pageState,
2744
- componentId,
2745
- orgId,
2746
- updateQuietly: handleQuietCellChange,
2747
- triggerSaveSuccess,
2748
- rowData: row.data
2749
- }
2750
- }
2751
- ) }, col.name);
4974
+ className: `border-b border-l border-slate-200 p-0 relative ${colType === "RELATION" ? "overflow-visible" : "overflow-hidden"}`,
4975
+ style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
4976
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
4977
+ InputComponent,
4978
+ {
4979
+ value,
4980
+ column: col,
4981
+ rowId: row.id,
4982
+ onChange: (v) => handleCellChange(row.id, col.name, v),
4983
+ context: {
4984
+ 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",
4985
+ tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
4986
+ onMarkForDeletion: (fileId) => setPendingDeletions((prev) => [...prev, fileId]),
4987
+ relationOptions,
4988
+ refetchRelation,
4989
+ executeAction,
4990
+ emitEvent,
4991
+ pageState,
4992
+ componentId,
4993
+ orgId,
4994
+ updateQuietly: handleQuietCellChange,
4995
+ triggerSaveSuccess,
4996
+ rowData: row.data
4997
+ }
4998
+ }
4999
+ )
5000
+ },
5001
+ col.name
5002
+ );
2752
5003
  }),
2753
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
5004
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
2754
5005
  ] }),
2755
- isExpanded && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5006
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2756
5007
  ExpandedSubTables,
2757
5008
  {
2758
5009
  rowId: row.id,
@@ -2767,37 +5018,38 @@ function TableBlockClient({
2767
5018
  tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
2768
5019
  rowData: row.data,
2769
5020
  updateQuietly: handleQuietCellChange,
2770
- triggerSaveSuccess
5021
+ triggerSaveSuccess,
5022
+ onUpdateColumnConfig: handleUpdateColumnConfig
2771
5023
  }
2772
5024
  }
2773
5025
  )
2774
5026
  ] }, row.id);
2775
5027
  }) }),
2776
- showSummary && filteredData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tfoot", { className: "bg-slate-50 border-t-2 border-slate-300 sticky bottom-0 z-10 shadow-[0_-2px_4px_rgba(0,0,0,0.02)]", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("tr", { children: [
2777
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center font-bold text-slate-600 text-xs", children: '\u05E1\u05D4"\u05DB' }),
5028
+ showSummary && filteredData.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tfoot", { className: "bg-slate-50 border-t-2 border-slate-300 sticky bottom-0 z-10 shadow-[0_-2px_4px_rgba(0,0,0,0.02)]", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("tr", { children: [
5029
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center font-bold text-slate-600 text-xs", children: '\u05E1\u05D4"\u05DB' }),
2778
5030
  filteredColumns.map((col) => {
2779
- var _a;
5031
+ var _a, _b;
2780
5032
  const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
2781
5033
  const isNumeric = typeUpper === "CURRENCY" || typeUpper === "NUMBER";
2782
5034
  const total = columnTotals[col.name];
2783
5035
  let displayVal = "";
2784
5036
  if (isNumeric && total !== void 0) {
2785
5037
  displayVal = new Intl.NumberFormat("en-US").format(total);
2786
- if (typeUpper === "CURRENCY") {
2787
- const symbol = getCurrencySymbol(col.currencySymbol);
5038
+ if (col.type === "CURRENCY") {
5039
+ const symbol = getCurrencySymbol((_b = col.config) == null ? void 0 : _b.currencySymbol);
2788
5040
  displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
2789
5041
  }
2790
5042
  }
2791
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-l border-slate-200 p-2 text-sm font-semibold text-slate-700 bg-slate-50 relative", children: isNumeric && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: displayVal }) }) }, col.name);
5043
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "border-b border-l border-slate-200 p-2 text-sm font-semibold text-slate-700 bg-slate-50 relative", children: isNumeric && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "truncate", children: displayVal }) }) }, col.name);
2792
5044
  }),
2793
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
5045
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
2794
5046
  ] }) })
2795
5047
  ] })
2796
5048
  ] }),
2797
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-3 px-4 py-3 bg-slate-50 border-t border-slate-200 text-xs text-slate-600 rounded-b-xl", children: [
2798
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
2799
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
2800
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
5049
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-3 px-4 py-3 bg-slate-50 border-t border-slate-200 text-xs text-slate-600 rounded-b-xl", children: [
5050
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2", children: [
5051
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
5052
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2801
5053
  "select",
2802
5054
  {
2803
5055
  value: limit,
@@ -2805,27 +5057,27 @@ function TableBlockClient({
2805
5057
  disabled: isLoading || isUpdatingActive,
2806
5058
  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",
2807
5059
  children: [
2808
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: 20, children: "20" }),
2809
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: 50, children: "50" }),
2810
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: 100, children: "100" })
5060
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: 20, children: "20" }),
5061
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: 50, children: "50" }),
5062
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: 100, children: "100" })
2811
5063
  ]
2812
5064
  }
2813
5065
  )
2814
5066
  ] }),
2815
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-4", children: [
2816
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-medium text-slate-600", children: [
5067
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-4", children: [
5068
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-medium text-slate-600", children: [
2817
5069
  "\u05E2\u05DE\u05D5\u05D3 ",
2818
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { className: "text-slate-900", children: page }),
5070
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { className: "text-slate-900", children: page }),
2819
5071
  " \u05DE\u05EA\u05D5\u05DA ",
2820
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { className: "text-slate-900", children: totalPages || 1 }),
2821
- totalRecords > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-slate-500 font-normal", children: [
5072
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { className: "text-slate-900", children: totalPages || 1 }),
5073
+ totalRecords > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-slate-500 font-normal", children: [
2822
5074
  " (",
2823
5075
  totalRecords,
2824
5076
  ' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
2825
5077
  ] })
2826
5078
  ] }),
2827
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2828
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5079
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1.5", children: [
5080
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2829
5081
  "button",
2830
5082
  {
2831
5083
  onClick: handlePrevPage,
@@ -2835,7 +5087,7 @@ function TableBlockClient({
2835
5087
  children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
2836
5088
  }
2837
5089
  ),
2838
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5090
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2839
5091
  "button",
2840
5092
  {
2841
5093
  onClick: handleNextPage,
@@ -2861,11 +5113,11 @@ function ExpandedSubTables({
2861
5113
  context
2862
5114
  }) {
2863
5115
  var _a;
2864
- const [activeTab, setActiveTab] = (0, import_react7.useState)((_a = subTableColumns[0]) == null ? void 0 : _a.name);
5116
+ const [activeTab, setActiveTab] = (0, import_react12.useState)((_a = subTableColumns[0]) == null ? void 0 : _a.name);
2865
5117
  if (subTableColumns.length === 0) return null;
2866
5118
  if (subTableColumns.length === 1) {
2867
5119
  const stCol = subTableColumns[0];
2868
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5120
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2869
5121
  SubTableViewer,
2870
5122
  {
2871
5123
  rowId,
@@ -2877,8 +5129,8 @@ function ExpandedSubTables({
2877
5129
  ) }) });
2878
5130
  }
2879
5131
  const activeCol = subTableColumns.find((c) => c.name === activeTab) || subTableColumns[0];
2880
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50 overflow-hidden", children: [
2881
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex border-b border-slate-200 bg-slate-100/50 px-2 pt-2 gap-1 overflow-hidden", children: subTableColumns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5132
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("td", { colSpan: filteredColumnsLength + 2, className: "p-0 border-b border-slate-200 bg-slate-50/50 overflow-hidden", children: [
5133
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex border-b border-slate-200 bg-slate-100/50 px-2 pt-2 gap-1 overflow-hidden", children: subTableColumns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2882
5134
  "button",
2883
5135
  {
2884
5136
  type: "button",
@@ -2888,7 +5140,7 @@ function ExpandedSubTables({
2888
5140
  },
2889
5141
  col.name
2890
5142
  )) }),
2891
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "bg-white", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
5143
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "bg-white", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2892
5144
  SubTableViewer,
2893
5145
  {
2894
5146
  rowId,
@@ -2903,9 +5155,9 @@ function ExpandedSubTables({
2903
5155
  }
2904
5156
 
2905
5157
  // src/components/TableBlock/TableBlock.tsx
2906
- var import_jsx_runtime7 = require("react/jsx-runtime");
5158
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2907
5159
  function TableBlock(props) {
2908
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableBlockClient, __spreadValues({}, props));
5160
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(TableBlockClient, __spreadValues({}, props));
2909
5161
  }
2910
5162
 
2911
5163
  // src/registry.ts
@@ -2914,10 +5166,31 @@ var UNIVERSE_COMPONENTS = {
2914
5166
  };
2915
5167
  // Annotate the CommonJS export names for ESM import in node:
2916
5168
  0 && (module.exports = {
5169
+ ColumnHeaderTitle,
5170
+ DatePickerCell,
5171
+ LinkPickerCell,
5172
+ PASTEL_PALETTES,
5173
+ RelationPickerCell,
2917
5174
  TableBlock,
5175
+ TimePickerCell,
2918
5176
  ToastContext,
2919
5177
  ToastProvider,
2920
5178
  UNIVERSE_COMPONENTS,
5179
+ calculateMinColumnWidth,
2921
5180
  cn,
5181
+ formatConflictCellValue,
5182
+ formatPhoneDisplay,
5183
+ formatTimeInput,
5184
+ formatTimeIso,
5185
+ getDeterministicPastelBadge,
5186
+ measureTextWidth,
5187
+ normalizeRelationValue,
5188
+ openWhatsAppChat,
5189
+ parseLinkValue,
5190
+ parseTimeParts,
5191
+ resolveProtocol,
5192
+ splitHeaderTitle,
5193
+ useColumnReorder,
5194
+ useColumnResize,
2922
5195
  useToast
2923
5196
  });