@universe-platform/ui 0.1.0-beta.31 → 0.1.0-beta.32

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
@@ -286,18 +286,18 @@ function getStatusConfig(rawStatus) {
286
286
  isSelectable: false
287
287
  };
288
288
  }
289
- function reindexVariables(text) {
290
- if (!text) return "";
289
+ function reindexVariables(text2) {
290
+ if (!text2) return "";
291
291
  let counter = 1;
292
- return text.replace(/\{\{\s*\d+\s*\}\}/g, () => {
292
+ return text2.replace(/\{\{\s*\d+\s*\}\}/g, () => {
293
293
  const replacement = `{{${counter}}}`;
294
294
  counter++;
295
295
  return replacement;
296
296
  });
297
297
  }
298
- function seamlessVariableEngine(text) {
299
- if (!text) return "";
300
- let result = text;
298
+ function seamlessVariableEngine(text2) {
299
+ if (!text2) return "";
300
+ let result = text2;
301
301
  result = result.replace(/\{\{([^}]*)\}\}/g, (_match, inner) => {
302
302
  const digits = inner.replace(/\D/g, "");
303
303
  if (!digits) return "";
@@ -360,40 +360,40 @@ function isDuplicateTemplateName(name, existingNames = [], language) {
360
360
  return false;
361
361
  });
362
362
  }
363
- function hasBracketSpaces(text) {
364
- if (!text) return false;
365
- return /\{\s+\{|\}\s+\}|\{\{\s+\d+|\d+\s+\}\}/.test(text);
363
+ function hasBracketSpaces(text2) {
364
+ if (!text2) return false;
365
+ return /\{\s+\{|\}\s+\}|\{\{\s+\d+|\d+\s+\}\}/.test(text2);
366
366
  }
367
- function hasConsecutiveVariables(text) {
368
- if (!text) return false;
369
- return /\{\{\s*\d+\s*\}\}\{\{\s*\d+\s*\}\}/.test(text);
367
+ function hasConsecutiveVariables(text2) {
368
+ if (!text2) return false;
369
+ return /\{\{\s*\d+\s*\}\}\{\{\s*\d+\s*\}\}/.test(text2);
370
370
  }
371
- function extractVariableIndices(text) {
372
- if (!text) return [];
373
- const matches = text.match(/\{\{\s*(\d+)\s*\}\}/g) || [];
371
+ function extractVariableIndices(text2) {
372
+ if (!text2) return [];
373
+ const matches = text2.match(/\{\{\s*(\d+)\s*\}\}/g) || [];
374
374
  return matches.map((m) => parseInt(m.replace(/[\{\}\s]/g, ""), 10));
375
375
  }
376
- function extractUniqueVariableIndices(text) {
377
- if (!text) return [];
378
- const indices = extractVariableIndices(text);
376
+ function extractUniqueVariableIndices(text2) {
377
+ if (!text2) return [];
378
+ const indices = extractVariableIndices(text2);
379
379
  return Array.from(new Set(indices)).sort((a, b) => a - b);
380
380
  }
381
- function getNextVariableIndex(text) {
382
- const indices = extractVariableIndices(text);
381
+ function getNextVariableIndex(text2) {
382
+ const indices = extractVariableIndices(text2);
383
383
  if (indices.length === 0) return 1;
384
384
  return Math.max(...indices) + 1;
385
385
  }
386
386
  function isWordToken(token) {
387
387
  return /[\p{L}\p{N}]/u.test(token);
388
388
  }
389
- function hasFloatingVariables(text) {
389
+ function hasFloatingVariables(text2) {
390
390
  var _a, _b;
391
- if (!text) return { hasFloating: false };
392
- const varMatches = Array.from(text.matchAll(/\{\{\s*\d+\s*\}\}/g));
391
+ if (!text2) return { hasFloating: false };
392
+ const varMatches = Array.from(text2.matchAll(/\{\{\s*\d+\s*\}\}/g));
393
393
  if (varMatches.length === 0) return { hasFloating: false };
394
394
  const firstMatch = varMatches[0];
395
395
  const lastMatch = varMatches[varMatches.length - 1];
396
- const beforeText = text.slice(0, (_a = firstMatch.index) != null ? _a : 0);
396
+ const beforeText = text2.slice(0, (_a = firstMatch.index) != null ? _a : 0);
397
397
  const wordsBefore = beforeText.trim().split(/\s+/).filter(isWordToken);
398
398
  if (wordsBefore.length === 0) {
399
399
  return {
@@ -402,7 +402,7 @@ function hasFloatingVariables(text) {
402
402
  };
403
403
  }
404
404
  const lastMatchEnd = ((_b = lastMatch.index) != null ? _b : 0) + lastMatch[0].length;
405
- const afterText = text.slice(lastMatchEnd);
405
+ const afterText = text2.slice(lastMatchEnd);
406
406
  const wordsAfter = afterText.trim().split(/\s+/).filter(isWordToken);
407
407
  if (wordsAfter.length === 0) {
408
408
  return {
@@ -412,17 +412,17 @@ function hasFloatingVariables(text) {
412
412
  }
413
413
  return { hasFloating: false };
414
414
  }
415
- function hasInsufficientContextBetweenVariables(text) {
415
+ function hasInsufficientContextBetweenVariables(text2) {
416
416
  var _a, _b;
417
- if (!text) return { insufficient: false };
418
- const varMatches = Array.from(text.matchAll(/\{\{\s*\d+\s*\}\}/g));
417
+ if (!text2) return { insufficient: false };
418
+ const varMatches = Array.from(text2.matchAll(/\{\{\s*\d+\s*\}\}/g));
419
419
  if (varMatches.length < 2) return { insufficient: false };
420
420
  for (let i = 0; i < varMatches.length - 1; i++) {
421
421
  const currentMatch = varMatches[i];
422
422
  const nextMatch = varMatches[i + 1];
423
423
  const startIndex = ((_a = currentMatch.index) != null ? _a : 0) + currentMatch[0].length;
424
424
  const endIndex = (_b = nextMatch.index) != null ? _b : 0;
425
- const textBetween = text.slice(startIndex, endIndex);
425
+ const textBetween = text2.slice(startIndex, endIndex);
426
426
  const wordsBetween = textBetween.trim().split(/\s+/).filter(isWordToken);
427
427
  if (wordsBetween.length < 2) {
428
428
  return {
@@ -433,13 +433,13 @@ function hasInsufficientContextBetweenVariables(text) {
433
433
  }
434
434
  return { insufficient: false };
435
435
  }
436
- function validateWordToVariableRatio(text) {
437
- if (!text) {
436
+ function validateWordToVariableRatio(text2) {
437
+ if (!text2) {
438
438
  return { isValid: false, reason: "\u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05EA\u05D5\u05DB\u05DF \u05DC\u05D4\u05D5\u05D3\u05E2\u05D4", staticWordsCount: 0, variableCount: 0 };
439
439
  }
440
- const allVars = text.match(/\{\{\s*\d+\s*\}\}/g) || [];
440
+ const allVars = text2.match(/\{\{\s*\d+\s*\}\}/g) || [];
441
441
  const variableCount = allVars.length;
442
- const staticText = text.replace(/\{\{\s*\d+\s*\}\}/g, " ");
442
+ const staticText = text2.replace(/\{\{\s*\d+\s*\}\}/g, " ");
443
443
  const staticWords = staticText.trim().split(/\s+/).filter(isWordToken);
444
444
  const staticWordsCount = staticWords.length;
445
445
  if (variableCount > 0) {
@@ -463,9 +463,9 @@ function validateWordToVariableRatio(text) {
463
463
  }
464
464
  return { isValid: true, staticWordsCount, variableCount };
465
465
  }
466
- function validateSequentialVariables(text) {
467
- if (!text) return { isValid: true, uniqueIndices: [], maxIndex: 0 };
468
- const uniqueIndices = extractUniqueVariableIndices(text);
466
+ function validateSequentialVariables(text2) {
467
+ if (!text2) return { isValid: true, uniqueIndices: [], maxIndex: 0 };
468
+ const uniqueIndices = extractUniqueVariableIndices(text2);
469
469
  if (uniqueIndices.length === 0) return { isValid: true, uniqueIndices: [], maxIndex: 0 };
470
470
  const maxIndex = uniqueIndices[uniqueIndices.length - 1];
471
471
  const uniqueSet = new Set(uniqueIndices);
@@ -489,11 +489,11 @@ function validateSequentialVariables(text) {
489
489
  }
490
490
  return { isValid: true, uniqueIndices, maxIndex };
491
491
  }
492
- function findVariableAtPosition(text, cursorPos, isBackspace) {
493
- if (!text) return null;
492
+ function findVariableAtPosition(text2, cursorPos, isBackspace) {
493
+ if (!text2) return null;
494
494
  const regex = /\{\{\s*\d+\s*\}\}/g;
495
495
  let match;
496
- while ((match = regex.exec(text)) !== null) {
496
+ while ((match = regex.exec(text2)) !== null) {
497
497
  const start = match.index;
498
498
  const end = match.index + match[0].length;
499
499
  if (isBackspace) {
@@ -574,17 +574,17 @@ function validateTemplateButtons(buttons) {
574
574
  return;
575
575
  }
576
576
  const type = btn.type;
577
- const text = (btn.text || "").trim();
577
+ const text2 = (btn.text || "").trim();
578
578
  if (type === "QUICK_REPLY") {
579
- if (!text) {
579
+ if (!text2) {
580
580
  errors.push(`\u05DB\u05E4\u05EA\u05D5\u05E8 ${btnNum}: \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05D8\u05E7\u05E1\u05D8 \u05DC\u05DB\u05E4\u05EA\u05D5\u05E8 \u05EA\u05D2\u05D5\u05D1\u05D4 \u05DE\u05D4\u05D9\u05E8\u05D4`);
581
- } else if (text.length > 25) {
581
+ } else if (text2.length > 25) {
582
582
  errors.push(`\u05DB\u05E4\u05EA\u05D5\u05E8 ${btnNum}: \u05D8\u05E7\u05E1\u05D8 \u05D4\u05DB\u05E4\u05EA\u05D5\u05E8 \u05D0\u05D9\u05E0\u05D5 \u05D9\u05DB\u05D5\u05DC \u05DC\u05E2\u05DC\u05D5\u05EA \u05E2\u05DC 25 \u05EA\u05D5\u05D5\u05D9\u05DD`);
583
583
  }
584
584
  } else if (type === "URL") {
585
- if (!text) {
585
+ if (!text2) {
586
586
  errors.push(`\u05DB\u05E4\u05EA\u05D5\u05E8 ${btnNum}: \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05D8\u05E7\u05E1\u05D8 \u05DC\u05DB\u05E4\u05EA\u05D5\u05E8 \u05E7\u05D9\u05E9\u05D5\u05E8`);
587
- } else if (text.length > 25) {
587
+ } else if (text2.length > 25) {
588
588
  errors.push(`\u05DB\u05E4\u05EA\u05D5\u05E8 ${btnNum}: \u05D8\u05E7\u05E1\u05D8 \u05D4\u05DB\u05E4\u05EA\u05D5\u05E8 \u05D0\u05D9\u05E0\u05D5 \u05D9\u05DB\u05D5\u05DC \u05DC\u05E2\u05DC\u05D5\u05EA \u05E2\u05DC 25 \u05EA\u05D5\u05D5\u05D9\u05DD`);
589
589
  }
590
590
  const url = (btn.url || "").trim();
@@ -596,9 +596,9 @@ function validateTemplateButtons(buttons) {
596
596
  errors.push(`\u05DB\u05E4\u05EA\u05D5\u05E8 ${btnNum}: \u05DB\u05EA\u05D5\u05D1\u05EA \u05D4\u05D0\u05EA\u05E8 \u05D0\u05D9\u05E0\u05D4 \u05EA\u05E7\u05D9\u05E0\u05D4 (\u05D7\u05D9\u05D9\u05D1\u05EA \u05DC\u05D4\u05EA\u05D7\u05D9\u05DC \u05D1-http:// \u05D0\u05D5 https:// \u05DC\u05DC\u05D0 \u05E8\u05D5\u05D5\u05D7\u05D9\u05DD)`);
597
597
  }
598
598
  } else if (type === "PHONE_NUMBER") {
599
- if (!text) {
599
+ if (!text2) {
600
600
  errors.push(`\u05DB\u05E4\u05EA\u05D5\u05E8 ${btnNum}: \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05D8\u05E7\u05E1\u05D8 \u05DC\u05DB\u05E4\u05EA\u05D5\u05E8 \u05D7\u05D9\u05D5\u05D2`);
601
- } else if (text.length > 25) {
601
+ } else if (text2.length > 25) {
602
602
  errors.push(`\u05DB\u05E4\u05EA\u05D5\u05E8 ${btnNum}: \u05D8\u05E7\u05E1\u05D8 \u05D4\u05DB\u05E4\u05EA\u05D5\u05E8 \u05D0\u05D9\u05E0\u05D5 \u05D9\u05DB\u05D5\u05DC \u05DC\u05E2\u05DC\u05D5\u05EA \u05E2\u05DC 25 \u05EA\u05D5\u05D5\u05D9\u05DD`);
603
603
  }
604
604
  const phone = (btn.phone_number || "").trim();
@@ -610,7 +610,7 @@ function validateTemplateButtons(buttons) {
610
610
  errors.push(`\u05DB\u05E4\u05EA\u05D5\u05E8 ${btnNum}: \u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF (\u05E4\u05D5\u05E8\u05DE\u05D8 \u05D7\u05D5\u05D1\u05D4: +[\u05E7\u05D9\u05D3\u05D5\u05DE\u05EA][\u05DE\u05E1\u05E4\u05E8], \u05DC\u05D3\u05D5\u05D2\u05DE\u05D4: +972501234567)`);
611
611
  }
612
612
  } else if (type === "COPY_CODE") {
613
- if (text && text.length > 25) {
613
+ if (text2 && text2.length > 25) {
614
614
  errors.push(`\u05DB\u05E4\u05EA\u05D5\u05E8 ${btnNum}: \u05D8\u05E7\u05E1\u05D8 \u05D4\u05DB\u05E4\u05EA\u05D5\u05E8 \u05D0\u05D9\u05E0\u05D5 \u05D9\u05DB\u05D5\u05DC \u05DC\u05E2\u05DC\u05D5\u05EA \u05E2\u05DC 25 \u05EA\u05D5\u05D5\u05D9\u05DD`);
615
615
  }
616
616
  const example = (btn.example || "").trim();
@@ -710,7 +710,7 @@ function formatFileSize(bytes) {
710
710
 
711
711
  // ../shared/src/formula.ts
712
712
  var FORMULA_COLUMN_TYPE = "FORMULA";
713
- var FORMULA_SOURCE_TYPES = ["NUMBER", "CURRENCY", "STRING"];
713
+ var FORMULA_SOURCE_TYPES = ["NUMBER", "CURRENCY", "STRING", "BOOLEAN", "DATE", "TIME", "PHONE"];
714
714
  function extractFormulaFields(expr) {
715
715
  const out = /* @__PURE__ */ new Set();
716
716
  for (const m of (expr || "").matchAll(/\{([^{}]+)\}/g)) out.add(m[1].trim());
@@ -767,6 +767,42 @@ var toNum = (x) => {
767
767
  const n = typeof x === "number" ? x : Number(x);
768
768
  return Number.isFinite(n) ? n : NaN;
769
769
  };
770
+ var isBlank = (x) => x === null || x === void 0 || x === "";
771
+ var isNumLike = (x) => typeof x === "number" || typeof x === "string" && x.trim() !== "" && Number.isFinite(Number(x));
772
+ var isoDate = (x) => typeof x === "string" && /^\d{4}-\d{2}-\d{2}/.test(x) ? x.slice(0, 10) : null;
773
+ var truthy = (x) => {
774
+ if (x === null || x === "") return false;
775
+ if (typeof x === "number") return x !== 0 && !Number.isNaN(x);
776
+ const s = x.trim().toLowerCase();
777
+ return s !== "" && s !== "0" && s !== "false";
778
+ };
779
+ var text = (x) => String(x != null ? x : "").trim().toLowerCase();
780
+ function compareValues(l, r) {
781
+ const ld = isoDate(l), rd = isoDate(r);
782
+ if (ld && rd) return ld < rd ? -1 : ld > rd ? 1 : 0;
783
+ if ((isNumLike(l) || isBlank(l)) && (isNumLike(r) || isBlank(r))) {
784
+ const a2 = toNum(l), b2 = toNum(r);
785
+ return a2 < b2 ? -1 : a2 > b2 ? 1 : 0;
786
+ }
787
+ const a = text(l), b = text(r);
788
+ return a < b ? -1 : a > b ? 1 : 0;
789
+ }
790
+ var dayNumber = (iso) => Date.UTC(+iso.slice(0, 4), +iso.slice(5, 7) - 1, +iso.slice(8, 10));
791
+ var ARITY = {
792
+ ROUND: [1, 2],
793
+ MIN: [1, 99],
794
+ MAX: [1, 99],
795
+ ABS: [1, 1],
796
+ IF: [3, 3],
797
+ AND: [1, 99],
798
+ OR: [1, 99],
799
+ NOT: [1, 1],
800
+ CONTAINS: [2, 2],
801
+ STARTSWITH: [2, 2],
802
+ ENDSWITH: [2, 2],
803
+ ISEMPTY: [1, 1],
804
+ DAYS: [2, 2]
805
+ };
770
806
  function evaluateFormula(expr, getField) {
771
807
  const toks = tokenize(expr);
772
808
  let p = 0;
@@ -784,8 +820,8 @@ function evaluateFormula(expr, getField) {
784
820
  let l = parseConcat();
785
821
  while (isOp(">", "<", ">=", "<=", "=", "<>")) {
786
822
  const op = eat().v, r = parseConcat();
787
- const a = toNum(l), b = toNum(r);
788
- l = (op === ">" ? a > b : op === "<" ? a < b : op === ">=" ? a >= b : op === "<=" ? a <= b : op === "=" ? a === b : a !== b) ? 1 : 0;
823
+ const c = compareValues(l, r);
824
+ l = (op === ">" ? c > 0 : op === "<" ? c < 0 : op === ">=" ? c >= 0 : op === "<=" ? c <= 0 : op === "=" ? c === 0 : c !== 0) ? 1 : 0;
789
825
  }
790
826
  return l;
791
827
  }
@@ -836,8 +872,11 @@ function evaluateFormula(expr, getField) {
836
872
  }
837
873
  if (t.k === "field") {
838
874
  p++;
839
- const v = getField(t.v);
840
- return v === void 0 || v === null ? null : v;
875
+ const raw = getField(t.v);
876
+ if (raw === void 0 || raw === null) return null;
877
+ if (typeof raw === "boolean") return raw ? 1 : 0;
878
+ if (typeof raw === "number" || typeof raw === "string") return raw;
879
+ return null;
841
880
  }
842
881
  if (isOp("(")) {
843
882
  eat();
@@ -857,6 +896,12 @@ function evaluateFormula(expr, getField) {
857
896
  }
858
897
  }
859
898
  eat(")");
899
+ const ar = ARITY[t.v];
900
+ if (!ar) throw new Error(`\u05E4\u05D5\u05E0\u05E7\u05E6\u05D9\u05D4 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8\u05EA: ${t.v}`);
901
+ if (args.length < ar[0] || args.length > ar[1]) {
902
+ const need = ar[1] === 99 ? `\u05DC\u05E4\u05D7\u05D5\u05EA ${ar[0]}` : ar[0] === ar[1] ? `${ar[0]}` : `${ar[0]}-${ar[1]}`;
903
+ throw new Error(`\u05D4\u05E4\u05D5\u05E0\u05E7\u05E6\u05D9\u05D4 ${t.v} \u05DE\u05E7\u05D1\u05DC\u05EA ${need} \u05E4\u05E8\u05DE\u05D8\u05E8\u05D9\u05DD`);
904
+ }
860
905
  const n = args.map(toNum);
861
906
  switch (t.v) {
862
907
  case "ROUND": {
@@ -870,7 +915,25 @@ function evaluateFormula(expr, getField) {
870
915
  case "ABS":
871
916
  return Math.abs(n[0]);
872
917
  case "IF":
873
- return toNum(args[0]) ? (_b = args[1]) != null ? _b : null : (_c = args[2]) != null ? _c : null;
918
+ return truthy(args[0]) ? (_b = args[1]) != null ? _b : null : (_c = args[2]) != null ? _c : null;
919
+ case "AND":
920
+ return args.every(truthy) ? 1 : 0;
921
+ case "OR":
922
+ return args.some(truthy) ? 1 : 0;
923
+ case "NOT":
924
+ return truthy(args[0]) ? 0 : 1;
925
+ case "CONTAINS":
926
+ return text(args[0]).includes(text(args[1])) ? 1 : 0;
927
+ case "STARTSWITH":
928
+ return text(args[0]).startsWith(text(args[1])) ? 1 : 0;
929
+ case "ENDSWITH":
930
+ return text(args[0]).endsWith(text(args[1])) ? 1 : 0;
931
+ case "ISEMPTY":
932
+ return isBlank(args[0]) ? 1 : 0;
933
+ case "DAYS": {
934
+ const a = isoDate(args[0]), b = isoDate(args[1]);
935
+ return a && b ? Math.round((dayNumber(a) - dayNumber(b)) / 864e5) : null;
936
+ }
874
937
  default:
875
938
  throw new Error(`\u05E4\u05D5\u05E0\u05E7\u05E6\u05D9\u05D4 \u05DC\u05D0 \u05DE\u05D5\u05DB\u05E8\u05EA: ${t.v}`);
876
939
  }
@@ -914,8 +977,85 @@ function applyFormulaColumns(data, columns) {
914
977
  return data;
915
978
  }
916
979
 
980
+ // ../shared/src/relationCopy.ts
981
+ var isRelation = (c) => !!c && String(c.type).toUpperCase() === "RELATION";
982
+ function getSelectedRelationId(value) {
983
+ if (value === null || value === void 0 || value === "") return null;
984
+ const first = Array.isArray(value) ? value[0] : value;
985
+ if (first === null || first === void 0 || first === "") return null;
986
+ if (typeof first === "object") {
987
+ const id = first.id || first._id || first.value;
988
+ return id ? String(id) : null;
989
+ }
990
+ return String(first);
991
+ }
992
+ function getRelationCopyTargetNames(col) {
993
+ var _a, _b;
994
+ if (!isRelation(col) || ((_a = col.config) == null ? void 0 : _a.allowMultiple)) return [];
995
+ const list = (_b = col.config) == null ? void 0 : _b.copyTargets;
996
+ return Array.isArray(list) ? list.filter((n) => typeof n === "string" && n) : [];
997
+ }
998
+ function getEligibleCopyTargets(referencedTableId, columns, ownName) {
999
+ if (!referencedTableId) return [];
1000
+ return (columns || []).filter(
1001
+ (c) => {
1002
+ var _a;
1003
+ return isRelation(c) && c.name !== ownName && c.name !== "_id" && ((_a = c.config) == null ? void 0 : _a.referencedTableId) === referencedTableId && getRelationCopyTargetNames(c).length === 0;
1004
+ }
1005
+ // עמודה ראשית אחרת לא יכולה להיות נלווית
1006
+ );
1007
+ }
1008
+ function resolveTargets(master, columns) {
1009
+ var _a;
1010
+ const refId = (_a = master.config) == null ? void 0 : _a.referencedTableId;
1011
+ return getRelationCopyTargetNames(master).filter((n) => {
1012
+ var _a2;
1013
+ const t = columns.find((c) => c.name === n);
1014
+ return isRelation(t) && ((_a2 = t.config) == null ? void 0 : _a2.referencedTableId) === refId && n !== master.name;
1015
+ });
1016
+ }
1017
+ function getRelationCopyLockedTargets(columns) {
1018
+ const out = /* @__PURE__ */ new Set();
1019
+ const cols = columns || [];
1020
+ for (const c of cols) for (const n of resolveTargets(c, cols)) out.add(n);
1021
+ return out;
1022
+ }
1023
+ function buildRelationCopyPatch(master, masterValue, columns) {
1024
+ const id = getSelectedRelationId(masterValue);
1025
+ const patch = {};
1026
+ for (const n of resolveTargets(master, columns)) patch[n] = id ? [id] : [];
1027
+ return patch;
1028
+ }
1029
+ function applyRelationCopy(data, columns, changedKeys, existing) {
1030
+ var _a;
1031
+ for (const master of columns || []) {
1032
+ const targets = resolveTargets(master, columns);
1033
+ if (targets.length === 0) continue;
1034
+ if (changedKeys && !changedKeys.includes(master.name)) {
1035
+ for (const t of targets) {
1036
+ if (changedKeys.includes(t)) data[t] = (_a = existing == null ? void 0 : existing[t]) != null ? _a : [];
1037
+ }
1038
+ continue;
1039
+ }
1040
+ Object.assign(data, buildRelationCopyPatch(master, data[master.name], columns));
1041
+ }
1042
+ return data;
1043
+ }
1044
+ function validateRelationCopyTargets(targets, referencedTableId, columns, ownName) {
1045
+ if (targets.length === 0) return "\u05E1\u05D9\u05DE\u05E0\u05EA \u05D4\u05E2\u05EA\u05E7\u05EA \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD - \u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05DC\u05E4\u05D7\u05D5\u05EA \u05E2\u05DE\u05D5\u05D3\u05D4 \u05D0\u05D7\u05EA";
1046
+ const eligible = getEligibleCopyTargets(referencedTableId, columns, ownName).map((c) => c.name);
1047
+ const bad = targets.find((n) => !eligible.includes(n));
1048
+ return bad ? `\u05D4\u05E2\u05DE\u05D5\u05D3\u05D4 "${bad}" \u05D0\u05D9\u05E0\u05D4 \u05E2\u05DE\u05D5\u05D3\u05EA \u05E7\u05E9\u05E8 \u05DC\u05D0\u05D5\u05EA\u05D4 \u05D8\u05D1\u05DC\u05D4 \u05D5\u05DC\u05DB\u05DF \u05D0\u05D9 \u05D0\u05E4\u05E9\u05E8 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05D1\u05D4` : null;
1049
+ }
1050
+ function renameCopyTarget(col, oldName, newName) {
1051
+ var _a;
1052
+ const list = (_a = col == null ? void 0 : col.config) == null ? void 0 : _a.copyTargets;
1053
+ if (!Array.isArray(list)) return;
1054
+ col.config.copyTargets = list.map((n) => n === oldName ? newName : n);
1055
+ }
1056
+
917
1057
  // src/components/TableBlock/TableBlockClient.tsx
918
- import React12, { useState as useState13, useMemo as useMemo6, useEffect as useEffect11, useCallback as useCallback11, useRef as useRef10 } from "react";
1058
+ import React12, { useState as useState13, useMemo as useMemo6, useEffect as useEffect11, useCallback as useCallback12, useRef as useRef11 } from "react";
919
1059
 
920
1060
  // src/hooks/useToast.ts
921
1061
  import { useContext as useContext2 } from "react";
@@ -1516,8 +1656,8 @@ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1516
1656
  var checkElementTruncation = (el) => {
1517
1657
  if (!el) return false;
1518
1658
  const isInput = el instanceof HTMLInputElement || el.tagName === "INPUT";
1519
- const text = isInput ? el.value : el.textContent;
1520
- if (!text) return false;
1659
+ const text2 = isInput ? el.value : el.textContent;
1660
+ if (!text2) return false;
1521
1661
  if (!isInput && typeof document !== "undefined" && document.createRange) {
1522
1662
  try {
1523
1663
  const range = document.createRange();
@@ -1585,8 +1725,8 @@ function useSmartTooltip() {
1585
1725
  window.removeEventListener("resize", handleWindowEvents);
1586
1726
  };
1587
1727
  }, [showBubble]);
1588
- const renderTooltip = (text, dir) => {
1589
- if (!showBubble || !isTruncated || !text || typeof document === "undefined") return null;
1728
+ const renderTooltip = (text2, dir) => {
1729
+ if (!showBubble || !isTruncated || !text2 || typeof document === "undefined") return null;
1590
1730
  return createPortal(
1591
1731
  /* @__PURE__ */ jsx3(
1592
1732
  "div",
@@ -1598,7 +1738,7 @@ function useSmartTooltip() {
1598
1738
  left: coords ? Math.max(12, Math.min(coords.left, (typeof window !== "undefined" ? window.innerWidth : 800) - 280)) : 0,
1599
1739
  transform: coords && coords.top > 36 ? "translateY(-100%)" : void 0
1600
1740
  },
1601
- children: text
1741
+ children: text2
1602
1742
  }
1603
1743
  ),
1604
1744
  document.body
@@ -1616,7 +1756,7 @@ function useSmartTooltip() {
1616
1756
  };
1617
1757
  }
1618
1758
  var TruncatedTooltip = ({
1619
- text,
1759
+ text: text2,
1620
1760
  tooltipText,
1621
1761
  dir = "auto",
1622
1762
  className = "",
@@ -1628,7 +1768,7 @@ var TruncatedTooltip = ({
1628
1768
  const [coords, setCoords] = useState3(null);
1629
1769
  const containerRef = useRef3(null);
1630
1770
  const spanRef = useRef3(null);
1631
- const content = text !== void 0 && text !== null ? String(text) : "";
1771
+ const content = text2 !== void 0 && text2 !== null ? String(text2) : "";
1632
1772
  const tooltipContent = tooltipText !== void 0 ? tooltipText : content;
1633
1773
  const handleMouseEnter = () => {
1634
1774
  const el = spanRef.current;
@@ -2005,13 +2145,13 @@ function DatePickerCell({ value, onChange, readOnly = false }) {
2005
2145
  };
2006
2146
  }, [isOpen, updatePopoverPosition]);
2007
2147
  const handleInputChange = (e) => {
2008
- const text = e.target.value;
2009
- setRawInput(text);
2010
- if (!text.trim()) {
2148
+ const text2 = e.target.value;
2149
+ setRawInput(text2);
2150
+ if (!text2.trim()) {
2011
2151
  onChange(null);
2012
2152
  return;
2013
2153
  }
2014
- const parts = parseDateParts(text);
2154
+ const parts = parseDateParts(text2);
2015
2155
  if (parts) {
2016
2156
  const iso = formatDateIso(parts.year, parts.month, parts.day);
2017
2157
  onChange(iso);
@@ -2358,23 +2498,23 @@ function TimePickerCell({ value, onChange, readOnly = false }) {
2358
2498
  }
2359
2499
  };
2360
2500
  const handleInputBlur = () => {
2361
- let text = rawInput.trim();
2362
- if (!text) {
2501
+ let text2 = rawInput.trim();
2502
+ if (!text2) {
2363
2503
  onChange(null);
2364
2504
  return;
2365
2505
  }
2366
- if (!text.includes(":")) {
2367
- if (text.length === 1 || text.length === 2) {
2368
- text = `${text}:00`;
2369
- } else if (text.length === 3) {
2370
- text = `0${text[0]}:${text.slice(1)}`;
2371
- } else if (text.length === 4) {
2372
- text = `${text.slice(0, 2)}:${text.slice(2)}`;
2506
+ if (!text2.includes(":")) {
2507
+ if (text2.length === 1 || text2.length === 2) {
2508
+ text2 = `${text2}:00`;
2509
+ } else if (text2.length === 3) {
2510
+ text2 = `0${text2[0]}:${text2.slice(1)}`;
2511
+ } else if (text2.length === 4) {
2512
+ text2 = `${text2.slice(0, 2)}:${text2.slice(2)}`;
2373
2513
  }
2374
- } else if (text.endsWith(":")) {
2375
- text = `${text}00`;
2514
+ } else if (text2.endsWith(":")) {
2515
+ text2 = `${text2}00`;
2376
2516
  }
2377
- const parts = parseTimeParts(text);
2517
+ const parts = parseTimeParts(text2);
2378
2518
  if (parts) {
2379
2519
  const iso = formatTimeIso(parts.hour, parts.minute);
2380
2520
  setRawInput(iso);
@@ -3551,19 +3691,19 @@ function formatFormulaValue(value, column) {
3551
3691
  if (value === null || value === void 0 || value === "") return "";
3552
3692
  const f = (_a = column == null ? void 0 : column.config) == null ? void 0 : _a.formula;
3553
3693
  if (typeof value === "number") {
3554
- const text = new Intl.NumberFormat("en-US", { maximumFractionDigits: 6 }).format(value);
3694
+ const text2 = new Intl.NumberFormat("en-US", { maximumFractionDigits: 6 }).format(value);
3555
3695
  if ((f == null ? void 0 : f.resultType) === "CURRENCY") {
3556
3696
  const code = f.currencySymbol;
3557
3697
  const s = code ? SYMBOLS[code.toUpperCase()] || code : "";
3558
- return s ? `${s} ${text}` : text;
3698
+ return s ? `${s} ${text2}` : text2;
3559
3699
  }
3560
- return text;
3700
+ return text2;
3561
3701
  }
3562
3702
  return String(value);
3563
3703
  }
3564
3704
  var FormulaDisplay = ({ value, column }) => {
3565
- const text = formatFormulaValue(value, column);
3566
- return /* @__PURE__ */ jsx8(SmartTextCell, { value: text, tooltipText: text, readOnly: true });
3705
+ const text2 = formatFormulaValue(value, column);
3706
+ return /* @__PURE__ */ jsx8(SmartTextCell, { value: text2, tooltipText: text2, readOnly: true });
3567
3707
  };
3568
3708
  var FormulaInputRenderer = ({ value, column, context }) => {
3569
3709
  const live = (context == null ? void 0 : context.rowData) ? computeFormulaValue(column, context.rowData) : value;
@@ -4125,15 +4265,15 @@ function useColumnReorder({
4125
4265
  import { useState as useState10, useEffect as useEffect8 } from "react";
4126
4266
  import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
4127
4267
  var canvas = null;
4128
- function measureTextWidth(text, font = '600 14px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif') {
4129
- if (typeof document === "undefined") return text.length * 9;
4268
+ function measureTextWidth(text2, font = '600 14px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif') {
4269
+ if (typeof document === "undefined") return text2.length * 9;
4130
4270
  if (!canvas) {
4131
4271
  canvas = document.createElement("canvas");
4132
4272
  }
4133
4273
  const ctx = canvas.getContext("2d");
4134
- if (!ctx) return text.length * 9;
4274
+ if (!ctx) return text2.length * 9;
4135
4275
  ctx.font = font;
4136
- return ctx.measureText(text).width;
4276
+ return ctx.measureText(text2).width;
4137
4277
  }
4138
4278
  function splitHeaderTitle(name) {
4139
4279
  if (!name) return { isSingleWord: true, line1: "" };
@@ -4219,8 +4359,8 @@ function formatConflictCellValue(rawVal, colDef, relationOptionsMap) {
4219
4359
  return /* @__PURE__ */ jsx11("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" });
4220
4360
  }
4221
4361
  if (colType === "LINK" || typeof rawVal === "object" && rawVal !== null && ("url" in rawVal || "label" in rawVal)) {
4222
- const text = (rawVal == null ? void 0 : rawVal.label) || (rawVal == null ? void 0 : rawVal.url);
4223
- return text ? String(text) : "-";
4362
+ const text2 = (rawVal == null ? void 0 : rawVal.label) || (rawVal == null ? void 0 : rawVal.url);
4363
+ return text2 ? String(text2) : "-";
4224
4364
  }
4225
4365
  if (colType === "SUB_TABLE" || Array.isArray(rawVal) && rawVal.length > 0 && typeof rawVal[0] === "object" && ("recordId" in rawVal[0] || "id" in rawVal[0])) {
4226
4366
  return /* @__PURE__ */ jsxs10("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: [
@@ -5478,8 +5618,23 @@ function SubTableViewer({ rowId, column, value, onChange, context, readOnly }) {
5478
5618
  // src/components/TableBlock/TableBlockClient.tsx
5479
5619
  import { X as X8, Copy as Copy2, RotateCcw as RotateCcw2, Download, Filter, Loader2 as Loader23, ExternalLink as ExternalLink2 } from "lucide-react";
5480
5620
 
5621
+ // src/components/TableBlock/useRelationCopy.ts
5622
+ import { useCallback as useCallback10, useRef as useRef9 } from "react";
5623
+ function useRelationCopyHandler({ columns, handleCellChange }) {
5624
+ const latest = useRef9({ columns, handleCellChange });
5625
+ latest.current = { columns, handleCellChange };
5626
+ return useCallback10((rowId, colName, value) => {
5627
+ const { columns: cols, handleCellChange: change } = latest.current;
5628
+ change(rowId, colName, value);
5629
+ const col = (cols || []).find((c) => (c == null ? void 0 : c.name) === colName);
5630
+ if (getRelationCopyTargetNames(col).length === 0) return;
5631
+ const patch = buildRelationCopyPatch(col, value, cols);
5632
+ for (const [target, v] of Object.entries(patch)) change(rowId, target, v);
5633
+ }, []);
5634
+ }
5635
+
5481
5636
  // src/components/TableBlock/RelationFilterPopover.tsx
5482
- import { useState as useState12, useEffect as useEffect10, useRef as useRef9, useMemo as useMemo5, useCallback as useCallback10 } from "react";
5637
+ import { useState as useState12, useEffect as useEffect10, useRef as useRef10, useMemo as useMemo5, useCallback as useCallback11 } from "react";
5483
5638
  import { Search as Search2, X as X7, RotateCcw } from "lucide-react";
5484
5639
  import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
5485
5640
  function calculatePopoverCoords(rect) {
@@ -5513,9 +5668,9 @@ function RelationFilterPopover({
5513
5668
  onSelectionChange,
5514
5669
  isLoading = false
5515
5670
  }) {
5516
- const popoverRef = useRef9(null);
5517
- const searchInputRef = useRef9(null);
5518
- const selectAllRef = useRef9(null);
5671
+ const popoverRef = useRef10(null);
5672
+ const searchInputRef = useRef10(null);
5673
+ const selectAllRef = useRef10(null);
5519
5674
  const [searchQuery, setSearchQuery] = useState12("");
5520
5675
  const [coords, setCoords] = useState12(
5521
5676
  () => calculatePopoverCoords(triggerRect)
@@ -5523,7 +5678,7 @@ function RelationFilterPopover({
5523
5678
  const [mode, setMode] = useState12("include");
5524
5679
  const [checkedSet, setCheckedSet] = useState12(/* @__PURE__ */ new Set());
5525
5680
  const [excludedSet, setExcludedSet] = useState12(/* @__PURE__ */ new Set());
5526
- const prevIsOpenRef = useRef9(isOpen);
5681
+ const prevIsOpenRef = useRef10(isOpen);
5527
5682
  useEffect10(() => {
5528
5683
  const justOpened = isOpen && !prevIsOpenRef.current;
5529
5684
  prevIsOpenRef.current = isOpen;
@@ -5544,7 +5699,7 @@ function RelationFilterPopover({
5544
5699
  }
5545
5700
  }
5546
5701
  }, [isOpen, filterValue, selectedValues]);
5547
- const updatePosition = useCallback10(() => {
5702
+ const updatePosition = useCallback11(() => {
5548
5703
  const next = calculatePopoverCoords(triggerRect);
5549
5704
  if (next) setCoords(next);
5550
5705
  }, [triggerRect]);
@@ -5598,7 +5753,7 @@ function RelationFilterPopover({
5598
5753
  const q = searchQuery.trim().toLowerCase();
5599
5754
  return options.filter((opt) => opt.label.toLowerCase().includes(q));
5600
5755
  }, [options, searchQuery]);
5601
- const isOptionChecked = useCallback10(
5756
+ const isOptionChecked = useCallback11(
5602
5757
  (label) => {
5603
5758
  if (mode === "exclude") {
5604
5759
  return !excludedSet.has(label);
@@ -5861,7 +6016,7 @@ function TableBlockClient({
5861
6016
  return calculateMinColumnWidth(colName, false, col == null ? void 0 : col.type);
5862
6017
  }
5863
6018
  });
5864
- const executeActionRef = useRef10(executeAction);
6019
+ const executeActionRef = useRef11(executeAction);
5865
6020
  useEffect11(() => {
5866
6021
  executeActionRef.current = executeAction;
5867
6022
  }, [executeAction]);
@@ -5921,7 +6076,7 @@ function TableBlockClient({
5921
6076
  return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
5922
6077
  });
5923
6078
  };
5924
- const mergeColumnDefs = useCallback11((existingCols, incomingCols) => {
6079
+ const mergeColumnDefs = useCallback12((existingCols, incomingCols) => {
5925
6080
  if (!incomingCols || incomingCols.length === 0) return existingCols || [];
5926
6081
  if (!existingCols || existingCols.length === 0) return incomingCols;
5927
6082
  const existingMap = new Map(existingCols.map((c) => [c.name, c]));
@@ -5948,11 +6103,11 @@ function TableBlockClient({
5948
6103
  }
5949
6104
  }, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
5950
6105
  const [dirty, setDirty] = useState13({ added: [], modified: {}, deleted: [] });
5951
- const dirtyRef = useRef10(dirty);
6106
+ const dirtyRef = useRef11(dirty);
5952
6107
  useEffect11(() => {
5953
6108
  dirtyRef.current = dirty;
5954
6109
  }, [dirty]);
5955
- const mergeWithDirty = useCallback11((baseRecords) => {
6110
+ const mergeWithDirty = useCallback12((baseRecords) => {
5956
6111
  const { added, modified, deleted } = dirtyRef.current;
5957
6112
  const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
5958
6113
  const modifiedRecords = nonDeleted.map((r) => {
@@ -5993,15 +6148,15 @@ function TableBlockClient({
5993
6148
  const [searchQuery, setSearchQuery] = useState13("");
5994
6149
  const [columnFilters, setColumnFilters] = useState13({});
5995
6150
  const [activeSearchCol, setActiveSearchCol] = useState13(null);
5996
- const activeSearchRef = useRef10(null);
6151
+ const activeSearchRef = useRef11(null);
5997
6152
  const [activeRelationCol, setActiveRelationCol] = useState13(null);
5998
6153
  const [relationTriggerRect, setRelationTriggerRect] = useState13(null);
5999
- const filterButtonRefs = useRef10({});
6154
+ const filterButtonRefs = useRef11({});
6000
6155
  const [relationOptions, setRelationOptions] = useState13({});
6001
6156
  const [relationFilterOptions, setRelationFilterOptions] = useState13({});
6002
6157
  const [loadingFilterCol, setLoadingFilterCol] = useState13(null);
6003
- const relationDictionaryRef = useRef10({});
6004
- const mergeRelationOptions = useCallback11((colName, newOptions) => {
6158
+ const relationDictionaryRef = useRef11({});
6159
+ const mergeRelationOptions = useCallback12((colName, newOptions) => {
6005
6160
  if (!Array.isArray(newOptions) || newOptions.length === 0) return;
6006
6161
  if (!relationDictionaryRef.current[colName]) {
6007
6162
  relationDictionaryRef.current[colName] = /* @__PURE__ */ new Map();
@@ -6052,7 +6207,7 @@ function TableBlockClient({
6052
6207
  }, 300);
6053
6208
  return () => clearTimeout(timer);
6054
6209
  }, [searchQuery]);
6055
- const isSearchMountedRef = useRef10(false);
6210
+ const isSearchMountedRef = useRef11(false);
6056
6211
  useEffect11(() => {
6057
6212
  if (!isSearchMountedRef.current) {
6058
6213
  isSearchMountedRef.current = true;
@@ -6061,8 +6216,8 @@ function TableBlockClient({
6061
6216
  setPage(1);
6062
6217
  }, [debouncedSearch]);
6063
6218
  const [isFetching, setIsFetching] = useState13(false);
6064
- const fetchRequestIdRef = useRef10(0);
6065
- const fetchTableData = useCallback11((targetPage, targetLimit, targetSearch, targetFiltersKey) => {
6219
+ const fetchRequestIdRef = useRef11(0);
6220
+ const fetchTableData = useCallback12((targetPage, targetLimit, targetSearch, targetFiltersKey) => {
6066
6221
  const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
6067
6222
  const action = executeActionRef.current;
6068
6223
  if (!tableId || !action) {
@@ -6252,10 +6407,10 @@ function TableBlockClient({
6252
6407
  }
6253
6408
  }
6254
6409
  }, [initialRecords, mergeWithDirty, debouncedSearch, columnFilters, fetchTableData, page, limit, filtersKey]);
6255
- const refetchTableData = useCallback11(() => {
6410
+ const refetchTableData = useCallback12(() => {
6256
6411
  return fetchTableData(page, limit, debouncedSearch, filtersKey);
6257
6412
  }, [page, limit, debouncedSearch, filtersKey, fetchTableData]);
6258
- const handleApplyColumnFilter = useCallback11((colName, nextVal) => {
6413
+ const handleApplyColumnFilter = useCallback12((colName, nextVal) => {
6259
6414
  setColumnFilters((prev) => {
6260
6415
  const next = __spreadValues({}, prev);
6261
6416
  if (nextVal === void 0 || Array.isArray(nextVal) && nextVal.length === 0 || typeof nextVal === "string" && !nextVal.trim() || typeof nextVal === "object" && "values" in nextVal && Array.isArray(nextVal.values) && nextVal.values.length === 0) {
@@ -6281,7 +6436,7 @@ function TableBlockClient({
6281
6436
  setPage((prev) => Math.min(totalPages, prev + 1));
6282
6437
  };
6283
6438
  const [selectedIds, setSelectedIds] = useState13(/* @__PURE__ */ new Set());
6284
- const isExternalSyncRef = useRef10(false);
6439
+ const isExternalSyncRef = useRef11(false);
6285
6440
  useEffect11(() => {
6286
6441
  if (selectedRowIds !== void 0) {
6287
6442
  const nextSet = new Set(selectedRowIds);
@@ -6294,7 +6449,7 @@ function TableBlockClient({
6294
6449
  });
6295
6450
  }
6296
6451
  }, [selectedRowIds]);
6297
- const isFirstSelectionChangeRef = useRef10(true);
6452
+ const isFirstSelectionChangeRef = useRef11(true);
6298
6453
  useEffect11(() => {
6299
6454
  if (isFirstSelectionChangeRef.current) {
6300
6455
  isFirstSelectionChangeRef.current = false;
@@ -6312,7 +6467,7 @@ function TableBlockClient({
6312
6467
  const [isSaveSuccess, setIsSaveSuccess] = useState13(false);
6313
6468
  const [expandedRowIds, setExpandedRowIds] = useState13(/* @__PURE__ */ new Set());
6314
6469
  const schemaColsString = useMemo6(() => JSON.stringify(localColumns || []), [localColumns]);
6315
- const refetchRelation = useCallback11(async (colName, params) => {
6470
+ const refetchRelation = useCallback12(async (colName, params) => {
6316
6471
  var _a, _b, _c, _d, _e, _f, _g;
6317
6472
  let parsedCols = [];
6318
6473
  try {
@@ -6351,7 +6506,7 @@ function TableBlockClient({
6351
6506
  }
6352
6507
  return [];
6353
6508
  }, [schemaColsString, executeAction, mergeRelationOptions]);
6354
- const fetchRelationFilterOptions = useCallback11(async (colName) => {
6509
+ const fetchRelationFilterOptions = useCallback12(async (colName) => {
6355
6510
  var _a;
6356
6511
  let parsedCols = [];
6357
6512
  try {
@@ -6387,7 +6542,7 @@ function TableBlockClient({
6387
6542
  setLoadingFilterCol(null);
6388
6543
  }
6389
6544
  }, [schemaColsString, schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, executeAction, mergeRelationOptions]);
6390
- const requestedRelationIdsRef = useRef10({});
6545
+ const requestedRelationIdsRef = useRef11({});
6391
6546
  useEffect11(() => {
6392
6547
  if (!executeAction || !data || data.length === 0) return;
6393
6548
  let parsedCols = [];
@@ -6478,7 +6633,7 @@ function TableBlockClient({
6478
6633
  return normalizedColumns.filter((col) => !systemFields.includes(col.name));
6479
6634
  }, [normalizedColumns]);
6480
6635
  const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = useState13(false);
6481
- const dropdownRef = useRef10(null);
6636
+ const dropdownRef = useRef11(null);
6482
6637
  useEffect11(() => {
6483
6638
  const handleClickOutside = (e) => {
6484
6639
  if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
@@ -6689,7 +6844,7 @@ function TableBlockClient({
6689
6844
  setData((prev) => [newRow, ...prev]);
6690
6845
  setDirty((prev) => __spreadProps(__spreadValues({}, prev), { added: [newRow, ...prev.added] }));
6691
6846
  };
6692
- const handleCellChange = useCallback11((rowId, colName, value) => {
6847
+ const handleCellChange = useCallback12((rowId, colName, value) => {
6693
6848
  setData((prev) => prev.map(
6694
6849
  (row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
6695
6850
  ));
@@ -6721,13 +6876,14 @@ function TableBlockClient({
6721
6876
  });
6722
6877
  });
6723
6878
  }, [baseRecordsMap]);
6724
- const triggerSaveSuccess = useCallback11(() => {
6879
+ const handleCellChangeWithCopy = useRelationCopyHandler({ columns: localColumns, handleCellChange });
6880
+ const triggerSaveSuccess = useCallback12(() => {
6725
6881
  setIsSaveSuccess(true);
6726
6882
  setTimeout(() => {
6727
6883
  setIsSaveSuccess(false);
6728
6884
  }, 2500);
6729
6885
  }, []);
6730
- const handleQuietCellChange = useCallback11((rowId, colName, value) => {
6886
+ const handleQuietCellChange = useCallback12((rowId, colName, value) => {
6731
6887
  setData((prev) => prev.map(
6732
6888
  (row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
6733
6889
  ));
@@ -6751,12 +6907,12 @@ function TableBlockClient({
6751
6907
  });
6752
6908
  }
6753
6909
  }, []);
6754
- const toggleSelectAll = useCallback11((checked) => {
6910
+ const toggleSelectAll = useCallback12((checked) => {
6755
6911
  onRowToggle == null ? void 0 : onRowToggle("ALL", checked);
6756
6912
  const next = checked ? new Set(filteredData.map((r) => r.id)) : /* @__PURE__ */ new Set();
6757
6913
  setSelectedIds(next);
6758
6914
  }, [filteredData, onRowToggle]);
6759
- const toggleSelectRow = useCallback11((rowId, checked) => {
6915
+ const toggleSelectRow = useCallback12((rowId, checked) => {
6760
6916
  onRowToggle == null ? void 0 : onRowToggle(rowId, checked);
6761
6917
  setSelectedIds((prev) => {
6762
6918
  const next = new Set(prev);
@@ -6765,7 +6921,7 @@ function TableBlockClient({
6765
6921
  return next;
6766
6922
  });
6767
6923
  }, [onRowToggle]);
6768
- const handleToggleExpand = useCallback11((rowId) => {
6924
+ const handleToggleExpand = useCallback12((rowId) => {
6769
6925
  setExpandedRowIds((prev) => {
6770
6926
  const next = new Set(prev);
6771
6927
  if (next.has(rowId)) next.delete(rowId);
@@ -6773,7 +6929,7 @@ function TableBlockClient({
6773
6929
  return next;
6774
6930
  });
6775
6931
  }, []);
6776
- const handleMarkForDeletion = useCallback11((fileId) => {
6932
+ const handleMarkForDeletion = useCallback12((fileId) => {
6777
6933
  setPendingDeletions((prev) => [...prev, fileId]);
6778
6934
  }, []);
6779
6935
  const handleDeleteSelected = () => {
@@ -7001,7 +7157,7 @@ function TableBlockClient({
7001
7157
  setIsSaving(false);
7002
7158
  }
7003
7159
  };
7004
- const getRowRelationLabels = useCallback11((rowVal, col) => {
7160
+ const getRowRelationLabels = useCallback12((rowVal, col) => {
7005
7161
  const ids = normalizeRelationValue(rowVal);
7006
7162
  if (ids.length === 0) return [];
7007
7163
  const options = relationOptions[col.name] || [];
@@ -7020,7 +7176,7 @@ function TableBlockClient({
7020
7176
  return "";
7021
7177
  }).filter(Boolean);
7022
7178
  }, [relationOptions]);
7023
- const getUniqueRelationOptions = useCallback11((col) => {
7179
+ const getUniqueRelationOptions = useCallback12((col) => {
7024
7180
  if (relationFilterOptions[col.name]) {
7025
7181
  return relationFilterOptions[col.name];
7026
7182
  }
@@ -7448,7 +7604,7 @@ function TableBlockClient({
7448
7604
  const isDragOver = canReorderColumns && dragOverColName === col.name;
7449
7605
  const colMinWidth = calculateMinColumnWidth(col.name, false, col.type);
7450
7606
  const currentWidth = Math.max(colMinWidth, columnWidths[col.name] || 200);
7451
- const isRelation = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION";
7607
+ const isRelation2 = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "RELATION";
7452
7608
  const filterVal = columnFilters[col.name];
7453
7609
  const hasActiveFilter = Array.isArray(filterVal) ? filterVal.length > 0 : filterVal && typeof filterVal === "object" && "values" in filterVal ? filterVal.values.length > 0 : Boolean(filterVal && filterVal.trim() !== "");
7454
7610
  let filterTooltip = "\u05D7\u05E4\u05E9 \u05D5\u05E1\u05E0\u05DF \u05D1\u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5";
@@ -7479,7 +7635,7 @@ function TableBlockClient({
7479
7635
  title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
7480
7636
  }
7481
7637
  ),
7482
- isSearching && !isRelation ? /* @__PURE__ */ jsxs12(
7638
+ isSearching && !isRelation2 ? /* @__PURE__ */ jsxs12(
7483
7639
  "div",
7484
7640
  {
7485
7641
  ref: activeSearchRef,
@@ -7536,7 +7692,7 @@ function TableBlockClient({
7536
7692
  onClick: (e) => {
7537
7693
  e.stopPropagation();
7538
7694
  e.preventDefault();
7539
- if (isRelation) {
7695
+ if (isRelation2) {
7540
7696
  if (activeRelationCol === col.name) {
7541
7697
  setActiveRelationCol(null);
7542
7698
  setRelationTriggerRect(null);
@@ -7552,7 +7708,7 @@ function TableBlockClient({
7552
7708
  setActiveSearchCol(col.name);
7553
7709
  }
7554
7710
  },
7555
- className: `p-0.5 rounded transition-colors cursor-pointer mb-0.5 shrink-0 ${hasActiveFilter ? "opacity-100 text-blue-600 bg-blue-100 hover:bg-blue-200" : activeRelationCol === col.name ? "opacity-100 text-blue-600 bg-blue-100" : isRelation ? "opacity-100 text-slate-400 hover:text-slate-600 hover:bg-slate-200/60" : "opacity-0 group-hover:opacity-100 text-slate-400 hover:text-slate-600 hover:bg-slate-200/60"}`,
7711
+ className: `p-0.5 rounded transition-colors cursor-pointer mb-0.5 shrink-0 ${hasActiveFilter ? "opacity-100 text-blue-600 bg-blue-100 hover:bg-blue-200" : activeRelationCol === col.name ? "opacity-100 text-blue-600 bg-blue-100" : isRelation2 ? "opacity-100 text-slate-400 hover:text-slate-600 hover:bg-slate-200/60" : "opacity-0 group-hover:opacity-100 text-slate-400 hover:text-slate-600 hover:bg-slate-200/60"}`,
7556
7712
  title: filterTooltip,
7557
7713
  children: /* @__PURE__ */ jsx13(Filter, { className: "w-3 h-3" })
7558
7714
  }
@@ -7597,7 +7753,7 @@ function TableBlockClient({
7597
7753
  isUpdatingActive,
7598
7754
  onToggleSelect: toggleSelectRow,
7599
7755
  onToggleExpand: handleToggleExpand,
7600
- handleCellChange,
7756
+ handleCellChange: handleCellChangeWithCopy,
7601
7757
  handleQuietCellChange,
7602
7758
  handleUpdateColumnConfig,
7603
7759
  onMarkForDeletion: handleMarkForDeletion,
@@ -7801,6 +7957,7 @@ var TableRow = React12.memo(function TableRow2({
7801
7957
  readOnly,
7802
7958
  permissions
7803
7959
  }) {
7960
+ const lockedCopyTargets = getRelationCopyLockedTargets(schema == null ? void 0 : schema.columns);
7804
7961
  return /* @__PURE__ */ jsxs12(React12.Fragment, { children: [
7805
7962
  /* @__PURE__ */ jsxs12("tr", { className: `transition-colors group hover:bg-blue-50 ${isSelected ? "bg-blue-50" : ""}`, children: [
7806
7963
  /* @__PURE__ */ jsx13("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", style: { width: 80, minWidth: 80, maxWidth: 80 }, children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-center gap-1.5", children: [
@@ -7896,7 +8053,7 @@ var TableRow = React12.memo(function TableRow2({
7896
8053
  column: col,
7897
8054
  rowId: row.id,
7898
8055
  onChange: (v) => handleCellChange(row.id, col.name, v),
7899
- readOnly,
8056
+ readOnly: readOnly || lockedCopyTargets.has(col.name),
7900
8057
  context: {
7901
8058
  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",
7902
8059
  tableId: (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id),
@@ -7957,7 +8114,7 @@ function TableBlock(props) {
7957
8114
  }
7958
8115
 
7959
8116
  // src/components/PlacementBlock/PlacementBlock.tsx
7960
- import { useState as useState14, useEffect as useEffect12, useRef as useRef11, useCallback as useCallback12, useMemo as useMemo7 } from "react";
8117
+ import { useState as useState14, useEffect as useEffect12, useRef as useRef12, useCallback as useCallback13, useMemo as useMemo7 } from "react";
7961
8118
  import { AgGridReact } from "ag-grid-react";
7962
8119
  import {
7963
8120
  ModuleRegistry,
@@ -8457,9 +8614,9 @@ var PlacementBlock = (props) => {
8457
8614
  const targetTableId = config == null ? void 0 : config.targetTableId;
8458
8615
  const displayField = (config == null ? void 0 : config.sourceDisplayFieldId) || "name";
8459
8616
  const assignmentField = config == null ? void 0 : config.targetAssignmentFieldId;
8460
- const executeActionRef = useRef11(executeAction);
8617
+ const executeActionRef = useRef12(executeAction);
8461
8618
  executeActionRef.current = executeAction;
8462
- const legacyRef = useRef11({ fetchSourceData, fetchTargetData, updateAssignment });
8619
+ const legacyRef = useRef12({ fetchSourceData, fetchTargetData, updateAssignment });
8463
8620
  legacyRef.current = { fetchSourceData, fetchTargetData, updateAssignment };
8464
8621
  const [sourceRows, setSourceRows] = useState14([]);
8465
8622
  const [sourceColumns, setSourceColumns] = useState14([]);
@@ -8477,7 +8634,7 @@ var PlacementBlock = (props) => {
8477
8634
  const [loadError, setLoadError] = useState14(null);
8478
8635
  const [saveError, setSaveError] = useState14(null);
8479
8636
  const [targetFilters, setTargetFilters] = useState14({});
8480
- const loadTable = useCallback12(async (tableId, kind) => {
8637
+ const loadTable = useCallback13(async (tableId, kind) => {
8481
8638
  const exec = executeActionRef.current;
8482
8639
  if (exec) {
8483
8640
  const res = await exec("FETCH_TABLE_DATA", { tableId, tableMetaId: tableId, limit: FETCH_LIMIT, skip: 0 });
@@ -8517,10 +8674,10 @@ var PlacementBlock = (props) => {
8517
8674
  cancelled = true;
8518
8675
  };
8519
8676
  }, [sourceTableId, targetTableId, loadTable]);
8520
- const displayValue = useCallback12((col, val) => {
8677
+ const displayValue = useCallback13((col, val) => {
8521
8678
  var _a2, _b2, _c, _d, _e;
8522
- let text = cellText(val);
8523
- if (text && /^[a-fA-F0-9]{24}$/.test(text)) {
8679
+ let text2 = cellText(val);
8680
+ if (text2 && /^[a-fA-F0-9]{24}$/.test(text2)) {
8524
8681
  let opts = targetRelOptions[col == null ? void 0 : col.name] || targetRelOptions[col == null ? void 0 : col.id] || [];
8525
8682
  if (opts.length === 0 && ((_a2 = col == null ? void 0 : col.name) == null ? void 0 : _a2.includes(RELATION_SEP))) {
8526
8683
  const baseName = col.name.split(RELATION_SEP)[0];
@@ -8532,10 +8689,10 @@ var PlacementBlock = (props) => {
8532
8689
  if (opts.length === 0) {
8533
8690
  opts = [...targetRows.map((r) => r.data), ...sourceRows.map((r) => r.data)];
8534
8691
  }
8535
- const found = opts.find((o) => String(o.id) === text || String(o._id) === text || String(o.value) === text);
8692
+ const found = opts.find((o) => String(o.id) === text2 || String(o._id) === text2 || String(o.value) === text2);
8536
8693
  if (found) return cellText((_e = (_d = (_c = (_b2 = found.label) != null ? _b2 : found.title) != null ? _c : found.name) != null ? _d : found.value) != null ? _e : found);
8537
8694
  }
8538
- return text;
8695
+ return text2;
8539
8696
  }, [targetRelOptions, targetRows, sourceRows]);
8540
8697
  const filterColumns = useMemo7(() => {
8541
8698
  const definedFilters = (config == null ? void 0 : config.filterFields) || [];
@@ -8594,7 +8751,7 @@ var PlacementBlock = (props) => {
8594
8751
  const assignmentColumn = useMemo7(() => targetColumns.find((c) => c.name === assignmentField), [targetColumns, assignmentField]);
8595
8752
  const isRelationField = ((_b = assignmentColumn == null ? void 0 : assignmentColumn.type) == null ? void 0 : _b.toUpperCase()) === "RELATION";
8596
8753
  const assignmentLabel = (assignmentColumn == null ? void 0 : assignmentColumn.label) || (assignmentColumn == null ? void 0 : assignmentColumn.name) || assignmentField || "";
8597
- const nameOf = useCallback12((row) => cellText(readColumnValue(row.data, displayField)) || "\u05DC\u05DC\u05D0 \u05E9\u05DD", [displayField]);
8754
+ const nameOf = useCallback13((row) => cellText(readColumnValue(row.data, displayField)) || "\u05DC\u05DC\u05D0 \u05E9\u05DD", [displayField]);
8598
8755
  const assignedIds = useMemo7(() => {
8599
8756
  var _a2;
8600
8757
  const target = targetRows.find((r) => r.id === selectedTargetId);
@@ -8609,13 +8766,13 @@ var PlacementBlock = (props) => {
8609
8766
  }).filter((id) => !!id && sourceRows.some((s) => s.id === id));
8610
8767
  return Array.from(new Set(ids));
8611
8768
  }, [selectedTargetId, targetRows, sourceRows, assignmentField, isRelationField, nameOf]);
8612
- const assignedIdsRef = useRef11(assignedIds);
8769
+ const assignedIdsRef = useRef12(assignedIds);
8613
8770
  assignedIdsRef.current = assignedIds;
8614
8771
  useEffect12(() => {
8615
8772
  setCandidateIds(assignedIdsRef.current);
8616
8773
  setCheckedIds(assignedIdsRef.current);
8617
8774
  }, [selectedTargetId, sourceRows]);
8618
- const toGridRow = useCallback12((r, checked = false) => __spreadProps(__spreadValues({}, r.data), { id: r.id, __label: nameOf(r), __checked: checked, statusId: statusMap[r.id] || defaultStatusId }), [nameOf, statusMap, defaultStatusId]);
8775
+ const toGridRow = useCallback13((r, checked = false) => __spreadProps(__spreadValues({}, r.data), { id: r.id, __label: nameOf(r), __checked: checked, statusId: statusMap[r.id] || defaultStatusId }), [nameOf, statusMap, defaultStatusId]);
8619
8776
  const candidateGridData = useMemo7(() => {
8620
8777
  const checked = new Set(checkedIds);
8621
8778
  return candidateIds.map((id) => sourceRows.find((r) => r.id === id)).filter((r) => !!r).map((r) => toGridRow(r, checked.has(r.id)));
@@ -8624,7 +8781,7 @@ var PlacementBlock = (props) => {
8624
8781
  const set = new Set(candidateIds);
8625
8782
  return sourceRows.filter((r) => !set.has(r.id)).map((r) => toGridRow(r));
8626
8783
  }, [candidateIds, sourceRows, toGridRow]);
8627
- const persistAssignment = useCallback12(async (nextIds) => {
8784
+ const persistAssignment = useCallback13(async (nextIds) => {
8628
8785
  const exec = executeActionRef.current;
8629
8786
  if (exec && targetTableId && assignmentField && selectedTargetId) {
8630
8787
  const value = isRelationField ? nextIds : nextIds.map((id) => sourceRows.find((r) => r.id === id)).filter((r) => !!r).map(nameOf).join(", ");
@@ -8636,33 +8793,33 @@ var PlacementBlock = (props) => {
8636
8793
  for (const id of nextIds.filter((i) => !assignedIds.includes(i))) await legacyRef.current.updateAssignment(selectedTargetId, id);
8637
8794
  }
8638
8795
  }, [targetTableId, assignmentField, selectedTargetId, isRelationField, sourceRows, nameOf, assignedIds]);
8639
- const moveToCandidates = useCallback12((id) => {
8796
+ const moveToCandidates = useCallback13((id) => {
8640
8797
  setCandidateIds((prev) => prev.includes(id) ? prev : [...prev, id]);
8641
8798
  }, []);
8642
- const moveToSource = useCallback12((id) => {
8799
+ const moveToSource = useCallback13((id) => {
8643
8800
  setCandidateIds((prev) => prev.filter((x) => x !== id));
8644
8801
  setCheckedIds((prev) => prev.filter((x) => x !== id));
8645
8802
  setStatusMap((prev) => __spreadProps(__spreadValues({}, prev), { [id]: defaultStatusId }));
8646
8803
  }, [defaultStatusId]);
8647
- const moveToCandidatesRef = useRef11(moveToCandidates);
8804
+ const moveToCandidatesRef = useRef12(moveToCandidates);
8648
8805
  moveToCandidatesRef.current = moveToCandidates;
8649
- const moveToSourceRef = useRef11(moveToSource);
8806
+ const moveToSourceRef = useRef12(moveToSource);
8650
8807
  moveToSourceRef.current = moveToSource;
8651
- const toggleChecked = useCallback12((id) => {
8808
+ const toggleChecked = useCallback13((id) => {
8652
8809
  setCheckedIds((prev) => prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]);
8653
8810
  }, []);
8654
8811
  const allChecked = candidateIds.length > 0 && candidateIds.every((id) => checkedIds.includes(id));
8655
8812
  const someChecked = candidateIds.some((id) => checkedIds.includes(id));
8656
- const toggleAll = useCallback12(() => {
8813
+ const toggleAll = useCallback13(() => {
8657
8814
  setCheckedIds(allChecked ? [] : [...candidateIds]);
8658
8815
  }, [allChecked, candidateIds]);
8659
- const returnAll = useCallback12(() => {
8816
+ const returnAll = useCallback13(() => {
8660
8817
  setCandidateIds([]);
8661
8818
  setCheckedIds([]);
8662
8819
  }, []);
8663
8820
  const checkedCandidates = useMemo7(() => candidateIds.filter((id) => checkedIds.includes(id)), [candidateIds, checkedIds]);
8664
8821
  const isDirty = checkedCandidates.length !== assignedIds.length || checkedCandidates.some((id) => !assignedIds.includes(id));
8665
- const submitAssignment = useCallback12(async () => {
8822
+ const submitAssignment = useCallback13(async () => {
8666
8823
  if (!selectedTargetId) {
8667
8824
  alert("\u05D0\u05E0\u05D0 \u05D1\u05D7\u05E8 \u05E7\u05D5\u05D3\u05DD \u05E8\u05E9\u05D5\u05DE\u05EA \u05D9\u05E2\u05D3 \u05DC\u05E4\u05E0\u05D9 \u05D4\u05E9\u05D9\u05D1\u05D5\u05E5");
8668
8825
  return;
@@ -8678,14 +8835,14 @@ var PlacementBlock = (props) => {
8678
8835
  setIsSaving(false);
8679
8836
  }
8680
8837
  }, [selectedTargetId, persistAssignment, checkedCandidates]);
8681
- const cycleStatus = useCallback12((recordId) => {
8838
+ const cycleStatus = useCallback13((recordId) => {
8682
8839
  setStatusMap((prev) => {
8683
8840
  const current = prev[recordId] || defaultStatusId;
8684
8841
  const idx = statuses.findIndex((c) => c.id === current);
8685
8842
  return __spreadProps(__spreadValues({}, prev), { [recordId]: statuses[(idx + 1) % statuses.length].id });
8686
8843
  });
8687
8844
  }, [statuses, defaultStatusId]);
8688
- const cancelAssignment = useCallback12(async () => {
8845
+ const cancelAssignment = useCallback13(async () => {
8689
8846
  if (!selectedTargetId || assignedIds.length === 0) return;
8690
8847
  if (!window.confirm(`\u05DC\u05D1\u05D8\u05DC \u05D0\u05EA \u05D4\u05E9\u05D9\u05D1\u05D5\u05E5 \u05D5\u05DC\u05DE\u05D7\u05D5\u05E7 \u05D0\u05EA \u05D4\u05E0\u05EA\u05D5\u05DF \u05DE\u05E9\u05D3\u05D4 "${assignmentLabel}"?`)) return;
8691
8848
  const removed = new Set(assignedIds);
@@ -8701,7 +8858,7 @@ var PlacementBlock = (props) => {
8701
8858
  setIsSaving(false);
8702
8859
  }
8703
8860
  }, [selectedTargetId, assignedIds, assignmentLabel, persistAssignment]);
8704
- const makeColDefs = useCallback12((columns, fallbackName, withCheckbox = false) => {
8861
+ const makeColDefs = useCallback13((columns, fallbackName, withCheckbox = false) => {
8705
8862
  const defs = [];
8706
8863
  if (withCheckbox) {
8707
8864
  defs.push({
@@ -8740,9 +8897,9 @@ var PlacementBlock = (props) => {
8740
8897
  const sourceHeader = displayField === "name" ? "\u05E9\u05DD" : columnRefLabel(displayField);
8741
8898
  const sourceColDefs = useMemo7(() => makeColDefs(sourceColumns, sourceHeader), [makeColDefs, sourceColumns, sourceHeader]);
8742
8899
  const candidateColDefs = useMemo7(() => makeColDefs(sourceColumns, sourceHeader, true), [makeColDefs, sourceColumns, sourceHeader]);
8743
- const getRowId = useCallback12((p) => p.data.id, []);
8744
- const sourceContainerRef = useRef11(null);
8745
- const assignedContainerRef = useRef11(null);
8900
+ const getRowId = useCallback13((p) => p.data.id, []);
8901
+ const sourceContainerRef = useRef12(null);
8902
+ const assignedContainerRef = useRef12(null);
8746
8903
  const [sourceApi, setSourceApi] = useState14(null);
8747
8904
  const [assignedApi, setAssignedApi] = useState14(null);
8748
8905
  useEffect12(() => {
@@ -8777,7 +8934,7 @@ var PlacementBlock = (props) => {
8777
8934
  [assignedIds, sourceRows, nameOf]
8778
8935
  );
8779
8936
  const activeTarget = targetRows.find((r) => r.id === selectedTargetId);
8780
- const targetLabel = useCallback12((r) => {
8937
+ const targetLabel = useCallback13((r) => {
8781
8938
  const col = targetColumns.find((c) => c.name === selectorField || c.id === selectorField);
8782
8939
  return displayValue(col || { name: selectorField }, readColumnValue(r.data, selectorField)) || "\u05DC\u05DC\u05D0 \u05E9\u05DD";
8783
8940
  }, [selectorField, targetColumns, displayValue]);
@@ -8797,15 +8954,15 @@ var PlacementBlock = (props) => {
8797
8954
  ] }),
8798
8955
  activeTarget ? /* @__PURE__ */ jsxs14("div", { className: "space-y-2 text-xs text-slate-700 overflow-y-auto pr-1 max-h-32", children: [
8799
8956
  /* @__PURE__ */ jsx16("div", { className: "font-bold text-slate-900 text-sm mb-1", children: targetLabel(activeTarget) }),
8800
- previewColumns.map((col) => ({ col, text: displayValue(col, readColumnValue(activeTarget.data, col.name)) })).filter(({ col, text }) => {
8957
+ previewColumns.map((col) => ({ col, text: displayValue(col, readColumnValue(activeTarget.data, col.name)) })).filter(({ col, text: text2 }) => {
8801
8958
  var _a2;
8802
- return text && (col.type === "RELATION" || typeof ((_a2 = activeTarget.data) == null ? void 0 : _a2[col.name]) !== "object");
8803
- }).map(({ col, text }) => /* @__PURE__ */ jsxs14("div", { className: "flex gap-2 items-start", children: [
8959
+ return text2 && (col.type === "RELATION" || typeof ((_a2 = activeTarget.data) == null ? void 0 : _a2[col.name]) !== "object");
8960
+ }).map(({ col, text: text2 }) => /* @__PURE__ */ jsxs14("div", { className: "flex gap-2 items-start", children: [
8804
8961
  /* @__PURE__ */ jsxs14("span", { className: "font-semibold shrink-0", children: [
8805
8962
  col.label || col.name,
8806
8963
  ":"
8807
8964
  ] }),
8808
- /* @__PURE__ */ jsx16("span", { className: "break-words line-clamp-2", children: text })
8965
+ /* @__PURE__ */ jsx16("span", { className: "break-words line-clamp-2", children: text2 })
8809
8966
  ] }, col.name)),
8810
8967
  assignmentField && assignedText && /* @__PURE__ */ jsxs14("div", { className: "flex gap-2 items-start", children: [
8811
8968
  /* @__PURE__ */ jsxs14("span", { className: "font-semibold shrink-0", children: [
@@ -8919,7 +9076,7 @@ import React18 from "react";
8919
9076
  import { CheckCircle2 as CheckCircle24, AlertCircle as AlertCircle5, X as X12, Loader2 as Loader28, Phone as Phone4, Send as Send3, Image as ImageIcon3, FileText as FileText4, Video as Video3 } from "lucide-react";
8920
9077
 
8921
9078
  // src/components/WhatsAppComponent/CreateTemplateModal.tsx
8922
- import { useState as useState15, useEffect as useEffect13, useRef as useRef12, useMemo as useMemo8 } from "react";
9079
+ import { useState as useState15, useEffect as useEffect13, useRef as useRef13, useMemo as useMemo8 } from "react";
8923
9080
  import {
8924
9081
  X as X9,
8925
9082
  Plus,
@@ -9082,14 +9239,14 @@ function CreateTemplateModal({
9082
9239
  const [fileBase64, setFileBase64] = useState15("");
9083
9240
  const [buttons, setButtons] = useState15([]);
9084
9241
  const [isAddButtonOpen, setIsAddButtonOpen] = useState15(false);
9085
- const addButtonDropdownRef = useRef12(null);
9242
+ const addButtonDropdownRef = useRef13(null);
9086
9243
  const [isSubmitting, setIsSubmitting] = useState15(false);
9087
9244
  const [submittingStep, setSubmittingStep] = useState15("");
9088
9245
  const [submitError, setSubmitError] = useState15(null);
9089
9246
  const [fileError, setFileError] = useState15(null);
9090
- const textareaRef = useRef12(null);
9091
- const fileInputRef = useRef12(null);
9092
- const emojiPickerRef = useRef12(null);
9247
+ const textareaRef = useRef13(null);
9248
+ const fileInputRef = useRef13(null);
9249
+ const emojiPickerRef = useRef13(null);
9093
9250
  const [isEmojiPickerOpen, setIsEmojiPickerOpen] = useState15(false);
9094
9251
  useEffect13(() => {
9095
9252
  function handleClickOutside(event) {
@@ -10154,7 +10311,7 @@ function CreateTemplateModal({
10154
10311
  }
10155
10312
 
10156
10313
  // src/components/WhatsAppComponent/hooks/useWhatsAppState.ts
10157
- import { useState as useState16, useEffect as useEffect14, useRef as useRef13, useMemo as useMemo9, useCallback as useCallback13 } from "react";
10314
+ import { useState as useState16, useEffect as useEffect14, useRef as useRef14, useMemo as useMemo9, useCallback as useCallback14 } from "react";
10158
10315
 
10159
10316
  // src/components/WhatsAppComponent/utils/recipientEngine.ts
10160
10317
  var STORAGE_KEY_TEST_PHONE = "whatsapp_test_phone";
@@ -11476,12 +11633,12 @@ function useWhatsAppState(props) {
11476
11633
  const [filters, setFilters] = useState16({});
11477
11634
  const [selectedRowIds, setSelectedRowIds] = useState16([]);
11478
11635
  const [autoSelectCount, setAutoSelectCount] = useState16(null);
11479
- const isAutoSelectingRef = useRef13(false);
11480
- const isManualOverrideRef = useRef13(false);
11481
- const prevAutoSelectCountRef = useRef13(null);
11482
- const fetchedTableIdsRef = useRef13(/* @__PURE__ */ new Set());
11483
- const fullyFetchedRelationKeysRef = useRef13(/* @__PURE__ */ new Set());
11484
- const loadTableData = useCallback13(async () => {
11636
+ const isAutoSelectingRef = useRef14(false);
11637
+ const isManualOverrideRef = useRef14(false);
11638
+ const prevAutoSelectCountRef = useRef14(null);
11639
+ const fetchedTableIdsRef = useRef14(/* @__PURE__ */ new Set());
11640
+ const fullyFetchedRelationKeysRef = useRef14(/* @__PURE__ */ new Set());
11641
+ const loadTableData = useCallback14(async () => {
11485
11642
  var _a2;
11486
11643
  const tableId = (settings == null ? void 0 : settings.tableMetaId) || (injectedData == null ? void 0 : injectedData.tableMetaId) || (injectedData == null ? void 0 : injectedData.tableId);
11487
11644
  if (!tableId || !executeAction) return;
@@ -11745,10 +11902,10 @@ function useWhatsAppState(props) {
11745
11902
  });
11746
11903
  const [broadcastSummary, setBroadcastSummary] = useState16(null);
11747
11904
  const [rowStatusMap, setRowStatusMap] = useState16({});
11748
- const clearBroadcastSummary = useCallback13(() => {
11905
+ const clearBroadcastSummary = useCallback14(() => {
11749
11906
  setBroadcastSummary(null);
11750
11907
  }, []);
11751
- const handleTestPhoneChange = useCallback13((val) => {
11908
+ const handleTestPhoneChange = useCallback14((val) => {
11752
11909
  setTestPhoneNumber(val);
11753
11910
  if (typeof window !== "undefined") {
11754
11911
  try {
@@ -11758,7 +11915,7 @@ function useWhatsAppState(props) {
11758
11915
  }
11759
11916
  }
11760
11917
  }, []);
11761
- const getRelationOptionsForCol = useCallback13(
11918
+ const getRelationOptionsForCol = useCallback14(
11762
11919
  (colName, parentColName) => {
11763
11920
  var _a2, _b2, _c, _d;
11764
11921
  if (parentColName) {
@@ -12049,7 +12206,7 @@ function useWhatsAppState(props) {
12049
12206
  isManualOverrideRef.current = false;
12050
12207
  prevAutoSelectCountRef.current = autoSelectCount;
12051
12208
  }, [autoSelectCount, filteredData]);
12052
- const embeddedTableExecuteAction = useCallback13(async (actionType, payload) => {
12209
+ const embeddedTableExecuteAction = useCallback14(async (actionType, payload) => {
12053
12210
  if (actionType === "FETCH_TABLE_DATA") {
12054
12211
  const colFilters = (payload == null ? void 0 : payload.columnFilters) || (payload == null ? void 0 : payload.filters);
12055
12212
  const searchQuery = payload == null ? void 0 : payload.search;
@@ -12095,7 +12252,7 @@ function useWhatsAppState(props) {
12095
12252
  const activeFiltersCount = useMemo9(() => {
12096
12253
  return Object.values(filters).filter((v) => v !== "").length;
12097
12254
  }, [filters]);
12098
- const handleSelectionChange = useCallback13((selectedIds) => {
12255
+ const handleSelectionChange = useCallback14((selectedIds) => {
12099
12256
  setSelectedRowIds((prev) => {
12100
12257
  if (prev.length === selectedIds.length && prev.every((id, idx) => id === selectedIds[idx])) {
12101
12258
  return prev;
@@ -12109,13 +12266,13 @@ function useWhatsAppState(props) {
12109
12266
  return selectedIds;
12110
12267
  });
12111
12268
  }, [autoSelectCount]);
12112
- const handleRowToggle = useCallback13((rowId, checked) => {
12269
+ const handleRowToggle = useCallback14((rowId, checked) => {
12113
12270
  if (autoSelectCount !== null && autoSelectCount > 0) {
12114
12271
  isManualOverrideRef.current = true;
12115
12272
  setAutoSelectCount(null);
12116
12273
  }
12117
12274
  }, [autoSelectCount]);
12118
- const toggleRowSelection = useCallback13((rowId, checked) => {
12275
+ const toggleRowSelection = useCallback14((rowId, checked) => {
12119
12276
  if (autoSelectCount !== null && autoSelectCount > 0) {
12120
12277
  isManualOverrideRef.current = true;
12121
12278
  setAutoSelectCount(null);
@@ -12139,7 +12296,7 @@ function useWhatsAppState(props) {
12139
12296
  const [isDropdownOpen, setIsDropdownOpen] = useState16(false);
12140
12297
  const [isDeleting, setIsDeleting] = useState16(false);
12141
12298
  const [feedback, setFeedback] = useState16(null);
12142
- const loadTemplates = useCallback13(async () => {
12299
+ const loadTemplates = useCallback14(async () => {
12143
12300
  var _a2, _b2;
12144
12301
  if (!executeAction) {
12145
12302
  setIsLoading(false);
@@ -12234,7 +12391,7 @@ function useWhatsAppState(props) {
12234
12391
  setHeaderMediaUrl("");
12235
12392
  }
12236
12393
  }, [templateHeaderComp, selectedTemplate == null ? void 0 : selectedTemplate.name]);
12237
- const handleHeaderMediaUrlChange = useCallback13(
12394
+ const handleHeaderMediaUrlChange = useCallback14(
12238
12395
  (newUrl) => {
12239
12396
  setHeaderMediaUrl(newUrl);
12240
12397
  if ((selectedTemplate == null ? void 0 : selectedTemplate.name) && typeof window !== "undefined") {
@@ -12253,7 +12410,7 @@ function useWhatsAppState(props) {
12253
12410
  },
12254
12411
  [selectedTemplate == null ? void 0 : selectedTemplate.name]
12255
12412
  );
12256
- const handleResetHeaderMediaUrl = useCallback13(() => {
12413
+ const handleResetHeaderMediaUrl = useCallback14(() => {
12257
12414
  if ((selectedTemplate == null ? void 0 : selectedTemplate.name) && typeof window !== "undefined") {
12258
12415
  try {
12259
12416
  localStorage.removeItem(`whatsapp_template_media_${selectedTemplate.name}`);
@@ -12268,7 +12425,7 @@ function useWhatsAppState(props) {
12268
12425
  setHeaderMediaUrl(defaultUrl || "");
12269
12426
  }, [templateHeaderComp, selectedTemplate == null ? void 0 : selectedTemplate.name]);
12270
12427
  const [isUploadingMedia, setIsUploadingMedia] = useState16(false);
12271
- const handleFileUpload = useCallback13(
12428
+ const handleFileUpload = useCallback14(
12272
12429
  async (file, templateName) => {
12273
12430
  const tplName = templateName || (selectedTemplate == null ? void 0 : selectedTemplate.name) || "";
12274
12431
  if (!file) return;
@@ -12525,7 +12682,7 @@ function useWhatsAppState(props) {
12525
12682
  setIsSendingTest(false);
12526
12683
  }
12527
12684
  };
12528
- const handleSendMessages = useCallback13(async () => {
12685
+ const handleSendMessages = useCallback14(async () => {
12529
12686
  var _a2, _b2;
12530
12687
  if (isSendDisabled || isSendingBroadcast) return;
12531
12688
  const recipients = preparedRecipients;
@@ -12831,7 +12988,7 @@ function useWhatsAppState(props) {
12831
12988
  }
12832
12989
 
12833
12990
  // src/components/WhatsAppComponent/ui/TemplateSelectionBlock.tsx
12834
- import { useRef as useRef14 } from "react";
12991
+ import { useRef as useRef15 } from "react";
12835
12992
  import {
12836
12993
  FileText as FileText3,
12837
12994
  Trash2 as Trash23,
@@ -12874,7 +13031,7 @@ function TemplateSelectionBlock({
12874
13031
  isUploadingMedia = false,
12875
13032
  handleFileUpload
12876
13033
  }) {
12877
- const fileInputRef = useRef14(null);
13034
+ const fileInputRef = useRef15(null);
12878
13035
  return /* @__PURE__ */ jsxs16("div", { className: "col-span-12 lg:col-span-5 min-h-[26rem] h-full flex flex-col bg-slate-50/70 border border-slate-200 rounded-2xl p-3.5 relative", children: [
12879
13036
  /* @__PURE__ */ jsxs16("div", { className: "space-y-1.5 shrink-0", children: [
12880
13037
  /* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between pb-1.5 border-b border-slate-200/70 shrink-0 gap-2", children: [
@@ -13841,7 +13998,7 @@ function SettingsAndActionsBlock({
13841
13998
  }
13842
13999
 
13843
14000
  // src/components/WhatsAppComponent/inbox/useInboxState.ts
13844
- import { useState as useState17, useEffect as useEffect15, useCallback as useCallback14, useRef as useRef15 } from "react";
14001
+ import { useState as useState17, useEffect as useEffect15, useCallback as useCallback15, useRef as useRef16 } from "react";
13845
14002
  function useInboxState(orgId, actions) {
13846
14003
  const [conversations, setConversations] = useState17([]);
13847
14004
  const [activeConversationId, setActiveConversationId] = useState17(null);
@@ -13849,11 +14006,11 @@ function useInboxState(orgId, actions) {
13849
14006
  const [isLoading, setIsLoading] = useState17(false);
13850
14007
  const [isSending, setIsSending] = useState17(false);
13851
14008
  const [error, setError] = useState17(null);
13852
- const actionsRef = useRef15(actions);
14009
+ const actionsRef = useRef16(actions);
13853
14010
  useEffect15(() => {
13854
14011
  actionsRef.current = actions;
13855
14012
  });
13856
- const fetchConversations = useCallback14(async () => {
14013
+ const fetchConversations = useCallback15(async () => {
13857
14014
  if (!orgId) return;
13858
14015
  const res = await actionsRef.current.getConversations(orgId);
13859
14016
  if (res.success && res.data) {
@@ -13862,7 +14019,7 @@ function useInboxState(orgId, actions) {
13862
14019
  setError(res.error);
13863
14020
  }
13864
14021
  }, [orgId]);
13865
- const fetchMessages = useCallback14(async (conversationId, silent = false) => {
14022
+ const fetchMessages = useCallback15(async (conversationId, silent = false) => {
13866
14023
  if (!silent) setIsLoading(true);
13867
14024
  const res = await actionsRef.current.getMessages(conversationId);
13868
14025
  if (res.success && res.data) {
@@ -13889,18 +14046,18 @@ function useInboxState(orgId, actions) {
13889
14046
  setActiveConversationId(id);
13890
14047
  fetchMessages(id);
13891
14048
  };
13892
- const handleSendMessage = async (text) => {
13893
- if (!activeConversationId || !text.trim()) return;
14049
+ const handleSendMessage = async (text2) => {
14050
+ if (!activeConversationId || !text2.trim()) return;
13894
14051
  setIsSending(true);
13895
14052
  const tempMsg = {
13896
14053
  id: Date.now().toString(),
13897
14054
  direction: "OUTBOUND",
13898
- content: text,
14055
+ content: text2,
13899
14056
  status: "SENDING",
13900
14057
  createdAt: /* @__PURE__ */ new Date()
13901
14058
  };
13902
14059
  setMessages((prev) => [tempMsg, ...prev]);
13903
- const res = await actions.sendMessage(activeConversationId, text, orgId);
14060
+ const res = await actions.sendMessage(activeConversationId, text2, orgId);
13904
14061
  if (res.success && res.data) {
13905
14062
  setMessages((prev) => prev.map((m) => m.id === tempMsg.id ? res.data : m));
13906
14063
  fetchConversations();
@@ -13974,12 +14131,12 @@ function ConversationList({ conversations, activeId, onSelect }) {
13974
14131
  }
13975
14132
 
13976
14133
  // src/components/WhatsAppComponent/inbox/ChatWindow.tsx
13977
- import { useState as useState18, useRef as useRef16, useEffect as useEffect16 } from "react";
14134
+ import { useState as useState18, useRef as useRef17, useEffect as useEffect16 } from "react";
13978
14135
  import { Send as Send2, User as User2, Loader2 as Loader27 } from "lucide-react";
13979
14136
  import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
13980
14137
  function ChatWindow({ activeConversation, messages, isLoading, isSending, onSendMessage }) {
13981
14138
  const [inputText, setInputText] = useState18("");
13982
- const messagesTopRef = useRef16(null);
14139
+ const messagesTopRef = useRef17(null);
13983
14140
  const scrollToTop = () => {
13984
14141
  var _a;
13985
14142
  (_a = messagesTopRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
@@ -14153,12 +14310,12 @@ function WhatsAppComponent(props) {
14153
14310
  return { success: false, error: (e == null ? void 0 : e.message) || "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D8\u05E2\u05D9\u05E0\u05EA \u05D4\u05D5\u05D3\u05E2\u05D5\u05EA" };
14154
14311
  }
14155
14312
  },
14156
- sendInboxMessageAction: async (convId, text, currentOrgId) => {
14313
+ sendInboxMessageAction: async (convId, text2, currentOrgId) => {
14157
14314
  if (!executeAction) return { success: false, error: "executeAction missing" };
14158
14315
  try {
14159
14316
  const data = await executeAction("SEND_WHATSAPP_INBOX_MESSAGE", {
14160
14317
  conversationId: convId,
14161
- text,
14318
+ text: text2,
14162
14319
  orgId: currentOrgId
14163
14320
  });
14164
14321
  return { success: true, data };
@@ -14708,7 +14865,9 @@ export {
14708
14865
  UNIVERSE_COMPONENTS,
14709
14866
  WhatsAppComponent,
14710
14867
  applyFormulaColumns,
14868
+ applyRelationCopy,
14711
14869
  buildColumnOptions,
14870
+ buildRelationCopyPatch,
14712
14871
  buildRelationRef,
14713
14872
  calculateMinColumnWidth,
14714
14873
  checkElementTruncation,
@@ -14728,8 +14887,12 @@ export {
14728
14887
  formatTimeIso,
14729
14888
  generateWhatsAppLink,
14730
14889
  getDeterministicPastelBadge,
14890
+ getEligibleCopyTargets,
14731
14891
  getNextVariableIndex,
14892
+ getRelationCopyLockedTargets,
14893
+ getRelationCopyTargetNames,
14732
14894
  getRolePermissions,
14895
+ getSelectedRelationId,
14733
14896
  getStatusConfig,
14734
14897
  hasBracketSpaces,
14735
14898
  hasConsecutiveVariables,
@@ -14753,6 +14916,7 @@ export {
14753
14916
  parseTimeParts,
14754
14917
  readColumnValue,
14755
14918
  reindexVariables,
14919
+ renameCopyTarget,
14756
14920
  resolveDefaultStatusId,
14757
14921
  resolveProtocol,
14758
14922
  sanitizePhoneNumber,
@@ -14766,6 +14930,7 @@ export {
14766
14930
  useToast,
14767
14931
  useWhatsAppState,
14768
14932
  validateFormula,
14933
+ validateRelationCopyTargets,
14769
14934
  validateSequentialVariables,
14770
14935
  validateTemplateBody,
14771
14936
  validateTemplateButtons,