@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 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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@universe-platform/ui",
3
- "version": "0.1.0-beta.24",
3
+ "version": "0.1.0-beta.25",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",