@universe-platform/ui 0.1.0-beta.4 → 0.1.0-beta.6
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 +337 -2
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +983 -114
- package/dist/index.mjs +983 -114
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -39,7 +39,7 @@ function cn(...inputs) {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
42
|
-
import { useState as
|
|
42
|
+
import { useState as useState4, useMemo as useMemo2, useEffect as useEffect2, useCallback as useCallback3, useRef as useRef3 } from "react";
|
|
43
43
|
|
|
44
44
|
// src/hooks/useToast.ts
|
|
45
45
|
import { useContext as useContext2 } from "react";
|
|
@@ -239,7 +239,7 @@ function useToast() {
|
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
// src/components/TableBlock/fields/fieldRegistry.tsx
|
|
242
|
-
import
|
|
242
|
+
import React4 from "react";
|
|
243
243
|
|
|
244
244
|
// src/components/TableBlock/fields/DrivePickerCell.tsx
|
|
245
245
|
import { useState as useState2 } from "react";
|
|
@@ -361,8 +361,311 @@ function DrivePickerCell({ value, onChange, tableName, onMarkForDeletion, contex
|
|
|
361
361
|
) });
|
|
362
362
|
}
|
|
363
363
|
|
|
364
|
-
// src/components/TableBlock/fields/
|
|
364
|
+
// src/components/TableBlock/fields/DatePickerCell.tsx
|
|
365
|
+
import { useState as useState3, useRef as useRef2, useEffect, useMemo, useCallback as useCallback2 } from "react";
|
|
366
|
+
import { Calendar as CalendarIcon, ChevronLeft, ChevronRight, X as X3 } from "lucide-react";
|
|
365
367
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
368
|
+
function parseDateParts(val) {
|
|
369
|
+
if (val === void 0 || val === null || val === "") return null;
|
|
370
|
+
if (typeof val === "string") {
|
|
371
|
+
const trimmed = val.trim();
|
|
372
|
+
if (!trimmed) return null;
|
|
373
|
+
const ymdMatch = trimmed.match(/^(\d{4})[-/.](\d{1,2})[-/.](\d{1,2})/);
|
|
374
|
+
if (ymdMatch) {
|
|
375
|
+
const year = parseInt(ymdMatch[1], 10);
|
|
376
|
+
const month = parseInt(ymdMatch[2], 10);
|
|
377
|
+
const day = parseInt(ymdMatch[3], 10);
|
|
378
|
+
if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
|
|
379
|
+
return { year, month, day };
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
const dmyMatch = trimmed.match(/^(\d{1,2})[-/.](\d{1,2})[-/.](\d{4})/);
|
|
383
|
+
if (dmyMatch) {
|
|
384
|
+
const day = parseInt(dmyMatch[1], 10);
|
|
385
|
+
const month = parseInt(dmyMatch[2], 10);
|
|
386
|
+
const year = parseInt(dmyMatch[3], 10);
|
|
387
|
+
if (month >= 1 && month <= 12 && day >= 1 && day <= 31) {
|
|
388
|
+
return { year, month, day };
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
const parsed = new Date(trimmed);
|
|
392
|
+
if (!isNaN(parsed.getTime())) {
|
|
393
|
+
return {
|
|
394
|
+
year: parsed.getFullYear(),
|
|
395
|
+
month: parsed.getMonth() + 1,
|
|
396
|
+
day: parsed.getDate()
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
} else if (val instanceof Date && !isNaN(val.getTime())) {
|
|
400
|
+
return {
|
|
401
|
+
year: val.getFullYear(),
|
|
402
|
+
month: val.getMonth() + 1,
|
|
403
|
+
day: val.getDate()
|
|
404
|
+
};
|
|
405
|
+
} else if (typeof val === "number" && !isNaN(val)) {
|
|
406
|
+
const parsed = new Date(val);
|
|
407
|
+
if (!isNaN(parsed.getTime())) {
|
|
408
|
+
return {
|
|
409
|
+
year: parsed.getFullYear(),
|
|
410
|
+
month: parsed.getMonth() + 1,
|
|
411
|
+
day: parsed.getDate()
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
function formatDateIso(year, month, day) {
|
|
418
|
+
const mm = String(month).padStart(2, "0");
|
|
419
|
+
const dd = String(day).padStart(2, "0");
|
|
420
|
+
return `${year}-${mm}-${dd}`;
|
|
421
|
+
}
|
|
422
|
+
function formatDateDisplay(parts) {
|
|
423
|
+
if (!parts) return "";
|
|
424
|
+
const mm = String(parts.month).padStart(2, "0");
|
|
425
|
+
const dd = String(parts.day).padStart(2, "0");
|
|
426
|
+
return `${dd}/${mm}/${parts.year}`;
|
|
427
|
+
}
|
|
428
|
+
var HEBREW_MONTHS = [
|
|
429
|
+
"\u05D9\u05E0\u05D5\u05D0\u05E8",
|
|
430
|
+
"\u05E4\u05D1\u05E8\u05D5\u05D0\u05E8",
|
|
431
|
+
"\u05DE\u05E8\u05E5",
|
|
432
|
+
"\u05D0\u05E4\u05E8\u05D9\u05DC",
|
|
433
|
+
"\u05DE\u05D0\u05D9",
|
|
434
|
+
"\u05D9\u05D5\u05E0\u05D9",
|
|
435
|
+
"\u05D9\u05D5\u05DC\u05D9",
|
|
436
|
+
"\u05D0\u05D5\u05D2\u05D5\u05E1\u05D8",
|
|
437
|
+
"\u05E1\u05E4\u05D8\u05DE\u05D1\u05E8",
|
|
438
|
+
"\u05D0\u05D5\u05E7\u05D8\u05D5\u05D1\u05E8",
|
|
439
|
+
"\u05E0\u05D5\u05D1\u05DE\u05D1\u05E8",
|
|
440
|
+
"\u05D3\u05E6\u05DE\u05D1\u05E8"
|
|
441
|
+
];
|
|
442
|
+
var WEEKDAY_LABELS = ["\u05D0'", "\u05D1'", "\u05D2'", "\u05D3'", "\u05D4'", "\u05D5'", "\u05E9'"];
|
|
443
|
+
function DatePickerCell({ value, onChange, readOnly = false }) {
|
|
444
|
+
const [isOpen, setIsOpen] = useState3(false);
|
|
445
|
+
const containerRef = useRef2(null);
|
|
446
|
+
const [popoverPos, setPopoverPos] = useState3({ top: 0, right: 0 });
|
|
447
|
+
const parsedParts = useMemo(() => parseDateParts(value), [value]);
|
|
448
|
+
const displayString = useMemo(() => formatDateDisplay(parsedParts), [parsedParts]);
|
|
449
|
+
const [rawInput, setRawInput] = useState3(displayString);
|
|
450
|
+
useEffect(() => {
|
|
451
|
+
setRawInput(displayString);
|
|
452
|
+
}, [displayString]);
|
|
453
|
+
const now = /* @__PURE__ */ new Date();
|
|
454
|
+
const [viewYear, setViewYear] = useState3((parsedParts == null ? void 0 : parsedParts.year) || now.getFullYear());
|
|
455
|
+
const [viewMonth, setViewMonth] = useState3((parsedParts == null ? void 0 : parsedParts.month) || now.getMonth() + 1);
|
|
456
|
+
useEffect(() => {
|
|
457
|
+
if (parsedParts) {
|
|
458
|
+
setViewYear(parsedParts.year);
|
|
459
|
+
setViewMonth(parsedParts.month);
|
|
460
|
+
}
|
|
461
|
+
}, [parsedParts, isOpen]);
|
|
462
|
+
const updatePopoverPosition = useCallback2(() => {
|
|
463
|
+
if (containerRef.current) {
|
|
464
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
465
|
+
const right = window.innerWidth - rect.right;
|
|
466
|
+
const popoverHeight = 320;
|
|
467
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
468
|
+
if (spaceBelow < popoverHeight && rect.top > popoverHeight) {
|
|
469
|
+
setPopoverPos({
|
|
470
|
+
top: Math.max(10, rect.top - popoverHeight - 4),
|
|
471
|
+
right: Math.max(10, right)
|
|
472
|
+
});
|
|
473
|
+
} else {
|
|
474
|
+
setPopoverPos({
|
|
475
|
+
top: Math.min(window.innerHeight - popoverHeight - 10, rect.bottom + 4),
|
|
476
|
+
right: Math.max(10, right)
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}, []);
|
|
481
|
+
useEffect(() => {
|
|
482
|
+
if (!isOpen) return;
|
|
483
|
+
updatePopoverPosition();
|
|
484
|
+
function handleScrollOrResize() {
|
|
485
|
+
updatePopoverPosition();
|
|
486
|
+
}
|
|
487
|
+
function handleClickOutside(event) {
|
|
488
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
489
|
+
const popoverEl = document.getElementById("date-picker-popover");
|
|
490
|
+
if (popoverEl && popoverEl.contains(event.target)) {
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
setIsOpen(false);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
window.addEventListener("scroll", handleScrollOrResize, true);
|
|
497
|
+
window.addEventListener("resize", handleScrollOrResize);
|
|
498
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
499
|
+
return () => {
|
|
500
|
+
window.removeEventListener("scroll", handleScrollOrResize, true);
|
|
501
|
+
window.removeEventListener("resize", handleScrollOrResize);
|
|
502
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
503
|
+
};
|
|
504
|
+
}, [isOpen, updatePopoverPosition]);
|
|
505
|
+
const handleInputChange = (e) => {
|
|
506
|
+
const text = e.target.value;
|
|
507
|
+
setRawInput(text);
|
|
508
|
+
if (!text.trim()) {
|
|
509
|
+
onChange(null);
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
const parts = parseDateParts(text);
|
|
513
|
+
if (parts) {
|
|
514
|
+
const iso = formatDateIso(parts.year, parts.month, parts.day);
|
|
515
|
+
onChange(iso);
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
const handleInputBlur = () => {
|
|
519
|
+
const parts = parseDateParts(rawInput);
|
|
520
|
+
if (parts) {
|
|
521
|
+
setRawInput(formatDateDisplay(parts));
|
|
522
|
+
} else if (!rawInput.trim()) {
|
|
523
|
+
setRawInput("");
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
const handleSelectDay = (day) => {
|
|
527
|
+
const iso = formatDateIso(viewYear, viewMonth, day);
|
|
528
|
+
onChange(iso);
|
|
529
|
+
setRawInput(formatDateDisplay({ year: viewYear, month: viewMonth, day }));
|
|
530
|
+
setIsOpen(false);
|
|
531
|
+
};
|
|
532
|
+
const handlePrevMonth = () => {
|
|
533
|
+
if (viewMonth === 1) {
|
|
534
|
+
setViewMonth(12);
|
|
535
|
+
setViewYear((prev) => prev - 1);
|
|
536
|
+
} else {
|
|
537
|
+
setViewMonth((prev) => prev - 1);
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
const handleNextMonth = () => {
|
|
541
|
+
if (viewMonth === 12) {
|
|
542
|
+
setViewMonth(1);
|
|
543
|
+
setViewYear((prev) => prev + 1);
|
|
544
|
+
} else {
|
|
545
|
+
setViewMonth((prev) => prev + 1);
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
const calendarDays = useMemo(() => {
|
|
549
|
+
const firstDayIndex = new Date(viewYear, viewMonth - 1, 1).getDay();
|
|
550
|
+
const totalDays = new Date(viewYear, viewMonth, 0).getDate();
|
|
551
|
+
const days = [];
|
|
552
|
+
const prevMonthTotalDays = new Date(viewYear, viewMonth - 1, 0).getDate();
|
|
553
|
+
for (let i = firstDayIndex - 1; i >= 0; i--) {
|
|
554
|
+
days.push({ day: prevMonthTotalDays - i, isCurrentMonth: false });
|
|
555
|
+
}
|
|
556
|
+
for (let d = 1; d <= totalDays; d++) {
|
|
557
|
+
days.push({ day: d, isCurrentMonth: true });
|
|
558
|
+
}
|
|
559
|
+
const remaining = 7 - days.length % 7;
|
|
560
|
+
if (remaining < 7) {
|
|
561
|
+
for (let d = 1; d <= remaining; d++) {
|
|
562
|
+
days.push({ day: d, isCurrentMonth: false });
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return days;
|
|
566
|
+
}, [viewYear, viewMonth]);
|
|
567
|
+
if (readOnly) {
|
|
568
|
+
return /* @__PURE__ */ jsx3("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 });
|
|
569
|
+
}
|
|
570
|
+
return /* @__PURE__ */ jsxs3("div", { ref: containerRef, className: "relative w-full h-full flex items-center", children: [
|
|
571
|
+
/* @__PURE__ */ jsx3(
|
|
572
|
+
"input",
|
|
573
|
+
{
|
|
574
|
+
type: "text",
|
|
575
|
+
dir: "ltr",
|
|
576
|
+
placeholder: "DD/MM/YYYY",
|
|
577
|
+
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",
|
|
578
|
+
value: rawInput,
|
|
579
|
+
onChange: handleInputChange,
|
|
580
|
+
onBlur: handleInputBlur
|
|
581
|
+
}
|
|
582
|
+
),
|
|
583
|
+
/* @__PURE__ */ jsx3(
|
|
584
|
+
"button",
|
|
585
|
+
{
|
|
586
|
+
type: "button",
|
|
587
|
+
onClick: () => {
|
|
588
|
+
setIsOpen((prev) => {
|
|
589
|
+
const next = !prev;
|
|
590
|
+
if (next) updatePopoverPosition();
|
|
591
|
+
return next;
|
|
592
|
+
});
|
|
593
|
+
},
|
|
594
|
+
className: "absolute left-1.5 p-1 text-slate-400 hover:text-blue-600 rounded transition-colors",
|
|
595
|
+
title: "\u05D1\u05D7\u05E8 \u05EA\u05D0\u05E8\u05D9\u05DA",
|
|
596
|
+
children: /* @__PURE__ */ jsx3(CalendarIcon, { className: "w-4 h-4" })
|
|
597
|
+
}
|
|
598
|
+
),
|
|
599
|
+
isOpen && /* @__PURE__ */ jsxs3(
|
|
600
|
+
"div",
|
|
601
|
+
{
|
|
602
|
+
id: "date-picker-popover",
|
|
603
|
+
dir: "rtl",
|
|
604
|
+
style: { top: `${popoverPos.top}px`, right: `${popoverPos.right}px` },
|
|
605
|
+
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",
|
|
606
|
+
children: [
|
|
607
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between border-b border-slate-100 pb-2.5 mb-2.5", children: [
|
|
608
|
+
/* @__PURE__ */ jsx3("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" }),
|
|
609
|
+
/* @__PURE__ */ jsx3(
|
|
610
|
+
"button",
|
|
611
|
+
{
|
|
612
|
+
onClick: () => setIsOpen(false),
|
|
613
|
+
className: "text-slate-400 hover:text-slate-600 p-0.5 rounded-full hover:bg-slate-100",
|
|
614
|
+
children: /* @__PURE__ */ jsx3(X3, { className: "w-4 h-4" })
|
|
615
|
+
}
|
|
616
|
+
)
|
|
617
|
+
] }),
|
|
618
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between mb-3 px-1", children: [
|
|
619
|
+
/* @__PURE__ */ jsx3(
|
|
620
|
+
"button",
|
|
621
|
+
{
|
|
622
|
+
type: "button",
|
|
623
|
+
onClick: handleNextMonth,
|
|
624
|
+
className: "p-1 text-slate-600 hover:bg-slate-100 rounded-lg transition-colors",
|
|
625
|
+
title: "\u05D7\u05D5\u05D3\u05E9 \u05D4\u05D1\u05D0",
|
|
626
|
+
children: /* @__PURE__ */ jsx3(ChevronRight, { className: "w-4 h-4" })
|
|
627
|
+
}
|
|
628
|
+
),
|
|
629
|
+
/* @__PURE__ */ jsxs3("span", { className: "font-bold text-sm text-slate-800", children: [
|
|
630
|
+
HEBREW_MONTHS[viewMonth - 1],
|
|
631
|
+
" ",
|
|
632
|
+
viewYear
|
|
633
|
+
] }),
|
|
634
|
+
/* @__PURE__ */ jsx3(
|
|
635
|
+
"button",
|
|
636
|
+
{
|
|
637
|
+
type: "button",
|
|
638
|
+
onClick: handlePrevMonth,
|
|
639
|
+
className: "p-1 text-slate-600 hover:bg-slate-100 rounded-lg transition-colors",
|
|
640
|
+
title: "\u05D7\u05D5\u05D3\u05E9 \u05E7\u05D5\u05D3\u05DD",
|
|
641
|
+
children: /* @__PURE__ */ jsx3(ChevronLeft, { className: "w-4 h-4" })
|
|
642
|
+
}
|
|
643
|
+
)
|
|
644
|
+
] }),
|
|
645
|
+
/* @__PURE__ */ jsx3("div", { className: "grid grid-cols-7 gap-1 text-center mb-1.5", children: WEEKDAY_LABELS.map((label, idx) => /* @__PURE__ */ jsx3("span", { className: "text-[11px] font-bold text-slate-400 select-none py-0.5", children: label }, idx)) }),
|
|
646
|
+
/* @__PURE__ */ jsx3("div", { className: "grid grid-cols-7 gap-1 text-center", children: calendarDays.map((item, idx) => {
|
|
647
|
+
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;
|
|
648
|
+
const isToday = item.isCurrentMonth && now.getFullYear() === viewYear && now.getMonth() + 1 === viewMonth && now.getDate() === item.day;
|
|
649
|
+
return /* @__PURE__ */ jsx3(
|
|
650
|
+
"button",
|
|
651
|
+
{
|
|
652
|
+
type: "button",
|
|
653
|
+
disabled: !item.isCurrentMonth,
|
|
654
|
+
onClick: () => item.isCurrentMonth && handleSelectDay(item.day),
|
|
655
|
+
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"}`,
|
|
656
|
+
children: item.day
|
|
657
|
+
},
|
|
658
|
+
idx
|
|
659
|
+
);
|
|
660
|
+
}) })
|
|
661
|
+
]
|
|
662
|
+
}
|
|
663
|
+
)
|
|
664
|
+
] });
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// src/components/TableBlock/fields/fieldRegistry.tsx
|
|
668
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
366
669
|
var CURRENCY_SYMBOLS = {
|
|
367
670
|
USD: "$",
|
|
368
671
|
EUR: "\u20AC",
|
|
@@ -398,17 +701,22 @@ function getRelationDisplayLabel(opt, column) {
|
|
|
398
701
|
return "\u05E2\u05E8\u05DA \u05E8\u05D9\u05E7";
|
|
399
702
|
}
|
|
400
703
|
var FORM_INPUTS = {
|
|
704
|
+
DATE: ({ value, onChange, column }) => /* @__PURE__ */ jsx4(DatePickerCell, { value, onChange, column }),
|
|
401
705
|
CURRENCY: ({ value, column, onChange }) => {
|
|
402
706
|
const symbol = getCurrencySymbol(column.currencySymbol);
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
707
|
+
const [isFocused, setIsFocused] = React4.useState(false);
|
|
708
|
+
const displayValue = !isFocused && value !== void 0 && value !== null && value !== "" && !isNaN(Number(value)) ? new Intl.NumberFormat("en-US").format(Number(value)) : value !== void 0 && value !== null ? value : "";
|
|
709
|
+
return /* @__PURE__ */ jsxs4("div", { className: "relative w-full h-full", children: [
|
|
710
|
+
symbol && /* @__PURE__ */ jsx4("span", { className: "absolute left-2 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none text-sm", children: symbol }),
|
|
711
|
+
/* @__PURE__ */ jsx4(
|
|
406
712
|
"input",
|
|
407
713
|
{
|
|
408
|
-
type: "number",
|
|
714
|
+
type: isFocused ? "number" : "text",
|
|
409
715
|
step: "any",
|
|
410
716
|
className: `w-full h-8 ${symbol ? "pl-6 pr-2" : "px-2"} bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm`,
|
|
411
|
-
value:
|
|
717
|
+
value: displayValue,
|
|
718
|
+
onFocus: () => setIsFocused(true),
|
|
719
|
+
onBlur: () => setIsFocused(false),
|
|
412
720
|
onChange: (e) => {
|
|
413
721
|
const val = e.target.value;
|
|
414
722
|
onChange(val === "" ? "" : Number(val));
|
|
@@ -417,7 +725,7 @@ var FORM_INPUTS = {
|
|
|
417
725
|
)
|
|
418
726
|
] });
|
|
419
727
|
},
|
|
420
|
-
TIME: ({ value, onChange }) => /* @__PURE__ */
|
|
728
|
+
TIME: ({ value, onChange }) => /* @__PURE__ */ jsx4(
|
|
421
729
|
"input",
|
|
422
730
|
{
|
|
423
731
|
type: "time",
|
|
@@ -427,13 +735,13 @@ var FORM_INPUTS = {
|
|
|
427
735
|
}
|
|
428
736
|
),
|
|
429
737
|
LINK: ({ value, onChange }) => {
|
|
430
|
-
const [isEditing, setIsEditing] =
|
|
738
|
+
const [isEditing, setIsEditing] = React4.useState(false);
|
|
431
739
|
const label = (value == null ? void 0 : value.label) || "";
|
|
432
740
|
const url = (value == null ? void 0 : value.url) || "";
|
|
433
741
|
if (!isEditing) {
|
|
434
|
-
return /* @__PURE__ */
|
|
435
|
-
url ? /* @__PURE__ */
|
|
436
|
-
/* @__PURE__ */
|
|
742
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 px-2 py-1 h-full w-full", children: [
|
|
743
|
+
url ? /* @__PURE__ */ jsx4("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline flex-1 truncate", children: label || url }) : /* @__PURE__ */ jsx4("span", { className: "text-slate-400 italic flex-1 text-sm", children: "\u05E8\u05D9\u05E7" }),
|
|
744
|
+
/* @__PURE__ */ jsx4(
|
|
437
745
|
"button",
|
|
438
746
|
{
|
|
439
747
|
onClick: () => setIsEditing(true),
|
|
@@ -444,8 +752,8 @@ var FORM_INPUTS = {
|
|
|
444
752
|
)
|
|
445
753
|
] });
|
|
446
754
|
}
|
|
447
|
-
return /* @__PURE__ */
|
|
448
|
-
/* @__PURE__ */
|
|
755
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex gap-2 p-1 w-full min-w-[250px] items-center bg-white border border-blue-200 rounded shadow-sm z-10", children: [
|
|
756
|
+
/* @__PURE__ */ jsx4(
|
|
449
757
|
"input",
|
|
450
758
|
{
|
|
451
759
|
type: "text",
|
|
@@ -455,7 +763,7 @@ var FORM_INPUTS = {
|
|
|
455
763
|
onChange: (e) => onChange({ label: e.target.value, url })
|
|
456
764
|
}
|
|
457
765
|
),
|
|
458
|
-
/* @__PURE__ */
|
|
766
|
+
/* @__PURE__ */ jsx4(
|
|
459
767
|
"input",
|
|
460
768
|
{
|
|
461
769
|
type: "url",
|
|
@@ -465,7 +773,7 @@ var FORM_INPUTS = {
|
|
|
465
773
|
onChange: (e) => onChange({ label, url: e.target.value })
|
|
466
774
|
}
|
|
467
775
|
),
|
|
468
|
-
/* @__PURE__ */
|
|
776
|
+
/* @__PURE__ */ jsx4(
|
|
469
777
|
"button",
|
|
470
778
|
{
|
|
471
779
|
onClick: () => setIsEditing(false),
|
|
@@ -476,7 +784,7 @@ var FORM_INPUTS = {
|
|
|
476
784
|
)
|
|
477
785
|
] });
|
|
478
786
|
},
|
|
479
|
-
BOOLEAN: ({ value, onChange }) => /* @__PURE__ */
|
|
787
|
+
BOOLEAN: ({ value, onChange }) => /* @__PURE__ */ jsx4("div", { className: "flex items-center justify-center w-full h-full p-2", children: /* @__PURE__ */ jsx4(
|
|
480
788
|
"input",
|
|
481
789
|
{
|
|
482
790
|
type: "checkbox",
|
|
@@ -485,7 +793,7 @@ var FORM_INPUTS = {
|
|
|
485
793
|
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
486
794
|
}
|
|
487
795
|
) }),
|
|
488
|
-
GOOGLE_DRIVE_FILE: ({ value, onChange, context }) => /* @__PURE__ */
|
|
796
|
+
GOOGLE_DRIVE_FILE: ({ value, onChange, context }) => /* @__PURE__ */ jsx4(
|
|
489
797
|
DrivePickerCell,
|
|
490
798
|
{
|
|
491
799
|
value: value || null,
|
|
@@ -498,7 +806,7 @@ var FORM_INPUTS = {
|
|
|
498
806
|
RELATION: ({ value, onChange, column, context }) => {
|
|
499
807
|
var _a;
|
|
500
808
|
const options = ((_a = context == null ? void 0 : context.relationOptions) == null ? void 0 : _a[column.name]) || [];
|
|
501
|
-
|
|
809
|
+
React4.useEffect(() => {
|
|
502
810
|
if (typeof value === "string" && value !== "" && options.length > 0) {
|
|
503
811
|
const isValidId = options.some((o) => String(o.id) === String(value));
|
|
504
812
|
if (!isValidId) {
|
|
@@ -517,7 +825,7 @@ var FORM_INPUTS = {
|
|
|
517
825
|
_displayLabel: getRelationDisplayLabel(opt, column)
|
|
518
826
|
}));
|
|
519
827
|
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");
|
|
520
|
-
return /* @__PURE__ */
|
|
828
|
+
return /* @__PURE__ */ jsxs4(
|
|
521
829
|
"select",
|
|
522
830
|
{
|
|
523
831
|
className: "w-full h-8 px-2 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm",
|
|
@@ -529,13 +837,13 @@ var FORM_INPUTS = {
|
|
|
529
837
|
}
|
|
530
838
|
},
|
|
531
839
|
children: [
|
|
532
|
-
/* @__PURE__ */
|
|
533
|
-
validOptions.length > 0 ? validOptions.map((opt) => /* @__PURE__ */
|
|
840
|
+
/* @__PURE__ */ jsx4("option", { value: "", children: "\u05D1\u05D7\u05E8..." }),
|
|
841
|
+
validOptions.length > 0 ? validOptions.map((opt) => /* @__PURE__ */ jsx4("option", { value: opt.id, children: opt._displayLabel }, opt.id)) : options.length > 0 ? /* @__PURE__ */ jsx4("option", { value: "empty_all", disabled: true, children: "\u05DB\u05DC \u05D4\u05E2\u05E8\u05DB\u05D9\u05DD \u05D1\u05D8\u05D1\u05DC\u05D4 \u05D4\u05DE\u05E7\u05D5\u05E9\u05E8\u05EA \u05E8\u05D9\u05E7\u05D9\u05DD" }) : null
|
|
534
842
|
]
|
|
535
843
|
}
|
|
536
844
|
);
|
|
537
845
|
},
|
|
538
|
-
NUMBER: ({ value, onChange }) => /* @__PURE__ */
|
|
846
|
+
NUMBER: ({ value, onChange }) => /* @__PURE__ */ jsx4(
|
|
539
847
|
"input",
|
|
540
848
|
{
|
|
541
849
|
type: "number",
|
|
@@ -547,7 +855,7 @@ var FORM_INPUTS = {
|
|
|
547
855
|
}
|
|
548
856
|
}
|
|
549
857
|
),
|
|
550
|
-
DEFAULT: ({ value, onChange }) => /* @__PURE__ */
|
|
858
|
+
DEFAULT: ({ value, onChange }) => /* @__PURE__ */ jsx4(
|
|
551
859
|
"input",
|
|
552
860
|
{
|
|
553
861
|
type: "text",
|
|
@@ -559,7 +867,8 @@ var FORM_INPUTS = {
|
|
|
559
867
|
};
|
|
560
868
|
|
|
561
869
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
562
|
-
import {
|
|
870
|
+
import { X as X4, Copy as Copy2 } from "lucide-react";
|
|
871
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
563
872
|
function TableBlockClient({
|
|
564
873
|
data: initialRecords,
|
|
565
874
|
settings: schema,
|
|
@@ -576,6 +885,68 @@ function TableBlockClient({
|
|
|
576
885
|
"data-testid": dataTestId
|
|
577
886
|
}) {
|
|
578
887
|
const { showError, addToast } = useToast();
|
|
888
|
+
const [columnWidths, setColumnWidths] = useState4({});
|
|
889
|
+
const [isMounted, setIsMounted] = useState4(false);
|
|
890
|
+
const tableKey = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id) || (schema == null ? void 0 : schema.name) || "default";
|
|
891
|
+
const [page, setPage] = useState4(1);
|
|
892
|
+
const [limit, setLimit] = useState4(50);
|
|
893
|
+
const [totalRecords, setTotalRecords] = useState4(0);
|
|
894
|
+
const [totalPages, setTotalPages] = useState4(1);
|
|
895
|
+
useEffect2(() => {
|
|
896
|
+
if (typeof window !== "undefined") {
|
|
897
|
+
const savedWidths = localStorage.getItem(`table_widths_${tableKey}`);
|
|
898
|
+
if (savedWidths) {
|
|
899
|
+
try {
|
|
900
|
+
setColumnWidths(JSON.parse(savedWidths));
|
|
901
|
+
} catch (e) {
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
const savedSummary = localStorage.getItem(`table_summary_${tableKey}`);
|
|
905
|
+
if (savedSummary !== null) {
|
|
906
|
+
setShowSummary(savedSummary === "true");
|
|
907
|
+
}
|
|
908
|
+
const savedLimit = localStorage.getItem(`table_limit_${tableKey}`);
|
|
909
|
+
if (savedLimit) {
|
|
910
|
+
const parsed = parseInt(savedLimit, 10);
|
|
911
|
+
if ([20, 50, 100].includes(parsed)) {
|
|
912
|
+
setLimit(parsed);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
setIsMounted(true);
|
|
917
|
+
}, [tableKey]);
|
|
918
|
+
const [showSummary, setShowSummary] = useState4(false);
|
|
919
|
+
const toggleSummary = () => {
|
|
920
|
+
setShowSummary((prev) => {
|
|
921
|
+
const next = !prev;
|
|
922
|
+
const tableKey2 = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id) || (schema == null ? void 0 : schema.name) || "default";
|
|
923
|
+
localStorage.setItem(`table_summary_${tableKey2}`, String(next));
|
|
924
|
+
return next;
|
|
925
|
+
});
|
|
926
|
+
};
|
|
927
|
+
const [resizingCol, setResizingCol] = useState4(null);
|
|
928
|
+
useEffect2(() => {
|
|
929
|
+
if (!resizingCol) return;
|
|
930
|
+
const handleMouseMove = (e) => {
|
|
931
|
+
const diffX = resizingCol.startX - e.clientX;
|
|
932
|
+
const newWidth = Math.max(100, Math.min(500, resizingCol.startWidth + diffX));
|
|
933
|
+
setColumnWidths((prev) => __spreadProps(__spreadValues({}, prev), { [resizingCol.name]: newWidth }));
|
|
934
|
+
};
|
|
935
|
+
const handleMouseUp = () => {
|
|
936
|
+
setResizingCol(null);
|
|
937
|
+
setColumnWidths((prev) => {
|
|
938
|
+
const tableKey2 = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id) || (schema == null ? void 0 : schema.name) || "default";
|
|
939
|
+
localStorage.setItem(`table_widths_${tableKey2}`, JSON.stringify(prev));
|
|
940
|
+
return prev;
|
|
941
|
+
});
|
|
942
|
+
};
|
|
943
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
944
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
945
|
+
return () => {
|
|
946
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
947
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
948
|
+
};
|
|
949
|
+
}, [resizingCol, schema]);
|
|
579
950
|
const normalizeRecords = (records) => {
|
|
580
951
|
return (records || []).map((row) => {
|
|
581
952
|
var _c;
|
|
@@ -601,18 +972,38 @@ function TableBlockClient({
|
|
|
601
972
|
return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
|
|
602
973
|
});
|
|
603
974
|
};
|
|
604
|
-
const
|
|
605
|
-
|
|
975
|
+
const mergeColumnDefs = useCallback3((existingCols, incomingCols) => {
|
|
976
|
+
if (!incomingCols || incomingCols.length === 0) return existingCols || [];
|
|
977
|
+
if (!existingCols || existingCols.length === 0) return incomingCols;
|
|
978
|
+
const existingMap = new Map(existingCols.map((c) => [c.name, c]));
|
|
979
|
+
const merged = incomingCols.map((inc) => {
|
|
980
|
+
const ext = existingMap.get(inc.name);
|
|
981
|
+
if (ext) {
|
|
982
|
+
existingMap.delete(inc.name);
|
|
983
|
+
return __spreadValues(__spreadValues({}, ext), inc);
|
|
984
|
+
}
|
|
985
|
+
return inc;
|
|
986
|
+
});
|
|
987
|
+
for (const [, extCol] of existingMap) {
|
|
988
|
+
merged.push(extCol);
|
|
989
|
+
}
|
|
990
|
+
return merged.sort((a, b) => {
|
|
991
|
+
var _a, _b;
|
|
992
|
+
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
993
|
+
});
|
|
994
|
+
}, []);
|
|
995
|
+
const [localColumns, setLocalColumns] = useState4(() => (schema == null ? void 0 : schema.columns) || []);
|
|
996
|
+
useEffect2(() => {
|
|
606
997
|
if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
|
|
607
|
-
setLocalColumns(schema.columns);
|
|
998
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
|
|
608
999
|
}
|
|
609
|
-
}, [schema == null ? void 0 : schema.columns]);
|
|
610
|
-
const [dirty, setDirty] =
|
|
611
|
-
const dirtyRef =
|
|
612
|
-
|
|
1000
|
+
}, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
|
|
1001
|
+
const [dirty, setDirty] = useState4({ added: [], modified: {}, deleted: [] });
|
|
1002
|
+
const dirtyRef = useRef3(dirty);
|
|
1003
|
+
useEffect2(() => {
|
|
613
1004
|
dirtyRef.current = dirty;
|
|
614
1005
|
}, [dirty]);
|
|
615
|
-
const mergeWithDirty =
|
|
1006
|
+
const mergeWithDirty = useCallback3((baseRecords) => {
|
|
616
1007
|
const { added, modified, deleted } = dirtyRef.current;
|
|
617
1008
|
const nonDeleted = (baseRecords || []).filter((r) => !deleted.includes(r.id));
|
|
618
1009
|
const modifiedRecords = nonDeleted.map((r) => {
|
|
@@ -625,8 +1016,8 @@ function TableBlockClient({
|
|
|
625
1016
|
const uniqueAdded = added.filter((r) => !baseIds.has(r.id));
|
|
626
1017
|
return [...uniqueAdded, ...modifiedRecords];
|
|
627
1018
|
}, []);
|
|
628
|
-
const [data, setData] =
|
|
629
|
-
|
|
1019
|
+
const [data, setData] = useState4(() => normalizeRecords(initialRecords));
|
|
1020
|
+
useEffect2(() => {
|
|
630
1021
|
if (initialRecords) {
|
|
631
1022
|
setData(mergeWithDirty(normalizeRecords(initialRecords)));
|
|
632
1023
|
}
|
|
@@ -641,54 +1032,82 @@ function TableBlockClient({
|
|
|
641
1032
|
}
|
|
642
1033
|
return false;
|
|
643
1034
|
};
|
|
644
|
-
const [baseRecordsMap, setBaseRecordsMap] =
|
|
1035
|
+
const [baseRecordsMap, setBaseRecordsMap] = useState4(() => {
|
|
645
1036
|
const map = /* @__PURE__ */ new Map();
|
|
646
1037
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
647
1038
|
return map;
|
|
648
1039
|
});
|
|
649
|
-
|
|
1040
|
+
useEffect2(() => {
|
|
650
1041
|
if (initialRecords && initialRecords.length > 0) {
|
|
651
1042
|
const map = /* @__PURE__ */ new Map();
|
|
652
1043
|
(normalizeRecords(initialRecords) || []).forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
653
1044
|
setBaseRecordsMap(map);
|
|
654
1045
|
}
|
|
655
1046
|
}, [initialRecords]);
|
|
656
|
-
|
|
1047
|
+
const refetchTableData = useCallback3((targetPage) => {
|
|
657
1048
|
const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
658
|
-
if (!tableId || !executeAction) return;
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
1049
|
+
if (!tableId || !executeAction) return Promise.resolve();
|
|
1050
|
+
const activePage = targetPage !== void 0 ? targetPage : page;
|
|
1051
|
+
const skip = (activePage - 1) * limit;
|
|
1052
|
+
return executeAction("FETCH_TABLE_DATA", { tableId, page: activePage, limit, skip }).then((res) => {
|
|
1053
|
+
var _a;
|
|
1054
|
+
if (res) {
|
|
1055
|
+
if (((_a = res.schema) == null ? void 0 : _a.columns) && res.schema.columns.length > 0) {
|
|
1056
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, res.schema.columns));
|
|
1057
|
+
}
|
|
1058
|
+
if (res.records && Array.isArray(res.records)) {
|
|
1059
|
+
const norm = normalizeRecords(res.records);
|
|
1060
|
+
const map = /* @__PURE__ */ new Map();
|
|
1061
|
+
norm.forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
1062
|
+
setBaseRecordsMap(map);
|
|
1063
|
+
setData(norm);
|
|
1064
|
+
}
|
|
1065
|
+
if (res.meta) {
|
|
1066
|
+
const total = typeof res.meta.totalRecords === "number" ? res.meta.totalRecords : 0;
|
|
1067
|
+
const pages = typeof res.meta.totalPages === "number" ? res.meta.totalPages : Math.ceil(total / limit) || 1;
|
|
1068
|
+
setTotalRecords(total);
|
|
1069
|
+
setTotalPages(pages);
|
|
1070
|
+
if (activePage > pages && pages >= 1) {
|
|
1071
|
+
setPage(pages);
|
|
672
1072
|
}
|
|
1073
|
+
} else if (res.records && Array.isArray(res.records)) {
|
|
1074
|
+
setTotalRecords(res.records.length);
|
|
1075
|
+
setTotalPages(Math.ceil(res.records.length / limit) || 1);
|
|
673
1076
|
}
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
|
|
1077
|
+
}
|
|
1078
|
+
}).catch((err) => {
|
|
1079
|
+
console.error("[TableBlock] Failed to auto-fetch table data:", err);
|
|
1080
|
+
});
|
|
1081
|
+
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeWithDirty, mergeColumnDefs]);
|
|
1082
|
+
useEffect2(() => {
|
|
1083
|
+
refetchTableData();
|
|
1084
|
+
}, [refetchTableData]);
|
|
1085
|
+
const handleLimitChange = (newLimit) => {
|
|
1086
|
+
setLimit(newLimit);
|
|
1087
|
+
setPage(1);
|
|
1088
|
+
if (typeof window !== "undefined") {
|
|
1089
|
+
localStorage.setItem(`table_limit_${tableKey}`, String(newLimit));
|
|
677
1090
|
}
|
|
678
|
-
}
|
|
679
|
-
|
|
1091
|
+
};
|
|
1092
|
+
const handlePrevPage = () => {
|
|
1093
|
+
setPage((prev) => Math.max(1, prev - 1));
|
|
1094
|
+
};
|
|
1095
|
+
const handleNextPage = () => {
|
|
1096
|
+
setPage((prev) => Math.min(totalPages, prev + 1));
|
|
1097
|
+
};
|
|
1098
|
+
useEffect2(() => {
|
|
680
1099
|
if (error) {
|
|
681
1100
|
showError(error, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E8\u05DB\u05D9\u05D1");
|
|
682
1101
|
}
|
|
683
1102
|
}, [error, showError]);
|
|
684
|
-
const [searchQuery, setSearchQuery] =
|
|
685
|
-
const [selectedIds, setSelectedIds] =
|
|
686
|
-
const [pendingDeletions, setPendingDeletions] =
|
|
687
|
-
const [isSaving, setIsSaving] =
|
|
688
|
-
const [isSaveSuccess, setIsSaveSuccess] =
|
|
689
|
-
const [relationOptions, setRelationOptions] =
|
|
690
|
-
const schemaColsString =
|
|
691
|
-
const refetchRelation =
|
|
1103
|
+
const [searchQuery, setSearchQuery] = useState4("");
|
|
1104
|
+
const [selectedIds, setSelectedIds] = useState4(/* @__PURE__ */ new Set());
|
|
1105
|
+
const [pendingDeletions, setPendingDeletions] = useState4([]);
|
|
1106
|
+
const [isSaving, setIsSaving] = useState4(false);
|
|
1107
|
+
const [isSaveSuccess, setIsSaveSuccess] = useState4(false);
|
|
1108
|
+
const [relationOptions, setRelationOptions] = useState4({});
|
|
1109
|
+
const schemaColsString = useMemo2(() => JSON.stringify(localColumns || []), [localColumns]);
|
|
1110
|
+
const refetchRelation = useCallback3(async (colName) => {
|
|
692
1111
|
var _a;
|
|
693
1112
|
let parsedCols = [];
|
|
694
1113
|
try {
|
|
@@ -708,7 +1127,7 @@ function TableBlockClient({
|
|
|
708
1127
|
console.warn(`[TableBlock] Could not fetch relation options for column ${colName}:`, err);
|
|
709
1128
|
}
|
|
710
1129
|
}, [schemaColsString, executeAction]);
|
|
711
|
-
|
|
1130
|
+
useEffect2(() => {
|
|
712
1131
|
let parsedCols = [];
|
|
713
1132
|
try {
|
|
714
1133
|
parsedCols = JSON.parse(schemaColsString);
|
|
@@ -722,10 +1141,144 @@ function TableBlockClient({
|
|
|
722
1141
|
refetchRelation(col.name);
|
|
723
1142
|
});
|
|
724
1143
|
}, [schemaColsString, refetchRelation]);
|
|
725
|
-
const
|
|
726
|
-
|
|
727
|
-
|
|
1144
|
+
const normalizedColumns = useMemo2(() => {
|
|
1145
|
+
return (localColumns || []).map((col, idx) => {
|
|
1146
|
+
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
1147
|
+
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
1148
|
+
const isProtected = isRequired || isUnique;
|
|
1149
|
+
return __spreadProps(__spreadValues({}, col), {
|
|
1150
|
+
order: typeof col.order === "number" ? col.order : idx,
|
|
1151
|
+
isHidden: isProtected ? false : Boolean(col.isHidden)
|
|
1152
|
+
});
|
|
1153
|
+
}).sort((a, b) => {
|
|
1154
|
+
var _a, _b;
|
|
1155
|
+
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
1156
|
+
});
|
|
728
1157
|
}, [localColumns]);
|
|
1158
|
+
const filteredColumns = useMemo2(() => {
|
|
1159
|
+
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1160
|
+
return normalizedColumns.filter((col) => !systemFields.includes(col.name) && !col.isHidden);
|
|
1161
|
+
}, [normalizedColumns]);
|
|
1162
|
+
const customizableColumns = useMemo2(() => {
|
|
1163
|
+
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1164
|
+
return normalizedColumns.filter((col) => !systemFields.includes(col.name));
|
|
1165
|
+
}, [normalizedColumns]);
|
|
1166
|
+
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = useState4(false);
|
|
1167
|
+
const dropdownRef = useRef3(null);
|
|
1168
|
+
useEffect2(() => {
|
|
1169
|
+
const handleClickOutside = (e) => {
|
|
1170
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
1171
|
+
setIsColumnsDropdownOpen(false);
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1174
|
+
if (isColumnsDropdownOpen) {
|
|
1175
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1176
|
+
}
|
|
1177
|
+
return () => {
|
|
1178
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1179
|
+
};
|
|
1180
|
+
}, [isColumnsDropdownOpen]);
|
|
1181
|
+
const handleShowAllColumns = async () => {
|
|
1182
|
+
var _a;
|
|
1183
|
+
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1184
|
+
const systemCols = (localColumns || []).filter((c) => systemFields.includes(c.name));
|
|
1185
|
+
const updatedCustomCols = customizableColumns.map((col) => __spreadProps(__spreadValues({}, col), {
|
|
1186
|
+
isHidden: false
|
|
1187
|
+
}));
|
|
1188
|
+
const fullUpdatedColumns = [...systemCols, ...updatedCustomCols];
|
|
1189
|
+
setLocalColumns(fullUpdatedColumns);
|
|
1190
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
1191
|
+
if (targetTableId && executeAction) {
|
|
1192
|
+
try {
|
|
1193
|
+
const res = await executeAction("UPDATE_TABLE_COLUMNS", {
|
|
1194
|
+
tableId: targetTableId,
|
|
1195
|
+
tableMetaId: targetTableId,
|
|
1196
|
+
columns: fullUpdatedColumns
|
|
1197
|
+
});
|
|
1198
|
+
const returnedCols = (res == null ? void 0 : res.columns) || ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.columns);
|
|
1199
|
+
if (returnedCols && Array.isArray(returnedCols)) {
|
|
1200
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, returnedCols));
|
|
1201
|
+
}
|
|
1202
|
+
} catch (err) {
|
|
1203
|
+
console.error("[TableBlock] Failed to save show all columns:", err);
|
|
1204
|
+
showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D4\u05E6\u05D2\u05EA \u05DB\u05DC \u05D4\u05E2\u05DE\u05D5\u05D3\u05D5\u05EA");
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
};
|
|
1208
|
+
const handleToggleColumnVisibility = async (colName, isVisible) => {
|
|
1209
|
+
var _a;
|
|
1210
|
+
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1211
|
+
const systemCols = (localColumns || []).filter((c) => systemFields.includes(c.name));
|
|
1212
|
+
const updatedCustomCols = customizableColumns.map((col) => {
|
|
1213
|
+
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
1214
|
+
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
1215
|
+
const isProtected = isRequired || isUnique;
|
|
1216
|
+
if (col.name === colName) {
|
|
1217
|
+
if (isProtected) {
|
|
1218
|
+
return __spreadProps(__spreadValues({}, col), { isHidden: false });
|
|
1219
|
+
}
|
|
1220
|
+
return __spreadProps(__spreadValues({}, col), { isHidden: !isVisible });
|
|
1221
|
+
}
|
|
1222
|
+
return __spreadProps(__spreadValues({}, col), {
|
|
1223
|
+
isHidden: isProtected ? false : Boolean(col.isHidden)
|
|
1224
|
+
});
|
|
1225
|
+
});
|
|
1226
|
+
const fullUpdatedColumns = [...systemCols, ...updatedCustomCols];
|
|
1227
|
+
setLocalColumns(fullUpdatedColumns);
|
|
1228
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
1229
|
+
if (targetTableId && executeAction) {
|
|
1230
|
+
try {
|
|
1231
|
+
const res = await executeAction("UPDATE_TABLE_COLUMNS", {
|
|
1232
|
+
tableId: targetTableId,
|
|
1233
|
+
tableMetaId: targetTableId,
|
|
1234
|
+
columns: fullUpdatedColumns
|
|
1235
|
+
});
|
|
1236
|
+
const returnedCols = (res == null ? void 0 : res.columns) || ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.columns);
|
|
1237
|
+
if (returnedCols && Array.isArray(returnedCols)) {
|
|
1238
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, returnedCols));
|
|
1239
|
+
}
|
|
1240
|
+
} catch (err) {
|
|
1241
|
+
console.error("[TableBlock] Failed to save column visibility:", err);
|
|
1242
|
+
showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E2\u05D3\u05DB\u05D5\u05DF \u05D4\u05E1\u05EA\u05E8\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA");
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
};
|
|
1246
|
+
const [draggedColName, setDraggedColName] = useState4(null);
|
|
1247
|
+
const [dragOverColName, setDragOverColName] = useState4(null);
|
|
1248
|
+
const handleColumnReorder = async (draggedName, dropTargetName) => {
|
|
1249
|
+
var _a;
|
|
1250
|
+
if (draggedName === dropTargetName) return;
|
|
1251
|
+
const currentCustomCols = [...customizableColumns];
|
|
1252
|
+
const fromIndex = currentCustomCols.findIndex((c) => c.name === draggedName);
|
|
1253
|
+
const toIndex = currentCustomCols.findIndex((c) => c.name === dropTargetName);
|
|
1254
|
+
if (fromIndex === -1 || toIndex === -1 || fromIndex === toIndex) return;
|
|
1255
|
+
const [draggedItem] = currentCustomCols.splice(fromIndex, 1);
|
|
1256
|
+
currentCustomCols.splice(toIndex, 0, draggedItem);
|
|
1257
|
+
const updatedCustomCols = currentCustomCols.map((col, idx) => __spreadProps(__spreadValues({}, col), {
|
|
1258
|
+
order: idx
|
|
1259
|
+
}));
|
|
1260
|
+
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1261
|
+
const systemCols = (localColumns || []).filter((c) => systemFields.includes(c.name));
|
|
1262
|
+
const fullUpdatedColumns = [...systemCols, ...updatedCustomCols];
|
|
1263
|
+
setLocalColumns(fullUpdatedColumns);
|
|
1264
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
1265
|
+
if (targetTableId && executeAction) {
|
|
1266
|
+
try {
|
|
1267
|
+
const res = await executeAction("UPDATE_TABLE_COLUMNS", {
|
|
1268
|
+
tableId: targetTableId,
|
|
1269
|
+
tableMetaId: targetTableId,
|
|
1270
|
+
columns: fullUpdatedColumns
|
|
1271
|
+
});
|
|
1272
|
+
const returnedCols = (res == null ? void 0 : res.columns) || ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.columns);
|
|
1273
|
+
if (returnedCols && Array.isArray(returnedCols)) {
|
|
1274
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, returnedCols));
|
|
1275
|
+
}
|
|
1276
|
+
} catch (err) {
|
|
1277
|
+
console.error("[TableBlock] Failed to save column reorder:", err);
|
|
1278
|
+
showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E2\u05D3\u05DB\u05D5\u05DF \u05E1\u05D3\u05E8 \u05D4\u05E2\u05DE\u05D5\u05D3\u05D5\u05EA");
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
729
1282
|
const generateTempId = () => `temp_${Math.random().toString(36).substr(2, 9)}`;
|
|
730
1283
|
const handleAddRow = () => {
|
|
731
1284
|
const defaultData = {};
|
|
@@ -755,6 +1308,34 @@ function TableBlockClient({
|
|
|
755
1308
|
setData((prev) => [newRow, ...prev]);
|
|
756
1309
|
setDirty((prev) => __spreadProps(__spreadValues({}, prev), { added: [newRow, ...prev.added] }));
|
|
757
1310
|
};
|
|
1311
|
+
const handleDuplicateRow = () => {
|
|
1312
|
+
if (selectedIds.size !== 1) return;
|
|
1313
|
+
const targetId = Array.from(selectedIds)[0];
|
|
1314
|
+
const sourceRow = data.find((r) => r.id === targetId);
|
|
1315
|
+
if (!sourceRow) return;
|
|
1316
|
+
const uniqueColNames = new Set(
|
|
1317
|
+
(localColumns || []).filter((c) => c.isUnique === true || String(c.isUnique) === "true").map((c) => c.name)
|
|
1318
|
+
);
|
|
1319
|
+
const fieldsToScrub = /* @__PURE__ */ new Set(["id", "_id", "createdAt", "updatedAt", "created_at", "updated_at"]);
|
|
1320
|
+
const clonedData = __spreadValues({}, sourceRow.data);
|
|
1321
|
+
Object.keys(clonedData).forEach((key) => {
|
|
1322
|
+
var _a;
|
|
1323
|
+
if (fieldsToScrub.has(key) || uniqueColNames.has(key)) {
|
|
1324
|
+
const col = (localColumns || []).find((c) => c.name === key);
|
|
1325
|
+
const typeUpper = (_a = col == null ? void 0 : col.type) == null ? void 0 : _a.toUpperCase();
|
|
1326
|
+
if (typeUpper === "NUMBER" || typeUpper === "CURRENCY") {
|
|
1327
|
+
clonedData[key] = 0;
|
|
1328
|
+
} else if (typeUpper === "BOOLEAN") {
|
|
1329
|
+
clonedData[key] = false;
|
|
1330
|
+
} else {
|
|
1331
|
+
clonedData[key] = "";
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
const newRow = { id: generateTempId(), data: clonedData };
|
|
1336
|
+
setData((prev) => [newRow, ...prev]);
|
|
1337
|
+
setDirty((prev) => __spreadProps(__spreadValues({}, prev), { added: [newRow, ...prev.added] }));
|
|
1338
|
+
};
|
|
758
1339
|
const handleCellChange = (rowId, colName, value) => {
|
|
759
1340
|
setData((prev) => prev.map(
|
|
760
1341
|
(row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
|
|
@@ -975,6 +1556,7 @@ function TableBlockClient({
|
|
|
975
1556
|
return next;
|
|
976
1557
|
});
|
|
977
1558
|
setDirty({ added: [], modified: {}, deleted: [] });
|
|
1559
|
+
await refetchTableData();
|
|
978
1560
|
setIsSaveSuccess(true);
|
|
979
1561
|
setTimeout(() => {
|
|
980
1562
|
setIsSaveSuccess(false);
|
|
@@ -987,7 +1569,7 @@ function TableBlockClient({
|
|
|
987
1569
|
setIsSaving(false);
|
|
988
1570
|
}
|
|
989
1571
|
};
|
|
990
|
-
const filteredData =
|
|
1572
|
+
const filteredData = useMemo2(() => {
|
|
991
1573
|
if (!searchQuery) return data;
|
|
992
1574
|
const lowerQuery = searchQuery.toLowerCase();
|
|
993
1575
|
return data.filter(
|
|
@@ -998,32 +1580,60 @@ function TableBlockClient({
|
|
|
998
1580
|
}, [data, searchQuery]);
|
|
999
1581
|
const isUpdatingActive = Boolean(isUpdating || isSaving);
|
|
1000
1582
|
const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
|
|
1001
|
-
|
|
1583
|
+
const columnTotals = useMemo2(() => {
|
|
1584
|
+
const totals = {};
|
|
1585
|
+
if (!showSummary) return totals;
|
|
1586
|
+
filteredColumns.forEach((col) => {
|
|
1587
|
+
var _a;
|
|
1588
|
+
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
1589
|
+
if (typeUpper === "CURRENCY" || typeUpper === "NUMBER") {
|
|
1590
|
+
const sum = filteredData.reduce((acc, row) => {
|
|
1591
|
+
var _a2;
|
|
1592
|
+
const val = (_a2 = row.data) == null ? void 0 : _a2[col.name];
|
|
1593
|
+
const num = Number(val);
|
|
1594
|
+
return acc + (isNaN(num) ? 0 : num);
|
|
1595
|
+
}, 0);
|
|
1596
|
+
totals[col.name] = sum;
|
|
1597
|
+
}
|
|
1598
|
+
});
|
|
1599
|
+
return totals;
|
|
1600
|
+
}, [filteredData, filteredColumns, showSummary]);
|
|
1601
|
+
return /* @__PURE__ */ jsxs5(
|
|
1002
1602
|
"div",
|
|
1003
1603
|
{
|
|
1004
1604
|
id: componentId,
|
|
1005
1605
|
"data-testid": dataTestId || (componentId ? `table-block-${componentId}` : void 0),
|
|
1006
|
-
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs overflow-hidden ${className}`,
|
|
1606
|
+
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs min-h-[350px] overflow-hidden ${className}`,
|
|
1007
1607
|
dir: "rtl",
|
|
1008
1608
|
children: [
|
|
1009
|
-
errorMessage && /* @__PURE__ */
|
|
1010
|
-
/* @__PURE__ */
|
|
1011
|
-
/* @__PURE__ */
|
|
1609
|
+
errorMessage && /* @__PURE__ */ jsx5("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
1610
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 text-rose-500 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
1611
|
+
/* @__PURE__ */ jsx5("span", { children: errorMessage })
|
|
1012
1612
|
] }) }),
|
|
1013
|
-
/* @__PURE__ */
|
|
1014
|
-
/* @__PURE__ */
|
|
1015
|
-
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */
|
|
1016
|
-
/* @__PURE__ */
|
|
1613
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap items-center justify-between gap-3 p-3.5 sm:p-4 bg-slate-50 border-b border-slate-200", children: [
|
|
1614
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap items-center gap-2.5", children: [
|
|
1615
|
+
((schema == null ? void 0 : schema.title) || (schema == null ? void 0 : schema.name)) && /* @__PURE__ */ jsx5("div", { className: "font-bold text-slate-800 text-sm sm:text-base border-l border-slate-300 pl-3 ml-1", children: /* @__PURE__ */ jsx5("span", { children: schema.title || schema.name }) }),
|
|
1616
|
+
/* @__PURE__ */ jsx5(
|
|
1017
1617
|
"button",
|
|
1018
1618
|
{
|
|
1019
1619
|
onClick: handleAddRow,
|
|
1020
1620
|
disabled: isLoading || isUpdatingActive,
|
|
1021
1621
|
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",
|
|
1022
1622
|
title: "\u05D4\u05D5\u05E1\u05E3 \u05E9\u05D5\u05E8\u05D4 \u05D7\u05D3\u05E9\u05D4",
|
|
1023
|
-
children: /* @__PURE__ */
|
|
1623
|
+
children: /* @__PURE__ */ jsx5("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
|
|
1624
|
+
}
|
|
1625
|
+
),
|
|
1626
|
+
/* @__PURE__ */ jsx5(
|
|
1627
|
+
"button",
|
|
1628
|
+
{
|
|
1629
|
+
onClick: handleDuplicateRow,
|
|
1630
|
+
disabled: isLoading || isUpdatingActive || selectedIds.size !== 1,
|
|
1631
|
+
className: "w-9 h-9 bg-blue-50 hover:bg-blue-100 border border-blue-200 text-blue-700 rounded-lg shadow-2xs flex items-center justify-center transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
|
|
1632
|
+
title: "\u05E9\u05DB\u05E4\u05DC \u05E9\u05D5\u05E8\u05D4 \u05E0\u05D1\u05D7\u05E8\u05EA",
|
|
1633
|
+
children: /* @__PURE__ */ jsx5(Copy2, { className: "w-4 h-4 text-blue-600 shrink-0" })
|
|
1024
1634
|
}
|
|
1025
1635
|
),
|
|
1026
|
-
/* @__PURE__ */
|
|
1636
|
+
/* @__PURE__ */ jsxs5(
|
|
1027
1637
|
"button",
|
|
1028
1638
|
{
|
|
1029
1639
|
onClick: handleDeleteSelected,
|
|
@@ -1031,14 +1641,120 @@ function TableBlockClient({
|
|
|
1031
1641
|
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",
|
|
1032
1642
|
title: "\u05DE\u05D7\u05E7 \u05E9\u05D5\u05E8\u05D5\u05EA \u05E0\u05D1\u05D7\u05E8\u05D5\u05EA",
|
|
1033
1643
|
children: [
|
|
1034
|
-
/* @__PURE__ */
|
|
1035
|
-
selectedIds.size > 0 && /* @__PURE__ */
|
|
1644
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-4.5 h-4.5 text-rose-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }),
|
|
1645
|
+
selectedIds.size > 0 && /* @__PURE__ */ jsx5("span", { className: "absolute -top-1.5 -right-1.5 bg-rose-600 text-white min-w-[18px] h-[18px] px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs", children: selectedIds.size })
|
|
1036
1646
|
]
|
|
1037
1647
|
}
|
|
1038
1648
|
),
|
|
1039
|
-
/* @__PURE__ */
|
|
1040
|
-
|
|
1041
|
-
|
|
1649
|
+
/* @__PURE__ */ jsxs5(
|
|
1650
|
+
"button",
|
|
1651
|
+
{
|
|
1652
|
+
onClick: toggleSummary,
|
|
1653
|
+
disabled: isLoading || isUpdatingActive,
|
|
1654
|
+
className: `h-9 px-3 border font-semibold rounded-lg shadow-2xs flex items-center gap-1.5 text-xs transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer ${showSummary ? "bg-indigo-50 border-indigo-200 text-indigo-700 hover:bg-indigo-100" : "bg-white border-slate-300 text-slate-700 hover:bg-slate-100"}`,
|
|
1655
|
+
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
|
|
1656
|
+
children: [
|
|
1657
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
|
|
1658
|
+
/* @__PURE__ */ jsx5("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
|
|
1659
|
+
]
|
|
1660
|
+
}
|
|
1661
|
+
),
|
|
1662
|
+
/* @__PURE__ */ jsxs5("div", { className: "relative", ref: dropdownRef, children: [
|
|
1663
|
+
/* @__PURE__ */ jsxs5(
|
|
1664
|
+
"button",
|
|
1665
|
+
{
|
|
1666
|
+
onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
|
|
1667
|
+
disabled: isLoading || isUpdatingActive,
|
|
1668
|
+
className: "h-9 px-3 bg-white hover:bg-slate-100 border border-slate-300 text-slate-700 font-semibold rounded-lg shadow-2xs flex items-center gap-1.5 text-xs transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
|
|
1669
|
+
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
|
|
1670
|
+
children: [
|
|
1671
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" }) }),
|
|
1672
|
+
/* @__PURE__ */ jsx5("svg", { className: `w-3.5 h-3.5 text-slate-500 transition-transform ${isColumnsDropdownOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
|
|
1673
|
+
]
|
|
1674
|
+
}
|
|
1675
|
+
),
|
|
1676
|
+
isColumnsDropdownOpen && /* @__PURE__ */ jsxs5("div", { className: "absolute right-0 top-full mt-1.5 w-56 bg-white border border-slate-200 rounded-xl shadow-xl z-50 p-1.5 dir-rtl animate-in fade-in slide-in-from-top-2 duration-150", children: [
|
|
1677
|
+
/* @__PURE__ */ jsxs5("div", { className: "px-2 py-1.5 text-xs font-bold text-slate-500 border-b border-slate-100 mb-1 flex items-center justify-between", children: [
|
|
1678
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5", children: [
|
|
1679
|
+
/* @__PURE__ */ jsx5("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
|
|
1680
|
+
/* @__PURE__ */ jsxs5("span", { className: "text-[10px] font-normal text-slate-400", children: [
|
|
1681
|
+
"(",
|
|
1682
|
+
customizableColumns.filter((c) => !c.isHidden).length,
|
|
1683
|
+
"/",
|
|
1684
|
+
customizableColumns.length,
|
|
1685
|
+
")"
|
|
1686
|
+
] })
|
|
1687
|
+
] }),
|
|
1688
|
+
/* @__PURE__ */ jsx5(
|
|
1689
|
+
"button",
|
|
1690
|
+
{
|
|
1691
|
+
type: "button",
|
|
1692
|
+
onClick: handleShowAllColumns,
|
|
1693
|
+
className: "text-xs text-brand hover:text-brand-hover font-semibold hover:underline cursor-pointer",
|
|
1694
|
+
children: "\u05D4\u05E6\u05D2 \u05D4\u05DB\u05DC"
|
|
1695
|
+
}
|
|
1696
|
+
)
|
|
1697
|
+
] }),
|
|
1698
|
+
/* @__PURE__ */ jsx5("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
|
|
1699
|
+
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
1700
|
+
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
1701
|
+
const isProtected = isRequired || isUnique;
|
|
1702
|
+
const isVisible = !col.isHidden;
|
|
1703
|
+
let protectedExplanation = "";
|
|
1704
|
+
if (isRequired && isUnique) {
|
|
1705
|
+
protectedExplanation = "\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4 \u05D5\u05D9\u05D9\u05D7\u05D5\u05D3\u05D9 - \u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D4\u05D5\u05E8\u05D9\u05D3 \u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5 \u05DE\u05D4\u05EA\u05E6\u05D5\u05D2\u05D4";
|
|
1706
|
+
} else if (isRequired) {
|
|
1707
|
+
protectedExplanation = "\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4 - \u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D4\u05D5\u05E8\u05D9\u05D3 \u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5 \u05DE\u05D4\u05EA\u05E6\u05D5\u05D2\u05D4";
|
|
1708
|
+
} else if (isUnique) {
|
|
1709
|
+
protectedExplanation = "\u05E9\u05D3\u05D4 \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9 - \u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D4\u05D5\u05E8\u05D9\u05D3 \u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5 \u05DE\u05D4\u05EA\u05E6\u05D5\u05D2\u05D4";
|
|
1710
|
+
}
|
|
1711
|
+
const badgeLabel = isRequired && isUnique ? "\u05D7\u05D5\u05D1\u05D4 + \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9" : isRequired ? "\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4" : "\u05E9\u05D3\u05D4 \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9";
|
|
1712
|
+
return /* @__PURE__ */ jsxs5(
|
|
1713
|
+
"div",
|
|
1714
|
+
{
|
|
1715
|
+
onClick: () => {
|
|
1716
|
+
if (!isProtected) {
|
|
1717
|
+
handleToggleColumnVisibility(col.name, !isVisible);
|
|
1718
|
+
}
|
|
1719
|
+
},
|
|
1720
|
+
title: isProtected ? protectedExplanation : void 0,
|
|
1721
|
+
className: `group flex items-center justify-between px-2.5 py-1.5 rounded-lg text-xs transition-colors select-none ${isProtected ? "opacity-75 bg-slate-50 border border-slate-100/70 cursor-not-allowed" : "hover:bg-slate-100 active:bg-slate-200 cursor-pointer"}`,
|
|
1722
|
+
children: [
|
|
1723
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
1724
|
+
/* @__PURE__ */ jsx5(
|
|
1725
|
+
"input",
|
|
1726
|
+
{
|
|
1727
|
+
type: "checkbox",
|
|
1728
|
+
checked: isVisible,
|
|
1729
|
+
disabled: isProtected,
|
|
1730
|
+
onChange: () => {
|
|
1731
|
+
},
|
|
1732
|
+
className: "w-3.5 h-3.5 rounded border-slate-300 text-brand focus:ring-brand/20 cursor-pointer disabled:cursor-not-allowed disabled:opacity-60"
|
|
1733
|
+
}
|
|
1734
|
+
),
|
|
1735
|
+
/* @__PURE__ */ jsx5("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
|
|
1736
|
+
] }),
|
|
1737
|
+
isProtected && /* @__PURE__ */ jsxs5(
|
|
1738
|
+
"div",
|
|
1739
|
+
{
|
|
1740
|
+
className: "flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-semibold bg-amber-50 text-amber-800 border border-amber-200/80 cursor-help",
|
|
1741
|
+
title: protectedExplanation,
|
|
1742
|
+
children: [
|
|
1743
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-3 h-3 text-amber-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: "2.2", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }),
|
|
1744
|
+
/* @__PURE__ */ jsx5("span", { children: badgeLabel })
|
|
1745
|
+
]
|
|
1746
|
+
}
|
|
1747
|
+
)
|
|
1748
|
+
]
|
|
1749
|
+
},
|
|
1750
|
+
col.name
|
|
1751
|
+
);
|
|
1752
|
+
}) })
|
|
1753
|
+
] })
|
|
1754
|
+
] }),
|
|
1755
|
+
/* @__PURE__ */ jsx5("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
|
|
1756
|
+
/* @__PURE__ */ jsxs5("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
|
|
1757
|
+
/* @__PURE__ */ jsx5(
|
|
1042
1758
|
"input",
|
|
1043
1759
|
{
|
|
1044
1760
|
placeholder: "\u05D7\u05D9\u05E4\u05D5\u05E9 \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA...",
|
|
@@ -1048,36 +1764,45 @@ function TableBlockClient({
|
|
|
1048
1764
|
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"
|
|
1049
1765
|
}
|
|
1050
1766
|
),
|
|
1051
|
-
|
|
1767
|
+
searchQuery ? /* @__PURE__ */ jsx5(
|
|
1768
|
+
"button",
|
|
1769
|
+
{
|
|
1770
|
+
type: "button",
|
|
1771
|
+
onClick: () => setSearchQuery(""),
|
|
1772
|
+
className: "absolute right-2.5 top-2.5 text-slate-400 hover:text-slate-600 transition-colors p-0.5 rounded-full hover:bg-slate-100 cursor-pointer",
|
|
1773
|
+
title: "Clear search",
|
|
1774
|
+
children: /* @__PURE__ */ jsx5(X4, { className: "w-3.5 h-3.5" })
|
|
1775
|
+
}
|
|
1776
|
+
) : /* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 text-slate-400 absolute right-2.5 top-2.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
|
|
1052
1777
|
] })
|
|
1053
1778
|
] }),
|
|
1054
|
-
/* @__PURE__ */
|
|
1055
|
-
isUpdatingActive ? /* @__PURE__ */
|
|
1056
|
-
/* @__PURE__ */
|
|
1779
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
|
|
1780
|
+
isUpdatingActive ? /* @__PURE__ */ jsxs5("span", { className: "text-xs text-blue-600 font-semibold flex items-center gap-1.5 bg-blue-50 border border-blue-200 px-3 py-1.5 rounded-lg animate-pulse", children: [
|
|
1781
|
+
/* @__PURE__ */ jsx5("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
|
|
1057
1782
|
"\u05DE\u05E2\u05D3\u05DB\u05DF..."
|
|
1058
|
-
] }) : isSaveSuccess ? /* @__PURE__ */
|
|
1059
|
-
/* @__PURE__ */
|
|
1783
|
+
] }) : isSaveSuccess ? /* @__PURE__ */ jsxs5("span", { className: "text-xs text-emerald-700 font-semibold flex items-center gap-1.5 bg-emerald-50 border border-emerald-200 px-3 py-1.5 rounded-lg animate-in fade-in duration-200", children: [
|
|
1784
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 text-emerald-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M5 13l4 4L19 7" }) }),
|
|
1060
1785
|
"\u05E2\u05D5\u05D3\u05DB\u05DF \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
1061
|
-
] }) : hasChanges ? /* @__PURE__ */
|
|
1062
|
-
/* @__PURE__ */
|
|
1786
|
+
] }) : hasChanges ? /* @__PURE__ */ jsx5("span", { className: "text-xs font-semibold text-amber-700 animate-in fade-in", children: "\u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD \u05E9\u05DC\u05D0 \u05E0\u05E9\u05DE\u05E8\u05D5" }) : null,
|
|
1787
|
+
/* @__PURE__ */ jsx5(
|
|
1063
1788
|
"button",
|
|
1064
1789
|
{
|
|
1065
1790
|
onClick: handleSave,
|
|
1066
1791
|
disabled: isUpdatingActive || isLoading || !hasChanges,
|
|
1067
1792
|
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"}`,
|
|
1068
|
-
children: /* @__PURE__ */
|
|
1793
|
+
children: /* @__PURE__ */ jsx5("span", { children: isUpdatingActive ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DE\u05D9\u05E8\u05EA \u05E9\u05D9\u05E0\u05D5\u05D9\u05D9\u05DD" })
|
|
1069
1794
|
}
|
|
1070
1795
|
)
|
|
1071
1796
|
] })
|
|
1072
1797
|
] }),
|
|
1073
|
-
/* @__PURE__ */
|
|
1074
|
-
isLoading && /* @__PURE__ */
|
|
1075
|
-
/* @__PURE__ */
|
|
1076
|
-
/* @__PURE__ */
|
|
1798
|
+
/* @__PURE__ */ jsxs5("div", { className: `overflow-x-auto relative min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
|
|
1799
|
+
isLoading && /* @__PURE__ */ jsxs5("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
|
|
1800
|
+
/* @__PURE__ */ jsx5("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
|
|
1801
|
+
/* @__PURE__ */ jsx5("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
|
|
1077
1802
|
] }),
|
|
1078
|
-
/* @__PURE__ */
|
|
1079
|
-
/* @__PURE__ */
|
|
1080
|
-
/* @__PURE__ */
|
|
1803
|
+
/* @__PURE__ */ jsxs5("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
|
|
1804
|
+
/* @__PURE__ */ jsx5("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ jsxs5("tr", { children: [
|
|
1805
|
+
/* @__PURE__ */ jsx5("th", { className: "border-b border-l border-slate-200 p-2.5 w-10 text-center shrink-0", style: { width: 50, minWidth: 50, maxWidth: 50 }, children: /* @__PURE__ */ jsx5(
|
|
1081
1806
|
"input",
|
|
1082
1807
|
{
|
|
1083
1808
|
type: "checkbox",
|
|
@@ -1087,13 +1812,83 @@ function TableBlockClient({
|
|
|
1087
1812
|
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
1088
1813
|
}
|
|
1089
1814
|
) }),
|
|
1090
|
-
filteredColumns.map((col) =>
|
|
1815
|
+
filteredColumns.map((col) => {
|
|
1816
|
+
const isDragging = draggedColName === col.name;
|
|
1817
|
+
const isDragOver = dragOverColName === col.name;
|
|
1818
|
+
const currentWidth = columnWidths[col.name] || 200;
|
|
1819
|
+
return /* @__PURE__ */ jsxs5(
|
|
1820
|
+
"th",
|
|
1821
|
+
{
|
|
1822
|
+
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
1823
|
+
draggable: !isLoading && !isUpdatingActive,
|
|
1824
|
+
onDragStart: (e) => {
|
|
1825
|
+
e.dataTransfer.setData("text/plain", col.name);
|
|
1826
|
+
e.dataTransfer.effectAllowed = "move";
|
|
1827
|
+
setDraggedColName(col.name);
|
|
1828
|
+
},
|
|
1829
|
+
onDragOver: (e) => {
|
|
1830
|
+
e.preventDefault();
|
|
1831
|
+
e.dataTransfer.dropEffect = "move";
|
|
1832
|
+
if (dragOverColName !== col.name) {
|
|
1833
|
+
setDragOverColName(col.name);
|
|
1834
|
+
}
|
|
1835
|
+
},
|
|
1836
|
+
onDragLeave: () => {
|
|
1837
|
+
if (dragOverColName === col.name) {
|
|
1838
|
+
setDragOverColName(null);
|
|
1839
|
+
}
|
|
1840
|
+
},
|
|
1841
|
+
onDrop: (e) => {
|
|
1842
|
+
e.preventDefault();
|
|
1843
|
+
if (draggedColName && draggedColName !== col.name) {
|
|
1844
|
+
handleColumnReorder(draggedColName, col.name);
|
|
1845
|
+
}
|
|
1846
|
+
setDraggedColName(null);
|
|
1847
|
+
setDragOverColName(null);
|
|
1848
|
+
},
|
|
1849
|
+
onDragEnd: () => {
|
|
1850
|
+
setDraggedColName(null);
|
|
1851
|
+
setDragOverColName(null);
|
|
1852
|
+
},
|
|
1853
|
+
className: `relative border-b border-l border-slate-200 px-4 py-2.5 font-semibold text-slate-700 whitespace-nowrap select-none cursor-grab active:cursor-grabbing transition-colors ${isDragging ? "opacity-40 bg-slate-200 border-dashed border-2 border-brand" : ""} ${isDragOver ? "bg-blue-50 border-r-4 border-r-brand text-brand font-bold" : "hover:bg-slate-200/60"}`,
|
|
1854
|
+
children: [
|
|
1855
|
+
/* @__PURE__ */ jsx5(
|
|
1856
|
+
"div",
|
|
1857
|
+
{
|
|
1858
|
+
onMouseDown: (e) => {
|
|
1859
|
+
e.preventDefault();
|
|
1860
|
+
e.stopPropagation();
|
|
1861
|
+
setResizingCol({ name: col.name, startWidth: currentWidth, startX: e.clientX });
|
|
1862
|
+
},
|
|
1863
|
+
className: "absolute left-0 top-0 bottom-0 w-1.5 cursor-col-resize hover:bg-brand active:bg-brand-hover z-20",
|
|
1864
|
+
title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
|
|
1865
|
+
}
|
|
1866
|
+
),
|
|
1867
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between gap-2 group overflow-hidden", title: "\u05D2\u05E8\u05D5\u05E8 \u05DC\u05E9\u05D9\u05E0\u05D5\u05D9 \u05E1\u05D3\u05E8 \u05D4\u05E2\u05DE\u05D5\u05D3\u05D4", children: [
|
|
1868
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate", children: col.name }),
|
|
1869
|
+
/* @__PURE__ */ jsx5(
|
|
1870
|
+
"svg",
|
|
1871
|
+
{
|
|
1872
|
+
className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
|
|
1873
|
+
fill: "none",
|
|
1874
|
+
viewBox: "0 0 24 24",
|
|
1875
|
+
stroke: "currentColor",
|
|
1876
|
+
children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
|
|
1877
|
+
}
|
|
1878
|
+
)
|
|
1879
|
+
] })
|
|
1880
|
+
]
|
|
1881
|
+
},
|
|
1882
|
+
col.name
|
|
1883
|
+
);
|
|
1884
|
+
}),
|
|
1885
|
+
/* @__PURE__ */ jsx5("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none" })
|
|
1091
1886
|
] }) }),
|
|
1092
|
-
/* @__PURE__ */
|
|
1093
|
-
/* @__PURE__ */
|
|
1094
|
-
/* @__PURE__ */
|
|
1095
|
-
] }) }) }) : filteredData.map((row) => /* @__PURE__ */
|
|
1096
|
-
/* @__PURE__ */
|
|
1887
|
+
/* @__PURE__ */ jsx5("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ jsx5("tr", { children: /* @__PURE__ */ jsx5("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center justify-center gap-2", children: [
|
|
1888
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }),
|
|
1889
|
+
/* @__PURE__ */ jsx5("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
|
|
1890
|
+
] }) }) }) : filteredData.map((row) => /* @__PURE__ */ jsxs5("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
|
|
1891
|
+
/* @__PURE__ */ jsx5("td", { className: "border-b border-l border-slate-200 p-1.5 text-center bg-white group-hover:bg-transparent", children: /* @__PURE__ */ jsx5(
|
|
1097
1892
|
"input",
|
|
1098
1893
|
{
|
|
1099
1894
|
type: "checkbox",
|
|
@@ -1115,7 +1910,7 @@ function TableBlockClient({
|
|
|
1115
1910
|
}
|
|
1116
1911
|
}
|
|
1117
1912
|
if (value === void 0) value = null;
|
|
1118
|
-
return /* @__PURE__ */
|
|
1913
|
+
return /* @__PURE__ */ jsx5("td", { className: "border-b border-l border-slate-200 p-0 relative", children: /* @__PURE__ */ jsx5(
|
|
1119
1914
|
InputComponent,
|
|
1120
1915
|
{
|
|
1121
1916
|
value,
|
|
@@ -1135,8 +1930,82 @@ function TableBlockClient({
|
|
|
1135
1930
|
}
|
|
1136
1931
|
}
|
|
1137
1932
|
) }, col.name);
|
|
1138
|
-
})
|
|
1139
|
-
|
|
1933
|
+
}),
|
|
1934
|
+
/* @__PURE__ */ jsx5("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
|
|
1935
|
+
] }, row.id)) }),
|
|
1936
|
+
showSummary && filteredData.length > 0 && /* @__PURE__ */ jsx5("tfoot", { className: "bg-slate-50 border-t-2 border-slate-300 sticky bottom-0 z-10 shadow-[0_-2px_4px_rgba(0,0,0,0.02)]", children: /* @__PURE__ */ jsxs5("tr", { children: [
|
|
1937
|
+
/* @__PURE__ */ jsx5("td", { className: "border-b border-l border-slate-200 p-1.5 text-center font-bold text-slate-600 text-xs", children: '\u05E1\u05D4"\u05DB' }),
|
|
1938
|
+
filteredColumns.map((col) => {
|
|
1939
|
+
var _a;
|
|
1940
|
+
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
1941
|
+
const isNumeric = typeUpper === "CURRENCY" || typeUpper === "NUMBER";
|
|
1942
|
+
const total = columnTotals[col.name];
|
|
1943
|
+
let displayVal = "";
|
|
1944
|
+
if (isNumeric && total !== void 0) {
|
|
1945
|
+
displayVal = new Intl.NumberFormat("en-US").format(total);
|
|
1946
|
+
if (typeUpper === "CURRENCY") {
|
|
1947
|
+
const symbol = getCurrencySymbol(col.currencySymbol);
|
|
1948
|
+
displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
return /* @__PURE__ */ jsx5("td", { className: "border-b border-l border-slate-200 p-2 text-sm font-semibold text-slate-700 bg-slate-50 relative", children: isNumeric && /* @__PURE__ */ jsx5("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ jsx5("span", { className: "truncate", children: displayVal }) }) }, col.name);
|
|
1952
|
+
}),
|
|
1953
|
+
/* @__PURE__ */ jsx5("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
|
|
1954
|
+
] }) })
|
|
1955
|
+
] })
|
|
1956
|
+
] }),
|
|
1957
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-3 px-4 py-3 bg-slate-50 border-t border-slate-200 text-xs text-slate-600 rounded-b-xl", children: [
|
|
1958
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
1959
|
+
/* @__PURE__ */ jsx5("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
|
|
1960
|
+
/* @__PURE__ */ jsxs5(
|
|
1961
|
+
"select",
|
|
1962
|
+
{
|
|
1963
|
+
value: limit,
|
|
1964
|
+
onChange: (e) => handleLimitChange(Number(e.target.value)),
|
|
1965
|
+
disabled: isLoading || isUpdatingActive,
|
|
1966
|
+
className: "bg-white border border-slate-300 rounded-lg px-2.5 py-1 text-slate-700 font-semibold shadow-2xs cursor-pointer focus:outline-none focus:ring-2 focus:ring-brand disabled:opacity-50",
|
|
1967
|
+
children: [
|
|
1968
|
+
/* @__PURE__ */ jsx5("option", { value: 20, children: "20" }),
|
|
1969
|
+
/* @__PURE__ */ jsx5("option", { value: 50, children: "50" }),
|
|
1970
|
+
/* @__PURE__ */ jsx5("option", { value: 100, children: "100" })
|
|
1971
|
+
]
|
|
1972
|
+
}
|
|
1973
|
+
)
|
|
1974
|
+
] }),
|
|
1975
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-4", children: [
|
|
1976
|
+
/* @__PURE__ */ jsxs5("span", { className: "font-medium text-slate-600", children: [
|
|
1977
|
+
"\u05E2\u05DE\u05D5\u05D3 ",
|
|
1978
|
+
/* @__PURE__ */ jsx5("strong", { className: "text-slate-900", children: page }),
|
|
1979
|
+
" \u05DE\u05EA\u05D5\u05DA ",
|
|
1980
|
+
/* @__PURE__ */ jsx5("strong", { className: "text-slate-900", children: totalPages || 1 }),
|
|
1981
|
+
totalRecords > 0 && /* @__PURE__ */ jsxs5("span", { className: "text-slate-500 font-normal", children: [
|
|
1982
|
+
" (",
|
|
1983
|
+
totalRecords,
|
|
1984
|
+
' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
|
|
1985
|
+
] })
|
|
1986
|
+
] }),
|
|
1987
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5", children: [
|
|
1988
|
+
/* @__PURE__ */ jsx5(
|
|
1989
|
+
"button",
|
|
1990
|
+
{
|
|
1991
|
+
onClick: handlePrevPage,
|
|
1992
|
+
disabled: page <= 1 || isLoading || isUpdatingActive,
|
|
1993
|
+
className: "px-3 py-1.5 bg-white border border-slate-300 hover:bg-slate-100 font-semibold text-slate-700 rounded-lg shadow-2xs disabled:opacity-40 disabled:pointer-events-none transition-colors cursor-pointer",
|
|
1994
|
+
title: "\u05E2\u05DE\u05D5\u05D3 \u05E7\u05D5\u05D3\u05DD",
|
|
1995
|
+
children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
|
|
1996
|
+
}
|
|
1997
|
+
),
|
|
1998
|
+
/* @__PURE__ */ jsx5(
|
|
1999
|
+
"button",
|
|
2000
|
+
{
|
|
2001
|
+
onClick: handleNextPage,
|
|
2002
|
+
disabled: page >= totalPages || isLoading || isUpdatingActive,
|
|
2003
|
+
className: "px-3 py-1.5 bg-white border border-slate-300 hover:bg-slate-100 font-semibold text-slate-700 rounded-lg shadow-2xs disabled:opacity-40 disabled:pointer-events-none transition-colors cursor-pointer",
|
|
2004
|
+
title: "\u05E2\u05DE\u05D5\u05D3 \u05D4\u05D1\u05D0",
|
|
2005
|
+
children: "\u05D4\u05D1\u05D0"
|
|
2006
|
+
}
|
|
2007
|
+
)
|
|
2008
|
+
] })
|
|
1140
2009
|
] })
|
|
1141
2010
|
] })
|
|
1142
2011
|
]
|
|
@@ -1145,9 +2014,9 @@ function TableBlockClient({
|
|
|
1145
2014
|
}
|
|
1146
2015
|
|
|
1147
2016
|
// src/components/TableBlock/TableBlock.tsx
|
|
1148
|
-
import { jsx as
|
|
2017
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
1149
2018
|
function TableBlock(props) {
|
|
1150
|
-
return /* @__PURE__ */
|
|
2019
|
+
return /* @__PURE__ */ jsx6(TableBlockClient, __spreadValues({}, props));
|
|
1151
2020
|
}
|
|
1152
2021
|
|
|
1153
2022
|
// src/registry.ts
|