@universe-platform/ui 0.1.0-beta.3 → 0.1.0-beta.5
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/globals.css +114 -0
- package/dist/index.js +451 -97
- package/dist/index.mjs +451 -97
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -77,7 +77,7 @@ function cn(...inputs) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
80
|
-
var
|
|
80
|
+
var import_react6 = require("react");
|
|
81
81
|
|
|
82
82
|
// src/hooks/useToast.ts
|
|
83
83
|
var import_react2 = require("react");
|
|
@@ -277,7 +277,7 @@ function useToast() {
|
|
|
277
277
|
}
|
|
278
278
|
|
|
279
279
|
// src/components/TableBlock/fields/fieldRegistry.tsx
|
|
280
|
-
var
|
|
280
|
+
var import_react5 = __toESM(require("react"));
|
|
281
281
|
|
|
282
282
|
// src/components/TableBlock/fields/DrivePickerCell.tsx
|
|
283
283
|
var import_react3 = require("react");
|
|
@@ -399,8 +399,311 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
|
|
|
399
399
|
) });
|
|
400
400
|
}
|
|
401
401
|
|
|
402
|
-
// src/components/TableBlock/fields/
|
|
402
|
+
// src/components/TableBlock/fields/DatePickerCell.tsx
|
|
403
|
+
var import_react4 = require("react");
|
|
404
|
+
var import_lucide_react3 = require("lucide-react");
|
|
403
405
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
406
|
+
function parseDateParts(val) {
|
|
407
|
+
if (val === void 0 || val === null || val === "") return null;
|
|
408
|
+
if (typeof val === "string") {
|
|
409
|
+
const trimmed = val.trim();
|
|
410
|
+
if (!trimmed) return null;
|
|
411
|
+
const ymdMatch = trimmed.match(/^(\d{4})[-/.](\d{1,2})[-/.](\d{1,2})/);
|
|
412
|
+
if (ymdMatch) {
|
|
413
|
+
const year = parseInt(ymdMatch[1], 10);
|
|
414
|
+
const month = parseInt(ymdMatch[2], 10);
|
|
415
|
+
const day = parseInt(ymdMatch[3], 10);
|
|
416
|
+
if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
|
|
417
|
+
return { year, month, day };
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
const dmyMatch = trimmed.match(/^(\d{1,2})[-/.](\d{1,2})[-/.](\d{4})/);
|
|
421
|
+
if (dmyMatch) {
|
|
422
|
+
const day = parseInt(dmyMatch[1], 10);
|
|
423
|
+
const month = parseInt(dmyMatch[2], 10);
|
|
424
|
+
const year = parseInt(dmyMatch[3], 10);
|
|
425
|
+
if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
|
|
426
|
+
return { year, month, day };
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
const parsed = new Date(trimmed);
|
|
430
|
+
if (!isNaN(parsed.getTime())) {
|
|
431
|
+
return {
|
|
432
|
+
year: parsed.getFullYear(),
|
|
433
|
+
month: parsed.getMonth() + 1,
|
|
434
|
+
day: parsed.getDate()
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
} else if (val instanceof Date && !isNaN(val.getTime())) {
|
|
438
|
+
return {
|
|
439
|
+
year: val.getFullYear(),
|
|
440
|
+
month: val.getMonth() + 1,
|
|
441
|
+
day: val.getDate()
|
|
442
|
+
};
|
|
443
|
+
} else if (typeof val === "number" && !isNaN(val)) {
|
|
444
|
+
const parsed = new Date(val);
|
|
445
|
+
if (!isNaN(parsed.getTime())) {
|
|
446
|
+
return {
|
|
447
|
+
year: parsed.getFullYear(),
|
|
448
|
+
month: parsed.getMonth() + 1,
|
|
449
|
+
day: parsed.getDate()
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
455
|
+
function formatDateIso(year, month, day) {
|
|
456
|
+
const mm = String(month).padStart(2, "0");
|
|
457
|
+
const dd = String(day).padStart(2, "0");
|
|
458
|
+
return `${year}-${mm}-${dd}`;
|
|
459
|
+
}
|
|
460
|
+
function formatDateDisplay(parts) {
|
|
461
|
+
if (!parts) return "";
|
|
462
|
+
const mm = String(parts.month).padStart(2, "0");
|
|
463
|
+
const dd = String(parts.day).padStart(2, "0");
|
|
464
|
+
return `${dd}/${mm}/${parts.year}`;
|
|
465
|
+
}
|
|
466
|
+
var HEBREW_MONTHS = [
|
|
467
|
+
"\u05D9\u05E0\u05D5\u05D0\u05E8",
|
|
468
|
+
"\u05E4\u05D1\u05E8\u05D5\u05D0\u05E8",
|
|
469
|
+
"\u05DE\u05E8\u05E5",
|
|
470
|
+
"\u05D0\u05E4\u05E8\u05D9\u05DC",
|
|
471
|
+
"\u05DE\u05D0\u05D9",
|
|
472
|
+
"\u05D9\u05D5\u05E0\u05D9",
|
|
473
|
+
"\u05D9\u05D5\u05DC\u05D9",
|
|
474
|
+
"\u05D0\u05D5\u05D2\u05D5\u05E1\u05D8",
|
|
475
|
+
"\u05E1\u05E4\u05D8\u05DE\u05D1\u05E8",
|
|
476
|
+
"\u05D0\u05D5\u05E7\u05D8\u05D5\u05D1\u05E8",
|
|
477
|
+
"\u05E0\u05D5\u05D1\u05DE\u05D1\u05E8",
|
|
478
|
+
"\u05D3\u05E6\u05DE\u05D1\u05E8"
|
|
479
|
+
];
|
|
480
|
+
var WEEKDAY_LABELS = ["\u05D0'", "\u05D1'", "\u05D2'", "\u05D3'", "\u05D4'", "\u05D5'", "\u05E9'"];
|
|
481
|
+
function DatePickerCell({ value, onChange, readOnly = false }) {
|
|
482
|
+
const [isOpen, setIsOpen] = (0, import_react4.useState)(false);
|
|
483
|
+
const containerRef = (0, import_react4.useRef)(null);
|
|
484
|
+
const [popoverPos, setPopoverPos] = (0, import_react4.useState)({ top: 0, right: 0 });
|
|
485
|
+
const parsedParts = (0, import_react4.useMemo)(() => parseDateParts(value), [value]);
|
|
486
|
+
const displayString = (0, import_react4.useMemo)(() => formatDateDisplay(parsedParts), [parsedParts]);
|
|
487
|
+
const [rawInput, setRawInput] = (0, import_react4.useState)(displayString);
|
|
488
|
+
(0, import_react4.useEffect)(() => {
|
|
489
|
+
setRawInput(displayString);
|
|
490
|
+
}, [displayString]);
|
|
491
|
+
const now = /* @__PURE__ */ new Date();
|
|
492
|
+
const [viewYear, setViewYear] = (0, import_react4.useState)((parsedParts == null ? void 0 : parsedParts.year) || now.getFullYear());
|
|
493
|
+
const [viewMonth, setViewMonth] = (0, import_react4.useState)((parsedParts == null ? void 0 : parsedParts.month) || now.getMonth() + 1);
|
|
494
|
+
(0, import_react4.useEffect)(() => {
|
|
495
|
+
if (parsedParts) {
|
|
496
|
+
setViewYear(parsedParts.year);
|
|
497
|
+
setViewMonth(parsedParts.month);
|
|
498
|
+
}
|
|
499
|
+
}, [parsedParts, isOpen]);
|
|
500
|
+
const updatePopoverPosition = (0, import_react4.useCallback)(() => {
|
|
501
|
+
if (containerRef.current) {
|
|
502
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
503
|
+
const right = window.innerWidth - rect.right;
|
|
504
|
+
const popoverHeight = 320;
|
|
505
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
506
|
+
if (spaceBelow < popoverHeight && rect.top > popoverHeight) {
|
|
507
|
+
setPopoverPos({
|
|
508
|
+
top: Math.max(10, rect.top - popoverHeight - 4),
|
|
509
|
+
right: Math.max(10, right)
|
|
510
|
+
});
|
|
511
|
+
} else {
|
|
512
|
+
setPopoverPos({
|
|
513
|
+
top: Math.min(window.innerHeight - popoverHeight - 10, rect.bottom + 4),
|
|
514
|
+
right: Math.max(10, right)
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}, []);
|
|
519
|
+
(0, import_react4.useEffect)(() => {
|
|
520
|
+
if (!isOpen) return;
|
|
521
|
+
updatePopoverPosition();
|
|
522
|
+
function handleScrollOrResize() {
|
|
523
|
+
updatePopoverPosition();
|
|
524
|
+
}
|
|
525
|
+
function handleClickOutside(event) {
|
|
526
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
527
|
+
const popoverEl = document.getElementById("date-picker-popover");
|
|
528
|
+
if (popoverEl && popoverEl.contains(event.target)) {
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
setIsOpen(false);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
window.addEventListener("scroll", handleScrollOrResize, true);
|
|
535
|
+
window.addEventListener("resize", handleScrollOrResize);
|
|
536
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
537
|
+
return () => {
|
|
538
|
+
window.removeEventListener("scroll", handleScrollOrResize, true);
|
|
539
|
+
window.removeEventListener("resize", handleScrollOrResize);
|
|
540
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
541
|
+
};
|
|
542
|
+
}, [isOpen, updatePopoverPosition]);
|
|
543
|
+
const handleInputChange = (e) => {
|
|
544
|
+
const text = e.target.value;
|
|
545
|
+
setRawInput(text);
|
|
546
|
+
if (!text.trim()) {
|
|
547
|
+
onChange(null);
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
const parts = parseDateParts(text);
|
|
551
|
+
if (parts) {
|
|
552
|
+
const iso = formatDateIso(parts.year, parts.month, parts.day);
|
|
553
|
+
onChange(iso);
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
const handleInputBlur = () => {
|
|
557
|
+
const parts = parseDateParts(rawInput);
|
|
558
|
+
if (parts) {
|
|
559
|
+
setRawInput(formatDateDisplay(parts));
|
|
560
|
+
} else if (!rawInput.trim()) {
|
|
561
|
+
setRawInput("");
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
const handleSelectDay = (day) => {
|
|
565
|
+
const iso = formatDateIso(viewYear, viewMonth, day);
|
|
566
|
+
onChange(iso);
|
|
567
|
+
setRawInput(formatDateDisplay({ year: viewYear, month: viewMonth, day }));
|
|
568
|
+
setIsOpen(false);
|
|
569
|
+
};
|
|
570
|
+
const handlePrevMonth = () => {
|
|
571
|
+
if (viewMonth === 1) {
|
|
572
|
+
setViewMonth(12);
|
|
573
|
+
setViewYear((prev) => prev - 1);
|
|
574
|
+
} else {
|
|
575
|
+
setViewMonth((prev) => prev - 1);
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
const handleNextMonth = () => {
|
|
579
|
+
if (viewMonth === 12) {
|
|
580
|
+
setViewMonth(1);
|
|
581
|
+
setViewYear((prev) => prev + 1);
|
|
582
|
+
} else {
|
|
583
|
+
setViewMonth((prev) => prev + 1);
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
const calendarDays = (0, import_react4.useMemo)(() => {
|
|
587
|
+
const firstDayIndex = new Date(viewYear, viewMonth - 1, 1).getDay();
|
|
588
|
+
const totalDays = new Date(viewYear, viewMonth, 0).getDate();
|
|
589
|
+
const days = [];
|
|
590
|
+
const prevMonthTotalDays = new Date(viewYear, viewMonth - 1, 0).getDate();
|
|
591
|
+
for (let i = firstDayIndex - 1; i >= 0; i--) {
|
|
592
|
+
days.push({ day: prevMonthTotalDays - i, isCurrentMonth: false });
|
|
593
|
+
}
|
|
594
|
+
for (let d = 1; d <= totalDays; d++) {
|
|
595
|
+
days.push({ day: d, isCurrentMonth: true });
|
|
596
|
+
}
|
|
597
|
+
const remaining = 7 - days.length % 7;
|
|
598
|
+
if (remaining < 7) {
|
|
599
|
+
for (let d = 1; d <= remaining; d++) {
|
|
600
|
+
days.push({ day: d, isCurrentMonth: false });
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
return days;
|
|
604
|
+
}, [viewYear, viewMonth]);
|
|
605
|
+
if (readOnly) {
|
|
606
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "px-2 py-1 flex items-center justify-end w-full h-full text-sm font-normal text-slate-800 text-right", dir: "ltr", children: displayString });
|
|
607
|
+
}
|
|
608
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { ref: containerRef, className: "relative w-full h-full flex items-center", children: [
|
|
609
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
610
|
+
"input",
|
|
611
|
+
{
|
|
612
|
+
type: "text",
|
|
613
|
+
dir: "ltr",
|
|
614
|
+
placeholder: "DD/MM/YYYY",
|
|
615
|
+
className: "w-full h-8 pl-8 pr-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm text-right font-normal text-slate-800",
|
|
616
|
+
value: rawInput,
|
|
617
|
+
onChange: handleInputChange,
|
|
618
|
+
onBlur: handleInputBlur
|
|
619
|
+
}
|
|
620
|
+
),
|
|
621
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
622
|
+
"button",
|
|
623
|
+
{
|
|
624
|
+
type: "button",
|
|
625
|
+
onClick: () => {
|
|
626
|
+
setIsOpen((prev) => {
|
|
627
|
+
const next = !prev;
|
|
628
|
+
if (next) updatePopoverPosition();
|
|
629
|
+
return next;
|
|
630
|
+
});
|
|
631
|
+
},
|
|
632
|
+
className: "absolute left-1.5 p-1 text-slate-400 hover:text-blue-600 rounded transition-colors",
|
|
633
|
+
title: "\u05D1\u05D7\u05E8 \u05EA\u05D0\u05E8\u05D9\u05DA",
|
|
634
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.Calendar, { className: "w-4 h-4" })
|
|
635
|
+
}
|
|
636
|
+
),
|
|
637
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
638
|
+
"div",
|
|
639
|
+
{
|
|
640
|
+
id: "date-picker-popover",
|
|
641
|
+
dir: "rtl",
|
|
642
|
+
style: { top: `${popoverPos.top}px`, right: `${popoverPos.right}px` },
|
|
643
|
+
className: "fixed z-[99999] w-72 bg-white rounded-xl shadow-2xl border border-slate-200 p-3.5 animate-in fade-in zoom-in-95 duration-150",
|
|
644
|
+
children: [
|
|
645
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center justify-between border-b border-slate-100 pb-2.5 mb-2.5", children: [
|
|
646
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "text-xs font-semibold text-slate-500", children: parsedParts ? `${parsedParts.day} \u05D1${HEBREW_MONTHS[parsedParts.month - 1]} ${parsedParts.year}` : "\u05D1\u05D7\u05D9\u05E8\u05EA \u05EA\u05D0\u05E8\u05D9\u05DA" }),
|
|
647
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
648
|
+
"button",
|
|
649
|
+
{
|
|
650
|
+
onClick: () => setIsOpen(false),
|
|
651
|
+
className: "text-slate-400 hover:text-slate-600 p-0.5 rounded-full hover:bg-slate-100",
|
|
652
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.X, { className: "w-4 h-4" })
|
|
653
|
+
}
|
|
654
|
+
)
|
|
655
|
+
] }),
|
|
656
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center justify-between mb-3 px-1", children: [
|
|
657
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
658
|
+
"button",
|
|
659
|
+
{
|
|
660
|
+
type: "button",
|
|
661
|
+
onClick: handleNextMonth,
|
|
662
|
+
className: "p-1 text-slate-600 hover:bg-slate-100 rounded-lg transition-colors",
|
|
663
|
+
title: "\u05D7\u05D5\u05D3\u05E9 \u05D4\u05D1\u05D0",
|
|
664
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.ChevronRight, { className: "w-4 h-4" })
|
|
665
|
+
}
|
|
666
|
+
),
|
|
667
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "font-bold text-sm text-slate-800", children: [
|
|
668
|
+
HEBREW_MONTHS[viewMonth - 1],
|
|
669
|
+
" ",
|
|
670
|
+
viewYear
|
|
671
|
+
] }),
|
|
672
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
673
|
+
"button",
|
|
674
|
+
{
|
|
675
|
+
type: "button",
|
|
676
|
+
onClick: handlePrevMonth,
|
|
677
|
+
className: "p-1 text-slate-600 hover:bg-slate-100 rounded-lg transition-colors",
|
|
678
|
+
title: "\u05D7\u05D5\u05D3\u05E9 \u05E7\u05D5\u05D3\u05DD",
|
|
679
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.ChevronLeft, { className: "w-4 h-4" })
|
|
680
|
+
}
|
|
681
|
+
)
|
|
682
|
+
] }),
|
|
683
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "grid grid-cols-7 gap-1 text-center mb-1.5", children: WEEKDAY_LABELS.map((label, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-[11px] font-bold text-slate-400 select-none py-0.5", children: label }, idx)) }),
|
|
684
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "grid grid-cols-7 gap-1 text-center", children: calendarDays.map((item, idx) => {
|
|
685
|
+
const isSelected = item.isCurrentMonth && (parsedParts == null ? void 0 : parsedParts.year) === viewYear && (parsedParts == null ? void 0 : parsedParts.month) === viewMonth && (parsedParts == null ? void 0 : parsedParts.day) === item.day;
|
|
686
|
+
const isToday = item.isCurrentMonth && now.getFullYear() === viewYear && now.getMonth() + 1 === viewMonth && now.getDate() === item.day;
|
|
687
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
688
|
+
"button",
|
|
689
|
+
{
|
|
690
|
+
type: "button",
|
|
691
|
+
disabled: !item.isCurrentMonth,
|
|
692
|
+
onClick: () => item.isCurrentMonth && handleSelectDay(item.day),
|
|
693
|
+
className: `h-8 w-8 mx-auto flex items-center justify-center rounded-lg text-xs transition-all ${!item.isCurrentMonth ? "text-slate-300 cursor-not-allowed" : isSelected ? "bg-blue-600 text-white font-bold shadow-md scale-105" : isToday ? "bg-blue-50 text-blue-700 font-bold border border-blue-300 hover:bg-blue-100" : "text-slate-700 hover:bg-slate-100 font-medium"}`,
|
|
694
|
+
children: item.day
|
|
695
|
+
},
|
|
696
|
+
idx
|
|
697
|
+
);
|
|
698
|
+
}) })
|
|
699
|
+
]
|
|
700
|
+
}
|
|
701
|
+
)
|
|
702
|
+
] });
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// src/components/TableBlock/fields/fieldRegistry.tsx
|
|
706
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
404
707
|
var CURRENCY_SYMBOLS = {
|
|
405
708
|
USD: "$",
|
|
406
709
|
EUR: "\u20AC",
|
|
@@ -417,24 +720,31 @@ function getRelationDisplayLabel(opt, column) {
|
|
|
417
720
|
if (val !== void 0 && val !== null && val !== "") {
|
|
418
721
|
return String(val);
|
|
419
722
|
}
|
|
723
|
+
if (opt.label && opt.label !== opt.id) {
|
|
724
|
+
return String(opt.label);
|
|
725
|
+
}
|
|
420
726
|
if (opt.data) {
|
|
421
727
|
const fallbackField = Object.keys(opt.data).find((k) => {
|
|
422
728
|
if (k === "_id" || k === "id") return false;
|
|
423
729
|
const v = opt.data[k];
|
|
424
730
|
if (typeof v === "string" && v.trim() !== "") return true;
|
|
425
|
-
if (typeof v === "number") return true;
|
|
731
|
+
if (typeof v === "number" && !isNaN(v)) return true;
|
|
426
732
|
return false;
|
|
427
733
|
});
|
|
428
734
|
if (fallbackField) return String(opt.data[fallbackField]);
|
|
429
735
|
}
|
|
736
|
+
if (opt.label) {
|
|
737
|
+
return String(opt.label);
|
|
738
|
+
}
|
|
430
739
|
return "\u05E2\u05E8\u05DA \u05E8\u05D9\u05E7";
|
|
431
740
|
}
|
|
432
741
|
var FORM_INPUTS = {
|
|
742
|
+
DATE: ({ value, onChange, column }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DatePickerCell, { value, onChange, column }),
|
|
433
743
|
CURRENCY: ({ value, column, onChange }) => {
|
|
434
744
|
const symbol = getCurrencySymbol(column.currencySymbol);
|
|
435
|
-
return /* @__PURE__ */ (0,
|
|
436
|
-
symbol && /* @__PURE__ */ (0,
|
|
437
|
-
/* @__PURE__ */ (0,
|
|
745
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "relative w-full h-full", children: [
|
|
746
|
+
symbol && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "absolute left-2 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none text-sm", children: symbol }),
|
|
747
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
438
748
|
"input",
|
|
439
749
|
{
|
|
440
750
|
type: "number",
|
|
@@ -449,7 +759,7 @@ var FORM_INPUTS = {
|
|
|
449
759
|
)
|
|
450
760
|
] });
|
|
451
761
|
},
|
|
452
|
-
TIME: ({ value, onChange }) => /* @__PURE__ */ (0,
|
|
762
|
+
TIME: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
453
763
|
"input",
|
|
454
764
|
{
|
|
455
765
|
type: "time",
|
|
@@ -459,13 +769,13 @@ var FORM_INPUTS = {
|
|
|
459
769
|
}
|
|
460
770
|
),
|
|
461
771
|
LINK: ({ value, onChange }) => {
|
|
462
|
-
const [isEditing, setIsEditing] =
|
|
772
|
+
const [isEditing, setIsEditing] = import_react5.default.useState(false);
|
|
463
773
|
const label = (value == null ? void 0 : value.label) || "";
|
|
464
774
|
const url = (value == null ? void 0 : value.url) || "";
|
|
465
775
|
if (!isEditing) {
|
|
466
|
-
return /* @__PURE__ */ (0,
|
|
467
|
-
url ? /* @__PURE__ */ (0,
|
|
468
|
-
/* @__PURE__ */ (0,
|
|
776
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2 px-2 py-1 h-full w-full", children: [
|
|
777
|
+
url ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline flex-1 truncate", children: label || url }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-slate-400 italic flex-1 text-sm", children: "\u05E8\u05D9\u05E7" }),
|
|
778
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
469
779
|
"button",
|
|
470
780
|
{
|
|
471
781
|
onClick: () => setIsEditing(true),
|
|
@@ -476,8 +786,8 @@ var FORM_INPUTS = {
|
|
|
476
786
|
)
|
|
477
787
|
] });
|
|
478
788
|
}
|
|
479
|
-
return /* @__PURE__ */ (0,
|
|
480
|
-
/* @__PURE__ */ (0,
|
|
789
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex gap-2 p-1 w-full min-w-[250px] items-center bg-white border border-blue-200 rounded shadow-sm z-10", children: [
|
|
790
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
481
791
|
"input",
|
|
482
792
|
{
|
|
483
793
|
type: "text",
|
|
@@ -487,7 +797,7 @@ var FORM_INPUTS = {
|
|
|
487
797
|
onChange: (e) => onChange({ label: e.target.value, url })
|
|
488
798
|
}
|
|
489
799
|
),
|
|
490
|
-
/* @__PURE__ */ (0,
|
|
800
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
491
801
|
"input",
|
|
492
802
|
{
|
|
493
803
|
type: "url",
|
|
@@ -497,7 +807,7 @@ var FORM_INPUTS = {
|
|
|
497
807
|
onChange: (e) => onChange({ label, url: e.target.value })
|
|
498
808
|
}
|
|
499
809
|
),
|
|
500
|
-
/* @__PURE__ */ (0,
|
|
810
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
501
811
|
"button",
|
|
502
812
|
{
|
|
503
813
|
onClick: () => setIsEditing(false),
|
|
@@ -508,7 +818,7 @@ var FORM_INPUTS = {
|
|
|
508
818
|
)
|
|
509
819
|
] });
|
|
510
820
|
},
|
|
511
|
-
BOOLEAN: ({ value, onChange }) => /* @__PURE__ */ (0,
|
|
821
|
+
BOOLEAN: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex items-center justify-center w-full h-full p-2", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
512
822
|
"input",
|
|
513
823
|
{
|
|
514
824
|
type: "checkbox",
|
|
@@ -517,7 +827,7 @@ var FORM_INPUTS = {
|
|
|
517
827
|
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
518
828
|
}
|
|
519
829
|
) }),
|
|
520
|
-
GOOGLE_DRIVE_FILE: ({ value, onChange, context }) => /* @__PURE__ */ (0,
|
|
830
|
+
GOOGLE_DRIVE_FILE: ({ value, onChange, context }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
521
831
|
DrivePickerCell,
|
|
522
832
|
{
|
|
523
833
|
value: value || null,
|
|
@@ -530,7 +840,7 @@ var FORM_INPUTS = {
|
|
|
530
840
|
RELATION: ({ value, onChange, column, context }) => {
|
|
531
841
|
var _a;
|
|
532
842
|
const options = ((_a = context == null ? void 0 : context.relationOptions) == null ? void 0 : _a[column.name]) || [];
|
|
533
|
-
|
|
843
|
+
import_react5.default.useEffect(() => {
|
|
534
844
|
if (typeof value === "string" && value !== "" && options.length > 0) {
|
|
535
845
|
const isValidId = options.some((o) => String(o.id) === String(value));
|
|
536
846
|
if (!isValidId) {
|
|
@@ -549,7 +859,7 @@ var FORM_INPUTS = {
|
|
|
549
859
|
_displayLabel: getRelationDisplayLabel(opt, column)
|
|
550
860
|
}));
|
|
551
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");
|
|
552
|
-
return /* @__PURE__ */ (0,
|
|
862
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
553
863
|
"select",
|
|
554
864
|
{
|
|
555
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",
|
|
@@ -561,13 +871,13 @@ var FORM_INPUTS = {
|
|
|
561
871
|
}
|
|
562
872
|
},
|
|
563
873
|
children: [
|
|
564
|
-
/* @__PURE__ */ (0,
|
|
565
|
-
validOptions.length > 0 ? validOptions.map((opt) => /* @__PURE__ */ (0,
|
|
874
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: "\u05D1\u05D7\u05E8..." }),
|
|
875
|
+
validOptions.length > 0 ? validOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: opt.id, children: opt._displayLabel }, opt.id)) : options.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "empty_all", disabled: true, children: "\u05DB\u05DC \u05D4\u05E2\u05E8\u05DB\u05D9\u05DD \u05D1\u05D8\u05D1\u05DC\u05D4 \u05D4\u05DE\u05E7\u05D5\u05E9\u05E8\u05EA \u05E8\u05D9\u05E7\u05D9\u05DD" }) : null
|
|
566
876
|
]
|
|
567
877
|
}
|
|
568
878
|
);
|
|
569
879
|
},
|
|
570
|
-
NUMBER: ({ value, onChange }) => /* @__PURE__ */ (0,
|
|
880
|
+
NUMBER: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
571
881
|
"input",
|
|
572
882
|
{
|
|
573
883
|
type: "number",
|
|
@@ -579,7 +889,7 @@ var FORM_INPUTS = {
|
|
|
579
889
|
}
|
|
580
890
|
}
|
|
581
891
|
),
|
|
582
|
-
DEFAULT: ({ value, onChange }) => /* @__PURE__ */ (0,
|
|
892
|
+
DEFAULT: ({ value, onChange }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
583
893
|
"input",
|
|
584
894
|
{
|
|
585
895
|
type: "text",
|
|
@@ -591,7 +901,7 @@ var FORM_INPUTS = {
|
|
|
591
901
|
};
|
|
592
902
|
|
|
593
903
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
594
|
-
var
|
|
904
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
595
905
|
function TableBlockClient({
|
|
596
906
|
data: initialRecords,
|
|
597
907
|
settings: schema,
|
|
@@ -633,18 +943,18 @@ function TableBlockClient({
|
|
|
633
943
|
return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
|
|
634
944
|
});
|
|
635
945
|
};
|
|
636
|
-
const [localColumns, setLocalColumns] = (0,
|
|
637
|
-
(0,
|
|
946
|
+
const [localColumns, setLocalColumns] = (0, import_react6.useState)(() => (schema == null ? void 0 : schema.columns) || []);
|
|
947
|
+
(0, import_react6.useEffect)(() => {
|
|
638
948
|
if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
|
|
639
949
|
setLocalColumns(schema.columns);
|
|
640
950
|
}
|
|
641
951
|
}, [schema == null ? void 0 : schema.columns]);
|
|
642
|
-
const [dirty, setDirty] = (0,
|
|
643
|
-
const dirtyRef = (0,
|
|
644
|
-
(0,
|
|
952
|
+
const [dirty, setDirty] = (0, import_react6.useState)({ added: [], modified: {}, deleted: [] });
|
|
953
|
+
const dirtyRef = (0, import_react6.useRef)(dirty);
|
|
954
|
+
(0, import_react6.useEffect)(() => {
|
|
645
955
|
dirtyRef.current = dirty;
|
|
646
956
|
}, [dirty]);
|
|
647
|
-
const mergeWithDirty = (0,
|
|
957
|
+
const mergeWithDirty = (0, import_react6.useCallback)((baseRecords) => {
|
|
648
958
|
const { added, modified, deleted } = dirtyRef.current;
|
|
649
959
|
const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
|
|
650
960
|
const modifiedRecords = nonDeleted.map((r) => {
|
|
@@ -657,8 +967,8 @@ function TableBlockClient({
|
|
|
657
967
|
const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
|
|
658
968
|
return [...uniqueAdded, ...modifiedRecords];
|
|
659
969
|
}, []);
|
|
660
|
-
const [data, setData] = (0,
|
|
661
|
-
(0,
|
|
970
|
+
const [data, setData] = (0, import_react6.useState)(() => normalizeRecords(initialRecords));
|
|
971
|
+
(0, import_react6.useEffect)(() => {
|
|
662
972
|
if (initialRecords) {
|
|
663
973
|
setData(mergeWithDirty(normalizeRecords(initialRecords)));
|
|
664
974
|
}
|
|
@@ -673,20 +983,20 @@ function TableBlockClient({
|
|
|
673
983
|
}
|
|
674
984
|
return false;
|
|
675
985
|
};
|
|
676
|
-
const [baseRecordsMap, setBaseRecordsMap] = (0,
|
|
986
|
+
const [baseRecordsMap, setBaseRecordsMap] = (0, import_react6.useState)(() => {
|
|
677
987
|
const map = /* @__PURE__ */ new Map();
|
|
678
988
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
679
989
|
return map;
|
|
680
990
|
});
|
|
681
|
-
(0,
|
|
991
|
+
(0, import_react6.useEffect)(() => {
|
|
682
992
|
if (initialRecords && initialRecords.length > 0) {
|
|
683
993
|
const map = /* @__PURE__ */ new Map();
|
|
684
994
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
685
995
|
setBaseRecordsMap(map);
|
|
686
996
|
}
|
|
687
997
|
}, [initialRecords]);
|
|
688
|
-
(0,
|
|
689
|
-
const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.
|
|
998
|
+
(0, import_react6.useEffect)(() => {
|
|
999
|
+
const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
690
1000
|
if (!tableId || !executeAction) return;
|
|
691
1001
|
if (!(schema == null ? void 0 : schema.columns) || schema.columns.length === 0 || (!initialRecords || initialRecords.length === 0)) {
|
|
692
1002
|
executeAction("FETCH_TABLE_DATA", { tableId }).then((res) => {
|
|
@@ -707,20 +1017,20 @@ function TableBlockClient({
|
|
|
707
1017
|
console.error("[TableBlock] Failed to auto-fetch table data:", err);
|
|
708
1018
|
});
|
|
709
1019
|
}
|
|
710
|
-
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.
|
|
711
|
-
(0,
|
|
1020
|
+
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, schema == null ? void 0 : schema.columns, initialRecords, executeAction, mergeWithDirty]);
|
|
1021
|
+
(0, import_react6.useEffect)(() => {
|
|
712
1022
|
if (error) {
|
|
713
1023
|
showError(error, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E8\u05DB\u05D9\u05D1");
|
|
714
1024
|
}
|
|
715
1025
|
}, [error, showError]);
|
|
716
|
-
const [searchQuery, setSearchQuery] = (0,
|
|
717
|
-
const [selectedIds, setSelectedIds] = (0,
|
|
718
|
-
const [pendingDeletions, setPendingDeletions] = (0,
|
|
719
|
-
const [isSaving, setIsSaving] = (0,
|
|
720
|
-
const [isSaveSuccess, setIsSaveSuccess] = (0,
|
|
721
|
-
const [relationOptions, setRelationOptions] = (0,
|
|
722
|
-
const schemaColsString = (0,
|
|
723
|
-
const refetchRelation = (0,
|
|
1026
|
+
const [searchQuery, setSearchQuery] = (0, import_react6.useState)("");
|
|
1027
|
+
const [selectedIds, setSelectedIds] = (0, import_react6.useState)(/* @__PURE__ */ new Set());
|
|
1028
|
+
const [pendingDeletions, setPendingDeletions] = (0, import_react6.useState)([]);
|
|
1029
|
+
const [isSaving, setIsSaving] = (0, import_react6.useState)(false);
|
|
1030
|
+
const [isSaveSuccess, setIsSaveSuccess] = (0, import_react6.useState)(false);
|
|
1031
|
+
const [relationOptions, setRelationOptions] = (0, import_react6.useState)({});
|
|
1032
|
+
const schemaColsString = (0, import_react6.useMemo)(() => JSON.stringify(localColumns || []), [localColumns]);
|
|
1033
|
+
const refetchRelation = (0, import_react6.useCallback)(async (colName) => {
|
|
724
1034
|
var _a;
|
|
725
1035
|
let parsedCols = [];
|
|
726
1036
|
try {
|
|
@@ -731,7 +1041,7 @@ function TableBlockClient({
|
|
|
731
1041
|
if (!col || ((_a = col.type) == null ? void 0 : _a.toUpperCase()) !== "RELATION" || !col.referencedTableId) return;
|
|
732
1042
|
try {
|
|
733
1043
|
if (executeAction) {
|
|
734
|
-
const options = await executeAction("FETCH_RELATION", { referencedTableId: col.referencedTableId });
|
|
1044
|
+
const options = await executeAction("FETCH_RELATION", { referencedTableId: col.referencedTableId, displayField: col.displayField });
|
|
735
1045
|
if (options && Array.isArray(options)) {
|
|
736
1046
|
setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [colName]: options }));
|
|
737
1047
|
}
|
|
@@ -740,7 +1050,7 @@ function TableBlockClient({
|
|
|
740
1050
|
console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
|
|
741
1051
|
}
|
|
742
1052
|
}, [schemaColsString, executeAction]);
|
|
743
|
-
(0,
|
|
1053
|
+
(0, import_react6.useEffect)(() => {
|
|
744
1054
|
let parsedCols = [];
|
|
745
1055
|
try {
|
|
746
1056
|
parsedCols = JSON.parse(schemaColsString);
|
|
@@ -754,7 +1064,7 @@ function TableBlockClient({
|
|
|
754
1064
|
refetchRelation(col.name);
|
|
755
1065
|
});
|
|
756
1066
|
}, [schemaColsString, refetchRelation]);
|
|
757
|
-
const filteredColumns = (0,
|
|
1067
|
+
const filteredColumns = (0, import_react6.useMemo)(() => {
|
|
758
1068
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
759
1069
|
return (localColumns || []).filter((col) => !systemFields.includes(col.name));
|
|
760
1070
|
}, [localColumns]);
|
|
@@ -926,19 +1236,58 @@ function TableBlockClient({
|
|
|
926
1236
|
showError("\u05E8\u05DB\u05D9\u05D1 \u05D4\u05EA\u05E7\u05E9\u05D5\u05E8\u05EA \u05DC\u05D0 \u05D0\u05D5\u05EA\u05D7\u05DC", "\u05E9\u05D2\u05D9\u05D0\u05EA \u05EA\u05E7\u05E9\u05D5\u05E8\u05EA");
|
|
927
1237
|
return;
|
|
928
1238
|
}
|
|
929
|
-
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.
|
|
1239
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
930
1240
|
if (!targetTableId) {
|
|
931
1241
|
showError("\u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05E9\u05DE\u05D5\u05E8: \u05DE\u05D6\u05D4\u05D4 \u05D4\u05D8\u05D1\u05DC\u05D4 \u05D7\u05E1\u05E8 (tableId)", "\u05E9\u05D2\u05D9\u05D0\u05EA \u05E9\u05DE\u05D9\u05E8\u05D4");
|
|
932
1242
|
return;
|
|
933
1243
|
}
|
|
1244
|
+
const tempToRealMap = {};
|
|
1245
|
+
const realRecordDataMap = {};
|
|
934
1246
|
if (dirty.added.length > 0) {
|
|
935
1247
|
const payload = dirty.added.map((row) => formatPayload(row.data));
|
|
936
|
-
await executeAction("CREATE_RECORD", { tableId: targetTableId, tableMetaId: targetTableId, records: payload });
|
|
1248
|
+
const res = await executeAction("CREATE_RECORD", { tableId: targetTableId, tableMetaId: targetTableId, records: payload });
|
|
1249
|
+
const createdList = Array.isArray(res) ? res : (res == null ? void 0 : res.data) && Array.isArray(res.data) ? res.data : res ? [res] : [];
|
|
1250
|
+
if (createdList && createdList.length > 0) {
|
|
1251
|
+
dirty.added.forEach((addedRow, idx) => {
|
|
1252
|
+
const created = createdList[idx];
|
|
1253
|
+
if (created) {
|
|
1254
|
+
const realId = String(created.id || created._id || "");
|
|
1255
|
+
if (realId) {
|
|
1256
|
+
tempToRealMap[addedRow.id] = realId;
|
|
1257
|
+
const createdData = created.data && typeof created.data === "object" ? created.data : addedRow.data;
|
|
1258
|
+
realRecordDataMap[realId] = __spreadValues(__spreadValues({}, addedRow.data), createdData);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
});
|
|
1262
|
+
setData((prev) => prev.map((row) => {
|
|
1263
|
+
if (tempToRealMap[row.id]) {
|
|
1264
|
+
const realId = tempToRealMap[row.id];
|
|
1265
|
+
return __spreadProps(__spreadValues({}, row), {
|
|
1266
|
+
id: realId,
|
|
1267
|
+
data: realRecordDataMap[realId] || row.data
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
return row;
|
|
1271
|
+
}));
|
|
1272
|
+
setSelectedIds((prev) => {
|
|
1273
|
+
let changed = false;
|
|
1274
|
+
const next = new Set(prev);
|
|
1275
|
+
Object.entries(tempToRealMap).forEach(([tempId, realId]) => {
|
|
1276
|
+
if (next.has(tempId)) {
|
|
1277
|
+
next.delete(tempId);
|
|
1278
|
+
next.add(realId);
|
|
1279
|
+
changed = true;
|
|
1280
|
+
}
|
|
1281
|
+
});
|
|
1282
|
+
return changed ? next : prev;
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
937
1285
|
}
|
|
938
1286
|
if (Object.keys(dirty.modified).length > 0) {
|
|
939
1287
|
const payload = {};
|
|
940
1288
|
for (const [id, modData] of Object.entries(dirty.modified)) {
|
|
941
|
-
|
|
1289
|
+
const targetId = tempToRealMap[id] || id;
|
|
1290
|
+
payload[targetId] = formatPayload(modData);
|
|
942
1291
|
}
|
|
943
1292
|
await executeAction("UPDATE_RECORD", { tableId: targetTableId, tableMetaId: targetTableId, modifications: payload });
|
|
944
1293
|
}
|
|
@@ -954,10 +1303,15 @@ function TableBlockClient({
|
|
|
954
1303
|
}
|
|
955
1304
|
setBaseRecordsMap((prev) => {
|
|
956
1305
|
const next = new Map(prev);
|
|
957
|
-
dirty.added.forEach((r) =>
|
|
1306
|
+
dirty.added.forEach((r) => {
|
|
1307
|
+
const realId = tempToRealMap[r.id] || r.id;
|
|
1308
|
+
const dataToStore = realRecordDataMap[realId] || __spreadValues({}, r.data);
|
|
1309
|
+
next.set(realId, dataToStore);
|
|
1310
|
+
});
|
|
958
1311
|
Object.entries(dirty.modified).forEach(([id, mods]) => {
|
|
959
|
-
const
|
|
960
|
-
next.
|
|
1312
|
+
const realId = tempToRealMap[id] || id;
|
|
1313
|
+
const existing = next.get(realId) || {};
|
|
1314
|
+
next.set(realId, __spreadValues(__spreadValues({}, existing), mods));
|
|
961
1315
|
});
|
|
962
1316
|
dirty.deleted.forEach((id) => next.delete(id));
|
|
963
1317
|
return next;
|
|
@@ -975,7 +1329,7 @@ function TableBlockClient({
|
|
|
975
1329
|
setIsSaving(false);
|
|
976
1330
|
}
|
|
977
1331
|
};
|
|
978
|
-
const filteredData = (0,
|
|
1332
|
+
const filteredData = (0, import_react6.useMemo)(() => {
|
|
979
1333
|
if (!searchQuery) return data;
|
|
980
1334
|
const lowerQuery = searchQuery.toLowerCase();
|
|
981
1335
|
return data.filter(
|
|
@@ -986,7 +1340,7 @@ function TableBlockClient({
|
|
|
986
1340
|
}, [data, searchQuery]);
|
|
987
1341
|
const isUpdatingActive = Boolean(isUpdating || isSaving);
|
|
988
1342
|
const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
|
|
989
|
-
return /* @__PURE__ */ (0,
|
|
1343
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
990
1344
|
"div",
|
|
991
1345
|
{
|
|
992
1346
|
id: componentId,
|
|
@@ -994,24 +1348,24 @@ function TableBlockClient({
|
|
|
994
1348
|
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs overflow-hidden ${className}`,
|
|
995
1349
|
dir: "rtl",
|
|
996
1350
|
children: [
|
|
997
|
-
errorMessage && /* @__PURE__ */ (0,
|
|
998
|
-
/* @__PURE__ */ (0,
|
|
999
|
-
/* @__PURE__ */ (0,
|
|
1351
|
+
errorMessage && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1352
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
1353
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: errorMessage })
|
|
1000
1354
|
] }) }),
|
|
1001
|
-
/* @__PURE__ */ (0,
|
|
1002
|
-
/* @__PURE__ */ (0,
|
|
1003
|
-
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ (0,
|
|
1004
|
-
/* @__PURE__ */ (0,
|
|
1355
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-3 p-3.5 sm:p-4 bg-slate-50 border-b border-slate-200", children: [
|
|
1356
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center gap-2.5", children: [
|
|
1357
|
+
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: schema.title || schema.name }) }),
|
|
1358
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1005
1359
|
"button",
|
|
1006
1360
|
{
|
|
1007
1361
|
onClick: handleAddRow,
|
|
1008
1362
|
disabled: isLoading || isUpdatingActive,
|
|
1009
1363
|
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",
|
|
1010
1364
|
title: "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
|
|
1011
|
-
children: /* @__PURE__ */ (0,
|
|
1365
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
|
|
1012
1366
|
}
|
|
1013
1367
|
),
|
|
1014
|
-
/* @__PURE__ */ (0,
|
|
1368
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1015
1369
|
"button",
|
|
1016
1370
|
{
|
|
1017
1371
|
onClick: handleDeleteSelected,
|
|
@@ -1019,14 +1373,14 @@ function TableBlockClient({
|
|
|
1019
1373
|
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",
|
|
1020
1374
|
title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
|
|
1021
1375
|
children: [
|
|
1022
|
-
/* @__PURE__ */ (0,
|
|
1023
|
-
selectedIds.size > 0 && /* @__PURE__ */ (0,
|
|
1376
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
|
|
1377
|
+
selectedIds.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "absolute -top-1.5 -right-1.5 bg-rose-600 text-white min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs", children: selectedIds.size })
|
|
1024
1378
|
]
|
|
1025
1379
|
}
|
|
1026
1380
|
),
|
|
1027
|
-
/* @__PURE__ */ (0,
|
|
1028
|
-
/* @__PURE__ */ (0,
|
|
1029
|
-
/* @__PURE__ */ (0,
|
|
1381
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
|
|
1382
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
|
|
1383
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1030
1384
|
"input",
|
|
1031
1385
|
{
|
|
1032
1386
|
placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
|
|
@@ -1036,36 +1390,36 @@ function TableBlockClient({
|
|
|
1036
1390
|
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"
|
|
1037
1391
|
}
|
|
1038
1392
|
),
|
|
1039
|
-
/* @__PURE__ */ (0,
|
|
1393
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4 h-4 text-slate-400 absolute right-2.5 top-2.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
|
|
1040
1394
|
] })
|
|
1041
1395
|
] }),
|
|
1042
|
-
/* @__PURE__ */ (0,
|
|
1043
|
-
isUpdatingActive ? /* @__PURE__ */ (0,
|
|
1044
|
-
/* @__PURE__ */ (0,
|
|
1396
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
1397
|
+
isUpdatingActive ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "text-xs text-blue-600 font-semibold flex items-center gap-1.5 bg-blue-50 border border-blue-200 px-3 py-1.5 rounded-lg animate-pulse", children: [
|
|
1398
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
|
|
1045
1399
|
"\u05DE\u05E2\u05D3\u05DB\u05DF..."
|
|
1046
|
-
] }) : isSaveSuccess ? /* @__PURE__ */ (0,
|
|
1047
|
-
/* @__PURE__ */ (0,
|
|
1400
|
+
] }) : isSaveSuccess ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "text-xs text-emerald-700 font-semibold flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 px-3 py-1.5 rounded-lg animate-in fade-in duration-200", children: [
|
|
1401
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
|
|
1048
1402
|
"\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
1049
|
-
] }) : hasChanges ? /* @__PURE__ */ (0,
|
|
1050
|
-
/* @__PURE__ */ (0,
|
|
1403
|
+
] }) : hasChanges ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-xs font-semibold text-amber-700 animate-in fade-in", children: "\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5" }) : null,
|
|
1404
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1051
1405
|
"button",
|
|
1052
1406
|
{
|
|
1053
1407
|
onClick: handleSave,
|
|
1054
1408
|
disabled: isUpdatingActive || isLoading || !hasChanges,
|
|
1055
1409
|
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"}`,
|
|
1056
|
-
children: /* @__PURE__ */ (0,
|
|
1410
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
|
|
1057
1411
|
}
|
|
1058
1412
|
)
|
|
1059
1413
|
] })
|
|
1060
1414
|
] }),
|
|
1061
|
-
/* @__PURE__ */ (0,
|
|
1062
|
-
isLoading && /* @__PURE__ */ (0,
|
|
1063
|
-
/* @__PURE__ */ (0,
|
|
1064
|
-
/* @__PURE__ */ (0,
|
|
1415
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "overflow-x-auto relative", children: [
|
|
1416
|
+
isLoading && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
|
|
1417
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
|
|
1418
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
|
|
1065
1419
|
] }),
|
|
1066
|
-
/* @__PURE__ */ (0,
|
|
1067
|
-
/* @__PURE__ */ (0,
|
|
1068
|
-
/* @__PURE__ */ (0,
|
|
1420
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("table", { className: "w-full text-sm text-right border-collapse", children: [
|
|
1421
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { children: [
|
|
1422
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "border-b border-l border-slate-200 p-2.5 w-10 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1069
1423
|
"input",
|
|
1070
1424
|
{
|
|
1071
1425
|
type: "checkbox",
|
|
@@ -1075,13 +1429,13 @@ function TableBlockClient({
|
|
|
1075
1429
|
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
1076
1430
|
}
|
|
1077
1431
|
) }),
|
|
1078
|
-
filteredColumns.map((col) => /* @__PURE__ */ (0,
|
|
1432
|
+
filteredColumns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("th", { className: "border-b border-l border-slate-200 px-4 py-2.5 font-semibold text-slate-700 whitespace-nowrap min-w-[140px]", children: col.name }, col.name))
|
|
1079
1433
|
] }) }),
|
|
1080
|
-
/* @__PURE__ */ (0,
|
|
1081
|
-
/* @__PURE__ */ (0,
|
|
1082
|
-
/* @__PURE__ */ (0,
|
|
1083
|
-
] }) }) }) : filteredData.map((row) => /* @__PURE__ */ (0,
|
|
1084
|
-
/* @__PURE__ */ (0,
|
|
1434
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { colSpan: filteredColumns.length + 1, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col items-center justify-center gap-2", children: [
|
|
1435
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }),
|
|
1436
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
|
|
1437
|
+
] }) }) }) : filteredData.map((row) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
|
|
1438
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1085
1439
|
"input",
|
|
1086
1440
|
{
|
|
1087
1441
|
type: "checkbox",
|
|
@@ -1103,7 +1457,7 @@ function TableBlockClient({
|
|
|
1103
1457
|
}
|
|
1104
1458
|
}
|
|
1105
1459
|
if (value === void 0) value = null;
|
|
1106
|
-
return /* @__PURE__ */ (0,
|
|
1460
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("td", { className: "border-b border-l border-slate-200 p-0 relative", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1107
1461
|
InputComponent,
|
|
1108
1462
|
{
|
|
1109
1463
|
value,
|
|
@@ -1133,9 +1487,9 @@ function TableBlockClient({
|
|
|
1133
1487
|
}
|
|
1134
1488
|
|
|
1135
1489
|
// src/components/TableBlock/TableBlock.tsx
|
|
1136
|
-
var
|
|
1490
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1137
1491
|
function TableBlock(props) {
|
|
1138
|
-
return /* @__PURE__ */ (0,
|
|
1492
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TableBlockClient, __spreadValues({}, props));
|
|
1139
1493
|
}
|
|
1140
1494
|
|
|
1141
1495
|
// src/registry.ts
|