@dmitryvim/form-builder 0.3.4 → 0.5.0
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/browser/formbuilder.min.js +181 -123
- package/dist/browser/formbuilder.v0.5.0.min.js +1499 -0
- package/dist/cjs/index.cjs +150 -91
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +144 -89
- package/dist/esm/index.js.map +1 -1
- package/dist/form-builder.js +181 -123
- package/dist/types/components/file/library.d.ts +1 -1
- package/dist/types/components/textarea.d.ts +4 -2
- package/dist/types/styles/theme.d.ts +3 -0
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/schema.d.ts +32 -2
- package/dist/types/utils/styles.d.ts +3 -1
- package/package.json +19 -19
- package/dist/browser/formbuilder.v0.3.4.min.js +0 -1441
package/dist/esm/index.js
CHANGED
|
@@ -419,6 +419,20 @@ function ensureThemingHooks(doc) {
|
|
|
419
419
|
min-height: var(--fb-slide-card-min-height);
|
|
420
420
|
padding: var(--fb-slide-card-padding);
|
|
421
421
|
}
|
|
422
|
+
/* Slides-mode outer grid. Responsive by design \u2014 column count derives from
|
|
423
|
+
container width and --fb-slide-min-width, not from a schema "columns" prop.
|
|
424
|
+
min(100%, ...) prevents the card from overflowing a narrow container.
|
|
425
|
+
Override per-form: set --fb-slide-min-width / --fb-slides-gap on any
|
|
426
|
+
ancestor (theme, host CSS, or the form root). */
|
|
427
|
+
.fb-container-slides {
|
|
428
|
+
display: grid;
|
|
429
|
+
gap: var(--fb-slides-gap, 14px);
|
|
430
|
+
align-items: stretch;
|
|
431
|
+
grid-template-columns: repeat(
|
|
432
|
+
auto-fit,
|
|
433
|
+
minmax(min(100%, var(--fb-slide-min-width, 280px)), 1fr)
|
|
434
|
+
);
|
|
435
|
+
}
|
|
422
436
|
[data-fb-label-row] > label {
|
|
423
437
|
font-size: var(--fb-label-section-font-size);
|
|
424
438
|
letter-spacing: var(--fb-label-section-letter-spacing);
|
|
@@ -465,20 +479,60 @@ function ensureThemingHooks(doc) {
|
|
|
465
479
|
color: #ffffff;
|
|
466
480
|
border-color: var(--fb-primary-color);
|
|
467
481
|
}
|
|
482
|
+
/* \u2500\u2500\u2500 Row layout: flex-wrap container with per-child width tokens \u2500\u2500\u2500
|
|
483
|
+
Replaces the older Tailwind \`space-y-2\` class. Children without
|
|
484
|
+
data-fb-width (or width="full") take 100% basis \u2192 forced wrap \u2192 behaves
|
|
485
|
+
like a vertical stack. Mixed widths sit side-by-side in the same row. */
|
|
486
|
+
.fb-row {
|
|
487
|
+
display: flex;
|
|
488
|
+
flex-wrap: wrap;
|
|
489
|
+
gap: var(--fb-row-gap, 0.25rem);
|
|
490
|
+
align-items: flex-start;
|
|
491
|
+
}
|
|
492
|
+
.fb-row > [data-fb-width="full"],
|
|
493
|
+
.fb-row > :not([data-fb-width]) { flex: 0 0 100%; min-width: 0; }
|
|
494
|
+
.fb-row > [data-fb-width="1/2"] { flex: 0 0 calc(50% - var(--fb-row-gap, 0.25rem) / 2); min-width: 0; }
|
|
495
|
+
.fb-row > [data-fb-width="1/3"] { flex: 0 0 calc(33.333% - var(--fb-row-gap, 0.25rem) * 2 / 3); min-width: 0; }
|
|
496
|
+
.fb-row > [data-fb-width="2/3"] { flex: 0 0 calc(66.666% - var(--fb-row-gap, 0.25rem) / 3); min-width: 0; }
|
|
497
|
+
/* \u2500\u2500\u2500 Density tokens: re-bind --fb-input-padding-* and --fb-font-size at
|
|
498
|
+
the wrapper level so every component that reads those vars (text, textarea,
|
|
499
|
+
select, number, colour, switcher, file) picks the size up via cascade. md
|
|
500
|
+
uses the defaults set in theme.ts (2px / 8px / 14px). The scale primarily
|
|
501
|
+
varies font-size; vertical padding stays close to md so an "lg" heading
|
|
502
|
+
field does not visually break the form's row rhythm \u2014 only the typography
|
|
503
|
+
announces "this is bigger". Picaz theme overrides padding directly for
|
|
504
|
+
its own density, independent of this scale. */
|
|
505
|
+
/* size-token side-effects on file tiles: --fb-file-wide-min controls the
|
|
506
|
+
single-file empty dropzone height, --fb-file-zone-min controls the inner
|
|
507
|
+
upload/library zones. Both read in src/components/file/styles.ts. */
|
|
508
|
+
.fb-size-xs { --fb-input-padding-y: 1px; --fb-input-padding-x: 6px; --fb-font-size: 12px; --fb-font-size-small: 10px; --fb-line-height: 1.25; --fb-file-wide-min: 64px; --fb-file-zone-min: 48px; --fb-file-zone-padding: 6px; }
|
|
509
|
+
.fb-size-sm { --fb-input-padding-y: 2px; --fb-input-padding-x: 6px; --fb-font-size: 13px; --fb-font-size-small: 11px; --fb-line-height: 1.35; --fb-file-wide-min: 80px; --fb-file-zone-min: 60px; --fb-file-zone-padding: 7px; }
|
|
510
|
+
/* .fb-size-md uses defaults \u2014 no override needed */
|
|
511
|
+
.fb-size-lg { --fb-input-padding-y: 2px; --fb-input-padding-x: 8px; --fb-font-size: 16px; --fb-font-size-small: 13px; --fb-file-wide-min: 128px; --fb-file-zone-min: 96px; --fb-file-zone-padding: 12px; }
|
|
512
|
+
.fb-size-xl { --fb-input-padding-y: 3px; --fb-input-padding-x: 8px; --fb-font-size: 18px; --fb-font-size-small: 14px; --fb-file-wide-min: 160px; --fb-file-zone-min: 120px; --fb-file-zone-padding: 14px; }
|
|
468
513
|
`;
|
|
469
514
|
doc.head.appendChild(style);
|
|
470
515
|
}
|
|
471
|
-
function applyAutoExpand(textarea) {
|
|
516
|
+
function applyAutoExpand(textarea, options = {}) {
|
|
472
517
|
textarea.style.overflow = "hidden";
|
|
473
518
|
textarea.style.resize = "none";
|
|
519
|
+
const minRows = Math.max(1, options.minRows ?? 1);
|
|
474
520
|
const lineCount = (textarea.value.match(/\n/g) || []).length + 1;
|
|
475
|
-
textarea.rows = Math.max(
|
|
521
|
+
textarea.rows = Math.max(minRows, lineCount);
|
|
476
522
|
const resize = () => {
|
|
477
523
|
if (!textarea.isConnected) return;
|
|
478
|
-
textarea.style.height = "
|
|
524
|
+
textarea.style.height = "";
|
|
479
525
|
const cs = getComputedStyle(textarea);
|
|
480
526
|
const borderY = parseFloat(cs.borderTopWidth || "0") + parseFloat(cs.borderBottomWidth || "0");
|
|
481
|
-
|
|
527
|
+
const lineHeight = parseFloat(cs.lineHeight || "0") || parseFloat(cs.fontSize || "0") * 1.5 || 20;
|
|
528
|
+
const padY = parseFloat(cs.paddingTop || "0") + parseFloat(cs.paddingBottom || "0");
|
|
529
|
+
const minHeight = lineHeight * minRows + padY + borderY;
|
|
530
|
+
if (textarea.value === "") {
|
|
531
|
+
textarea.style.height = `${minHeight}px`;
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
const contentHeight = textarea.scrollHeight + borderY;
|
|
535
|
+
textarea.style.height = `${Math.max(contentHeight, minHeight)}px`;
|
|
482
536
|
};
|
|
483
537
|
textarea.addEventListener("input", resize);
|
|
484
538
|
setTimeout(() => {
|
|
@@ -530,8 +584,8 @@ function createAddItemRow(classNameSuffix, onClick, options = {}) {
|
|
|
530
584
|
const label = options.label ?? "";
|
|
531
585
|
const showCounter = options.showCounter !== false;
|
|
532
586
|
const row = document.createElement("div");
|
|
533
|
-
row.className = "fb-add-row
|
|
534
|
-
row.style.cssText = "display:flex;align-items:stretch;width:100%;";
|
|
587
|
+
row.className = "fb-add-row";
|
|
588
|
+
row.style.cssText = "display:flex;align-items:stretch;width:100%;margin-top:4px;";
|
|
535
589
|
const button = document.createElement("button");
|
|
536
590
|
button.type = "button";
|
|
537
591
|
button.className = `add-${classNameSuffix}-btn`;
|
|
@@ -540,8 +594,8 @@ function createAddItemRow(classNameSuffix, onClick, options = {}) {
|
|
|
540
594
|
display: inline-flex;
|
|
541
595
|
align-items: center;
|
|
542
596
|
justify-content: center;
|
|
543
|
-
gap:
|
|
544
|
-
padding:
|
|
597
|
+
gap: 4px;
|
|
598
|
+
padding: 3px 10px;
|
|
545
599
|
border: 1px dashed var(--fb-primary-color);
|
|
546
600
|
border-radius: var(--fb-border-radius);
|
|
547
601
|
background: transparent;
|
|
@@ -686,12 +740,12 @@ function ensureChipStyles(doc) {
|
|
|
686
740
|
const style = doc.createElement("style");
|
|
687
741
|
style.setAttribute("data-fb-chip-styles", "");
|
|
688
742
|
style.textContent = `
|
|
689
|
-
.fb-chip-list { display: flex; flex-direction: column; gap:
|
|
743
|
+
.fb-chip-list { display: flex; flex-direction: column; gap: 2px; }
|
|
690
744
|
.fb-chip {
|
|
691
745
|
display: flex;
|
|
692
746
|
align-items: center;
|
|
693
|
-
gap:
|
|
694
|
-
padding:
|
|
747
|
+
gap: 6px;
|
|
748
|
+
padding: 3px 6px 3px 8px;
|
|
695
749
|
background: var(--fb-chip-bg, var(--fb-background-color, #fff));
|
|
696
750
|
border: 1px solid var(--fb-chip-border, var(--fb-border-color, #e2e8f0));
|
|
697
751
|
border-radius: 6px;
|
|
@@ -717,7 +771,13 @@ function ensureChipStyles(doc) {
|
|
|
717
771
|
color: var(--fb-chip-text, var(--fb-text-color, inherit));
|
|
718
772
|
font-size: var(--fb-font-size, 14px);
|
|
719
773
|
font-family: var(--fb-font-family, inherit);
|
|
720
|
-
line-height: 1.4;
|
|
774
|
+
line-height: var(--fb-line-height, 1.4);
|
|
775
|
+
/* Soft-wrap support (v0.4.0): chip-input is now a <textarea rows=1> that
|
|
776
|
+
grows vertically when content overflows the chip width. */
|
|
777
|
+
resize: none;
|
|
778
|
+
overflow: hidden;
|
|
779
|
+
word-break: break-word;
|
|
780
|
+
overflow-wrap: anywhere;
|
|
721
781
|
}
|
|
722
782
|
.fb-chip-input::placeholder { color: var(--fb-text-placeholder-color, #94a3b8); }
|
|
723
783
|
.fb-chip-input:read-only { color: var(--fb-text-secondary-color, #475569); }
|
|
@@ -802,7 +862,7 @@ function renderTextElement(element, ctx, wrapper, pathKey) {
|
|
|
802
862
|
overflow-wrap: anywhere;
|
|
803
863
|
`;
|
|
804
864
|
textInput.name = pathKey;
|
|
805
|
-
textInput.placeholder = element.placeholder
|
|
865
|
+
textInput.placeholder = element.placeholder ?? "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442";
|
|
806
866
|
textInput.value = ctx.prefill[element.key] || element.default || "";
|
|
807
867
|
textInput.readOnly = readonly;
|
|
808
868
|
applySingleLineMode(textInput);
|
|
@@ -875,8 +935,8 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
875
935
|
dot.className = "fb-chip-dot";
|
|
876
936
|
dot.setAttribute("aria-hidden", "true");
|
|
877
937
|
chip.appendChild(dot);
|
|
878
|
-
const input = document.createElement("
|
|
879
|
-
input.
|
|
938
|
+
const input = document.createElement("textarea");
|
|
939
|
+
input.rows = 1;
|
|
880
940
|
input.className = "fb-chip-input";
|
|
881
941
|
input.value = value;
|
|
882
942
|
input.placeholder = element.placeholder || t("placeholderText", state);
|
|
@@ -892,6 +952,8 @@ function renderMultipleTextElement(element, ctx, wrapper, pathKey) {
|
|
|
892
952
|
input.addEventListener("blur", handleChange);
|
|
893
953
|
input.addEventListener("input", handleChange);
|
|
894
954
|
}
|
|
955
|
+
applySingleLineMode(input);
|
|
956
|
+
applyAutoExpand(input);
|
|
895
957
|
if (!readonly) {
|
|
896
958
|
const rem = document.createElement("button");
|
|
897
959
|
rem.type = "button";
|
|
@@ -1110,13 +1172,13 @@ function renderTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1110
1172
|
const textareaInput = document.createElement("textarea");
|
|
1111
1173
|
textareaInput.className = "w-full border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none";
|
|
1112
1174
|
textareaInput.style.cssText = `
|
|
1113
|
-
padding: var(--fb-input-padding-y) var(--fb-input-padding-x)
|
|
1175
|
+
padding: var(--fb-input-padding-y) var(--fb-input-padding-x);
|
|
1114
1176
|
font-size: var(--fb-font-size);
|
|
1115
1177
|
font-family: var(--fb-font-family);
|
|
1178
|
+
line-height: var(--fb-line-height, 1.5);
|
|
1116
1179
|
`;
|
|
1117
1180
|
textareaInput.name = pathKey;
|
|
1118
|
-
textareaInput.placeholder = element.placeholder
|
|
1119
|
-
textareaInput.rows = element.rows || 4;
|
|
1181
|
+
textareaInput.placeholder = element.placeholder ?? "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442";
|
|
1120
1182
|
textareaInput.value = ctx.prefill[element.key] || element.default || "";
|
|
1121
1183
|
textareaInput.readOnly = readonly;
|
|
1122
1184
|
if (!readonly && ctx.instance) {
|
|
@@ -1127,9 +1189,7 @@ function renderTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1127
1189
|
textareaInput.addEventListener("blur", handleChange);
|
|
1128
1190
|
textareaInput.addEventListener("input", handleChange);
|
|
1129
1191
|
}
|
|
1130
|
-
|
|
1131
|
-
applyAutoExpand(textareaInput);
|
|
1132
|
-
}
|
|
1192
|
+
applyAutoExpand(textareaInput, { minRows: element.rows ?? 1 });
|
|
1133
1193
|
textareaWrapper.appendChild(textareaInput);
|
|
1134
1194
|
if (!readonly && (element.minLength != null || element.maxLength != null)) {
|
|
1135
1195
|
const counter = createCharCounter(element, textareaInput);
|
|
@@ -1148,7 +1208,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1148
1208
|
values.push(element.default || "");
|
|
1149
1209
|
}
|
|
1150
1210
|
const container = document.createElement("div");
|
|
1151
|
-
container.className = "
|
|
1211
|
+
container.className = "fb-row";
|
|
1152
1212
|
wrapper.appendChild(container);
|
|
1153
1213
|
function updateIndices() {
|
|
1154
1214
|
const items = container.querySelectorAll(".multiple-textarea-item");
|
|
@@ -1167,12 +1227,12 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1167
1227
|
const textareaInput = document.createElement("textarea");
|
|
1168
1228
|
textareaInput.className = "w-full border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none";
|
|
1169
1229
|
textareaInput.style.cssText = `
|
|
1170
|
-
padding: var(--fb-input-padding-y) var(--fb-input-padding-x)
|
|
1230
|
+
padding: var(--fb-input-padding-y) var(--fb-input-padding-x);
|
|
1171
1231
|
font-size: var(--fb-font-size);
|
|
1172
1232
|
font-family: var(--fb-font-family);
|
|
1233
|
+
line-height: var(--fb-line-height, 1.5);
|
|
1173
1234
|
`;
|
|
1174
1235
|
textareaInput.placeholder = element.placeholder || t("placeholderText", state);
|
|
1175
|
-
textareaInput.rows = element.rows || 4;
|
|
1176
1236
|
textareaInput.value = value;
|
|
1177
1237
|
textareaInput.readOnly = readonly;
|
|
1178
1238
|
if (!readonly && ctx.instance) {
|
|
@@ -1183,9 +1243,7 @@ function renderMultipleTextareaElement(element, ctx, wrapper, pathKey) {
|
|
|
1183
1243
|
textareaInput.addEventListener("blur", handleChange);
|
|
1184
1244
|
textareaInput.addEventListener("input", handleChange);
|
|
1185
1245
|
}
|
|
1186
|
-
|
|
1187
|
-
applyAutoExpand(textareaInput);
|
|
1188
|
-
}
|
|
1246
|
+
applyAutoExpand(textareaInput, { minRows: element.rows ?? 1 });
|
|
1189
1247
|
textareaContainer.appendChild(textareaInput);
|
|
1190
1248
|
if (!readonly && (element.minLength != null || element.maxLength != null)) {
|
|
1191
1249
|
const counter = createCharCounter(element, textareaInput);
|
|
@@ -1261,9 +1319,7 @@ function validateTextareaElement(element, key, context) {
|
|
|
1261
1319
|
}
|
|
1262
1320
|
function updateTextareaField(element, fieldPath, value, context) {
|
|
1263
1321
|
updateTextField(element, fieldPath, value, context);
|
|
1264
|
-
const { scopeRoot
|
|
1265
|
-
const shouldAutoExpand = element.autoExpand || isElementReadonly(element, state);
|
|
1266
|
-
if (!shouldAutoExpand) return;
|
|
1322
|
+
const { scopeRoot } = context;
|
|
1267
1323
|
if (element.multiple) {
|
|
1268
1324
|
const textareas = scopeRoot.querySelectorAll(
|
|
1269
1325
|
`textarea[name^="${fieldPath}["]`
|
|
@@ -1458,7 +1514,7 @@ function renderMultipleNumberElement(element, ctx, wrapper, pathKey) {
|
|
|
1458
1514
|
values.push(element.default || "");
|
|
1459
1515
|
}
|
|
1460
1516
|
const container = document.createElement("div");
|
|
1461
|
-
container.className = "
|
|
1517
|
+
container.className = "fb-row";
|
|
1462
1518
|
wrapper.appendChild(container);
|
|
1463
1519
|
function updateIndices() {
|
|
1464
1520
|
const items = container.querySelectorAll(".multiple-number-item");
|
|
@@ -1772,7 +1828,7 @@ function renderMultipleSelectElement(element, ctx, wrapper, pathKey) {
|
|
|
1772
1828
|
values.push(element.default || element.options?.[0]?.value || "");
|
|
1773
1829
|
}
|
|
1774
1830
|
const container = document.createElement("div");
|
|
1775
|
-
container.className = "
|
|
1831
|
+
container.className = "fb-row";
|
|
1776
1832
|
wrapper.appendChild(container);
|
|
1777
1833
|
function updateIndices() {
|
|
1778
1834
|
const items = container.querySelectorAll(".multiple-select-item");
|
|
@@ -2202,7 +2258,7 @@ function renderMultipleSwitcherElement(element, ctx, wrapper, pathKey) {
|
|
|
2202
2258
|
}
|
|
2203
2259
|
const readonly = isElementReadonly(element, state, ctx);
|
|
2204
2260
|
const container = document.createElement("div");
|
|
2205
|
-
container.className = "
|
|
2261
|
+
container.className = "fb-row";
|
|
2206
2262
|
wrapper.appendChild(container);
|
|
2207
2263
|
function updateIndices() {
|
|
2208
2264
|
const items = container.querySelectorAll(".multiple-switcher-item");
|
|
@@ -2774,7 +2830,9 @@ function ensureFileStyles() {
|
|
|
2774
2830
|
align-items: stretch;
|
|
2775
2831
|
gap: 0;
|
|
2776
2832
|
overflow: hidden;
|
|
2777
|
-
min-height
|
|
2833
|
+
/* min-height driven by --fb-file-wide-min so size-tokens (.fb-size-{xs|sm|lg|xl})
|
|
2834
|
+
can override per-field. Default 96px matches v0.4.0 compact density. */
|
|
2835
|
+
min-height: var(--fb-file-wide-min, 96px);
|
|
2778
2836
|
transition: border-color 150ms, background 150ms, box-shadow 150ms;
|
|
2779
2837
|
cursor: pointer;
|
|
2780
2838
|
}
|
|
@@ -2793,14 +2851,15 @@ function ensureFileStyles() {
|
|
|
2793
2851
|
upload + library on one row (~220 + 176), library wraps below. */
|
|
2794
2852
|
.fb-wide-tile-upload {
|
|
2795
2853
|
flex: 1 1 220px;
|
|
2796
|
-
min-height
|
|
2854
|
+
/* min-height theme-driven; default 72px matches v0.4.0 compact density. */
|
|
2855
|
+
min-height: var(--fb-file-zone-min, 72px);
|
|
2797
2856
|
display: flex;
|
|
2798
2857
|
flex-direction: column;
|
|
2799
2858
|
align-items: center;
|
|
2800
2859
|
justify-content: center;
|
|
2801
|
-
gap:
|
|
2860
|
+
gap: 4px;
|
|
2802
2861
|
color: #2563eb;
|
|
2803
|
-
padding:
|
|
2862
|
+
padding: var(--fb-file-zone-padding, 8px);
|
|
2804
2863
|
transition: background 150ms;
|
|
2805
2864
|
cursor: pointer;
|
|
2806
2865
|
background: transparent;
|
|
@@ -2820,14 +2879,16 @@ function ensureFileStyles() {
|
|
|
2820
2879
|
visual hierarchy "upload > library" in both layouts. */
|
|
2821
2880
|
.fb-wide-tile-library {
|
|
2822
2881
|
flex: 0 0 176px;
|
|
2823
|
-
min-
|
|
2882
|
+
/* Shares --fb-file-zone-min with the upload zone so size-tokens scale both
|
|
2883
|
+
uniformly. Default 72px matches v0.4.0 compact density. */
|
|
2884
|
+
min-height: var(--fb-file-zone-min, 72px);
|
|
2824
2885
|
display: flex;
|
|
2825
2886
|
flex-direction: column;
|
|
2826
2887
|
align-items: center;
|
|
2827
2888
|
justify-content: center;
|
|
2828
|
-
gap:
|
|
2889
|
+
gap: 4px;
|
|
2829
2890
|
color: #2563eb;
|
|
2830
|
-
padding:
|
|
2891
|
+
padding: var(--fb-file-zone-padding, 8px);
|
|
2831
2892
|
transition: background 150ms;
|
|
2832
2893
|
cursor: pointer;
|
|
2833
2894
|
background: transparent;
|
|
@@ -4088,7 +4149,9 @@ function downloadBlob(blob, fileName) {
|
|
|
4088
4149
|
URL.revokeObjectURL(blobUrl);
|
|
4089
4150
|
}, 100);
|
|
4090
4151
|
} catch (error) {
|
|
4091
|
-
throw new Error(`Blob download failed: ${error.message}
|
|
4152
|
+
throw new Error(`Blob download failed: ${error.message}`, {
|
|
4153
|
+
cause: error
|
|
4154
|
+
});
|
|
4092
4155
|
}
|
|
4093
4156
|
}
|
|
4094
4157
|
|
|
@@ -5028,7 +5091,7 @@ function renderResourcePills(opts) {
|
|
|
5028
5091
|
function renderFileElementEdit(element, ctx, wrapper, pathKey) {
|
|
5029
5092
|
const state = ctx.state;
|
|
5030
5093
|
const fileWrapper = document.createElement("div");
|
|
5031
|
-
fileWrapper.className = "
|
|
5094
|
+
fileWrapper.className = "fb-row";
|
|
5032
5095
|
fileWrapper.dataset.filesWrapper = pathKey;
|
|
5033
5096
|
const picker = document.createElement("input");
|
|
5034
5097
|
picker.type = "file";
|
|
@@ -5176,7 +5239,7 @@ function buildAcceptAttribute(accept) {
|
|
|
5176
5239
|
function setupMultiFileEditMode(element, ctx, wrapper, pathKey, maxFiles) {
|
|
5177
5240
|
const state = ctx.state;
|
|
5178
5241
|
const filesWrapper = document.createElement("div");
|
|
5179
|
-
filesWrapper.className = "
|
|
5242
|
+
filesWrapper.className = "fb-row";
|
|
5180
5243
|
filesWrapper.dataset.filesWrapper = pathKey;
|
|
5181
5244
|
const filesPicker = document.createElement("input");
|
|
5182
5245
|
filesPicker.type = "file";
|
|
@@ -5848,7 +5911,7 @@ function renderMultipleColourElement(element, ctx, wrapper, pathKey) {
|
|
|
5848
5911
|
values.push(element.default || "#000000");
|
|
5849
5912
|
}
|
|
5850
5913
|
const container = document.createElement("div");
|
|
5851
|
-
container.className = "
|
|
5914
|
+
container.className = "fb-row";
|
|
5852
5915
|
wrapper.appendChild(container);
|
|
5853
5916
|
function updateIndices() {
|
|
5854
5917
|
const items = container.querySelectorAll(".multiple-colour-item");
|
|
@@ -6704,7 +6767,7 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
|
|
|
6704
6767
|
const itemsWrap = document.createElement("div");
|
|
6705
6768
|
const columns = element.columns || 1;
|
|
6706
6769
|
if (columns === 1) {
|
|
6707
|
-
itemsWrap.className = "
|
|
6770
|
+
itemsWrap.className = "fb-row";
|
|
6708
6771
|
} else {
|
|
6709
6772
|
itemsWrap.className = `grid grid-cols-${columns} gap-2`;
|
|
6710
6773
|
}
|
|
@@ -6741,12 +6804,9 @@ function renderSingleContainerElement(element, ctx, wrapper, pathKey) {
|
|
|
6741
6804
|
containerWrap.appendChild(itemsWrap);
|
|
6742
6805
|
wrapper.appendChild(containerWrap);
|
|
6743
6806
|
}
|
|
6744
|
-
function getChildWrapperClass(
|
|
6745
|
-
if (isSlides) {
|
|
6746
|
-
return "space-y-2";
|
|
6747
|
-
}
|
|
6807
|
+
function getChildWrapperClass(columns) {
|
|
6748
6808
|
const cols = columns || 1;
|
|
6749
|
-
return cols === 1 ? "
|
|
6809
|
+
return cols === 1 ? "fb-row" : `grid grid-cols-${cols} gap-2`;
|
|
6750
6810
|
}
|
|
6751
6811
|
function mountRemoveButton(item, onRemove, state) {
|
|
6752
6812
|
const rem = document.createElement("button");
|
|
@@ -6789,11 +6849,8 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
6789
6849
|
const isSlides = element.displayMode === "slides";
|
|
6790
6850
|
if (isSlides) {
|
|
6791
6851
|
itemsWrap.className = "fb-container-slides";
|
|
6792
|
-
const slideCols = element.columns;
|
|
6793
|
-
const gridTemplateColumns = typeof slideCols === "number" && slideCols > 0 ? `repeat(${slideCols}, 1fr)` : "repeat(auto-fit, minmax(280px, 1fr))";
|
|
6794
|
-
itemsWrap.style.cssText = `display:grid;grid-template-columns:${gridTemplateColumns};gap:var(--fb-slides-gap, 14px);align-items:start;`;
|
|
6795
6852
|
} else {
|
|
6796
|
-
itemsWrap.className = "
|
|
6853
|
+
itemsWrap.className = "fb-row";
|
|
6797
6854
|
}
|
|
6798
6855
|
if (!containerIsReadonly) {
|
|
6799
6856
|
const hintsElement = createPrefillHints(element, element.key);
|
|
@@ -6827,7 +6884,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
6827
6884
|
item.setAttribute("data-fb-slide-card", "");
|
|
6828
6885
|
}
|
|
6829
6886
|
const childWrapper = document.createElement("div");
|
|
6830
|
-
childWrapper.className = getChildWrapperClass(
|
|
6887
|
+
childWrapper.className = getChildWrapperClass(
|
|
6888
|
+
isSlides ? void 0 : element.columns
|
|
6889
|
+
);
|
|
6831
6890
|
element.elements.forEach((child) => {
|
|
6832
6891
|
if (child.type !== "markdown" && (child.hidden || child.type === "hidden")) {
|
|
6833
6892
|
childWrapper.appendChild(
|
|
@@ -6893,16 +6952,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
6893
6952
|
item.setAttribute("data-fb-slide-card", "");
|
|
6894
6953
|
}
|
|
6895
6954
|
const childWrapper = document.createElement("div");
|
|
6896
|
-
|
|
6897
|
-
|
|
6898
|
-
|
|
6899
|
-
const columns = element.columns || 1;
|
|
6900
|
-
if (columns === 1) {
|
|
6901
|
-
childWrapper.className = "space-y-2";
|
|
6902
|
-
} else {
|
|
6903
|
-
childWrapper.className = `grid grid-cols-${columns} gap-2`;
|
|
6904
|
-
}
|
|
6905
|
-
}
|
|
6955
|
+
childWrapper.className = getChildWrapperClass(
|
|
6956
|
+
isSlides ? void 0 : element.columns
|
|
6957
|
+
);
|
|
6906
6958
|
element.elements.forEach((child) => {
|
|
6907
6959
|
if (child.type !== "markdown" && (child.hidden || child.type === "hidden")) {
|
|
6908
6960
|
const prefillVal = prefillObj?.[child.key] ?? ("default" in child ? child.default : null) ?? null;
|
|
@@ -6940,16 +6992,9 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
6940
6992
|
item.setAttribute("data-fb-slide-card", "");
|
|
6941
6993
|
}
|
|
6942
6994
|
const childWrapper = document.createElement("div");
|
|
6943
|
-
|
|
6944
|
-
|
|
6945
|
-
|
|
6946
|
-
const columns = element.columns || 1;
|
|
6947
|
-
if (columns === 1) {
|
|
6948
|
-
childWrapper.className = "space-y-2";
|
|
6949
|
-
} else {
|
|
6950
|
-
childWrapper.className = `grid grid-cols-${columns} gap-2`;
|
|
6951
|
-
}
|
|
6952
|
-
}
|
|
6995
|
+
childWrapper.className = getChildWrapperClass(
|
|
6996
|
+
isSlides ? void 0 : element.columns
|
|
6997
|
+
);
|
|
6953
6998
|
element.elements.forEach((child) => {
|
|
6954
6999
|
if (child.type !== "markdown" && (child.hidden || child.type === "hidden")) {
|
|
6955
7000
|
childWrapper.appendChild(
|
|
@@ -6978,7 +7023,6 @@ function renderMultipleContainerElement(element, ctx, wrapper, _pathKey) {
|
|
|
6978
7023
|
containerWrap.appendChild(itemsWrap);
|
|
6979
7024
|
if (!containerIsReadonly) {
|
|
6980
7025
|
if (isSlides) {
|
|
6981
|
-
itemsWrap.style.alignItems = "stretch";
|
|
6982
7026
|
const handle = createSlideAddTile(handleAddItem, {
|
|
6983
7027
|
label: element.addLabel
|
|
6984
7028
|
});
|
|
@@ -8499,7 +8543,7 @@ function validateTableElement(element, key, context) {
|
|
|
8499
8543
|
if (!hiddenInput) {
|
|
8500
8544
|
return { value: null, errors };
|
|
8501
8545
|
}
|
|
8502
|
-
let value
|
|
8546
|
+
let value;
|
|
8503
8547
|
try {
|
|
8504
8548
|
value = JSON.parse(hiddenInput.value);
|
|
8505
8549
|
} catch {
|
|
@@ -9824,7 +9868,7 @@ function validateRichInputElement(element, key, context) {
|
|
|
9824
9868
|
if (!hiddenInput) {
|
|
9825
9869
|
return { value: null, errors };
|
|
9826
9870
|
}
|
|
9827
|
-
let rawValue
|
|
9871
|
+
let rawValue;
|
|
9828
9872
|
try {
|
|
9829
9873
|
const parsed = JSON.parse(hiddenInput.value);
|
|
9830
9874
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
@@ -10463,7 +10507,8 @@ function setupEnableIfListeners(wrapper, element, ctx) {
|
|
|
10463
10507
|
}
|
|
10464
10508
|
function createFieldLabel(element) {
|
|
10465
10509
|
const title = document.createElement("label");
|
|
10466
|
-
title.className = "
|
|
10510
|
+
title.className = "font-medium text-gray-900";
|
|
10511
|
+
title.style.cssText = "font-size: var(--fb-label-font-size, 0.75rem); line-height: var(--fb-label-line-height, 1.2);";
|
|
10467
10512
|
title.textContent = element.label ?? element.key ?? "";
|
|
10468
10513
|
if (element.required) {
|
|
10469
10514
|
const req = document.createElement("span");
|
|
@@ -10494,7 +10539,8 @@ function createInfoButton(element) {
|
|
|
10494
10539
|
}
|
|
10495
10540
|
function createLabelContainer(element) {
|
|
10496
10541
|
const label = document.createElement("div");
|
|
10497
|
-
label.className = "flex items-center
|
|
10542
|
+
label.className = "flex items-center";
|
|
10543
|
+
label.style.marginBottom = "var(--fb-label-margin-bottom, 2px)";
|
|
10498
10544
|
label.dataset.fbLabelRow = "";
|
|
10499
10545
|
const title = createFieldLabel(element);
|
|
10500
10546
|
label.appendChild(title);
|
|
@@ -10605,11 +10651,12 @@ function renderElement2(element, ctx) {
|
|
|
10605
10651
|
}
|
|
10606
10652
|
const initiallyDisabled2 = shouldDisableElement(element, ctx);
|
|
10607
10653
|
const outerWrapper = document.createElement("div");
|
|
10608
|
-
outerWrapper.className =
|
|
10654
|
+
outerWrapper.className = `fb-field-wrapper fb-markdown-wrapper fb-size-${element.size || "md"}`;
|
|
10609
10655
|
outerWrapper.setAttribute(
|
|
10610
10656
|
"data-field-key",
|
|
10611
10657
|
getElementLookupKey(element, ctx.state)
|
|
10612
10658
|
);
|
|
10659
|
+
outerWrapper.setAttribute("data-fb-width", element.width || "full");
|
|
10613
10660
|
renderMarkdown(element, ctx, outerWrapper);
|
|
10614
10661
|
if (initiallyDisabled2) {
|
|
10615
10662
|
outerWrapper.style.display = "none";
|
|
@@ -10621,8 +10668,9 @@ function renderElement2(element, ctx) {
|
|
|
10621
10668
|
}
|
|
10622
10669
|
const initiallyDisabled = shouldDisableElement(element, ctx);
|
|
10623
10670
|
const wrapper = document.createElement("div");
|
|
10624
|
-
wrapper.className =
|
|
10671
|
+
wrapper.className = `fb-field-wrapper fb-size-${element.size || "md"}`;
|
|
10625
10672
|
wrapper.setAttribute("data-field-key", element.key);
|
|
10673
|
+
wrapper.setAttribute("data-fb-width", element.width || "full");
|
|
10626
10674
|
const ops = getComponentOperations(element.type);
|
|
10627
10675
|
if (!ops?.ownsLabel) {
|
|
10628
10676
|
const label = createLabelContainer(element);
|
|
@@ -10944,9 +10992,9 @@ var defaultTheme = {
|
|
|
10944
10992
|
// blue-500
|
|
10945
10993
|
// Spacing
|
|
10946
10994
|
inputPaddingX: "0.5rem",
|
|
10947
|
-
// 8px (compact density
|
|
10948
|
-
inputPaddingY: "0.
|
|
10949
|
-
//
|
|
10995
|
+
// 8px (compact density v3 — v0.4.0)
|
|
10996
|
+
inputPaddingY: "0.125rem",
|
|
10997
|
+
// 2px (compact density v3 — v0.4.0)
|
|
10950
10998
|
borderRadius: "0.5rem",
|
|
10951
10999
|
// rounded-lg (8px)
|
|
10952
11000
|
borderRadiusSmall: "0.375rem",
|
|
@@ -10984,13 +11032,20 @@ var defaultTheme = {
|
|
|
10984
11032
|
slideCardRadius: "0.5rem",
|
|
10985
11033
|
// matches borderRadius
|
|
10986
11034
|
slideCardMinHeight: "0",
|
|
10987
|
-
slideCardPadding: "
|
|
11035
|
+
slideCardPadding: "8px",
|
|
10988
11036
|
// Section-label defaults — same look as the regular field label. Themes
|
|
10989
11037
|
// that want the "ПРЕИМУЩЕСТВА" caps style override these three vars.
|
|
10990
11038
|
labelSectionFontSize: "0.875rem",
|
|
10991
11039
|
// matches fontSize
|
|
10992
11040
|
labelSectionLetterSpacing: "normal",
|
|
10993
|
-
labelSectionTextTransform: "none"
|
|
11041
|
+
labelSectionTextTransform: "none",
|
|
11042
|
+
// Per-field label defaults — compact density: 12px @ 1.2 line-height with
|
|
11043
|
+
// a 2px gap to the input. Themes that prefer roomier labels (Picaz, klein)
|
|
11044
|
+
// can bump these via their override block.
|
|
11045
|
+
labelFontSize: "0.75rem",
|
|
11046
|
+
// 12px
|
|
11047
|
+
labelLineHeight: "1.2",
|
|
11048
|
+
labelMarginBottom: "2px"
|
|
10994
11049
|
};
|
|
10995
11050
|
function generateCSSVariables(theme) {
|
|
10996
11051
|
const mergedTheme = { ...defaultTheme, ...theme };
|
|
@@ -11536,7 +11591,7 @@ var FormBuilderInstance = class {
|
|
|
11536
11591
|
root.setAttribute("data-fb-root", "true");
|
|
11537
11592
|
injectThemeVariables(root, this.state.config.theme);
|
|
11538
11593
|
const rootContainer = document.createElement("div");
|
|
11539
|
-
rootContainer.className = "
|
|
11594
|
+
rootContainer.className = "fb-row";
|
|
11540
11595
|
if (schema.prefillHints && !this.state.config.readonly) {
|
|
11541
11596
|
const hintsContainer = this.createRootPrefillHints(schema.prefillHints);
|
|
11542
11597
|
rootContainer.appendChild(hintsContainer);
|
|
@@ -11544,7 +11599,7 @@ var FormBuilderInstance = class {
|
|
|
11544
11599
|
const fieldsWrapper = document.createElement("div");
|
|
11545
11600
|
const columns = schema.columns || 1;
|
|
11546
11601
|
if (columns === 1) {
|
|
11547
|
-
fieldsWrapper.className = "
|
|
11602
|
+
fieldsWrapper.className = "fb-row";
|
|
11548
11603
|
} else {
|
|
11549
11604
|
fieldsWrapper.className = `grid grid-cols-${columns} gap-2`;
|
|
11550
11605
|
}
|