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