@universe-platform/ui 0.1.0-beta.54 → 0.1.0-beta.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -15465,28 +15465,187 @@ function WhatsAppComponent(props) {
15465
15465
  var import_react28 = require("react");
15466
15466
  var import_lucide_react18 = require("lucide-react");
15467
15467
  var import_jsx_runtime29 = require("react/jsx-runtime");
15468
- function FormBlock({ settings: schema, executeAction, componentId, className = "", onSuccess }) {
15468
+
15469
+ // src/components/FormBlock/StyledFormBlock.tsx
15470
+ var import_react29 = require("react");
15471
+ var import_lucide_react19 = require("lucide-react");
15472
+
15473
+ // src/components/FormBlock/formDesign.ts
15474
+ var FORM_PRESETS = {
15475
+ classic: {
15476
+ label: "\u05E7\u05DC\u05D0\u05E1\u05D9",
15477
+ description: "\u05DB\u05E8\u05D8\u05D9\u05E1 \u05DC\u05D1\u05DF, \u05E9\u05D3\u05D4 \u05D1\u05DB\u05DC \u05E9\u05D5\u05E8\u05D4",
15478
+ radius: 12,
15479
+ padding: 24,
15480
+ gap: 16,
15481
+ labelSize: 14,
15482
+ titleSize: 20,
15483
+ border: "1px solid #e2e8f0",
15484
+ shadow: "0 1px 2px rgba(0,0,0,0.05)",
15485
+ headerBand: false,
15486
+ inputStyle: "box",
15487
+ defaultColumns: 1,
15488
+ defaultBackground: "#ffffff",
15489
+ defaultText: "#1e293b",
15490
+ invertText: false
15491
+ },
15492
+ compact: {
15493
+ label: "\u05E7\u05D5\u05DE\u05E4\u05E7\u05D8\u05D9",
15494
+ description: "\u05E9\u05E0\u05D9 \u05E9\u05D3\u05D5\u05EA \u05D1\u05E9\u05D5\u05E8\u05D4, \u05E8\u05D9\u05D5\u05D5\u05D7 \u05E7\u05D8\u05DF - \u05D8\u05D5\u05E4\u05E1 \u05E7\u05E6\u05E8 \u05D9\u05D5\u05EA\u05E8",
15495
+ radius: 10,
15496
+ padding: 16,
15497
+ gap: 10,
15498
+ labelSize: 12,
15499
+ titleSize: 18,
15500
+ border: "1px solid #e2e8f0",
15501
+ shadow: "0 1px 2px rgba(0,0,0,0.05)",
15502
+ headerBand: false,
15503
+ inputStyle: "box",
15504
+ defaultColumns: 2,
15505
+ defaultBackground: "#ffffff",
15506
+ defaultText: "#1e293b",
15507
+ invertText: false
15508
+ },
15509
+ card: {
15510
+ label: "\u05DB\u05E8\u05D8\u05D9\u05E1",
15511
+ description: "\u05E4\u05D9\u05E0\u05D5\u05EA \u05E2\u05D2\u05D5\u05DC\u05D5\u05EA, \u05E6\u05DC, \u05DB\u05D5\u05EA\u05E8\u05EA \u05E2\u05DC \u05E4\u05E1 \u05E6\u05D1\u05E2\u05D5\u05E0\u05D9",
15512
+ radius: 20,
15513
+ padding: 28,
15514
+ gap: 18,
15515
+ labelSize: 14,
15516
+ titleSize: 22,
15517
+ border: "none",
15518
+ shadow: "0 20px 40px -12px rgba(15,23,42,0.18)",
15519
+ headerBand: true,
15520
+ inputStyle: "box",
15521
+ defaultColumns: 2,
15522
+ defaultBackground: "#ffffff",
15523
+ defaultText: "#1e293b",
15524
+ invertText: false
15525
+ },
15526
+ minimal: {
15527
+ label: "\u05DE\u05D9\u05E0\u05D9\u05DE\u05DC\u05D9\u05E1\u05D8\u05D9",
15528
+ description: "\u05D1\u05DC\u05D9 \u05DE\u05E1\u05D2\u05E8\u05EA, \u05E7\u05D5 \u05EA\u05D7\u05EA\u05D5\u05DF \u05DC\u05E9\u05D3\u05D5\u05EA",
15529
+ radius: 0,
15530
+ padding: 0,
15531
+ gap: 20,
15532
+ labelSize: 13,
15533
+ titleSize: 22,
15534
+ border: "none",
15535
+ shadow: "none",
15536
+ headerBand: false,
15537
+ inputStyle: "underline",
15538
+ defaultColumns: 1,
15539
+ defaultBackground: "transparent",
15540
+ defaultText: "#1e293b",
15541
+ invertText: false
15542
+ },
15543
+ bold: {
15544
+ label: "\u05D1\u05D5\u05DC\u05D8",
15545
+ description: "\u05E8\u05E7\u05E2 \u05D1\u05E6\u05D1\u05E2 \u05D4\u05DE\u05D5\u05EA\u05D2 \u05D5\u05D8\u05E7\u05E1\u05D8 \u05DC\u05D1\u05DF",
15546
+ radius: 16,
15547
+ padding: 28,
15548
+ gap: 16,
15549
+ labelSize: 14,
15550
+ titleSize: 22,
15551
+ border: "none",
15552
+ shadow: "0 10px 30px -10px rgba(0,0,0,0.3)",
15553
+ headerBand: false,
15554
+ inputStyle: "box",
15555
+ defaultColumns: 1,
15556
+ defaultBackground: "",
15557
+ defaultText: "#ffffff",
15558
+ invertText: true
15559
+ }
15560
+ };
15561
+ var DEFAULT_PRIMARY = "#00b7a2";
15562
+ var ALWAYS_FULL_TYPES = /* @__PURE__ */ new Set(["GOOGLE_DRIVE_FILE", "SUB_TABLE", "SUBTABLE", "LINK"]);
15563
+ function isFormPresetId(v) {
15564
+ return typeof v === "string" && v in FORM_PRESETS;
15565
+ }
15566
+ function resolveFormDesign(design) {
15567
+ var _a, _b;
15568
+ const presetId = isFormPresetId(design == null ? void 0 : design.preset) ? design.preset : "classic";
15569
+ const tokens = FORM_PRESETS[presetId];
15570
+ const primary = (design == null ? void 0 : design.primaryColor) || DEFAULT_PRIMARY;
15571
+ const background = (design == null ? void 0 : design.backgroundColor) || (tokens.invertText ? primary : tokens.defaultBackground);
15572
+ const text2 = (design == null ? void 0 : design.textColor) || tokens.defaultText;
15573
+ return {
15574
+ tokens,
15575
+ presetId,
15576
+ primary,
15577
+ background,
15578
+ text: text2,
15579
+ buttonText: ((_a = design == null ? void 0 : design.buttonText) == null ? void 0 : _a.trim()) || "\u05E9\u05DC\u05D9\u05D7\u05D4",
15580
+ buttonAlign: (design == null ? void 0 : design.buttonAlign) || (presetId === "compact" ? "full" : "end"),
15581
+ subtitle: ((_b = design == null ? void 0 : design.subtitle) == null ? void 0 : _b.trim()) || "",
15582
+ columns: (design == null ? void 0 : design.columns) || tokens.defaultColumns
15583
+ };
15584
+ }
15585
+ function resolveFieldWidth(colName, colType, design, columnsDefault) {
15586
+ var _a, _b;
15587
+ const manual = (_b = (_a = design == null ? void 0 : design.fields) == null ? void 0 : _a[colName]) == null ? void 0 : _b.width;
15588
+ if (manual) return manual;
15589
+ if ((colType || "").toUpperCase() === "BOOLEAN") return "third";
15590
+ if (ALWAYS_FULL_TYPES.has((colType || "").toUpperCase())) return "full";
15591
+ return columnsDefault === 3 ? "third" : columnsDefault === 2 ? "half" : "full";
15592
+ }
15593
+ var WIDTH_TO_SPAN = { full: 6, half: 3, third: 2, sixth: 1 };
15594
+ function resolveFieldSpan(colName, colType, design, columnsDefault) {
15595
+ var _a, _b;
15596
+ const manual = (_b = (_a = design == null ? void 0 : design.fields) == null ? void 0 : _a[colName]) == null ? void 0 : _b.span;
15597
+ if (manual && manual >= 1 && manual <= 6) return manual;
15598
+ return WIDTH_TO_SPAN[resolveFieldWidth(colName, colType, design, columnsDefault)];
15599
+ }
15600
+ function applyFieldOrder(cols, design) {
15601
+ const order = design == null ? void 0 : design.fieldOrder;
15602
+ if (!order || order.length === 0) return cols;
15603
+ const idx = (n) => {
15604
+ const i = order.indexOf(n);
15605
+ return i === -1 ? Number.MAX_SAFE_INTEGER : i;
15606
+ };
15607
+ return cols.map((c, i) => ({ c, i })).sort((a, b) => idx(a.c.name) - idx(b.c.name) || a.i - b.i).map((x) => x.c);
15608
+ }
15609
+
15610
+ // src/components/FormBlock/StyledFormBlock.tsx
15611
+ var import_jsx_runtime30 = require("react/jsx-runtime");
15612
+ var SYSTEM_FIELDS = ["_id", "id", "createdAt", "updatedAt", "orgId", "tableId"];
15613
+ function StyledFormBlock({
15614
+ settings: schema,
15615
+ executeAction,
15616
+ componentId,
15617
+ className = "",
15618
+ onSuccess,
15619
+ previewMode = false,
15620
+ onReorder,
15621
+ onFieldResize
15622
+ }) {
15469
15623
  const { showError, addToast } = useToast();
15470
- const [formData, setFormData] = (0, import_react28.useState)({});
15471
- const [isSubmitting, setIsSubmitting] = (0, import_react28.useState)(false);
15472
- const [isSubmitted, setIsSubmitted] = (0, import_react28.useState)(false);
15473
- const [columns, setColumns] = (0, import_react28.useState)((schema == null ? void 0 : schema.columns) || []);
15474
- const [isLoadingSchema, setIsLoadingSchema] = (0, import_react28.useState)(false);
15624
+ const uid = "fdz" + (0, import_react29.useId)().replace(/[^a-zA-Z0-9]/g, "");
15625
+ const design = schema == null ? void 0 : schema.design;
15626
+ const d = resolveFormDesign(design);
15627
+ const t = d.tokens;
15628
+ const [formData, setFormData] = (0, import_react29.useState)({});
15629
+ const [isSubmitting, setIsSubmitting] = (0, import_react29.useState)(false);
15630
+ const [isSubmitted, setIsSubmitted] = (0, import_react29.useState)(false);
15631
+ const [columns, setColumns] = (0, import_react29.useState)((schema == null ? void 0 : schema.columns) || []);
15632
+ const [isLoadingSchema, setIsLoadingSchema] = (0, import_react29.useState)(false);
15633
+ const [dragName, setDragName] = (0, import_react29.useState)(null);
15634
+ const [drop, setDrop] = (0, import_react29.useState)(null);
15635
+ const [resizing, setResizing] = (0, import_react29.useState)(null);
15636
+ const resizeRef = (0, import_react29.useRef)(null);
15637
+ const gridRef = (0, import_react29.useRef)(null);
15475
15638
  const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
15476
- (0, import_react28.useEffect)(() => {
15639
+ (0, import_react29.useEffect)(() => {
15477
15640
  let isMounted = true;
15478
- if ((!(schema == null ? void 0 : schema.columns) || schema.columns.length === 0) && targetTableId && executeAction) {
15641
+ if ((!(schema == null ? void 0 : schema.columns) || schema.columns.length === 0) && targetTableId && executeAction && !previewMode) {
15479
15642
  setIsLoadingSchema(true);
15480
15643
  executeAction("FETCH_TABLE_DATA", { tableId: targetTableId, limit: 1 }).then((res) => {
15481
15644
  var _a;
15482
15645
  if (!isMounted) return;
15483
15646
  const fetchedCols = ((_a = res == null ? void 0 : res.schema) == null ? void 0 : _a.columns) || (res == null ? void 0 : res.columns);
15484
- if (fetchedCols && Array.isArray(fetchedCols)) {
15485
- setColumns(fetchedCols);
15486
- }
15487
- }).catch((err) => {
15488
- console.error("[FormBlock] Failed to fetch table schema:", err);
15489
- }).finally(() => {
15647
+ if (fetchedCols && Array.isArray(fetchedCols)) setColumns(fetchedCols);
15648
+ }).catch((err) => console.error("[StyledFormBlock] Failed to fetch table schema:", err)).finally(() => {
15490
15649
  if (isMounted) setIsLoadingSchema(false);
15491
15650
  });
15492
15651
  } else if (schema == null ? void 0 : schema.columns) {
@@ -15496,18 +15655,151 @@ function FormBlock({ settings: schema, executeAction, componentId, className = "
15496
15655
  isMounted = false;
15497
15656
  };
15498
15657
  }, [schema == null ? void 0 : schema.columns, targetTableId]);
15499
- const systemFields = ["_id", "id", "createdAt", "updatedAt", "orgId", "tableId"];
15500
- const formColumns = (columns || []).filter(
15501
- (col) => !systemFields.includes(col.name) && !col.isHidden
15502
- ).sort((a, b) => {
15658
+ const baseColumns = (columns || []).filter((col) => !SYSTEM_FIELDS.includes(col.name) && !col.isHidden).sort((a, b) => {
15503
15659
  var _a, _b;
15504
15660
  return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
15505
15661
  });
15662
+ const isDesignHidden = (col) => {
15663
+ var _a, _b;
15664
+ return !col.isRequired && !!((_b = (_a = design == null ? void 0 : design.fields) == null ? void 0 : _a[col.name]) == null ? void 0 : _b.hidden);
15665
+ };
15666
+ const orderedColumns = applyFieldOrder(baseColumns, design);
15667
+ const formColumns = orderedColumns.filter((c) => !isDesignHidden(c));
15668
+ const hiddenColumns = orderedColumns.filter((c) => isDesignHidden(c));
15506
15669
  const handleFieldChange = (colName, value) => {
15507
15670
  setFormData((prev) => __spreadProps(__spreadValues({}, prev), { [colName]: value }));
15508
15671
  };
15672
+ const canReorder = !!onReorder;
15673
+ const reorderFields = (fromName, toName, side) => {
15674
+ if (!onReorder || fromName === toName) return;
15675
+ const original = orderedColumns.map((c) => c.name);
15676
+ const names = [...original];
15677
+ const from = names.indexOf(fromName);
15678
+ if (from === -1 || !names.includes(toName)) return;
15679
+ names.splice(from, 1);
15680
+ const to = names.indexOf(toName);
15681
+ names.splice(side === "before" ? to : to + 1, 0, fromName);
15682
+ if (names.every((n, i) => n === original[i])) return;
15683
+ onReorder(names);
15684
+ };
15685
+ const findDropTarget = (x, y, dragged) => {
15686
+ const grid = gridRef.current;
15687
+ if (!grid) return null;
15688
+ const rtl = getComputedStyle(grid).direction === "rtl";
15689
+ let best = null;
15690
+ const nodes = Array.from(grid.querySelectorAll("[data-fdz-field]"));
15691
+ for (const node of nodes) {
15692
+ const name = node.getAttribute("data-fdz-field");
15693
+ if (!name) continue;
15694
+ const r = node.getBoundingClientRect();
15695
+ if (name === dragged) {
15696
+ if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom) return null;
15697
+ continue;
15698
+ }
15699
+ const dx = x < r.left ? r.left - x : x > r.right ? x - r.right : 0;
15700
+ const dy = y < r.top ? r.top - y : y > r.bottom ? y - r.bottom : 0;
15701
+ const dist = Math.hypot(dx, dy);
15702
+ if (!best || dist < best.dist) {
15703
+ const cx = r.left + r.width / 2;
15704
+ const before = rtl ? x >= cx : x < cx;
15705
+ best = { name, side: before ? "before" : "after", dist };
15706
+ }
15707
+ }
15708
+ return best ? { name: best.name, side: best.side } : null;
15709
+ };
15710
+ const startDrag = (e, colName) => {
15711
+ if (!onReorder || e.pointerType === "mouse" && e.button !== 0) return;
15712
+ const startX = e.clientX;
15713
+ const startY = e.clientY;
15714
+ let started = false;
15715
+ let current = null;
15716
+ const prevUserSelect = document.body.style.userSelect;
15717
+ const prevCursor = document.body.style.cursor;
15718
+ const onMove = (ev) => {
15719
+ if (!started) {
15720
+ if (Math.hypot(ev.clientX - startX, ev.clientY - startY) < 5) return;
15721
+ started = true;
15722
+ document.body.style.userSelect = "none";
15723
+ document.body.style.cursor = "grabbing";
15724
+ setDragName(colName);
15725
+ }
15726
+ const next = findDropTarget(ev.clientX, ev.clientY, colName);
15727
+ if ((next == null ? void 0 : next.name) !== (current == null ? void 0 : current.name) || (next == null ? void 0 : next.side) !== (current == null ? void 0 : current.side)) {
15728
+ current = next;
15729
+ setDrop(next);
15730
+ }
15731
+ };
15732
+ const finish = (commit) => {
15733
+ window.removeEventListener("pointermove", onMove);
15734
+ window.removeEventListener("pointerup", onUp);
15735
+ window.removeEventListener("pointercancel", onCancel);
15736
+ document.body.style.userSelect = prevUserSelect;
15737
+ document.body.style.cursor = prevCursor;
15738
+ if (started && commit && current) reorderFields(colName, current.name, current.side);
15739
+ setDragName(null);
15740
+ setDrop(null);
15741
+ };
15742
+ const onUp = () => finish(true);
15743
+ const onCancel = () => {
15744
+ if (started) console.warn('[StyledFormBlock] \u05D4\u05D2\u05E8\u05D9\u05E8\u05D4 \u05D1\u05D5\u05D8\u05DC\u05D4 \u05E2"\u05D9 \u05D4\u05D3\u05E4\u05D3\u05E4\u05DF/\u05E8\u05DB\u05D9\u05D1 \u05D0\u05D1 (pointercancel)');
15745
+ finish(false);
15746
+ };
15747
+ window.addEventListener("pointermove", onMove);
15748
+ window.addEventListener("pointerup", onUp);
15749
+ window.addEventListener("pointercancel", onCancel);
15750
+ };
15751
+ const startResize = (e, colName, startSpan) => {
15752
+ var _a, _b, _c, _d;
15753
+ if (!onFieldResize) return;
15754
+ const grid = gridRef.current;
15755
+ const item = e.currentTarget.closest("[data-fdz-field]");
15756
+ if (!grid || !item) return;
15757
+ e.preventDefault();
15758
+ e.stopPropagation();
15759
+ const box = item.querySelector("[data-fdz-box]");
15760
+ const colW = (grid.clientWidth - t.gap * 5) / 6;
15761
+ const rtl = grid.closest('[dir="rtl"]') !== null || getComputedStyle(grid).direction === "rtl";
15762
+ const state = {
15763
+ name: colName,
15764
+ startX: e.clientX,
15765
+ startY: e.clientY,
15766
+ startSpan,
15767
+ step: colW + t.gap,
15768
+ rtl,
15769
+ startHeight: box ? box.offsetHeight : 40,
15770
+ hadHeight: !!((_b = (_a = design == null ? void 0 : design.fields) == null ? void 0 : _a[colName]) == null ? void 0 : _b.height),
15771
+ span: startSpan,
15772
+ height: (_d = (_c = design == null ? void 0 : design.fields) == null ? void 0 : _c[colName]) == null ? void 0 : _d.height
15773
+ };
15774
+ resizeRef.current = state;
15775
+ setResizing({ name: colName, span: state.span, height: state.height });
15776
+ const onMove = (ev) => {
15777
+ const dxRaw = ev.clientX - state.startX;
15778
+ const dx = state.rtl ? -dxRaw : dxRaw;
15779
+ const span = Math.max(1, Math.min(6, Math.round(state.startSpan + dx / state.step)));
15780
+ const dy = ev.clientY - state.startY;
15781
+ const height = Math.abs(dy) < 8 && !state.hadHeight ? void 0 : Math.max(40, Math.round(state.startHeight + dy));
15782
+ if (span !== state.span || height !== state.height) {
15783
+ state.span = span;
15784
+ state.height = height;
15785
+ setResizing({ name: state.name, span, height });
15786
+ }
15787
+ };
15788
+ const onUp = () => {
15789
+ window.removeEventListener("pointermove", onMove);
15790
+ window.removeEventListener("pointerup", onUp);
15791
+ window.removeEventListener("pointercancel", onUp);
15792
+ resizeRef.current = null;
15793
+ onFieldResize(state.name, { span: state.span, height: state.height });
15794
+ setResizing(null);
15795
+ };
15796
+ window.addEventListener("pointermove", onMove);
15797
+ window.addEventListener("pointerup", onUp);
15798
+ window.addEventListener("pointercancel", onUp);
15799
+ };
15509
15800
  const handleSubmit = async (e) => {
15510
15801
  e.preventDefault();
15802
+ if (previewMode) return;
15511
15803
  if (!executeAction) {
15512
15804
  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");
15513
15805
  return;
@@ -15525,108 +15817,294 @@ function FormBlock({ settings: schema, executeAction, componentId, className = "
15525
15817
  }
15526
15818
  setIsSubmitting(true);
15527
15819
  try {
15528
- const formattedPayload = {};
15820
+ const payload = {};
15529
15821
  formColumns.forEach((col) => {
15530
15822
  var _a;
15531
15823
  let val = formData[col.name];
15532
15824
  if (val !== void 0 && val !== null) {
15533
- if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
15534
- val = val === "" ? 0 : Number(val);
15535
- }
15536
- formattedPayload[col.name] = val;
15825
+ if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") val = val === "" ? 0 : Number(val);
15826
+ payload[col.name] = val;
15537
15827
  } else if (col.defaultValue !== void 0) {
15538
- formattedPayload[col.name] = col.defaultValue;
15828
+ payload[col.name] = col.defaultValue;
15539
15829
  }
15540
15830
  });
15831
+ hiddenColumns.forEach((col) => {
15832
+ if (col.defaultValue !== void 0) payload[col.name] = col.defaultValue;
15833
+ });
15541
15834
  await executeAction("CREATE_RECORD", {
15542
15835
  tableId: targetTableId,
15543
15836
  tableMetaId: targetTableId,
15544
- records: [formattedPayload]
15837
+ records: [payload]
15545
15838
  });
15546
15839
  addToast({ message: "\u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD \u05E0\u05E9\u05DE\u05E8\u05D5 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4", type: "success" });
15547
15840
  setFormData({});
15548
15841
  setIsSubmitted(true);
15549
15842
  if (onSuccess) onSuccess();
15550
15843
  } catch (err) {
15551
- console.error("[FormBlock] Submit error:", err);
15844
+ console.error("[StyledFormBlock] Submit error:", err);
15552
15845
  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");
15553
15846
  } finally {
15554
15847
  setIsSubmitting(false);
15555
15848
  }
15556
15849
  };
15850
+ const muted = t.invertText ? "rgba(255,255,255,0.85)" : "#64748b";
15851
+ const cardStyle = {
15852
+ background: d.background,
15853
+ color: d.text,
15854
+ borderRadius: t.radius,
15855
+ border: t.border,
15856
+ boxShadow: t.shadow,
15857
+ padding: t.headerBand ? 0 : t.padding,
15858
+ overflow: t.headerBand ? "hidden" : void 0
15859
+ };
15860
+ const inputBoxStyle = t.inputStyle === "underline" ? { borderBottom: "1px solid #cbd5e1", borderRadius: 0, background: "transparent", minHeight: 40, position: "relative" } : {
15861
+ border: "1px solid #e2e8f0",
15862
+ borderRadius: Math.min(t.radius, 10) || 6,
15863
+ background: "#ffffff",
15864
+ color: "#0f172a",
15865
+ minHeight: 40,
15866
+ position: "relative"
15867
+ };
15868
+ const booleanBoxStyle = __spreadProps(__spreadValues({}, inputBoxStyle), {
15869
+ minHeight: 0,
15870
+ width: "fit-content",
15871
+ alignSelf: "flex-start"
15872
+ });
15873
+ const css = `
15874
+ .${uid}{container-type:inline-size}
15875
+ .${uid} .fdz-grid{display:flex;flex-wrap:wrap;align-items:flex-start;gap:${t.gap}px}
15876
+ .${uid} .fdz-f{--n:6;flex:0 0 auto;box-sizing:border-box;min-width:0;display:flex;flex-direction:column;gap:6px;width:calc((100% - ${t.gap * 5}px) / 6 * var(--n) + ${t.gap}px * (var(--n) - 1) - 0.5px)}
15877
+ .${uid} .fdz-s1{--n:2}
15878
+ .${uid} .fdz-b{width:fit-content;max-width:140px;margin-inline-end:-${Math.max(0, t.gap - 8)}px}
15879
+ @container (min-width:480px){
15880
+ .${uid} .fdz-f{--n:var(--span)}
15881
+ }
15882
+ `;
15557
15883
  if (isLoadingSchema) {
15558
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "p-8 flex items-center justify-center gap-2 text-slate-500", children: [
15559
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react18.Loader2, { className: "w-5 h-5 animate-spin text-brand" }),
15560
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-sm", children: "\u05D8\u05D5\u05E2\u05DF \u05E9\u05D3\u05D5\u05EA \u05D8\u05D5\u05E4\u05E1..." })
15884
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "p-8 flex items-center justify-center gap-2 text-slate-500", dir: "rtl", children: [
15885
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react19.Loader2, { className: "w-5 h-5 animate-spin", style: { color: d.primary } }),
15886
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-sm", children: "\u05D8\u05D5\u05E2\u05DF \u05E9\u05D3\u05D5\u05EA \u05D8\u05D5\u05E4\u05E1..." })
15561
15887
  ] });
15562
15888
  }
15563
15889
  if (!formColumns || formColumns.length === 0) {
15564
- return /* @__PURE__ */ (0, import_jsx_runtime29.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." });
15890
+ return /* @__PURE__ */ (0, import_jsx_runtime30.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." });
15565
15891
  }
15892
+ const headerBlock = (schema == null ? void 0 : schema.title) || d.subtitle ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
15893
+ "div",
15894
+ {
15895
+ style: t.headerBand ? { background: d.primary, color: "#ffffff", padding: `${t.padding * 0.8}px ${t.padding}px` } : { marginBottom: t.gap + 4 },
15896
+ children: [
15897
+ (schema == null ? void 0 : schema.title) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h2", { style: { fontSize: t.titleSize, fontWeight: 800, margin: 0 }, children: schema.title }),
15898
+ d.subtitle && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { style: { fontSize: 14, margin: "6px 0 0", color: t.headerBand ? "rgba(255,255,255,0.9)" : muted }, children: d.subtitle })
15899
+ ]
15900
+ }
15901
+ ) : null;
15566
15902
  if (isSubmitted) {
15567
15903
  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.";
15568
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { id: componentId, className: `bg-white p-8 rounded-xl shadow-xs border border-slate-200 text-center dir-rtl ${className}`, children: [
15569
- /* @__PURE__ */ (0, import_jsx_runtime29.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_runtime29.jsx)(import_lucide_react18.CheckCircle2, { className: "w-8 h-8" }) }),
15570
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h3", { className: "text-2xl font-bold text-slate-800 mb-2", children: "\u05D4\u05D5\u05D3\u05E2\u05D4 \u05E0\u05E9\u05DC\u05D7\u05D4" }),
15571
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-slate-600 text-base max-w-md mx-auto whitespace-pre-wrap", children: customMessage }),
15572
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
15904
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { id: componentId, dir: "rtl", className, style: __spreadProps(__spreadValues({}, cardStyle), { padding: t.padding || 24, textAlign: "center" }), children: [
15905
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
15906
+ "div",
15907
+ {
15908
+ style: {
15909
+ width: 64,
15910
+ height: 64,
15911
+ borderRadius: "50%",
15912
+ margin: "0 auto 16px",
15913
+ display: "flex",
15914
+ alignItems: "center",
15915
+ justifyContent: "center",
15916
+ background: t.invertText ? "rgba(255,255,255,0.2)" : "#ecfdf5",
15917
+ color: t.invertText ? "#ffffff" : "#059669"
15918
+ },
15919
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react19.CheckCircle2, { className: "w-8 h-8" })
15920
+ }
15921
+ ),
15922
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h3", { style: { fontSize: 24, fontWeight: 800, margin: "0 0 8px" }, children: "\u05D4\u05D5\u05D3\u05E2\u05D4 \u05E0\u05E9\u05DC\u05D7\u05D4" }),
15923
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { style: { fontSize: 16, color: muted, maxWidth: 420, margin: "0 auto", whiteSpace: "pre-wrap" }, children: customMessage }),
15924
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
15573
15925
  "button",
15574
15926
  {
15575
15927
  type: "button",
15576
15928
  onClick: () => setIsSubmitted(false),
15577
- className: "mt-6 px-4 py-2 text-xs font-semibold text-brand hover:underline cursor-pointer",
15929
+ style: { marginTop: 24, fontSize: 12, fontWeight: 600, color: t.invertText ? "#ffffff" : d.primary, background: "none", border: "none", cursor: "pointer", textDecoration: "underline" },
15578
15930
  children: "\u05E9\u05DC\u05D9\u05D7\u05EA \u05DE\u05E2\u05E0\u05D4 \u05E0\u05D5\u05E1\u05E3"
15579
15931
  }
15580
15932
  )
15581
15933
  ] });
15582
15934
  }
15583
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { id: componentId, className: `bg-white p-6 rounded-xl shadow-xs border border-slate-200 dir-rtl ${className}`, children: [
15584
- (schema == null ? void 0 : schema.title) && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("h2", { className: "text-xl font-bold text-slate-800 mb-6", children: schema.title }),
15585
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
15586
- formColumns.map((col) => {
15587
- var _a, _b;
15588
- const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
15589
- const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
15590
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
15591
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "text-sm font-semibold text-slate-700", children: [
15592
- col.name,
15593
- " ",
15594
- col.isRequired && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-rose-500", children: "*" })
15595
- ] }),
15596
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "border border-slate-200 rounded-lg min-h-[40px] relative", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
15597
- InputComponent,
15935
+ const justify = d.buttonAlign === "center" ? "center" : d.buttonAlign === "end" ? "flex-end" : d.buttonAlign === "full" ? "stretch" : "flex-start";
15936
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { id: componentId, dir: "rtl", className: `${uid} ${className}`, style: cardStyle, children: [
15937
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("style", { children: css }),
15938
+ headerBlock,
15939
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { style: t.headerBand ? { padding: t.padding } : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("form", { onSubmit: handleSubmit, children: [
15940
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "fdz-grid", ref: gridRef, children: (() => {
15941
+ const spanOf = (col) => {
15942
+ var _a;
15943
+ if (resizing && resizing.name === col.name) return resizing.span;
15944
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
15945
+ return resolveFieldSpan(col.name, colType, design, d.columns);
15946
+ };
15947
+ const renderField = (col) => {
15948
+ var _a, _b, _c, _d, _e;
15949
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
15950
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
15951
+ const span = spanOf(col);
15952
+ const isBoolean = colType === "BOOLEAN";
15953
+ const fieldHeight = resizing && resizing.name === col.name ? resizing.height : (_c = (_b = design == null ? void 0 : design.fields) == null ? void 0 : _b[col.name]) == null ? void 0 : _c.height;
15954
+ const useTextarea = !!fieldHeight && fieldHeight > 56 && InputComponent === FORM_INPUTS.DEFAULT;
15955
+ const boxStyle = __spreadValues(__spreadValues(__spreadValues({}, isBoolean ? booleanBoxStyle : inputBoxStyle), fieldHeight && !isBoolean ? __spreadValues({ minHeight: fieldHeight }, useTextarea ? { height: fieldHeight } : {}) : {}), canReorder ? { pointerEvents: "none" } : {});
15956
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
15957
+ "div",
15598
15958
  {
15599
- column: col,
15600
- rowId: "new_form_record",
15601
- value: (_b = formData[col.name]) != null ? _b : "",
15602
- onChange: (val) => handleFieldChange(col.name, val),
15603
- context: {
15604
- executeAction,
15605
- tableId: targetTableId
15606
- }
15607
- }
15608
- ) })
15609
- ] }, col.name);
15610
- }),
15611
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "pt-4 border-t border-slate-100 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
15612
- "button",
15959
+ "data-fdz-field": col.name,
15960
+ className: `fdz-f fdz-s${span}${isBoolean ? " fdz-b" : ""}`,
15961
+ draggable: false,
15962
+ onDragStart: canReorder ? (e) => e.preventDefault() : void 0,
15963
+ onMouseDown: canReorder ? (e) => e.stopPropagation() : void 0,
15964
+ onTouchStart: canReorder ? (e) => e.stopPropagation() : void 0,
15965
+ onPointerDown: canReorder ? (e) => {
15966
+ e.stopPropagation();
15967
+ startDrag(e, col.name);
15968
+ } : void 0,
15969
+ style: __spreadValues({ "--span": span }, canReorder ? {
15970
+ position: "relative",
15971
+ cursor: "grab",
15972
+ touchAction: "none",
15973
+ userSelect: "none",
15974
+ opacity: dragName === col.name ? 0.4 : 1,
15975
+ outline: resizing && resizing.name === col.name ? `2px solid ${t.invertText ? "#ffffff" : d.primary}` : void 0,
15976
+ outlineOffset: 4,
15977
+ borderRadius: 6
15978
+ } : {}),
15979
+ children: [
15980
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { style: { fontSize: t.labelSize, fontWeight: 600, color: d.text }, children: [
15981
+ col.name,
15982
+ " ",
15983
+ col.isRequired && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { style: { color: t.invertText ? "#fecdd3" : "#f43f5e" }, children: "*" })
15984
+ ] }),
15985
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { "data-fdz-box": true, style: boxStyle, children: useTextarea ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
15986
+ "textarea",
15987
+ {
15988
+ value: (_d = formData[col.name]) != null ? _d : "",
15989
+ onChange: (e) => handleFieldChange(col.name, e.target.value),
15990
+ readOnly: previewMode,
15991
+ style: {
15992
+ width: "100%",
15993
+ height: "100%",
15994
+ minHeight: fieldHeight - 2,
15995
+ padding: "8px 12px",
15996
+ border: "none",
15997
+ outline: "none",
15998
+ background: "transparent",
15999
+ resize: "none",
16000
+ font: "inherit",
16001
+ color: "inherit",
16002
+ boxSizing: "border-box"
16003
+ }
16004
+ }
16005
+ ) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
16006
+ InputComponent,
16007
+ {
16008
+ column: col,
16009
+ rowId: "new_form_record",
16010
+ value: (_e = formData[col.name]) != null ? _e : "",
16011
+ onChange: (val) => handleFieldChange(col.name, val),
16012
+ readOnly: previewMode,
16013
+ context: { executeAction: previewMode ? void 0 : executeAction, tableId: targetTableId }
16014
+ }
16015
+ ) }),
16016
+ canReorder && dragName && drop && drop.name === col.name && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
16017
+ "div",
16018
+ {
16019
+ style: __spreadValues({
16020
+ position: "absolute",
16021
+ top: 0,
16022
+ bottom: 0,
16023
+ width: 4,
16024
+ borderRadius: 2,
16025
+ background: t.invertText ? "#ffffff" : d.primary,
16026
+ pointerEvents: "none",
16027
+ zIndex: 3
16028
+ }, drop.side === "before" ? { insetInlineStart: -(t.gap / 2) - 2 } : { insetInlineEnd: -(t.gap / 2) - 2 })
16029
+ }
16030
+ ),
16031
+ onFieldResize && !isBoolean && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
16032
+ "div",
16033
+ {
16034
+ onMouseDown: (e) => e.stopPropagation(),
16035
+ onTouchStart: (e) => e.stopPropagation(),
16036
+ onPointerDown: (e) => startResize(e, col.name, span),
16037
+ onDoubleClick: () => onFieldResize(col.name, { reset: true }),
16038
+ title: "\u05D2\u05E8\u05D5\u05E8 \u05DC\u05E9\u05D9\u05E0\u05D5\u05D9 \u05D2\u05D5\u05D3\u05DC (\u05DC\u05D7\u05D9\u05E6\u05D4 \u05DB\u05E4\u05D5\u05DC\u05D4 \u05DC\u05D0\u05D9\u05E4\u05D5\u05E1)",
16039
+ style: {
16040
+ position: "absolute",
16041
+ left: -6,
16042
+ bottom: -6,
16043
+ width: 14,
16044
+ height: 14,
16045
+ borderRadius: 4,
16046
+ background: "#ffffff",
16047
+ border: `2px solid ${d.primary}`,
16048
+ cursor: "nesw-resize",
16049
+ touchAction: "none",
16050
+ zIndex: 2
16051
+ }
16052
+ }
16053
+ )
16054
+ ]
16055
+ },
16056
+ col.name
16057
+ );
16058
+ };
16059
+ return formColumns.map((col) => renderField(col));
16060
+ })() }),
16061
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
16062
+ "div",
15613
16063
  {
15614
- type: "submit",
15615
- disabled: isSubmitting,
15616
- 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",
15617
- children: [
15618
- isSubmitting && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react18.Loader2, { className: "w-4 h-4 animate-spin" }),
15619
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: isSubmitting ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DC\u05D9\u05D7\u05D4" })
15620
- ]
16064
+ style: {
16065
+ marginTop: t.gap + 8,
16066
+ paddingTop: t.inputStyle === "underline" || t.invertText ? 0 : t.gap,
16067
+ borderTop: t.inputStyle === "underline" || t.invertText ? "none" : "1px solid rgba(148,163,184,0.25)",
16068
+ display: "flex",
16069
+ justifyContent: justify
16070
+ },
16071
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
16072
+ "button",
16073
+ {
16074
+ type: "submit",
16075
+ disabled: isSubmitting || previewMode,
16076
+ style: {
16077
+ display: "flex",
16078
+ alignItems: "center",
16079
+ justifyContent: "center",
16080
+ gap: 8,
16081
+ padding: "10px 28px",
16082
+ width: d.buttonAlign === "full" ? "100%" : void 0,
16083
+ background: t.invertText ? "#ffffff" : d.primary,
16084
+ color: t.invertText ? d.primary : "#ffffff",
16085
+ fontWeight: 700,
16086
+ fontSize: 15,
16087
+ border: "none",
16088
+ borderRadius: Math.min(t.radius, 10) || 6,
16089
+ boxShadow: "0 1px 2px rgba(0,0,0,0.1)",
16090
+ cursor: isSubmitting || previewMode ? "default" : "pointer",
16091
+ opacity: isSubmitting ? 0.5 : 1
16092
+ },
16093
+ children: [
16094
+ isSubmitting && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react19.Loader2, { className: "w-4 h-4 animate-spin" }),
16095
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: isSubmitting ? "\u05E9\u05D5\u05DE\u05E8..." : d.buttonText })
16096
+ ]
16097
+ }
16098
+ )
15621
16099
  }
15622
- ) })
15623
- ] })
16100
+ )
16101
+ ] }) })
15624
16102
  ] });
15625
16103
  }
15626
16104
 
15627
16105
  // src/themes/ThemeScope.tsx
15628
- var React22 = __toESM(require("react"));
15629
- var import_jsx_runtime30 = require("react/jsx-runtime");
16106
+ var React23 = __toESM(require("react"));
16107
+ var import_jsx_runtime31 = require("react/jsx-runtime");
15630
16108
  var UNIVERSE_THEME_IDS = ["classic", "clean", "ocean", "warm"];
15631
16109
  function resolveUniverseTheme(value) {
15632
16110
  return typeof value === "string" && UNIVERSE_THEME_IDS.includes(value) ? value : "classic";
@@ -15636,7 +16114,7 @@ function withThemeScope(Component) {
15636
16114
  var _a, _b, _c;
15637
16115
  const p = props;
15638
16116
  const theme = resolveUniverseTheme((_c = (_a = p.settings) == null ? void 0 : _a.theme) != null ? _c : (_b = p.config) == null ? void 0 : _b.theme);
15639
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { "data-theme": theme, style: { display: "contents" }, children: React22.createElement(Component, props) });
16117
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { "data-theme": theme, style: { display: "contents" }, children: React23.createElement(Component, props) });
15640
16118
  }
15641
16119
  ThemeScoped.displayName = `ThemeScoped(${Component.displayName || Component.name || "Component"})`;
15642
16120
  return ThemeScoped;
@@ -15646,7 +16124,7 @@ function withThemeScope(Component) {
15646
16124
  var UNIVERSE_COMPONENTS = {
15647
16125
  TABLE: withThemeScope(TableBlock),
15648
16126
  WHATSAPP: withThemeScope(WhatsAppComponent),
15649
- FORM: withThemeScope(FormBlock),
16127
+ FORM: withThemeScope(StyledFormBlock),
15650
16128
  PLACEMENT: withThemeScope(PlacementBlock)
15651
16129
  };
15652
16130
  // Annotate the CommonJS export names for ESM import in node: