@universe-platform/ui 0.1.0-beta.53 → 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.mjs CHANGED
@@ -5355,6 +5355,7 @@ function SubTableViewer({ rowId, column, value, onChange, context, readOnly }) {
5355
5355
  {
5356
5356
  type: "button",
5357
5357
  onClick: () => {
5358
+ var _a2, _b2, _c2;
5358
5359
  setIsCreating(true);
5359
5360
  const initialData = {};
5360
5361
  targetColumns.forEach((c) => {
@@ -5366,6 +5367,18 @@ function SubTableViewer({ rowId, column, value, onChange, context, readOnly }) {
5366
5367
  else initialData[c.name] = "";
5367
5368
  }
5368
5369
  });
5370
+ const linkCfg = (_a2 = column.config) == null ? void 0 : _a2.linkConfig;
5371
+ const parentRowData = (context == null ? void 0 : context.rowData) || ((_b2 = context == null ? void 0 : context.parentRecord) == null ? void 0 : _b2.data);
5372
+ if ((linkCfg == null ? void 0 : linkCfg.parentMatchField) && (linkCfg == null ? void 0 : linkCfg.subTableMatchField) && parentRowData) {
5373
+ const parentValue = parentRowData[linkCfg.parentMatchField];
5374
+ const hasParentValue = parentValue !== void 0 && parentValue !== null && String(parentValue).trim() !== "";
5375
+ const matchCol = targetColumns.find((c) => c.name === linkCfg.subTableMatchField);
5376
+ if (hasParentValue && matchCol) {
5377
+ const matchType = (_c2 = matchCol.type) == null ? void 0 : _c2.toUpperCase();
5378
+ const asNumber = Number(parentValue);
5379
+ initialData[matchCol.name] = matchType === "NUMBER" || matchType === "CURRENCY" ? isNaN(asNumber) ? 0 : asNumber : String(parentValue);
5380
+ }
5381
+ }
5369
5382
  setNewRecordData(initialData);
5370
5383
  },
5371
5384
  className: "h-7 px-2.5 text-[11px] font-semibold bg-emerald-50 hover:bg-emerald-100 text-emerald-700 border border-emerald-200 rounded-md transition-colors cursor-pointer flex items-center gap-1",
@@ -15357,28 +15370,187 @@ function WhatsAppComponent(props) {
15357
15370
  import { useState as useState21, useEffect as useEffect19 } from "react";
15358
15371
  import { Loader2 as Loader29, CheckCircle2 as CheckCircle25 } from "lucide-react";
15359
15372
  import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
15360
- function FormBlock({ settings: schema, executeAction, componentId, className = "", onSuccess }) {
15373
+
15374
+ // src/components/FormBlock/StyledFormBlock.tsx
15375
+ import { useState as useState22, useEffect as useEffect20, useId, useRef as useRef20 } from "react";
15376
+ import { Loader2 as Loader210, CheckCircle2 as CheckCircle26 } from "lucide-react";
15377
+
15378
+ // src/components/FormBlock/formDesign.ts
15379
+ var FORM_PRESETS = {
15380
+ classic: {
15381
+ label: "\u05E7\u05DC\u05D0\u05E1\u05D9",
15382
+ description: "\u05DB\u05E8\u05D8\u05D9\u05E1 \u05DC\u05D1\u05DF, \u05E9\u05D3\u05D4 \u05D1\u05DB\u05DC \u05E9\u05D5\u05E8\u05D4",
15383
+ radius: 12,
15384
+ padding: 24,
15385
+ gap: 16,
15386
+ labelSize: 14,
15387
+ titleSize: 20,
15388
+ border: "1px solid #e2e8f0",
15389
+ shadow: "0 1px 2px rgba(0,0,0,0.05)",
15390
+ headerBand: false,
15391
+ inputStyle: "box",
15392
+ defaultColumns: 1,
15393
+ defaultBackground: "#ffffff",
15394
+ defaultText: "#1e293b",
15395
+ invertText: false
15396
+ },
15397
+ compact: {
15398
+ label: "\u05E7\u05D5\u05DE\u05E4\u05E7\u05D8\u05D9",
15399
+ 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",
15400
+ radius: 10,
15401
+ padding: 16,
15402
+ gap: 10,
15403
+ labelSize: 12,
15404
+ titleSize: 18,
15405
+ border: "1px solid #e2e8f0",
15406
+ shadow: "0 1px 2px rgba(0,0,0,0.05)",
15407
+ headerBand: false,
15408
+ inputStyle: "box",
15409
+ defaultColumns: 2,
15410
+ defaultBackground: "#ffffff",
15411
+ defaultText: "#1e293b",
15412
+ invertText: false
15413
+ },
15414
+ card: {
15415
+ label: "\u05DB\u05E8\u05D8\u05D9\u05E1",
15416
+ 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",
15417
+ radius: 20,
15418
+ padding: 28,
15419
+ gap: 18,
15420
+ labelSize: 14,
15421
+ titleSize: 22,
15422
+ border: "none",
15423
+ shadow: "0 20px 40px -12px rgba(15,23,42,0.18)",
15424
+ headerBand: true,
15425
+ inputStyle: "box",
15426
+ defaultColumns: 2,
15427
+ defaultBackground: "#ffffff",
15428
+ defaultText: "#1e293b",
15429
+ invertText: false
15430
+ },
15431
+ minimal: {
15432
+ label: "\u05DE\u05D9\u05E0\u05D9\u05DE\u05DC\u05D9\u05E1\u05D8\u05D9",
15433
+ description: "\u05D1\u05DC\u05D9 \u05DE\u05E1\u05D2\u05E8\u05EA, \u05E7\u05D5 \u05EA\u05D7\u05EA\u05D5\u05DF \u05DC\u05E9\u05D3\u05D5\u05EA",
15434
+ radius: 0,
15435
+ padding: 0,
15436
+ gap: 20,
15437
+ labelSize: 13,
15438
+ titleSize: 22,
15439
+ border: "none",
15440
+ shadow: "none",
15441
+ headerBand: false,
15442
+ inputStyle: "underline",
15443
+ defaultColumns: 1,
15444
+ defaultBackground: "transparent",
15445
+ defaultText: "#1e293b",
15446
+ invertText: false
15447
+ },
15448
+ bold: {
15449
+ label: "\u05D1\u05D5\u05DC\u05D8",
15450
+ description: "\u05E8\u05E7\u05E2 \u05D1\u05E6\u05D1\u05E2 \u05D4\u05DE\u05D5\u05EA\u05D2 \u05D5\u05D8\u05E7\u05E1\u05D8 \u05DC\u05D1\u05DF",
15451
+ radius: 16,
15452
+ padding: 28,
15453
+ gap: 16,
15454
+ labelSize: 14,
15455
+ titleSize: 22,
15456
+ border: "none",
15457
+ shadow: "0 10px 30px -10px rgba(0,0,0,0.3)",
15458
+ headerBand: false,
15459
+ inputStyle: "box",
15460
+ defaultColumns: 1,
15461
+ defaultBackground: "",
15462
+ defaultText: "#ffffff",
15463
+ invertText: true
15464
+ }
15465
+ };
15466
+ var DEFAULT_PRIMARY = "#00b7a2";
15467
+ var ALWAYS_FULL_TYPES = /* @__PURE__ */ new Set(["GOOGLE_DRIVE_FILE", "SUB_TABLE", "SUBTABLE", "LINK"]);
15468
+ function isFormPresetId(v) {
15469
+ return typeof v === "string" && v in FORM_PRESETS;
15470
+ }
15471
+ function resolveFormDesign(design) {
15472
+ var _a, _b;
15473
+ const presetId = isFormPresetId(design == null ? void 0 : design.preset) ? design.preset : "classic";
15474
+ const tokens = FORM_PRESETS[presetId];
15475
+ const primary = (design == null ? void 0 : design.primaryColor) || DEFAULT_PRIMARY;
15476
+ const background = (design == null ? void 0 : design.backgroundColor) || (tokens.invertText ? primary : tokens.defaultBackground);
15477
+ const text2 = (design == null ? void 0 : design.textColor) || tokens.defaultText;
15478
+ return {
15479
+ tokens,
15480
+ presetId,
15481
+ primary,
15482
+ background,
15483
+ text: text2,
15484
+ buttonText: ((_a = design == null ? void 0 : design.buttonText) == null ? void 0 : _a.trim()) || "\u05E9\u05DC\u05D9\u05D7\u05D4",
15485
+ buttonAlign: (design == null ? void 0 : design.buttonAlign) || (presetId === "compact" ? "full" : "end"),
15486
+ subtitle: ((_b = design == null ? void 0 : design.subtitle) == null ? void 0 : _b.trim()) || "",
15487
+ columns: (design == null ? void 0 : design.columns) || tokens.defaultColumns
15488
+ };
15489
+ }
15490
+ function resolveFieldWidth(colName, colType, design, columnsDefault) {
15491
+ var _a, _b;
15492
+ const manual = (_b = (_a = design == null ? void 0 : design.fields) == null ? void 0 : _a[colName]) == null ? void 0 : _b.width;
15493
+ if (manual) return manual;
15494
+ if ((colType || "").toUpperCase() === "BOOLEAN") return "third";
15495
+ if (ALWAYS_FULL_TYPES.has((colType || "").toUpperCase())) return "full";
15496
+ return columnsDefault === 3 ? "third" : columnsDefault === 2 ? "half" : "full";
15497
+ }
15498
+ var WIDTH_TO_SPAN = { full: 6, half: 3, third: 2, sixth: 1 };
15499
+ function resolveFieldSpan(colName, colType, design, columnsDefault) {
15500
+ var _a, _b;
15501
+ const manual = (_b = (_a = design == null ? void 0 : design.fields) == null ? void 0 : _a[colName]) == null ? void 0 : _b.span;
15502
+ if (manual && manual >= 1 && manual <= 6) return manual;
15503
+ return WIDTH_TO_SPAN[resolveFieldWidth(colName, colType, design, columnsDefault)];
15504
+ }
15505
+ function applyFieldOrder(cols, design) {
15506
+ const order = design == null ? void 0 : design.fieldOrder;
15507
+ if (!order || order.length === 0) return cols;
15508
+ const idx = (n) => {
15509
+ const i = order.indexOf(n);
15510
+ return i === -1 ? Number.MAX_SAFE_INTEGER : i;
15511
+ };
15512
+ 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);
15513
+ }
15514
+
15515
+ // src/components/FormBlock/StyledFormBlock.tsx
15516
+ import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
15517
+ var SYSTEM_FIELDS = ["_id", "id", "createdAt", "updatedAt", "orgId", "tableId"];
15518
+ function StyledFormBlock({
15519
+ settings: schema,
15520
+ executeAction,
15521
+ componentId,
15522
+ className = "",
15523
+ onSuccess,
15524
+ previewMode = false,
15525
+ onReorder,
15526
+ onFieldResize
15527
+ }) {
15361
15528
  const { showError, addToast } = useToast();
15362
- const [formData, setFormData] = useState21({});
15363
- const [isSubmitting, setIsSubmitting] = useState21(false);
15364
- const [isSubmitted, setIsSubmitted] = useState21(false);
15365
- const [columns, setColumns] = useState21((schema == null ? void 0 : schema.columns) || []);
15366
- const [isLoadingSchema, setIsLoadingSchema] = useState21(false);
15529
+ const uid = "fdz" + useId().replace(/[^a-zA-Z0-9]/g, "");
15530
+ const design = schema == null ? void 0 : schema.design;
15531
+ const d = resolveFormDesign(design);
15532
+ const t = d.tokens;
15533
+ const [formData, setFormData] = useState22({});
15534
+ const [isSubmitting, setIsSubmitting] = useState22(false);
15535
+ const [isSubmitted, setIsSubmitted] = useState22(false);
15536
+ const [columns, setColumns] = useState22((schema == null ? void 0 : schema.columns) || []);
15537
+ const [isLoadingSchema, setIsLoadingSchema] = useState22(false);
15538
+ const [dragName, setDragName] = useState22(null);
15539
+ const [drop, setDrop] = useState22(null);
15540
+ const [resizing, setResizing] = useState22(null);
15541
+ const resizeRef = useRef20(null);
15542
+ const gridRef = useRef20(null);
15367
15543
  const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
15368
- useEffect19(() => {
15544
+ useEffect20(() => {
15369
15545
  let isMounted = true;
15370
- if ((!(schema == null ? void 0 : schema.columns) || schema.columns.length === 0) && targetTableId && executeAction) {
15546
+ if ((!(schema == null ? void 0 : schema.columns) || schema.columns.length === 0) && targetTableId && executeAction && !previewMode) {
15371
15547
  setIsLoadingSchema(true);
15372
15548
  executeAction("FETCH_TABLE_DATA", { tableId: targetTableId, limit: 1 }).then((res) => {
15373
15549
  var _a;
15374
15550
  if (!isMounted) return;
15375
15551
  const fetchedCols = ((_a = res == null ? void 0 : res.schema) == null ? void 0 : _a.columns) || (res == null ? void 0 : res.columns);
15376
- if (fetchedCols && Array.isArray(fetchedCols)) {
15377
- setColumns(fetchedCols);
15378
- }
15379
- }).catch((err) => {
15380
- console.error("[FormBlock] Failed to fetch table schema:", err);
15381
- }).finally(() => {
15552
+ if (fetchedCols && Array.isArray(fetchedCols)) setColumns(fetchedCols);
15553
+ }).catch((err) => console.error("[StyledFormBlock] Failed to fetch table schema:", err)).finally(() => {
15382
15554
  if (isMounted) setIsLoadingSchema(false);
15383
15555
  });
15384
15556
  } else if (schema == null ? void 0 : schema.columns) {
@@ -15388,18 +15560,151 @@ function FormBlock({ settings: schema, executeAction, componentId, className = "
15388
15560
  isMounted = false;
15389
15561
  };
15390
15562
  }, [schema == null ? void 0 : schema.columns, targetTableId]);
15391
- const systemFields = ["_id", "id", "createdAt", "updatedAt", "orgId", "tableId"];
15392
- const formColumns = (columns || []).filter(
15393
- (col) => !systemFields.includes(col.name) && !col.isHidden
15394
- ).sort((a, b) => {
15563
+ const baseColumns = (columns || []).filter((col) => !SYSTEM_FIELDS.includes(col.name) && !col.isHidden).sort((a, b) => {
15395
15564
  var _a, _b;
15396
15565
  return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
15397
15566
  });
15567
+ const isDesignHidden = (col) => {
15568
+ var _a, _b;
15569
+ return !col.isRequired && !!((_b = (_a = design == null ? void 0 : design.fields) == null ? void 0 : _a[col.name]) == null ? void 0 : _b.hidden);
15570
+ };
15571
+ const orderedColumns = applyFieldOrder(baseColumns, design);
15572
+ const formColumns = orderedColumns.filter((c) => !isDesignHidden(c));
15573
+ const hiddenColumns = orderedColumns.filter((c) => isDesignHidden(c));
15398
15574
  const handleFieldChange = (colName, value) => {
15399
15575
  setFormData((prev) => __spreadProps(__spreadValues({}, prev), { [colName]: value }));
15400
15576
  };
15577
+ const canReorder = !!onReorder;
15578
+ const reorderFields = (fromName, toName, side) => {
15579
+ if (!onReorder || fromName === toName) return;
15580
+ const original = orderedColumns.map((c) => c.name);
15581
+ const names = [...original];
15582
+ const from = names.indexOf(fromName);
15583
+ if (from === -1 || !names.includes(toName)) return;
15584
+ names.splice(from, 1);
15585
+ const to = names.indexOf(toName);
15586
+ names.splice(side === "before" ? to : to + 1, 0, fromName);
15587
+ if (names.every((n, i) => n === original[i])) return;
15588
+ onReorder(names);
15589
+ };
15590
+ const findDropTarget = (x, y, dragged) => {
15591
+ const grid = gridRef.current;
15592
+ if (!grid) return null;
15593
+ const rtl = getComputedStyle(grid).direction === "rtl";
15594
+ let best = null;
15595
+ const nodes = Array.from(grid.querySelectorAll("[data-fdz-field]"));
15596
+ for (const node of nodes) {
15597
+ const name = node.getAttribute("data-fdz-field");
15598
+ if (!name) continue;
15599
+ const r = node.getBoundingClientRect();
15600
+ if (name === dragged) {
15601
+ if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom) return null;
15602
+ continue;
15603
+ }
15604
+ const dx = x < r.left ? r.left - x : x > r.right ? x - r.right : 0;
15605
+ const dy = y < r.top ? r.top - y : y > r.bottom ? y - r.bottom : 0;
15606
+ const dist = Math.hypot(dx, dy);
15607
+ if (!best || dist < best.dist) {
15608
+ const cx = r.left + r.width / 2;
15609
+ const before = rtl ? x >= cx : x < cx;
15610
+ best = { name, side: before ? "before" : "after", dist };
15611
+ }
15612
+ }
15613
+ return best ? { name: best.name, side: best.side } : null;
15614
+ };
15615
+ const startDrag = (e, colName) => {
15616
+ if (!onReorder || e.pointerType === "mouse" && e.button !== 0) return;
15617
+ const startX = e.clientX;
15618
+ const startY = e.clientY;
15619
+ let started = false;
15620
+ let current = null;
15621
+ const prevUserSelect = document.body.style.userSelect;
15622
+ const prevCursor = document.body.style.cursor;
15623
+ const onMove = (ev) => {
15624
+ if (!started) {
15625
+ if (Math.hypot(ev.clientX - startX, ev.clientY - startY) < 5) return;
15626
+ started = true;
15627
+ document.body.style.userSelect = "none";
15628
+ document.body.style.cursor = "grabbing";
15629
+ setDragName(colName);
15630
+ }
15631
+ const next = findDropTarget(ev.clientX, ev.clientY, colName);
15632
+ 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)) {
15633
+ current = next;
15634
+ setDrop(next);
15635
+ }
15636
+ };
15637
+ const finish = (commit) => {
15638
+ window.removeEventListener("pointermove", onMove);
15639
+ window.removeEventListener("pointerup", onUp);
15640
+ window.removeEventListener("pointercancel", onCancel);
15641
+ document.body.style.userSelect = prevUserSelect;
15642
+ document.body.style.cursor = prevCursor;
15643
+ if (started && commit && current) reorderFields(colName, current.name, current.side);
15644
+ setDragName(null);
15645
+ setDrop(null);
15646
+ };
15647
+ const onUp = () => finish(true);
15648
+ const onCancel = () => {
15649
+ 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)');
15650
+ finish(false);
15651
+ };
15652
+ window.addEventListener("pointermove", onMove);
15653
+ window.addEventListener("pointerup", onUp);
15654
+ window.addEventListener("pointercancel", onCancel);
15655
+ };
15656
+ const startResize = (e, colName, startSpan) => {
15657
+ var _a, _b, _c, _d;
15658
+ if (!onFieldResize) return;
15659
+ const grid = gridRef.current;
15660
+ const item = e.currentTarget.closest("[data-fdz-field]");
15661
+ if (!grid || !item) return;
15662
+ e.preventDefault();
15663
+ e.stopPropagation();
15664
+ const box = item.querySelector("[data-fdz-box]");
15665
+ const colW = (grid.clientWidth - t.gap * 5) / 6;
15666
+ const rtl = grid.closest('[dir="rtl"]') !== null || getComputedStyle(grid).direction === "rtl";
15667
+ const state = {
15668
+ name: colName,
15669
+ startX: e.clientX,
15670
+ startY: e.clientY,
15671
+ startSpan,
15672
+ step: colW + t.gap,
15673
+ rtl,
15674
+ startHeight: box ? box.offsetHeight : 40,
15675
+ hadHeight: !!((_b = (_a = design == null ? void 0 : design.fields) == null ? void 0 : _a[colName]) == null ? void 0 : _b.height),
15676
+ span: startSpan,
15677
+ height: (_d = (_c = design == null ? void 0 : design.fields) == null ? void 0 : _c[colName]) == null ? void 0 : _d.height
15678
+ };
15679
+ resizeRef.current = state;
15680
+ setResizing({ name: colName, span: state.span, height: state.height });
15681
+ const onMove = (ev) => {
15682
+ const dxRaw = ev.clientX - state.startX;
15683
+ const dx = state.rtl ? -dxRaw : dxRaw;
15684
+ const span = Math.max(1, Math.min(6, Math.round(state.startSpan + dx / state.step)));
15685
+ const dy = ev.clientY - state.startY;
15686
+ const height = Math.abs(dy) < 8 && !state.hadHeight ? void 0 : Math.max(40, Math.round(state.startHeight + dy));
15687
+ if (span !== state.span || height !== state.height) {
15688
+ state.span = span;
15689
+ state.height = height;
15690
+ setResizing({ name: state.name, span, height });
15691
+ }
15692
+ };
15693
+ const onUp = () => {
15694
+ window.removeEventListener("pointermove", onMove);
15695
+ window.removeEventListener("pointerup", onUp);
15696
+ window.removeEventListener("pointercancel", onUp);
15697
+ resizeRef.current = null;
15698
+ onFieldResize(state.name, { span: state.span, height: state.height });
15699
+ setResizing(null);
15700
+ };
15701
+ window.addEventListener("pointermove", onMove);
15702
+ window.addEventListener("pointerup", onUp);
15703
+ window.addEventListener("pointercancel", onUp);
15704
+ };
15401
15705
  const handleSubmit = async (e) => {
15402
15706
  e.preventDefault();
15707
+ if (previewMode) return;
15403
15708
  if (!executeAction) {
15404
15709
  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");
15405
15710
  return;
@@ -15417,108 +15722,294 @@ function FormBlock({ settings: schema, executeAction, componentId, className = "
15417
15722
  }
15418
15723
  setIsSubmitting(true);
15419
15724
  try {
15420
- const formattedPayload = {};
15725
+ const payload = {};
15421
15726
  formColumns.forEach((col) => {
15422
15727
  var _a;
15423
15728
  let val = formData[col.name];
15424
15729
  if (val !== void 0 && val !== null) {
15425
- if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
15426
- val = val === "" ? 0 : Number(val);
15427
- }
15428
- formattedPayload[col.name] = val;
15730
+ if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") val = val === "" ? 0 : Number(val);
15731
+ payload[col.name] = val;
15429
15732
  } else if (col.defaultValue !== void 0) {
15430
- formattedPayload[col.name] = col.defaultValue;
15733
+ payload[col.name] = col.defaultValue;
15431
15734
  }
15432
15735
  });
15736
+ hiddenColumns.forEach((col) => {
15737
+ if (col.defaultValue !== void 0) payload[col.name] = col.defaultValue;
15738
+ });
15433
15739
  await executeAction("CREATE_RECORD", {
15434
15740
  tableId: targetTableId,
15435
15741
  tableMetaId: targetTableId,
15436
- records: [formattedPayload]
15742
+ records: [payload]
15437
15743
  });
15438
15744
  addToast({ message: "\u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD \u05E0\u05E9\u05DE\u05E8\u05D5 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4", type: "success" });
15439
15745
  setFormData({});
15440
15746
  setIsSubmitted(true);
15441
15747
  if (onSuccess) onSuccess();
15442
15748
  } catch (err) {
15443
- console.error("[FormBlock] Submit error:", err);
15749
+ console.error("[StyledFormBlock] Submit error:", err);
15444
15750
  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");
15445
15751
  } finally {
15446
15752
  setIsSubmitting(false);
15447
15753
  }
15448
15754
  };
15755
+ const muted = t.invertText ? "rgba(255,255,255,0.85)" : "#64748b";
15756
+ const cardStyle = {
15757
+ background: d.background,
15758
+ color: d.text,
15759
+ borderRadius: t.radius,
15760
+ border: t.border,
15761
+ boxShadow: t.shadow,
15762
+ padding: t.headerBand ? 0 : t.padding,
15763
+ overflow: t.headerBand ? "hidden" : void 0
15764
+ };
15765
+ const inputBoxStyle = t.inputStyle === "underline" ? { borderBottom: "1px solid #cbd5e1", borderRadius: 0, background: "transparent", minHeight: 40, position: "relative" } : {
15766
+ border: "1px solid #e2e8f0",
15767
+ borderRadius: Math.min(t.radius, 10) || 6,
15768
+ background: "#ffffff",
15769
+ color: "#0f172a",
15770
+ minHeight: 40,
15771
+ position: "relative"
15772
+ };
15773
+ const booleanBoxStyle = __spreadProps(__spreadValues({}, inputBoxStyle), {
15774
+ minHeight: 0,
15775
+ width: "fit-content",
15776
+ alignSelf: "flex-start"
15777
+ });
15778
+ const css = `
15779
+ .${uid}{container-type:inline-size}
15780
+ .${uid} .fdz-grid{display:flex;flex-wrap:wrap;align-items:flex-start;gap:${t.gap}px}
15781
+ .${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)}
15782
+ .${uid} .fdz-s1{--n:2}
15783
+ .${uid} .fdz-b{width:fit-content;max-width:140px;margin-inline-end:-${Math.max(0, t.gap - 8)}px}
15784
+ @container (min-width:480px){
15785
+ .${uid} .fdz-f{--n:var(--span)}
15786
+ }
15787
+ `;
15449
15788
  if (isLoadingSchema) {
15450
- return /* @__PURE__ */ jsxs25("div", { className: "p-8 flex items-center justify-center gap-2 text-slate-500", children: [
15451
- /* @__PURE__ */ jsx29(Loader29, { className: "w-5 h-5 animate-spin text-brand" }),
15452
- /* @__PURE__ */ jsx29("span", { className: "text-sm", children: "\u05D8\u05D5\u05E2\u05DF \u05E9\u05D3\u05D5\u05EA \u05D8\u05D5\u05E4\u05E1..." })
15789
+ return /* @__PURE__ */ jsxs26("div", { className: "p-8 flex items-center justify-center gap-2 text-slate-500", dir: "rtl", children: [
15790
+ /* @__PURE__ */ jsx30(Loader210, { className: "w-5 h-5 animate-spin", style: { color: d.primary } }),
15791
+ /* @__PURE__ */ jsx30("span", { className: "text-sm", children: "\u05D8\u05D5\u05E2\u05DF \u05E9\u05D3\u05D5\u05EA \u05D8\u05D5\u05E4\u05E1..." })
15453
15792
  ] });
15454
15793
  }
15455
15794
  if (!formColumns || formColumns.length === 0) {
15456
- return /* @__PURE__ */ jsx29("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." });
15795
+ return /* @__PURE__ */ jsx30("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." });
15457
15796
  }
15797
+ const headerBlock = (schema == null ? void 0 : schema.title) || d.subtitle ? /* @__PURE__ */ jsxs26(
15798
+ "div",
15799
+ {
15800
+ style: t.headerBand ? { background: d.primary, color: "#ffffff", padding: `${t.padding * 0.8}px ${t.padding}px` } : { marginBottom: t.gap + 4 },
15801
+ children: [
15802
+ (schema == null ? void 0 : schema.title) && /* @__PURE__ */ jsx30("h2", { style: { fontSize: t.titleSize, fontWeight: 800, margin: 0 }, children: schema.title }),
15803
+ d.subtitle && /* @__PURE__ */ jsx30("p", { style: { fontSize: 14, margin: "6px 0 0", color: t.headerBand ? "rgba(255,255,255,0.9)" : muted }, children: d.subtitle })
15804
+ ]
15805
+ }
15806
+ ) : null;
15458
15807
  if (isSubmitted) {
15459
15808
  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.";
15460
- return /* @__PURE__ */ jsxs25("div", { id: componentId, className: `bg-white p-8 rounded-xl shadow-xs border border-slate-200 text-center dir-rtl ${className}`, children: [
15461
- /* @__PURE__ */ jsx29("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__ */ jsx29(CheckCircle25, { className: "w-8 h-8" }) }),
15462
- /* @__PURE__ */ jsx29("h3", { className: "text-2xl font-bold text-slate-800 mb-2", children: "\u05D4\u05D5\u05D3\u05E2\u05D4 \u05E0\u05E9\u05DC\u05D7\u05D4" }),
15463
- /* @__PURE__ */ jsx29("p", { className: "text-slate-600 text-base max-w-md mx-auto whitespace-pre-wrap", children: customMessage }),
15464
- /* @__PURE__ */ jsx29(
15809
+ return /* @__PURE__ */ jsxs26("div", { id: componentId, dir: "rtl", className, style: __spreadProps(__spreadValues({}, cardStyle), { padding: t.padding || 24, textAlign: "center" }), children: [
15810
+ /* @__PURE__ */ jsx30(
15811
+ "div",
15812
+ {
15813
+ style: {
15814
+ width: 64,
15815
+ height: 64,
15816
+ borderRadius: "50%",
15817
+ margin: "0 auto 16px",
15818
+ display: "flex",
15819
+ alignItems: "center",
15820
+ justifyContent: "center",
15821
+ background: t.invertText ? "rgba(255,255,255,0.2)" : "#ecfdf5",
15822
+ color: t.invertText ? "#ffffff" : "#059669"
15823
+ },
15824
+ children: /* @__PURE__ */ jsx30(CheckCircle26, { className: "w-8 h-8" })
15825
+ }
15826
+ ),
15827
+ /* @__PURE__ */ jsx30("h3", { style: { fontSize: 24, fontWeight: 800, margin: "0 0 8px" }, children: "\u05D4\u05D5\u05D3\u05E2\u05D4 \u05E0\u05E9\u05DC\u05D7\u05D4" }),
15828
+ /* @__PURE__ */ jsx30("p", { style: { fontSize: 16, color: muted, maxWidth: 420, margin: "0 auto", whiteSpace: "pre-wrap" }, children: customMessage }),
15829
+ /* @__PURE__ */ jsx30(
15465
15830
  "button",
15466
15831
  {
15467
15832
  type: "button",
15468
15833
  onClick: () => setIsSubmitted(false),
15469
- className: "mt-6 px-4 py-2 text-xs font-semibold text-brand hover:underline cursor-pointer",
15834
+ style: { marginTop: 24, fontSize: 12, fontWeight: 600, color: t.invertText ? "#ffffff" : d.primary, background: "none", border: "none", cursor: "pointer", textDecoration: "underline" },
15470
15835
  children: "\u05E9\u05DC\u05D9\u05D7\u05EA \u05DE\u05E2\u05E0\u05D4 \u05E0\u05D5\u05E1\u05E3"
15471
15836
  }
15472
15837
  )
15473
15838
  ] });
15474
15839
  }
15475
- return /* @__PURE__ */ jsxs25("div", { id: componentId, className: `bg-white p-6 rounded-xl shadow-xs border border-slate-200 dir-rtl ${className}`, children: [
15476
- (schema == null ? void 0 : schema.title) && /* @__PURE__ */ jsx29("h2", { className: "text-xl font-bold text-slate-800 mb-6", children: schema.title }),
15477
- /* @__PURE__ */ jsxs25("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
15478
- formColumns.map((col) => {
15479
- var _a, _b;
15480
- const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
15481
- const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
15482
- return /* @__PURE__ */ jsxs25("div", { className: "flex flex-col gap-1.5", children: [
15483
- /* @__PURE__ */ jsxs25("label", { className: "text-sm font-semibold text-slate-700", children: [
15484
- col.name,
15485
- " ",
15486
- col.isRequired && /* @__PURE__ */ jsx29("span", { className: "text-rose-500", children: "*" })
15487
- ] }),
15488
- /* @__PURE__ */ jsx29("div", { className: "border border-slate-200 rounded-lg min-h-[40px] relative", children: /* @__PURE__ */ jsx29(
15489
- InputComponent,
15840
+ const justify = d.buttonAlign === "center" ? "center" : d.buttonAlign === "end" ? "flex-end" : d.buttonAlign === "full" ? "stretch" : "flex-start";
15841
+ return /* @__PURE__ */ jsxs26("div", { id: componentId, dir: "rtl", className: `${uid} ${className}`, style: cardStyle, children: [
15842
+ /* @__PURE__ */ jsx30("style", { children: css }),
15843
+ headerBlock,
15844
+ /* @__PURE__ */ jsx30("div", { style: t.headerBand ? { padding: t.padding } : void 0, children: /* @__PURE__ */ jsxs26("form", { onSubmit: handleSubmit, children: [
15845
+ /* @__PURE__ */ jsx30("div", { className: "fdz-grid", ref: gridRef, children: (() => {
15846
+ const spanOf = (col) => {
15847
+ var _a;
15848
+ if (resizing && resizing.name === col.name) return resizing.span;
15849
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
15850
+ return resolveFieldSpan(col.name, colType, design, d.columns);
15851
+ };
15852
+ const renderField = (col) => {
15853
+ var _a, _b, _c, _d, _e;
15854
+ const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
15855
+ const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
15856
+ const span = spanOf(col);
15857
+ const isBoolean = colType === "BOOLEAN";
15858
+ 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;
15859
+ const useTextarea = !!fieldHeight && fieldHeight > 56 && InputComponent === FORM_INPUTS.DEFAULT;
15860
+ const boxStyle = __spreadValues(__spreadValues(__spreadValues({}, isBoolean ? booleanBoxStyle : inputBoxStyle), fieldHeight && !isBoolean ? __spreadValues({ minHeight: fieldHeight }, useTextarea ? { height: fieldHeight } : {}) : {}), canReorder ? { pointerEvents: "none" } : {});
15861
+ return /* @__PURE__ */ jsxs26(
15862
+ "div",
15490
15863
  {
15491
- column: col,
15492
- rowId: "new_form_record",
15493
- value: (_b = formData[col.name]) != null ? _b : "",
15494
- onChange: (val) => handleFieldChange(col.name, val),
15495
- context: {
15496
- executeAction,
15497
- tableId: targetTableId
15498
- }
15499
- }
15500
- ) })
15501
- ] }, col.name);
15502
- }),
15503
- /* @__PURE__ */ jsx29("div", { className: "pt-4 border-t border-slate-100 flex justify-end", children: /* @__PURE__ */ jsxs25(
15504
- "button",
15864
+ "data-fdz-field": col.name,
15865
+ className: `fdz-f fdz-s${span}${isBoolean ? " fdz-b" : ""}`,
15866
+ draggable: false,
15867
+ onDragStart: canReorder ? (e) => e.preventDefault() : void 0,
15868
+ onMouseDown: canReorder ? (e) => e.stopPropagation() : void 0,
15869
+ onTouchStart: canReorder ? (e) => e.stopPropagation() : void 0,
15870
+ onPointerDown: canReorder ? (e) => {
15871
+ e.stopPropagation();
15872
+ startDrag(e, col.name);
15873
+ } : void 0,
15874
+ style: __spreadValues({ "--span": span }, canReorder ? {
15875
+ position: "relative",
15876
+ cursor: "grab",
15877
+ touchAction: "none",
15878
+ userSelect: "none",
15879
+ opacity: dragName === col.name ? 0.4 : 1,
15880
+ outline: resizing && resizing.name === col.name ? `2px solid ${t.invertText ? "#ffffff" : d.primary}` : void 0,
15881
+ outlineOffset: 4,
15882
+ borderRadius: 6
15883
+ } : {}),
15884
+ children: [
15885
+ /* @__PURE__ */ jsxs26("label", { style: { fontSize: t.labelSize, fontWeight: 600, color: d.text }, children: [
15886
+ col.name,
15887
+ " ",
15888
+ col.isRequired && /* @__PURE__ */ jsx30("span", { style: { color: t.invertText ? "#fecdd3" : "#f43f5e" }, children: "*" })
15889
+ ] }),
15890
+ /* @__PURE__ */ jsx30("div", { "data-fdz-box": true, style: boxStyle, children: useTextarea ? /* @__PURE__ */ jsx30(
15891
+ "textarea",
15892
+ {
15893
+ value: (_d = formData[col.name]) != null ? _d : "",
15894
+ onChange: (e) => handleFieldChange(col.name, e.target.value),
15895
+ readOnly: previewMode,
15896
+ style: {
15897
+ width: "100%",
15898
+ height: "100%",
15899
+ minHeight: fieldHeight - 2,
15900
+ padding: "8px 12px",
15901
+ border: "none",
15902
+ outline: "none",
15903
+ background: "transparent",
15904
+ resize: "none",
15905
+ font: "inherit",
15906
+ color: "inherit",
15907
+ boxSizing: "border-box"
15908
+ }
15909
+ }
15910
+ ) : /* @__PURE__ */ jsx30(
15911
+ InputComponent,
15912
+ {
15913
+ column: col,
15914
+ rowId: "new_form_record",
15915
+ value: (_e = formData[col.name]) != null ? _e : "",
15916
+ onChange: (val) => handleFieldChange(col.name, val),
15917
+ readOnly: previewMode,
15918
+ context: { executeAction: previewMode ? void 0 : executeAction, tableId: targetTableId }
15919
+ }
15920
+ ) }),
15921
+ canReorder && dragName && drop && drop.name === col.name && /* @__PURE__ */ jsx30(
15922
+ "div",
15923
+ {
15924
+ style: __spreadValues({
15925
+ position: "absolute",
15926
+ top: 0,
15927
+ bottom: 0,
15928
+ width: 4,
15929
+ borderRadius: 2,
15930
+ background: t.invertText ? "#ffffff" : d.primary,
15931
+ pointerEvents: "none",
15932
+ zIndex: 3
15933
+ }, drop.side === "before" ? { insetInlineStart: -(t.gap / 2) - 2 } : { insetInlineEnd: -(t.gap / 2) - 2 })
15934
+ }
15935
+ ),
15936
+ onFieldResize && !isBoolean && /* @__PURE__ */ jsx30(
15937
+ "div",
15938
+ {
15939
+ onMouseDown: (e) => e.stopPropagation(),
15940
+ onTouchStart: (e) => e.stopPropagation(),
15941
+ onPointerDown: (e) => startResize(e, col.name, span),
15942
+ onDoubleClick: () => onFieldResize(col.name, { reset: true }),
15943
+ 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)",
15944
+ style: {
15945
+ position: "absolute",
15946
+ left: -6,
15947
+ bottom: -6,
15948
+ width: 14,
15949
+ height: 14,
15950
+ borderRadius: 4,
15951
+ background: "#ffffff",
15952
+ border: `2px solid ${d.primary}`,
15953
+ cursor: "nesw-resize",
15954
+ touchAction: "none",
15955
+ zIndex: 2
15956
+ }
15957
+ }
15958
+ )
15959
+ ]
15960
+ },
15961
+ col.name
15962
+ );
15963
+ };
15964
+ return formColumns.map((col) => renderField(col));
15965
+ })() }),
15966
+ /* @__PURE__ */ jsx30(
15967
+ "div",
15505
15968
  {
15506
- type: "submit",
15507
- disabled: isSubmitting,
15508
- 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",
15509
- children: [
15510
- isSubmitting && /* @__PURE__ */ jsx29(Loader29, { className: "w-4 h-4 animate-spin" }),
15511
- /* @__PURE__ */ jsx29("span", { children: isSubmitting ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DC\u05D9\u05D7\u05D4" })
15512
- ]
15969
+ style: {
15970
+ marginTop: t.gap + 8,
15971
+ paddingTop: t.inputStyle === "underline" || t.invertText ? 0 : t.gap,
15972
+ borderTop: t.inputStyle === "underline" || t.invertText ? "none" : "1px solid rgba(148,163,184,0.25)",
15973
+ display: "flex",
15974
+ justifyContent: justify
15975
+ },
15976
+ children: /* @__PURE__ */ jsxs26(
15977
+ "button",
15978
+ {
15979
+ type: "submit",
15980
+ disabled: isSubmitting || previewMode,
15981
+ style: {
15982
+ display: "flex",
15983
+ alignItems: "center",
15984
+ justifyContent: "center",
15985
+ gap: 8,
15986
+ padding: "10px 28px",
15987
+ width: d.buttonAlign === "full" ? "100%" : void 0,
15988
+ background: t.invertText ? "#ffffff" : d.primary,
15989
+ color: t.invertText ? d.primary : "#ffffff",
15990
+ fontWeight: 700,
15991
+ fontSize: 15,
15992
+ border: "none",
15993
+ borderRadius: Math.min(t.radius, 10) || 6,
15994
+ boxShadow: "0 1px 2px rgba(0,0,0,0.1)",
15995
+ cursor: isSubmitting || previewMode ? "default" : "pointer",
15996
+ opacity: isSubmitting ? 0.5 : 1
15997
+ },
15998
+ children: [
15999
+ isSubmitting && /* @__PURE__ */ jsx30(Loader210, { className: "w-4 h-4 animate-spin" }),
16000
+ /* @__PURE__ */ jsx30("span", { children: isSubmitting ? "\u05E9\u05D5\u05DE\u05E8..." : d.buttonText })
16001
+ ]
16002
+ }
16003
+ )
15513
16004
  }
15514
- ) })
15515
- ] })
16005
+ )
16006
+ ] }) })
15516
16007
  ] });
15517
16008
  }
15518
16009
 
15519
16010
  // src/themes/ThemeScope.tsx
15520
- import * as React22 from "react";
15521
- import { jsx as jsx30 } from "react/jsx-runtime";
16011
+ import * as React23 from "react";
16012
+ import { jsx as jsx31 } from "react/jsx-runtime";
15522
16013
  var UNIVERSE_THEME_IDS = ["classic", "clean", "ocean", "warm"];
15523
16014
  function resolveUniverseTheme(value) {
15524
16015
  return typeof value === "string" && UNIVERSE_THEME_IDS.includes(value) ? value : "classic";
@@ -15528,7 +16019,7 @@ function withThemeScope(Component) {
15528
16019
  var _a, _b, _c;
15529
16020
  const p = props;
15530
16021
  const theme = resolveUniverseTheme((_c = (_a = p.settings) == null ? void 0 : _a.theme) != null ? _c : (_b = p.config) == null ? void 0 : _b.theme);
15531
- return /* @__PURE__ */ jsx30("div", { "data-theme": theme, style: { display: "contents" }, children: React22.createElement(Component, props) });
16022
+ return /* @__PURE__ */ jsx31("div", { "data-theme": theme, style: { display: "contents" }, children: React23.createElement(Component, props) });
15532
16023
  }
15533
16024
  ThemeScoped.displayName = `ThemeScoped(${Component.displayName || Component.name || "Component"})`;
15534
16025
  return ThemeScoped;
@@ -15538,7 +16029,7 @@ function withThemeScope(Component) {
15538
16029
  var UNIVERSE_COMPONENTS = {
15539
16030
  TABLE: withThemeScope(TableBlock),
15540
16031
  WHATSAPP: withThemeScope(WhatsAppComponent),
15541
- FORM: withThemeScope(FormBlock),
16032
+ FORM: withThemeScope(StyledFormBlock),
15542
16033
  PLACEMENT: withThemeScope(PlacementBlock)
15543
16034
  };
15544
16035
  export {