@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.mjs CHANGED
@@ -15370,28 +15370,187 @@ function WhatsAppComponent(props) {
15370
15370
  import { useState as useState21, useEffect as useEffect19 } from "react";
15371
15371
  import { Loader2 as Loader29, CheckCircle2 as CheckCircle25 } from "lucide-react";
15372
15372
  import { jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
15373
- 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
+ }) {
15374
15528
  const { showError, addToast } = useToast();
15375
- const [formData, setFormData] = useState21({});
15376
- const [isSubmitting, setIsSubmitting] = useState21(false);
15377
- const [isSubmitted, setIsSubmitted] = useState21(false);
15378
- const [columns, setColumns] = useState21((schema == null ? void 0 : schema.columns) || []);
15379
- 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);
15380
15543
  const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
15381
- useEffect19(() => {
15544
+ useEffect20(() => {
15382
15545
  let isMounted = true;
15383
- 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) {
15384
15547
  setIsLoadingSchema(true);
15385
15548
  executeAction("FETCH_TABLE_DATA", { tableId: targetTableId, limit: 1 }).then((res) => {
15386
15549
  var _a;
15387
15550
  if (!isMounted) return;
15388
15551
  const fetchedCols = ((_a = res == null ? void 0 : res.schema) == null ? void 0 : _a.columns) || (res == null ? void 0 : res.columns);
15389
- if (fetchedCols && Array.isArray(fetchedCols)) {
15390
- setColumns(fetchedCols);
15391
- }
15392
- }).catch((err) => {
15393
- console.error("[FormBlock] Failed to fetch table schema:", err);
15394
- }).finally(() => {
15552
+ if (fetchedCols && Array.isArray(fetchedCols)) setColumns(fetchedCols);
15553
+ }).catch((err) => console.error("[StyledFormBlock] Failed to fetch table schema:", err)).finally(() => {
15395
15554
  if (isMounted) setIsLoadingSchema(false);
15396
15555
  });
15397
15556
  } else if (schema == null ? void 0 : schema.columns) {
@@ -15401,18 +15560,151 @@ function FormBlock({ settings: schema, executeAction, componentId, className = "
15401
15560
  isMounted = false;
15402
15561
  };
15403
15562
  }, [schema == null ? void 0 : schema.columns, targetTableId]);
15404
- const systemFields = ["_id", "id", "createdAt", "updatedAt", "orgId", "tableId"];
15405
- const formColumns = (columns || []).filter(
15406
- (col) => !systemFields.includes(col.name) && !col.isHidden
15407
- ).sort((a, b) => {
15563
+ const baseColumns = (columns || []).filter((col) => !SYSTEM_FIELDS.includes(col.name) && !col.isHidden).sort((a, b) => {
15408
15564
  var _a, _b;
15409
15565
  return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
15410
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));
15411
15574
  const handleFieldChange = (colName, value) => {
15412
15575
  setFormData((prev) => __spreadProps(__spreadValues({}, prev), { [colName]: value }));
15413
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
+ };
15414
15705
  const handleSubmit = async (e) => {
15415
15706
  e.preventDefault();
15707
+ if (previewMode) return;
15416
15708
  if (!executeAction) {
15417
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");
15418
15710
  return;
@@ -15430,108 +15722,294 @@ function FormBlock({ settings: schema, executeAction, componentId, className = "
15430
15722
  }
15431
15723
  setIsSubmitting(true);
15432
15724
  try {
15433
- const formattedPayload = {};
15725
+ const payload = {};
15434
15726
  formColumns.forEach((col) => {
15435
15727
  var _a;
15436
15728
  let val = formData[col.name];
15437
15729
  if (val !== void 0 && val !== null) {
15438
- if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
15439
- val = val === "" ? 0 : Number(val);
15440
- }
15441
- 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;
15442
15732
  } else if (col.defaultValue !== void 0) {
15443
- formattedPayload[col.name] = col.defaultValue;
15733
+ payload[col.name] = col.defaultValue;
15444
15734
  }
15445
15735
  });
15736
+ hiddenColumns.forEach((col) => {
15737
+ if (col.defaultValue !== void 0) payload[col.name] = col.defaultValue;
15738
+ });
15446
15739
  await executeAction("CREATE_RECORD", {
15447
15740
  tableId: targetTableId,
15448
15741
  tableMetaId: targetTableId,
15449
- records: [formattedPayload]
15742
+ records: [payload]
15450
15743
  });
15451
15744
  addToast({ message: "\u05D4\u05E0\u05EA\u05D5\u05E0\u05D9\u05DD \u05E0\u05E9\u05DE\u05E8\u05D5 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4", type: "success" });
15452
15745
  setFormData({});
15453
15746
  setIsSubmitted(true);
15454
15747
  if (onSuccess) onSuccess();
15455
15748
  } catch (err) {
15456
- console.error("[FormBlock] Submit error:", err);
15749
+ console.error("[StyledFormBlock] Submit error:", err);
15457
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");
15458
15751
  } finally {
15459
15752
  setIsSubmitting(false);
15460
15753
  }
15461
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
+ `;
15462
15788
  if (isLoadingSchema) {
15463
- return /* @__PURE__ */ jsxs25("div", { className: "p-8 flex items-center justify-center gap-2 text-slate-500", children: [
15464
- /* @__PURE__ */ jsx29(Loader29, { className: "w-5 h-5 animate-spin text-brand" }),
15465
- /* @__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..." })
15466
15792
  ] });
15467
15793
  }
15468
15794
  if (!formColumns || formColumns.length === 0) {
15469
- 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." });
15470
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;
15471
15807
  if (isSubmitted) {
15472
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.";
15473
- 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: [
15474
- /* @__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" }) }),
15475
- /* @__PURE__ */ jsx29("h3", { className: "text-2xl font-bold text-slate-800 mb-2", children: "\u05D4\u05D5\u05D3\u05E2\u05D4 \u05E0\u05E9\u05DC\u05D7\u05D4" }),
15476
- /* @__PURE__ */ jsx29("p", { className: "text-slate-600 text-base max-w-md mx-auto whitespace-pre-wrap", children: customMessage }),
15477
- /* @__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(
15478
15830
  "button",
15479
15831
  {
15480
15832
  type: "button",
15481
15833
  onClick: () => setIsSubmitted(false),
15482
- 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" },
15483
15835
  children: "\u05E9\u05DC\u05D9\u05D7\u05EA \u05DE\u05E2\u05E0\u05D4 \u05E0\u05D5\u05E1\u05E3"
15484
15836
  }
15485
15837
  )
15486
15838
  ] });
15487
15839
  }
15488
- return /* @__PURE__ */ jsxs25("div", { id: componentId, className: `bg-white p-6 rounded-xl shadow-xs border border-slate-200 dir-rtl ${className}`, children: [
15489
- (schema == null ? void 0 : schema.title) && /* @__PURE__ */ jsx29("h2", { className: "text-xl font-bold text-slate-800 mb-6", children: schema.title }),
15490
- /* @__PURE__ */ jsxs25("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
15491
- formColumns.map((col) => {
15492
- var _a, _b;
15493
- const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
15494
- const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
15495
- return /* @__PURE__ */ jsxs25("div", { className: "flex flex-col gap-1.5", children: [
15496
- /* @__PURE__ */ jsxs25("label", { className: "text-sm font-semibold text-slate-700", children: [
15497
- col.name,
15498
- " ",
15499
- col.isRequired && /* @__PURE__ */ jsx29("span", { className: "text-rose-500", children: "*" })
15500
- ] }),
15501
- /* @__PURE__ */ jsx29("div", { className: "border border-slate-200 rounded-lg min-h-[40px] relative", children: /* @__PURE__ */ jsx29(
15502
- 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",
15503
15863
  {
15504
- column: col,
15505
- rowId: "new_form_record",
15506
- value: (_b = formData[col.name]) != null ? _b : "",
15507
- onChange: (val) => handleFieldChange(col.name, val),
15508
- context: {
15509
- executeAction,
15510
- tableId: targetTableId
15511
- }
15512
- }
15513
- ) })
15514
- ] }, col.name);
15515
- }),
15516
- /* @__PURE__ */ jsx29("div", { className: "pt-4 border-t border-slate-100 flex justify-end", children: /* @__PURE__ */ jsxs25(
15517
- "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",
15518
15968
  {
15519
- type: "submit",
15520
- disabled: isSubmitting,
15521
- 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",
15522
- children: [
15523
- isSubmitting && /* @__PURE__ */ jsx29(Loader29, { className: "w-4 h-4 animate-spin" }),
15524
- /* @__PURE__ */ jsx29("span", { children: isSubmitting ? "\u05E9\u05D5\u05DE\u05E8..." : "\u05E9\u05DC\u05D9\u05D7\u05D4" })
15525
- ]
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
+ )
15526
16004
  }
15527
- ) })
15528
- ] })
16005
+ )
16006
+ ] }) })
15529
16007
  ] });
15530
16008
  }
15531
16009
 
15532
16010
  // src/themes/ThemeScope.tsx
15533
- import * as React22 from "react";
15534
- import { jsx as jsx30 } from "react/jsx-runtime";
16011
+ import * as React23 from "react";
16012
+ import { jsx as jsx31 } from "react/jsx-runtime";
15535
16013
  var UNIVERSE_THEME_IDS = ["classic", "clean", "ocean", "warm"];
15536
16014
  function resolveUniverseTheme(value) {
15537
16015
  return typeof value === "string" && UNIVERSE_THEME_IDS.includes(value) ? value : "classic";
@@ -15541,7 +16019,7 @@ function withThemeScope(Component) {
15541
16019
  var _a, _b, _c;
15542
16020
  const p = props;
15543
16021
  const theme = resolveUniverseTheme((_c = (_a = p.settings) == null ? void 0 : _a.theme) != null ? _c : (_b = p.config) == null ? void 0 : _b.theme);
15544
- 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) });
15545
16023
  }
15546
16024
  ThemeScoped.displayName = `ThemeScoped(${Component.displayName || Component.name || "Component"})`;
15547
16025
  return ThemeScoped;
@@ -15551,7 +16029,7 @@ function withThemeScope(Component) {
15551
16029
  var UNIVERSE_COMPONENTS = {
15552
16030
  TABLE: withThemeScope(TableBlock),
15553
16031
  WHATSAPP: withThemeScope(WhatsAppComponent),
15554
- FORM: withThemeScope(FormBlock),
16032
+ FORM: withThemeScope(StyledFormBlock),
15555
16033
  PLACEMENT: withThemeScope(PlacementBlock)
15556
16034
  };
15557
16035
  export {