@universe-platform/ui 0.1.0-beta.24 → 0.1.0-beta.25
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 +33 -0
- package/dist/index.d.mts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +165 -1
- package/dist/index.mjs +165 -1
- package/package.json +1 -1
package/dist/globals.css
CHANGED
|
@@ -120,6 +120,10 @@
|
|
|
120
120
|
--text-sm--line-height: calc(1.25 / 0.875);
|
|
121
121
|
--text-base: 1rem;
|
|
122
122
|
--text-base--line-height: calc(1.5 / 1);
|
|
123
|
+
--text-xl: 1.25rem;
|
|
124
|
+
--text-xl--line-height: calc(1.75 / 1.25);
|
|
125
|
+
--text-2xl: 1.5rem;
|
|
126
|
+
--text-2xl--line-height: calc(2 / 1.5);
|
|
123
127
|
--font-weight-normal: 400;
|
|
124
128
|
--font-weight-medium: 500;
|
|
125
129
|
--font-weight-semibold: 600;
|
|
@@ -443,6 +447,9 @@
|
|
|
443
447
|
.mt-2 {
|
|
444
448
|
margin-top: calc(var(--spacing) * 2);
|
|
445
449
|
}
|
|
450
|
+
.mt-6 {
|
|
451
|
+
margin-top: calc(var(--spacing) * 6);
|
|
452
|
+
}
|
|
446
453
|
.mt-auto {
|
|
447
454
|
margin-top: auto;
|
|
448
455
|
}
|
|
@@ -473,6 +480,12 @@
|
|
|
473
480
|
.mb-3\.5 {
|
|
474
481
|
margin-bottom: calc(var(--spacing) * 3.5);
|
|
475
482
|
}
|
|
483
|
+
.mb-4 {
|
|
484
|
+
margin-bottom: calc(var(--spacing) * 4);
|
|
485
|
+
}
|
|
486
|
+
.mb-6 {
|
|
487
|
+
margin-bottom: calc(var(--spacing) * 6);
|
|
488
|
+
}
|
|
476
489
|
.ml-0\.5 {
|
|
477
490
|
margin-left: calc(var(--spacing) * 0.5);
|
|
478
491
|
}
|
|
@@ -554,6 +567,9 @@
|
|
|
554
567
|
.h-12 {
|
|
555
568
|
height: calc(var(--spacing) * 12);
|
|
556
569
|
}
|
|
570
|
+
.h-16 {
|
|
571
|
+
height: calc(var(--spacing) * 16);
|
|
572
|
+
}
|
|
557
573
|
.h-44 {
|
|
558
574
|
height: calc(var(--spacing) * 44);
|
|
559
575
|
}
|
|
@@ -596,6 +612,9 @@
|
|
|
596
612
|
.min-h-\[32px\] {
|
|
597
613
|
min-height: 32px;
|
|
598
614
|
}
|
|
615
|
+
.min-h-\[40px\] {
|
|
616
|
+
min-height: 40px;
|
|
617
|
+
}
|
|
599
618
|
.min-h-\[48px\] {
|
|
600
619
|
min-height: 48px;
|
|
601
620
|
}
|
|
@@ -1459,6 +1478,9 @@
|
|
|
1459
1478
|
.p-6 {
|
|
1460
1479
|
padding: calc(var(--spacing) * 6);
|
|
1461
1480
|
}
|
|
1481
|
+
.p-8 {
|
|
1482
|
+
padding: calc(var(--spacing) * 8);
|
|
1483
|
+
}
|
|
1462
1484
|
.p-10 {
|
|
1463
1485
|
padding: calc(var(--spacing) * 10);
|
|
1464
1486
|
}
|
|
@@ -1534,6 +1556,9 @@
|
|
|
1534
1556
|
.pt-2\.5 {
|
|
1535
1557
|
padding-top: calc(var(--spacing) * 2.5);
|
|
1536
1558
|
}
|
|
1559
|
+
.pt-4 {
|
|
1560
|
+
padding-top: calc(var(--spacing) * 4);
|
|
1561
|
+
}
|
|
1537
1562
|
.pr-0\.5 {
|
|
1538
1563
|
padding-right: calc(var(--spacing) * 0.5);
|
|
1539
1564
|
}
|
|
@@ -1609,6 +1634,10 @@
|
|
|
1609
1634
|
.font-sans {
|
|
1610
1635
|
font-family: var(--font-sans);
|
|
1611
1636
|
}
|
|
1637
|
+
.text-2xl {
|
|
1638
|
+
font-size: var(--text-2xl);
|
|
1639
|
+
line-height: var(--tw-leading, var(--text-2xl--line-height));
|
|
1640
|
+
}
|
|
1612
1641
|
.text-base {
|
|
1613
1642
|
font-size: var(--text-base);
|
|
1614
1643
|
line-height: var(--tw-leading, var(--text-base--line-height));
|
|
@@ -1617,6 +1646,10 @@
|
|
|
1617
1646
|
font-size: var(--text-sm);
|
|
1618
1647
|
line-height: var(--tw-leading, var(--text-sm--line-height));
|
|
1619
1648
|
}
|
|
1649
|
+
.text-xl {
|
|
1650
|
+
font-size: var(--text-xl);
|
|
1651
|
+
line-height: var(--tw-leading, var(--text-xl--line-height));
|
|
1652
|
+
}
|
|
1620
1653
|
.text-xs {
|
|
1621
1654
|
font-size: var(--text-xs);
|
|
1622
1655
|
line-height: var(--tw-leading, var(--text-xs--line-height));
|
package/dist/index.d.mts
CHANGED
|
@@ -666,6 +666,15 @@ interface SettingsAndActionsBlockProps {
|
|
|
666
666
|
}
|
|
667
667
|
declare function SettingsAndActionsBlock({ isScanningPhoneColumns, targetPhoneOptions, phoneColumnId, setPhoneColumnId, selectedPhoneOption, autoSelectCount, setAutoSelectCount, subtableFilterColumn, setSubtableFilterColumn, subtableFilterValue, setSubtableFilterValue, subtableSendLimit, setSubtableSendLimit, subtableFilterableColumns, selectedSubtableFilterCol, getRelationOptionsForCol, relationOptions, enablePostSendAction, setEnablePostSendAction, postSendActionColumn, setPostSendActionColumn, postSendActionValue, setPostSendActionValue, setPostSendActionTargetType, postSendActionTargetOptions, selectedPostSendOption, isTestDisabled, testButtonTitle, setIsTestPromptOpen, isSendDisabled, sendButtonTitle, handleSendMessages, selectedRowIdsCount, finalRecipientCount, validMainRowsCount, isSendingBroadcast, broadcastProgress, broadcastSummary, clearBroadcastSummary, }: SettingsAndActionsBlockProps): react_jsx_runtime.JSX.Element;
|
|
668
668
|
|
|
669
|
+
interface FormBlockProps {
|
|
670
|
+
settings: any;
|
|
671
|
+
executeAction?: (actionType: string, payload: Record<string, any>) => Promise<any>;
|
|
672
|
+
componentId?: string;
|
|
673
|
+
className?: string;
|
|
674
|
+
onSuccess?: () => void;
|
|
675
|
+
}
|
|
676
|
+
declare function FormBlock({ settings: schema, executeAction, componentId, className, onSuccess }: FormBlockProps): react_jsx_runtime.JSX.Element;
|
|
677
|
+
|
|
669
678
|
/**
|
|
670
679
|
* UNIVERSE_COMPONENTS
|
|
671
680
|
* Dynamic Component Registry dictionary mapping component type strings (e.g., "TABLE", "WHATSAPP")
|
|
@@ -674,6 +683,7 @@ declare function SettingsAndActionsBlock({ isScanningPhoneColumns, targetPhoneOp
|
|
|
674
683
|
declare const UNIVERSE_COMPONENTS: {
|
|
675
684
|
readonly TABLE: typeof TableBlock;
|
|
676
685
|
readonly WHATSAPP: typeof WhatsAppComponent;
|
|
686
|
+
readonly FORM: typeof FormBlock;
|
|
677
687
|
};
|
|
678
688
|
type ComponentRegistry = typeof UNIVERSE_COMPONENTS;
|
|
679
689
|
type UniverseComponentType = keyof ComponentRegistry;
|
package/dist/index.d.ts
CHANGED
|
@@ -666,6 +666,15 @@ interface SettingsAndActionsBlockProps {
|
|
|
666
666
|
}
|
|
667
667
|
declare function SettingsAndActionsBlock({ isScanningPhoneColumns, targetPhoneOptions, phoneColumnId, setPhoneColumnId, selectedPhoneOption, autoSelectCount, setAutoSelectCount, subtableFilterColumn, setSubtableFilterColumn, subtableFilterValue, setSubtableFilterValue, subtableSendLimit, setSubtableSendLimit, subtableFilterableColumns, selectedSubtableFilterCol, getRelationOptionsForCol, relationOptions, enablePostSendAction, setEnablePostSendAction, postSendActionColumn, setPostSendActionColumn, postSendActionValue, setPostSendActionValue, setPostSendActionTargetType, postSendActionTargetOptions, selectedPostSendOption, isTestDisabled, testButtonTitle, setIsTestPromptOpen, isSendDisabled, sendButtonTitle, handleSendMessages, selectedRowIdsCount, finalRecipientCount, validMainRowsCount, isSendingBroadcast, broadcastProgress, broadcastSummary, clearBroadcastSummary, }: SettingsAndActionsBlockProps): react_jsx_runtime.JSX.Element;
|
|
668
668
|
|
|
669
|
+
interface FormBlockProps {
|
|
670
|
+
settings: any;
|
|
671
|
+
executeAction?: (actionType: string, payload: Record<string, any>) => Promise<any>;
|
|
672
|
+
componentId?: string;
|
|
673
|
+
className?: string;
|
|
674
|
+
onSuccess?: () => void;
|
|
675
|
+
}
|
|
676
|
+
declare function FormBlock({ settings: schema, executeAction, componentId, className, onSuccess }: FormBlockProps): react_jsx_runtime.JSX.Element;
|
|
677
|
+
|
|
669
678
|
/**
|
|
670
679
|
* UNIVERSE_COMPONENTS
|
|
671
680
|
* Dynamic Component Registry dictionary mapping component type strings (e.g., "TABLE", "WHATSAPP")
|
|
@@ -674,6 +683,7 @@ declare function SettingsAndActionsBlock({ isScanningPhoneColumns, targetPhoneOp
|
|
|
674
683
|
declare const UNIVERSE_COMPONENTS: {
|
|
675
684
|
readonly TABLE: typeof TableBlock;
|
|
676
685
|
readonly WHATSAPP: typeof WhatsAppComponent;
|
|
686
|
+
readonly FORM: typeof FormBlock;
|
|
677
687
|
};
|
|
678
688
|
type ComponentRegistry = typeof UNIVERSE_COMPONENTS;
|
|
679
689
|
type UniverseComponentType = keyof ComponentRegistry;
|
package/dist/index.js
CHANGED
|
@@ -13043,10 +13043,174 @@ function WhatsAppComponent(props) {
|
|
|
13043
13043
|
);
|
|
13044
13044
|
}
|
|
13045
13045
|
|
|
13046
|
+
// src/components/FormBlock/FormBlock.tsx
|
|
13047
|
+
var import_react19 = require("react");
|
|
13048
|
+
var import_lucide_react15 = require("lucide-react");
|
|
13049
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
13050
|
+
function FormBlock({ settings: schema, executeAction, componentId, className = "", onSuccess }) {
|
|
13051
|
+
const { showError, addToast } = useToast();
|
|
13052
|
+
const [formData, setFormData] = (0, import_react19.useState)({});
|
|
13053
|
+
const [isSubmitting, setIsSubmitting] = (0, import_react19.useState)(false);
|
|
13054
|
+
const [isSubmitted, setIsSubmitted] = (0, import_react19.useState)(false);
|
|
13055
|
+
const [columns, setColumns] = (0, import_react19.useState)((schema == null ? void 0 : schema.columns) || []);
|
|
13056
|
+
const [isLoadingSchema, setIsLoadingSchema] = (0, import_react19.useState)(false);
|
|
13057
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
13058
|
+
(0, import_react19.useEffect)(() => {
|
|
13059
|
+
let isMounted = true;
|
|
13060
|
+
if ((!(schema == null ? void 0 : schema.columns) || schema.columns.length === 0) && targetTableId && executeAction) {
|
|
13061
|
+
setIsLoadingSchema(true);
|
|
13062
|
+
executeAction("FETCH_TABLE_DATA", { tableId: targetTableId, limit: 1 }).then((res) => {
|
|
13063
|
+
var _a;
|
|
13064
|
+
if (!isMounted) return;
|
|
13065
|
+
const fetchedCols = ((_a = res == null ? void 0 : res.schema) == null ? void 0 : _a.columns) || (res == null ? void 0 : res.columns);
|
|
13066
|
+
if (fetchedCols && Array.isArray(fetchedCols)) {
|
|
13067
|
+
setColumns(fetchedCols);
|
|
13068
|
+
}
|
|
13069
|
+
}).catch((err) => {
|
|
13070
|
+
console.error("[FormBlock] Failed to fetch table schema:", err);
|
|
13071
|
+
}).finally(() => {
|
|
13072
|
+
if (isMounted) setIsLoadingSchema(false);
|
|
13073
|
+
});
|
|
13074
|
+
} else if (schema == null ? void 0 : schema.columns) {
|
|
13075
|
+
setColumns(schema.columns);
|
|
13076
|
+
}
|
|
13077
|
+
return () => {
|
|
13078
|
+
isMounted = false;
|
|
13079
|
+
};
|
|
13080
|
+
}, [schema == null ? void 0 : schema.columns, targetTableId]);
|
|
13081
|
+
const systemFields = ["_id", "id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
13082
|
+
const formColumns = (columns || []).filter(
|
|
13083
|
+
(col) => !systemFields.includes(col.name) && !col.isHidden
|
|
13084
|
+
).sort((a, b) => {
|
|
13085
|
+
var _a, _b;
|
|
13086
|
+
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
13087
|
+
});
|
|
13088
|
+
const handleFieldChange = (colName, value) => {
|
|
13089
|
+
setFormData((prev) => __spreadProps(__spreadValues({}, prev), { [colName]: value }));
|
|
13090
|
+
};
|
|
13091
|
+
const handleSubmit = async (e) => {
|
|
13092
|
+
e.preventDefault();
|
|
13093
|
+
if (!executeAction) {
|
|
13094
|
+
showError("\u05E8\u05DB\u05D9\u05D1 \u05D4\u05EA\u05E7\u05E9\u05D5\u05E8\u05EA \u05DC\u05D0 \u05D0\u05D5\u05EA\u05D7\u05DC", "\u05E9\u05D2\u05D9\u05D0\u05EA \u05DE\u05E2\u05E8\u05DB\u05EA");
|
|
13095
|
+
return;
|
|
13096
|
+
}
|
|
13097
|
+
if (!targetTableId) {
|
|
13098
|
+
showError("\u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05E9\u05DE\u05D5\u05E8: \u05DE\u05D6\u05D4\u05D4 \u05D4\u05D8\u05D1\u05DC\u05D4 \u05D7\u05E1\u05E8", "\u05E9\u05D2\u05D9\u05D0\u05EA \u05E9\u05DE\u05D9\u05E8\u05D4");
|
|
13099
|
+
return;
|
|
13100
|
+
}
|
|
13101
|
+
const missingFields = formColumns.filter(
|
|
13102
|
+
(col) => col.isRequired && (formData[col.name] === void 0 || formData[col.name] === null || formData[col.name] === "")
|
|
13103
|
+
);
|
|
13104
|
+
if (missingFields.length > 0) {
|
|
13105
|
+
showError(`\u05D9\u05E9 \u05DC\u05DE\u05DC\u05D0 \u05D0\u05EA \u05D4\u05E9\u05D3\u05D5\u05EA \u05D4\u05D1\u05D0\u05D9\u05DD: ${missingFields.map((c) => c.name).join(", ")}`, "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D5\u05DC\u05D9\u05D3\u05E6\u05D9\u05D4");
|
|
13106
|
+
return;
|
|
13107
|
+
}
|
|
13108
|
+
setIsSubmitting(true);
|
|
13109
|
+
try {
|
|
13110
|
+
const formattedPayload = {};
|
|
13111
|
+
formColumns.forEach((col) => {
|
|
13112
|
+
var _a;
|
|
13113
|
+
let val = formData[col.name];
|
|
13114
|
+
if (val !== void 0 && val !== null) {
|
|
13115
|
+
if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
|
|
13116
|
+
val = val === "" ? 0 : Number(val);
|
|
13117
|
+
}
|
|
13118
|
+
formattedPayload[col.name] = val;
|
|
13119
|
+
} else if (col.defaultValue !== void 0) {
|
|
13120
|
+
formattedPayload[col.name] = col.defaultValue;
|
|
13121
|
+
}
|
|
13122
|
+
});
|
|
13123
|
+
await executeAction("CREATE_RECORD", {
|
|
13124
|
+
tableId: targetTableId,
|
|
13125
|
+
tableMetaId: targetTableId,
|
|
13126
|
+
records: [formattedPayload]
|
|
13127
|
+
});
|
|
13128
|
+
addToast({ message: "\u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD \u05E0\u05E9\u05DE\u05E8\u05D5 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4", type: "success" });
|
|
13129
|
+
setFormData({});
|
|
13130
|
+
setIsSubmitted(true);
|
|
13131
|
+
if (onSuccess) onSuccess();
|
|
13132
|
+
} catch (err) {
|
|
13133
|
+
console.error("[FormBlock] Submit error:", err);
|
|
13134
|
+
showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD");
|
|
13135
|
+
} finally {
|
|
13136
|
+
setIsSubmitting(false);
|
|
13137
|
+
}
|
|
13138
|
+
};
|
|
13139
|
+
if (isLoadingSchema) {
|
|
13140
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "p-8 flex items-center justify-center gap-2 text-slate-500", children: [
|
|
13141
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react15.Loader2, { className: "w-5 h-5 animate-spin text-brand" }),
|
|
13142
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-sm", children: "\u05D8\u05D5\u05E2\u05DF \u05E9\u05D3\u05D5\u05EA \u05D8\u05D5\u05E4\u05E1..." })
|
|
13143
|
+
] });
|
|
13144
|
+
}
|
|
13145
|
+
if (!formColumns || formColumns.length === 0) {
|
|
13146
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "p-4 text-center text-slate-500", children: "\u05DC\u05D0 \u05D4\u05D5\u05D2\u05D3\u05E8\u05D5 \u05E9\u05D3\u05D5\u05EA \u05DC\u05D8\u05D5\u05E4\u05E1 \u05D6\u05D4." });
|
|
13147
|
+
}
|
|
13148
|
+
if (isSubmitted) {
|
|
13149
|
+
const customMessage = (schema == null ? void 0 : schema.successMessage) || "\u05EA\u05D5\u05D3\u05D4 \u05E8\u05D1\u05D4! \u05D4\u05E4\u05E8\u05D8\u05D9\u05DD \u05D4\u05EA\u05E7\u05D1\u05DC\u05D5 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4.";
|
|
13150
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { id: componentId, className: `bg-white p-8 rounded-xl shadow-xs border border-slate-200 text-center dir-rtl ${className}`, children: [
|
|
13151
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "w-16 h-16 bg-emerald-50 text-emerald-600 rounded-full flex items-center justify-center mx-auto mb-4 animate-in zoom-in duration-200", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react15.CheckCircle2, { className: "w-8 h-8" }) }),
|
|
13152
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h3", { className: "text-2xl font-bold text-slate-800 mb-2", children: "\u05D4\u05D5\u05D3\u05E2\u05D4 \u05E0\u05E9\u05DC\u05D7\u05D4" }),
|
|
13153
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-slate-600 text-base max-w-md mx-auto whitespace-pre-wrap", children: customMessage }),
|
|
13154
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
13155
|
+
"button",
|
|
13156
|
+
{
|
|
13157
|
+
type: "button",
|
|
13158
|
+
onClick: () => setIsSubmitted(false),
|
|
13159
|
+
className: "mt-6 px-4 py-2 text-xs font-semibold text-brand hover:underline cursor-pointer",
|
|
13160
|
+
children: "\u05E9\u05DC\u05D9\u05D7\u05EA \u05DE\u05E2\u05E0\u05D4 \u05E0\u05D5\u05E1\u05E3"
|
|
13161
|
+
}
|
|
13162
|
+
)
|
|
13163
|
+
] });
|
|
13164
|
+
}
|
|
13165
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { id: componentId, className: `bg-white p-6 rounded-xl shadow-xs border border-slate-200 dir-rtl ${className}`, children: [
|
|
13166
|
+
(schema == null ? void 0 : schema.title) && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h2", { className: "text-xl font-bold text-slate-800 mb-6", children: schema.title }),
|
|
13167
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
|
|
13168
|
+
formColumns.map((col) => {
|
|
13169
|
+
var _a, _b;
|
|
13170
|
+
const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
13171
|
+
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
13172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
|
|
13173
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { className: "text-sm font-semibold text-slate-700", children: [
|
|
13174
|
+
col.name,
|
|
13175
|
+
" ",
|
|
13176
|
+
col.isRequired && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-rose-500", children: "*" })
|
|
13177
|
+
] }),
|
|
13178
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "border border-slate-200 rounded-lg min-h-[40px] relative", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
13179
|
+
InputComponent,
|
|
13180
|
+
{
|
|
13181
|
+
column: col,
|
|
13182
|
+
rowId: "new_form_record",
|
|
13183
|
+
value: (_b = formData[col.name]) != null ? _b : "",
|
|
13184
|
+
onChange: (val) => handleFieldChange(col.name, val),
|
|
13185
|
+
context: {
|
|
13186
|
+
executeAction,
|
|
13187
|
+
tableId: targetTableId
|
|
13188
|
+
}
|
|
13189
|
+
}
|
|
13190
|
+
) })
|
|
13191
|
+
] }, col.name);
|
|
13192
|
+
}),
|
|
13193
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "pt-4 border-t border-slate-100 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
13194
|
+
"button",
|
|
13195
|
+
{
|
|
13196
|
+
type: "submit",
|
|
13197
|
+
disabled: isSubmitting,
|
|
13198
|
+
className: "flex items-center gap-2 px-6 py.2.5 bg-brand hover:bg-brand-hover text-white font-bold rounded-lg shadow-sm transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
|
|
13199
|
+
children: [
|
|
13200
|
+
isSubmitting && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react15.Loader2, { className: "w-4 h-4 animate-spin" }),
|
|
13201
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: isSubmitting ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DC\u05D9\u05D7\u05D4" })
|
|
13202
|
+
]
|
|
13203
|
+
}
|
|
13204
|
+
) })
|
|
13205
|
+
] })
|
|
13206
|
+
] });
|
|
13207
|
+
}
|
|
13208
|
+
|
|
13046
13209
|
// src/registry.ts
|
|
13047
13210
|
var UNIVERSE_COMPONENTS = {
|
|
13048
13211
|
TABLE: TableBlock,
|
|
13049
|
-
WHATSAPP: WhatsAppComponent
|
|
13212
|
+
WHATSAPP: WhatsAppComponent,
|
|
13213
|
+
FORM: FormBlock
|
|
13050
13214
|
};
|
|
13051
13215
|
// Annotate the CommonJS export names for ESM import in node:
|
|
13052
13216
|
0 && (module.exports = {
|
package/dist/index.mjs
CHANGED
|
@@ -12991,10 +12991,174 @@ function WhatsAppComponent(props) {
|
|
|
12991
12991
|
);
|
|
12992
12992
|
}
|
|
12993
12993
|
|
|
12994
|
+
// src/components/FormBlock/FormBlock.tsx
|
|
12995
|
+
import { useState as useState16, useEffect as useEffect14 } from "react";
|
|
12996
|
+
import { Loader2 as Loader28, CheckCircle2 as CheckCircle25 } from "lucide-react";
|
|
12997
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
12998
|
+
function FormBlock({ settings: schema, executeAction, componentId, className = "", onSuccess }) {
|
|
12999
|
+
const { showError, addToast } = useToast();
|
|
13000
|
+
const [formData, setFormData] = useState16({});
|
|
13001
|
+
const [isSubmitting, setIsSubmitting] = useState16(false);
|
|
13002
|
+
const [isSubmitted, setIsSubmitted] = useState16(false);
|
|
13003
|
+
const [columns, setColumns] = useState16((schema == null ? void 0 : schema.columns) || []);
|
|
13004
|
+
const [isLoadingSchema, setIsLoadingSchema] = useState16(false);
|
|
13005
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
13006
|
+
useEffect14(() => {
|
|
13007
|
+
let isMounted = true;
|
|
13008
|
+
if ((!(schema == null ? void 0 : schema.columns) || schema.columns.length === 0) && targetTableId && executeAction) {
|
|
13009
|
+
setIsLoadingSchema(true);
|
|
13010
|
+
executeAction("FETCH_TABLE_DATA", { tableId: targetTableId, limit: 1 }).then((res) => {
|
|
13011
|
+
var _a;
|
|
13012
|
+
if (!isMounted) return;
|
|
13013
|
+
const fetchedCols = ((_a = res == null ? void 0 : res.schema) == null ? void 0 : _a.columns) || (res == null ? void 0 : res.columns);
|
|
13014
|
+
if (fetchedCols && Array.isArray(fetchedCols)) {
|
|
13015
|
+
setColumns(fetchedCols);
|
|
13016
|
+
}
|
|
13017
|
+
}).catch((err) => {
|
|
13018
|
+
console.error("[FormBlock] Failed to fetch table schema:", err);
|
|
13019
|
+
}).finally(() => {
|
|
13020
|
+
if (isMounted) setIsLoadingSchema(false);
|
|
13021
|
+
});
|
|
13022
|
+
} else if (schema == null ? void 0 : schema.columns) {
|
|
13023
|
+
setColumns(schema.columns);
|
|
13024
|
+
}
|
|
13025
|
+
return () => {
|
|
13026
|
+
isMounted = false;
|
|
13027
|
+
};
|
|
13028
|
+
}, [schema == null ? void 0 : schema.columns, targetTableId]);
|
|
13029
|
+
const systemFields = ["_id", "id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
13030
|
+
const formColumns = (columns || []).filter(
|
|
13031
|
+
(col) => !systemFields.includes(col.name) && !col.isHidden
|
|
13032
|
+
).sort((a, b) => {
|
|
13033
|
+
var _a, _b;
|
|
13034
|
+
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
13035
|
+
});
|
|
13036
|
+
const handleFieldChange = (colName, value) => {
|
|
13037
|
+
setFormData((prev) => __spreadProps(__spreadValues({}, prev), { [colName]: value }));
|
|
13038
|
+
};
|
|
13039
|
+
const handleSubmit = async (e) => {
|
|
13040
|
+
e.preventDefault();
|
|
13041
|
+
if (!executeAction) {
|
|
13042
|
+
showError("\u05E8\u05DB\u05D9\u05D1 \u05D4\u05EA\u05E7\u05E9\u05D5\u05E8\u05EA \u05DC\u05D0 \u05D0\u05D5\u05EA\u05D7\u05DC", "\u05E9\u05D2\u05D9\u05D0\u05EA \u05DE\u05E2\u05E8\u05DB\u05EA");
|
|
13043
|
+
return;
|
|
13044
|
+
}
|
|
13045
|
+
if (!targetTableId) {
|
|
13046
|
+
showError("\u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05E9\u05DE\u05D5\u05E8: \u05DE\u05D6\u05D4\u05D4 \u05D4\u05D8\u05D1\u05DC\u05D4 \u05D7\u05E1\u05E8", "\u05E9\u05D2\u05D9\u05D0\u05EA \u05E9\u05DE\u05D9\u05E8\u05D4");
|
|
13047
|
+
return;
|
|
13048
|
+
}
|
|
13049
|
+
const missingFields = formColumns.filter(
|
|
13050
|
+
(col) => col.isRequired && (formData[col.name] === void 0 || formData[col.name] === null || formData[col.name] === "")
|
|
13051
|
+
);
|
|
13052
|
+
if (missingFields.length > 0) {
|
|
13053
|
+
showError(`\u05D9\u05E9 \u05DC\u05DE\u05DC\u05D0 \u05D0\u05EA \u05D4\u05E9\u05D3\u05D5\u05EA \u05D4\u05D1\u05D0\u05D9\u05DD: ${missingFields.map((c) => c.name).join(", ")}`, "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D5\u05DC\u05D9\u05D3\u05E6\u05D9\u05D4");
|
|
13054
|
+
return;
|
|
13055
|
+
}
|
|
13056
|
+
setIsSubmitting(true);
|
|
13057
|
+
try {
|
|
13058
|
+
const formattedPayload = {};
|
|
13059
|
+
formColumns.forEach((col) => {
|
|
13060
|
+
var _a;
|
|
13061
|
+
let val = formData[col.name];
|
|
13062
|
+
if (val !== void 0 && val !== null) {
|
|
13063
|
+
if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
|
|
13064
|
+
val = val === "" ? 0 : Number(val);
|
|
13065
|
+
}
|
|
13066
|
+
formattedPayload[col.name] = val;
|
|
13067
|
+
} else if (col.defaultValue !== void 0) {
|
|
13068
|
+
formattedPayload[col.name] = col.defaultValue;
|
|
13069
|
+
}
|
|
13070
|
+
});
|
|
13071
|
+
await executeAction("CREATE_RECORD", {
|
|
13072
|
+
tableId: targetTableId,
|
|
13073
|
+
tableMetaId: targetTableId,
|
|
13074
|
+
records: [formattedPayload]
|
|
13075
|
+
});
|
|
13076
|
+
addToast({ message: "\u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD \u05E0\u05E9\u05DE\u05E8\u05D5 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4", type: "success" });
|
|
13077
|
+
setFormData({});
|
|
13078
|
+
setIsSubmitted(true);
|
|
13079
|
+
if (onSuccess) onSuccess();
|
|
13080
|
+
} catch (err) {
|
|
13081
|
+
console.error("[FormBlock] Submit error:", err);
|
|
13082
|
+
showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD");
|
|
13083
|
+
} finally {
|
|
13084
|
+
setIsSubmitting(false);
|
|
13085
|
+
}
|
|
13086
|
+
};
|
|
13087
|
+
if (isLoadingSchema) {
|
|
13088
|
+
return /* @__PURE__ */ jsxs18("div", { className: "p-8 flex items-center justify-center gap-2 text-slate-500", children: [
|
|
13089
|
+
/* @__PURE__ */ jsx19(Loader28, { className: "w-5 h-5 animate-spin text-brand" }),
|
|
13090
|
+
/* @__PURE__ */ jsx19("span", { className: "text-sm", children: "\u05D8\u05D5\u05E2\u05DF \u05E9\u05D3\u05D5\u05EA \u05D8\u05D5\u05E4\u05E1..." })
|
|
13091
|
+
] });
|
|
13092
|
+
}
|
|
13093
|
+
if (!formColumns || formColumns.length === 0) {
|
|
13094
|
+
return /* @__PURE__ */ jsx19("div", { className: "p-4 text-center text-slate-500", children: "\u05DC\u05D0 \u05D4\u05D5\u05D2\u05D3\u05E8\u05D5 \u05E9\u05D3\u05D5\u05EA \u05DC\u05D8\u05D5\u05E4\u05E1 \u05D6\u05D4." });
|
|
13095
|
+
}
|
|
13096
|
+
if (isSubmitted) {
|
|
13097
|
+
const customMessage = (schema == null ? void 0 : schema.successMessage) || "\u05EA\u05D5\u05D3\u05D4 \u05E8\u05D1\u05D4! \u05D4\u05E4\u05E8\u05D8\u05D9\u05DD \u05D4\u05EA\u05E7\u05D1\u05DC\u05D5 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4.";
|
|
13098
|
+
return /* @__PURE__ */ jsxs18("div", { id: componentId, className: `bg-white p-8 rounded-xl shadow-xs border border-slate-200 text-center dir-rtl ${className}`, children: [
|
|
13099
|
+
/* @__PURE__ */ jsx19("div", { className: "w-16 h-16 bg-emerald-50 text-emerald-600 rounded-full flex items-center justify-center mx-auto mb-4 animate-in zoom-in duration-200", children: /* @__PURE__ */ jsx19(CheckCircle25, { className: "w-8 h-8" }) }),
|
|
13100
|
+
/* @__PURE__ */ jsx19("h3", { className: "text-2xl font-bold text-slate-800 mb-2", children: "\u05D4\u05D5\u05D3\u05E2\u05D4 \u05E0\u05E9\u05DC\u05D7\u05D4" }),
|
|
13101
|
+
/* @__PURE__ */ jsx19("p", { className: "text-slate-600 text-base max-w-md mx-auto whitespace-pre-wrap", children: customMessage }),
|
|
13102
|
+
/* @__PURE__ */ jsx19(
|
|
13103
|
+
"button",
|
|
13104
|
+
{
|
|
13105
|
+
type: "button",
|
|
13106
|
+
onClick: () => setIsSubmitted(false),
|
|
13107
|
+
className: "mt-6 px-4 py-2 text-xs font-semibold text-brand hover:underline cursor-pointer",
|
|
13108
|
+
children: "\u05E9\u05DC\u05D9\u05D7\u05EA \u05DE\u05E2\u05E0\u05D4 \u05E0\u05D5\u05E1\u05E3"
|
|
13109
|
+
}
|
|
13110
|
+
)
|
|
13111
|
+
] });
|
|
13112
|
+
}
|
|
13113
|
+
return /* @__PURE__ */ jsxs18("div", { id: componentId, className: `bg-white p-6 rounded-xl shadow-xs border border-slate-200 dir-rtl ${className}`, children: [
|
|
13114
|
+
(schema == null ? void 0 : schema.title) && /* @__PURE__ */ jsx19("h2", { className: "text-xl font-bold text-slate-800 mb-6", children: schema.title }),
|
|
13115
|
+
/* @__PURE__ */ jsxs18("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
|
|
13116
|
+
formColumns.map((col) => {
|
|
13117
|
+
var _a, _b;
|
|
13118
|
+
const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
13119
|
+
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
13120
|
+
return /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-1.5", children: [
|
|
13121
|
+
/* @__PURE__ */ jsxs18("label", { className: "text-sm font-semibold text-slate-700", children: [
|
|
13122
|
+
col.name,
|
|
13123
|
+
" ",
|
|
13124
|
+
col.isRequired && /* @__PURE__ */ jsx19("span", { className: "text-rose-500", children: "*" })
|
|
13125
|
+
] }),
|
|
13126
|
+
/* @__PURE__ */ jsx19("div", { className: "border border-slate-200 rounded-lg min-h-[40px] relative", children: /* @__PURE__ */ jsx19(
|
|
13127
|
+
InputComponent,
|
|
13128
|
+
{
|
|
13129
|
+
column: col,
|
|
13130
|
+
rowId: "new_form_record",
|
|
13131
|
+
value: (_b = formData[col.name]) != null ? _b : "",
|
|
13132
|
+
onChange: (val) => handleFieldChange(col.name, val),
|
|
13133
|
+
context: {
|
|
13134
|
+
executeAction,
|
|
13135
|
+
tableId: targetTableId
|
|
13136
|
+
}
|
|
13137
|
+
}
|
|
13138
|
+
) })
|
|
13139
|
+
] }, col.name);
|
|
13140
|
+
}),
|
|
13141
|
+
/* @__PURE__ */ jsx19("div", { className: "pt-4 border-t border-slate-100 flex justify-end", children: /* @__PURE__ */ jsxs18(
|
|
13142
|
+
"button",
|
|
13143
|
+
{
|
|
13144
|
+
type: "submit",
|
|
13145
|
+
disabled: isSubmitting,
|
|
13146
|
+
className: "flex items-center gap-2 px-6 py.2.5 bg-brand hover:bg-brand-hover text-white font-bold rounded-lg shadow-sm transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
|
|
13147
|
+
children: [
|
|
13148
|
+
isSubmitting && /* @__PURE__ */ jsx19(Loader28, { className: "w-4 h-4 animate-spin" }),
|
|
13149
|
+
/* @__PURE__ */ jsx19("span", { children: isSubmitting ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DC\u05D9\u05D7\u05D4" })
|
|
13150
|
+
]
|
|
13151
|
+
}
|
|
13152
|
+
) })
|
|
13153
|
+
] })
|
|
13154
|
+
] });
|
|
13155
|
+
}
|
|
13156
|
+
|
|
12994
13157
|
// src/registry.ts
|
|
12995
13158
|
var UNIVERSE_COMPONENTS = {
|
|
12996
13159
|
TABLE: TableBlock,
|
|
12997
|
-
WHATSAPP: WhatsAppComponent
|
|
13160
|
+
WHATSAPP: WhatsAppComponent,
|
|
13161
|
+
FORM: FormBlock
|
|
12998
13162
|
};
|
|
12999
13163
|
export {
|
|
13000
13164
|
COLUMN_CAPABILITIES,
|