form-page-builder 1.0.0 → 2.0.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/README.md +84 -2
- package/dist/index.cjs +344 -178
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -2
- package/dist/index.d.ts +38 -2
- package/dist/index.js +364 -200
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/FormBuilder.tsx
|
|
4
4
|
import { forwardRef, useImperativeHandle, useState as useState8 } from "react";
|
|
5
|
-
import { Loader2 as Loader22 } from "lucide-react";
|
|
5
|
+
import { Loader2 as Loader22, Menu, SlidersHorizontal } from "lucide-react";
|
|
6
6
|
|
|
7
7
|
// src/i18n/languages.ts
|
|
8
8
|
var DEFAULT_LANGUAGES = [
|
|
@@ -333,6 +333,22 @@ function withLang(val, lang, value) {
|
|
|
333
333
|
return { ...base, [lang]: value };
|
|
334
334
|
}
|
|
335
335
|
|
|
336
|
+
// src/lib/color.ts
|
|
337
|
+
function mixHex(a, b, t2) {
|
|
338
|
+
const pa = parseHex(a);
|
|
339
|
+
const pb = parseHex(b);
|
|
340
|
+
if (!pa || !pb) return a;
|
|
341
|
+
const mix = (x, y) => Math.round(x + (y - x) * t2);
|
|
342
|
+
const toHex = (n) => n.toString(16).padStart(2, "0");
|
|
343
|
+
return `#${toHex(mix(pa[0], pb[0]))}${toHex(mix(pa[1], pb[1]))}${toHex(mix(pa[2], pb[2]))}`;
|
|
344
|
+
}
|
|
345
|
+
function parseHex(hex) {
|
|
346
|
+
const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());
|
|
347
|
+
if (!m) return null;
|
|
348
|
+
const n = parseInt(m[1], 16);
|
|
349
|
+
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
350
|
+
}
|
|
351
|
+
|
|
336
352
|
// src/lib/storage/compress.ts
|
|
337
353
|
import { compressToUTF16, decompressFromUTF16 } from "lz-string";
|
|
338
354
|
function compress(raw) {
|
|
@@ -599,6 +615,37 @@ function migrateDocument(raw) {
|
|
|
599
615
|
return { title, themeOverrides, sections };
|
|
600
616
|
}
|
|
601
617
|
|
|
618
|
+
// src/lib/features.ts
|
|
619
|
+
var DEFAULT_FEATURES = {
|
|
620
|
+
naming: true,
|
|
621
|
+
templates: true,
|
|
622
|
+
newForm: true,
|
|
623
|
+
autosave: true,
|
|
624
|
+
jsonView: true,
|
|
625
|
+
previewMode: true,
|
|
626
|
+
languageSwitcher: true,
|
|
627
|
+
design: false,
|
|
628
|
+
blockStyling: true,
|
|
629
|
+
contentBlocks: true,
|
|
630
|
+
fieldTypes: true,
|
|
631
|
+
sections: true,
|
|
632
|
+
dragReorder: true
|
|
633
|
+
};
|
|
634
|
+
function resolveFeatures(features) {
|
|
635
|
+
return {
|
|
636
|
+
...DEFAULT_FEATURES,
|
|
637
|
+
...features,
|
|
638
|
+
contentBlocks: Array.isArray(features?.contentBlocks) ? new Set(features.contentBlocks) : features?.contentBlocks ?? DEFAULT_FEATURES.contentBlocks,
|
|
639
|
+
fieldTypes: Array.isArray(features?.fieldTypes) ? new Set(features.fieldTypes) : features?.fieldTypes ?? DEFAULT_FEATURES.fieldTypes
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
function isContentBlockEnabled(features, type) {
|
|
643
|
+
return features.contentBlocks === true || features.contentBlocks instanceof Set && features.contentBlocks.has(type);
|
|
644
|
+
}
|
|
645
|
+
function isFieldTypeEnabled(features, type) {
|
|
646
|
+
return features.fieldTypes === true || features.fieldTypes instanceof Set && features.fieldTypes.has(type);
|
|
647
|
+
}
|
|
648
|
+
|
|
602
649
|
// src/hooks/useTheme.ts
|
|
603
650
|
import { useState } from "react";
|
|
604
651
|
|
|
@@ -833,6 +880,7 @@ var formKey = (id) => `form-page-builder:saved:${id}`;
|
|
|
833
880
|
var MAX_TEMPLATES = 5;
|
|
834
881
|
function usePersistence({
|
|
835
882
|
storage,
|
|
883
|
+
autosave,
|
|
836
884
|
language,
|
|
837
885
|
chrome,
|
|
838
886
|
document,
|
|
@@ -894,7 +942,7 @@ function usePersistence({
|
|
|
894
942
|
refreshLibrary();
|
|
895
943
|
}, []);
|
|
896
944
|
useEffect(() => {
|
|
897
|
-
if (!hasLoadedOnce.current) return;
|
|
945
|
+
if (!hasLoadedOnce.current || !autosave) return;
|
|
898
946
|
setSaveState("saving");
|
|
899
947
|
if (autosaveTimer.current) clearTimeout(autosaveTimer.current);
|
|
900
948
|
autosaveTimer.current = setTimeout(async () => {
|
|
@@ -1033,15 +1081,15 @@ var styles = {
|
|
|
1033
1081
|
titleInput: { border: "none", outline: "none", fontSize: 14, fontWeight: 600, background: "transparent", color: "var(--fb-ink)", padding: "4px 6px", borderRadius: 6, minWidth: 160 },
|
|
1034
1082
|
toolbarRight: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" },
|
|
1035
1083
|
toolbarDivider: { width: 1, height: 20, background: "var(--fb-border)", margin: "0 4px" },
|
|
1036
|
-
tabBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid transparent", background: "transparent", color: "
|
|
1084
|
+
tabBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid transparent", background: "transparent", color: "var(--fb-muted)", fontSize: 13, fontWeight: 500 },
|
|
1037
1085
|
tabBtnActive: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid var(--fb-border)", background: "var(--fb-primary-soft)", color: "var(--fb-primary)", fontSize: 13, fontWeight: 600 },
|
|
1038
|
-
ghostBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid var(--fb-border)", background: "var(--fb-surface)", color: "
|
|
1086
|
+
ghostBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid var(--fb-border)", background: "var(--fb-surface)", color: "var(--fb-ink)", fontSize: 13, fontWeight: 500 },
|
|
1039
1087
|
primaryBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 13px", borderRadius: 7, border: "1px solid var(--fb-primary)", background: "var(--fb-primary)", color: "#fff", fontSize: 13, fontWeight: 600 },
|
|
1040
1088
|
saveStatus: { display: "flex", alignItems: "center", gap: 5, fontSize: 12, color: "var(--fb-muted)", minWidth: 60 },
|
|
1041
1089
|
countBadge: { fontSize: 10.5, fontWeight: 700, background: "var(--fb-primary-soft)", color: "var(--fb-primary)", borderRadius: 9, padding: "1px 6px", marginLeft: 2 },
|
|
1042
1090
|
loadingScreen: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
|
|
1043
1091
|
libraryBody: { padding: "var(--fb-space-panel)", overflowY: "auto", display: "flex", flexDirection: "column", gap: 4 },
|
|
1044
|
-
libraryRow: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10, padding: "10px 8px", borderRadius: 8, border: "1px solid
|
|
1092
|
+
libraryRow: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10, padding: "10px 8px", borderRadius: 8, border: "1px solid var(--fb-border)" },
|
|
1045
1093
|
libraryRowTitle: { fontSize: 13.5, fontWeight: 600, color: "var(--fb-ink)", display: "flex", alignItems: "center", gap: 8, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
|
|
1046
1094
|
libraryRowMeta: { fontSize: 11.5, color: "var(--fb-muted)", marginTop: 2 },
|
|
1047
1095
|
currentBadge: { fontSize: 10, fontWeight: 700, color: "var(--fb-primary)", background: "var(--fb-primary-soft)", padding: "2px 6px", borderRadius: 5, flexShrink: 0 },
|
|
@@ -1050,7 +1098,7 @@ var styles = {
|
|
|
1050
1098
|
panelHeading: { fontSize: 11, fontWeight: 700, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--fb-muted)", marginBottom: 10 },
|
|
1051
1099
|
activeSectionHint: { fontSize: 11.5, color: "var(--fb-muted)", marginBottom: 14, lineHeight: 1.4 },
|
|
1052
1100
|
paletteList: { display: "flex", flexDirection: "column", gap: 4 },
|
|
1053
|
-
paletteItem: { display: "flex", alignItems: "center", gap: 9, padding: "8px 9px", borderRadius: 8, border: "1px solid transparent", background: "transparent", fontSize: 13, color: "
|
|
1101
|
+
paletteItem: { display: "flex", alignItems: "center", gap: 9, padding: "8px 9px", borderRadius: 8, border: "1px solid transparent", background: "transparent", fontSize: 13, color: "var(--fb-ink)", textAlign: "left" },
|
|
1054
1102
|
canvas: { flex: 1, padding: "var(--fb-space-canvas)", overflowY: "auto", background: "var(--fb-canvas)" },
|
|
1055
1103
|
sectionBlock: { borderRadius: 12, padding: "var(--fb-space-panel)", marginBottom: "var(--fb-space-section)", transition: "border-color 0.12s" },
|
|
1056
1104
|
sectionHeader: { display: "flex", alignItems: "center", gap: 8, marginBottom: 12, flexWrap: "wrap" },
|
|
@@ -1060,7 +1108,7 @@ var styles = {
|
|
|
1060
1108
|
sectionHeaderActions: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap", marginLeft: "auto" },
|
|
1061
1109
|
sectionEmpty: { fontSize: 12.5, color: "var(--fb-muted)", padding: "18px 4px", textAlign: "center", border: "1px dashed var(--fb-border)", borderRadius: 8 },
|
|
1062
1110
|
resetLinkBtn: { display: "flex", alignItems: "center", gap: 3, fontSize: 11, color: "var(--fb-muted)", background: "transparent", border: "none", padding: "2px 4px" },
|
|
1063
|
-
addSectionBtn: { display: "flex", alignItems: "center", justifyContent: "center", gap: 6, width: "100%", padding: "10px", borderRadius: 10, border: "1px dashed
|
|
1111
|
+
addSectionBtn: { display: "flex", alignItems: "center", justifyContent: "center", gap: 6, width: "100%", padding: "10px", borderRadius: 10, border: "1px dashed var(--fb-border)", background: "transparent", color: "var(--fb-primary)", fontSize: 13, fontWeight: 600 },
|
|
1064
1112
|
swatchRow: { display: "flex", alignItems: "center", gap: 5, flexWrap: "wrap" },
|
|
1065
1113
|
swatchBtn: { width: 20, height: 20, borderRadius: "50%", border: "1px solid var(--fb-border)", padding: 0 },
|
|
1066
1114
|
swatchBtnActive: { border: "2px solid var(--fb-primary)" },
|
|
@@ -1069,56 +1117,56 @@ var styles = {
|
|
|
1069
1117
|
ticket: { display: "flex", alignItems: "stretch", background: "var(--fb-surface)", border: "1px solid var(--fb-border)", borderRadius: 10, position: "relative", transition: "border-color 0.12s, box-shadow 0.12s" },
|
|
1070
1118
|
ticketSelected: { borderColor: "var(--fb-primary)", boxShadow: "0 0 0 3px var(--fb-primary-soft)" },
|
|
1071
1119
|
ticketDragOver: { borderColor: "var(--fb-muted)" },
|
|
1072
|
-
ticketIndex: { fontFamily: "'JetBrains Mono', monospace", fontSize: 13, fontWeight: 700, color: "
|
|
1120
|
+
ticketIndex: { fontFamily: "'JetBrains Mono', monospace", fontSize: 13, fontWeight: 700, color: "var(--fb-border)", width: 34, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 },
|
|
1073
1121
|
ticketPerforation: { width: 0, borderLeft: "1px dashed var(--fb-border)" },
|
|
1074
1122
|
ticketBody: { flex: 1, padding: "10px var(--fb-space-ticket)", minWidth: 0 },
|
|
1075
1123
|
ticketTop: { display: "flex", alignItems: "center", gap: 7, marginBottom: 4 },
|
|
1076
1124
|
typeBadge: { fontSize: 10.5, fontFamily: "'JetBrains Mono', monospace", color: "var(--fb-muted)" },
|
|
1077
|
-
requiredBadge: { fontSize: 10, fontWeight: 700, color: "
|
|
1125
|
+
requiredBadge: { fontSize: 10, fontWeight: 700, color: "var(--fb-danger)", background: "var(--fb-danger-soft)", padding: "2px 6px", borderRadius: 5, letterSpacing: "0.02em", marginLeft: "auto" },
|
|
1078
1126
|
chipRow: { display: "flex", gap: 5, marginBottom: 7, flexWrap: "wrap" },
|
|
1079
1127
|
miniBadge: { fontSize: 10, fontWeight: 600, color: "var(--fb-primary)", background: "var(--fb-primary-soft)", padding: "2px 6px", borderRadius: 5, letterSpacing: "0.02em" },
|
|
1080
|
-
langToggleTrack: { position: "relative", display: "flex", gap: 3, background: "
|
|
1128
|
+
langToggleTrack: { position: "relative", display: "flex", gap: 3, background: "var(--fb-surface-2)", padding: 3, borderRadius: 20 },
|
|
1081
1129
|
langToggleThumb: { position: "absolute", top: 3, left: 3, bottom: 3, background: "var(--fb-primary)", borderRadius: 17, transition: "transform 0.18s ease" },
|
|
1082
|
-
langToggleBtn: { position: "relative", zIndex: 1, padding: "5px 12px", borderRadius: 17, border: "none", background: "transparent", color: "
|
|
1130
|
+
langToggleBtn: { position: "relative", zIndex: 1, padding: "5px 12px", borderRadius: 17, border: "none", background: "transparent", color: "var(--fb-muted)", fontSize: 12.5, fontWeight: 600, whiteSpace: "nowrap" },
|
|
1083
1131
|
langToggleBtnActive: { position: "relative", zIndex: 1, padding: "5px 12px", borderRadius: 17, border: "none", background: "transparent", color: "#fff", fontSize: 12.5, fontWeight: 600, whiteSpace: "nowrap" },
|
|
1084
|
-
segmented: { display: "flex", gap: 3, background: "
|
|
1085
|
-
segmentedBtn: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 5, padding: "6px 8px", borderRadius: 6, border: "none", background: "transparent", color: "
|
|
1086
|
-
segmentedBtnActive: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 5, padding: "6px 8px", borderRadius: 6, border: "none", background: "
|
|
1132
|
+
segmented: { display: "flex", gap: 3, background: "var(--fb-surface-2)", padding: 3, borderRadius: 8, marginBottom: 4 },
|
|
1133
|
+
segmentedBtn: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 5, padding: "6px 8px", borderRadius: 6, border: "none", background: "transparent", color: "var(--fb-muted)", fontSize: 12.5, fontWeight: 500 },
|
|
1134
|
+
segmentedBtnActive: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 5, padding: "6px 8px", borderRadius: 6, border: "none", background: "var(--fb-surface)", color: "var(--fb-ink)", fontSize: 12.5, fontWeight: 600, boxShadow: "0 1px 2px rgba(0,0,0,0.08)" },
|
|
1087
1135
|
iconGrid: { display: "grid", gridTemplateColumns: "repeat(6, 1fr)", gap: 5, marginTop: 6 },
|
|
1088
|
-
iconGridBtn: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-border)", background: "
|
|
1136
|
+
iconGridBtn: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-border)", background: "var(--fb-surface)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
|
|
1089
1137
|
iconGridBtnActive: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-primary)", background: "var(--fb-primary-soft)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-primary)" },
|
|
1090
1138
|
styleToggleRow: { display: "flex", gap: 5, marginBottom: 4 },
|
|
1091
|
-
styleToggle: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-border)", background: "
|
|
1139
|
+
styleToggle: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-border)", background: "var(--fb-surface)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
|
|
1092
1140
|
styleToggleActive: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-primary)", background: "var(--fb-primary-soft)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-primary)" },
|
|
1093
|
-
previewInput: { border: "1px solid
|
|
1094
|
-
previewRadio: { display: "flex", alignItems: "center", gap: 6, fontSize: 13, color: "
|
|
1095
|
-
ticketActions: { display: "flex", flexDirection: "column", gap: 3, padding: 8, borderLeft: "1px solid
|
|
1096
|
-
iconBtn: { width: 24, height: 24, borderRadius: 6, border: "1px solid
|
|
1141
|
+
previewInput: { border: "1px solid var(--fb-border)", borderRadius: 7, padding: "7px 10px", fontSize: 13, color: "var(--fb-muted)", background: "var(--fb-surface-2)", display: "flex", alignItems: "center", justifyContent: "space-between" },
|
|
1142
|
+
previewRadio: { display: "flex", alignItems: "center", gap: 6, fontSize: 13, color: "var(--fb-ink)" },
|
|
1143
|
+
ticketActions: { display: "flex", flexDirection: "column", gap: 3, padding: 8, borderLeft: "1px solid var(--fb-border)" },
|
|
1144
|
+
iconBtn: { width: 24, height: 24, borderRadius: 6, border: "1px solid var(--fb-border)", background: "var(--fb-surface)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
|
|
1097
1145
|
iconBtnDanger: { color: "var(--fb-danger)" },
|
|
1098
1146
|
inspector: { width: 270, borderLeft: "1px solid var(--fb-border)", background: "var(--fb-surface)", padding: "var(--fb-space-panel)", overflowY: "auto" },
|
|
1099
1147
|
inspectorEmpty: { fontSize: 13, color: "var(--fb-muted)", lineHeight: 1.5, marginTop: 6 },
|
|
1100
1148
|
inspectorBody: { display: "flex", flexDirection: "column", gap: 4 },
|
|
1101
1149
|
helperText: { fontSize: 11, color: "var(--fb-muted)", lineHeight: 1.4, margin: "2px 0 4px" },
|
|
1102
|
-
propLabel: { fontSize: 11.5, fontWeight: 600, color: "
|
|
1103
|
-
propInput: { border: "1px solid var(--fb-border)", borderRadius: 7, padding: "7px 9px", fontSize: 13, color: "var(--fb-ink)", outline: "none", width: "100%", boxSizing: "border-box" },
|
|
1150
|
+
propLabel: { fontSize: 11.5, fontWeight: 600, color: "var(--fb-muted)", marginTop: 12, marginBottom: 5 },
|
|
1151
|
+
propInput: { border: "1px solid var(--fb-border)", borderRadius: 7, padding: "7px 9px", fontSize: 13, color: "var(--fb-ink)", background: "var(--fb-surface)", outline: "none", width: "100%", boxSizing: "border-box" },
|
|
1104
1152
|
optionList: { display: "flex", flexDirection: "column", gap: 6 },
|
|
1105
1153
|
optionRow: { display: "flex", gap: 6, alignItems: "center" },
|
|
1106
|
-
optionInput: { flex: 1, border: "1px solid var(--fb-border)", borderRadius: 6, padding: "6px 8px", fontSize: 12.5, outline: "none", minWidth: 0, boxSizing: "border-box" },
|
|
1107
|
-
addOptionBtn: { display: "flex", alignItems: "center", gap: 5, fontSize: 12.5, color: "var(--fb-primary)", background: "transparent", border: "1px dashed
|
|
1154
|
+
optionInput: { flex: 1, border: "1px solid var(--fb-border)", borderRadius: 6, padding: "6px 8px", fontSize: 12.5, color: "var(--fb-ink)", background: "var(--fb-surface)", outline: "none", minWidth: 0, boxSizing: "border-box" },
|
|
1155
|
+
addOptionBtn: { display: "flex", alignItems: "center", gap: 5, fontSize: 12.5, color: "var(--fb-primary)", background: "transparent", border: "1px dashed var(--fb-border)", borderRadius: 7, padding: "6px 8px", justifyContent: "center", marginTop: 2 },
|
|
1108
1156
|
toggleRow: { display: "flex", alignItems: "center", gap: 8, background: "transparent", border: "none", padding: "8px 0" },
|
|
1109
1157
|
toggleTrack: { width: 30, height: 17, borderRadius: 20, position: "relative", transition: "background 0.15s", display: "inline-block" },
|
|
1110
1158
|
toggleThumb: { position: "absolute", top: 2, left: 2, width: 13, height: 13, borderRadius: "50%", background: "#fff", transition: "transform 0.15s", boxShadow: "0 1px 2px rgba(0,0,0,0.2)" },
|
|
1111
1159
|
inspectorDivider: { height: 1, background: "var(--fb-border)", margin: "14px 0 10px" },
|
|
1112
1160
|
deleteFieldBtn: { display: "flex", alignItems: "center", gap: 6, fontSize: 12.5, color: "var(--fb-danger)", background: "var(--fb-danger-soft)", border: "none", borderRadius: 7, padding: "8px 10px", justifyContent: "center" },
|
|
1113
|
-
modalOverlay: { position: "fixed", inset: 0, background: "rgba(20,22,28,0.45)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 50 },
|
|
1114
|
-
modal: { background: "
|
|
1161
|
+
modalOverlay: { position: "fixed", inset: 0, background: "rgba(20,22,28,0.45)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 50, padding: 16, boxSizing: "border-box" },
|
|
1162
|
+
modal: { background: "var(--fb-surface)", borderRadius: 12, width: "100%", maxWidth: 520, maxHeight: "70vh", display: "flex", flexDirection: "column", overflow: "hidden", boxShadow: "0 20px 60px rgba(0,0,0,0.25)", boxSizing: "border-box" },
|
|
1115
1163
|
modalHeader: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "12px 16px", borderBottom: "1px solid var(--fb-border)" },
|
|
1116
1164
|
jsonPre: { margin: 0, padding: 16, fontSize: 12, lineHeight: 1.6, overflow: "auto", background: "#14171C", color: "#D6D8E0", fontFamily: "'JetBrains Mono', monospace" },
|
|
1117
1165
|
previewWrap: { flex: 1, display: "flex", justifyContent: "center", padding: "var(--fb-space-page) 20px", overflowY: "auto", background: "var(--fb-canvas)" },
|
|
1118
1166
|
previewToolbar: { width: "100%", display: "flex", gap: 10, marginBottom: 16, justifyContent: "center" },
|
|
1119
1167
|
previewCard: { width: "100%", maxWidth: 480, background: "var(--fb-page-bg)", border: "1px solid var(--fb-border)", borderRadius: 12, padding: "var(--fb-space-page)" },
|
|
1120
1168
|
previewTitle: { fontSize: 19, fontWeight: 700, margin: "0 0 20px" },
|
|
1121
|
-
previewLabel: { display: "block", fontSize: 13, fontWeight: 600, color: "
|
|
1169
|
+
previewLabel: { display: "block", fontSize: 13, fontWeight: 600, color: "var(--fb-ink)", marginBottom: 6 },
|
|
1122
1170
|
previewGrid: { display: "flex", flexWrap: "wrap", gap: "var(--fb-space-field)" },
|
|
1123
1171
|
sectionRuntimeTitle: { fontSize: 15, fontWeight: 700, margin: "0 0 12px", color: "var(--fb-ink)" },
|
|
1124
1172
|
imagePlaceholder: { display: "flex", alignItems: "center", justifyContent: "center", border: "1px dashed var(--fb-border)" },
|
|
@@ -1128,13 +1176,13 @@ var styles = {
|
|
|
1128
1176
|
submittedRow: { display: "flex", justifyContent: "space-between", gap: 12, fontSize: 13, padding: "6px 0", borderBottom: "1px solid var(--fb-border)" },
|
|
1129
1177
|
submittedLabel: { color: "var(--fb-muted)", flexShrink: 0 },
|
|
1130
1178
|
submittedValue: { color: "var(--fb-ink)", fontWeight: 600, textAlign: "right" },
|
|
1131
|
-
realInput: { width: "100%", border: "1px solid var(--fb-border)", borderRadius: 8, padding: "9px 11px", fontSize: 13.5, outline: "none", color: "var(--fb-ink)", boxSizing: "border-box" },
|
|
1179
|
+
realInput: { width: "100%", border: "1px solid var(--fb-border)", borderRadius: 8, padding: "9px 11px", fontSize: 13.5, outline: "none", color: "var(--fb-ink)", background: "var(--fb-surface)", boxSizing: "border-box" },
|
|
1132
1180
|
realInputError: { borderColor: "var(--fb-danger)" },
|
|
1133
1181
|
submitBtn: { marginTop: 8, color: "#fff", border: "none", borderRadius: 8, fontWeight: 600, width: "100%" },
|
|
1134
1182
|
layoutPanelHeader: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 4 },
|
|
1135
1183
|
spacingRow: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, padding: "4px 0" },
|
|
1136
|
-
spacingLabel: { fontSize: 12, color: "
|
|
1137
|
-
spacingInput: { width: 60, border: "1px solid var(--fb-border)", borderRadius: 6, padding: "4px 6px", fontSize: 12, textAlign: "right", outline: "none" }
|
|
1184
|
+
spacingLabel: { fontSize: 12, color: "var(--fb-ink)" },
|
|
1185
|
+
spacingInput: { width: 60, border: "1px solid var(--fb-border)", borderRadius: 6, padding: "4px 6px", fontSize: 12, textAlign: "right", color: "var(--fb-ink)", background: "var(--fb-surface)", outline: "none" }
|
|
1138
1186
|
};
|
|
1139
1187
|
|
|
1140
1188
|
// src/components/LanguageToggle.tsx
|
|
@@ -1175,6 +1223,7 @@ function Toolbar({
|
|
|
1175
1223
|
mode,
|
|
1176
1224
|
saveState,
|
|
1177
1225
|
chrome,
|
|
1226
|
+
features,
|
|
1178
1227
|
savedFormsCount,
|
|
1179
1228
|
onTitleChange,
|
|
1180
1229
|
onLanguageChange,
|
|
@@ -1187,7 +1236,7 @@ function Toolbar({
|
|
|
1187
1236
|
return /* @__PURE__ */ jsxs2("div", { style: styles.toolbar, children: [
|
|
1188
1237
|
/* @__PURE__ */ jsxs2("div", { style: styles.toolbarLeft, children: [
|
|
1189
1238
|
/* @__PURE__ */ jsx2("div", { style: styles.logoMark, children: "FB" }),
|
|
1190
|
-
/* @__PURE__ */ jsx2("input", { value: t(title, language), onChange: (e) => onTitleChange(e.target.value), style: styles.titleInput, "aria-label": "Form title" })
|
|
1239
|
+
features.naming ? /* @__PURE__ */ jsx2("input", { value: t(title, language), onChange: (e) => onTitleChange(e.target.value), style: styles.titleInput, "aria-label": "Form title" }) : /* @__PURE__ */ jsx2("span", { style: styles.titleInput, children: t(title, language) })
|
|
1191
1240
|
] }),
|
|
1192
1241
|
/* @__PURE__ */ jsxs2("div", { style: styles.toolbarRight, children: [
|
|
1193
1242
|
/* @__PURE__ */ jsxs2("span", { style: styles.saveStatus, children: [
|
|
@@ -1203,37 +1252,43 @@ function Toolbar({
|
|
|
1203
1252
|
chrome.saveFailed
|
|
1204
1253
|
] })
|
|
1205
1254
|
] }),
|
|
1206
|
-
/* @__PURE__ */
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
/* @__PURE__ */ jsxs2("button", { style: mode === "build" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("build"), children: [
|
|
1210
|
-
/* @__PURE__ */ jsx2(Pencil, { size: 14 }),
|
|
1211
|
-
" ",
|
|
1212
|
-
chrome.build
|
|
1255
|
+
features.languageSwitcher && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1256
|
+
/* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
|
|
1257
|
+
/* @__PURE__ */ jsx2(LanguageToggle, { languages, value: language, onChange: onLanguageChange })
|
|
1213
1258
|
] }),
|
|
1214
|
-
/* @__PURE__ */ jsxs2(
|
|
1215
|
-
/* @__PURE__ */ jsx2(
|
|
1216
|
-
" ",
|
|
1217
|
-
|
|
1259
|
+
features.previewMode && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1260
|
+
/* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
|
|
1261
|
+
/* @__PURE__ */ jsxs2("button", { style: mode === "build" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("build"), children: [
|
|
1262
|
+
/* @__PURE__ */ jsx2(Pencil, { size: 14 }),
|
|
1263
|
+
" ",
|
|
1264
|
+
chrome.build
|
|
1265
|
+
] }),
|
|
1266
|
+
/* @__PURE__ */ jsxs2("button", { style: mode === "preview" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("preview"), children: [
|
|
1267
|
+
/* @__PURE__ */ jsx2(Eye, { size: 14 }),
|
|
1268
|
+
" ",
|
|
1269
|
+
chrome.preview
|
|
1270
|
+
] })
|
|
1218
1271
|
] }),
|
|
1219
|
-
/* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
|
|
1220
|
-
/* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onNewForm, title: chrome.startNewForm, children: [
|
|
1272
|
+
(features.newForm || features.templates) && /* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
|
|
1273
|
+
features.newForm && /* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onNewForm, title: chrome.startNewForm, children: [
|
|
1221
1274
|
/* @__PURE__ */ jsx2(FilePlus2, { size: 14 }),
|
|
1222
1275
|
" ",
|
|
1223
1276
|
chrome.newForm
|
|
1224
1277
|
] }),
|
|
1225
|
-
/* @__PURE__ */ jsxs2(
|
|
1226
|
-
/* @__PURE__ */
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
/* @__PURE__ */
|
|
1233
|
-
|
|
1234
|
-
|
|
1278
|
+
features.templates && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1279
|
+
/* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onOpenLibrary, title: chrome.openTemplatesTitle, children: [
|
|
1280
|
+
/* @__PURE__ */ jsx2(FolderOpen, { size: 14 }),
|
|
1281
|
+
" ",
|
|
1282
|
+
chrome.templates,
|
|
1283
|
+
savedFormsCount > 0 && /* @__PURE__ */ jsx2("span", { style: styles.countBadge, children: savedFormsCount })
|
|
1284
|
+
] }),
|
|
1285
|
+
/* @__PURE__ */ jsxs2("button", { style: styles.primaryBtn, onClick: onSaveExisting, title: chrome.saveToLibraryTitle, children: [
|
|
1286
|
+
/* @__PURE__ */ jsx2(Save, { size: 14 }),
|
|
1287
|
+
" ",
|
|
1288
|
+
chrome.save
|
|
1289
|
+
] })
|
|
1235
1290
|
] }),
|
|
1236
|
-
/* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onOpenJson, children: [
|
|
1291
|
+
features.jsonView && /* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onOpenJson, children: [
|
|
1237
1292
|
/* @__PURE__ */ jsx2(Code2, { size: 14 }),
|
|
1238
1293
|
" ",
|
|
1239
1294
|
chrome.viewJson
|
|
@@ -1334,15 +1389,17 @@ function Palette({
|
|
|
1334
1389
|
activeSectionLabel,
|
|
1335
1390
|
chrome,
|
|
1336
1391
|
onAddField,
|
|
1337
|
-
|
|
1392
|
+
features,
|
|
1338
1393
|
theme,
|
|
1339
1394
|
updateThemeColor,
|
|
1340
1395
|
updateThemeLayout,
|
|
1341
1396
|
resetTheme
|
|
1342
1397
|
}) {
|
|
1343
1398
|
const [tab, setTab] = useState5("blocks");
|
|
1344
|
-
|
|
1345
|
-
|
|
1399
|
+
const contentTypes = CONTENT_TYPES.filter((f) => isContentBlockEnabled(features, f.type));
|
|
1400
|
+
const formTypes = FORM_TYPES.filter((f) => isFieldTypeEnabled(features, f.type));
|
|
1401
|
+
return /* @__PURE__ */ jsxs5("div", { className: "fb-palette", style: styles.palette, children: [
|
|
1402
|
+
features.design && /* @__PURE__ */ jsx5("div", { style: { marginBottom: 14 }, children: /* @__PURE__ */ jsx5(
|
|
1346
1403
|
Segmented,
|
|
1347
1404
|
{
|
|
1348
1405
|
options: [
|
|
@@ -1353,7 +1410,7 @@ function Palette({
|
|
|
1353
1410
|
onChange: setTab
|
|
1354
1411
|
}
|
|
1355
1412
|
) }),
|
|
1356
|
-
tab === "design" &&
|
|
1413
|
+
tab === "design" && features.design ? /* @__PURE__ */ jsx5(
|
|
1357
1414
|
DesignPanel,
|
|
1358
1415
|
{
|
|
1359
1416
|
chrome,
|
|
@@ -1368,24 +1425,28 @@ function Palette({
|
|
|
1368
1425
|
" ",
|
|
1369
1426
|
/* @__PURE__ */ jsx5("strong", { children: activeSectionLabel })
|
|
1370
1427
|
] }),
|
|
1371
|
-
/* @__PURE__ */
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
/* @__PURE__ */
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
/* @__PURE__ */
|
|
1387
|
-
|
|
1388
|
-
|
|
1428
|
+
contentTypes.length > 0 && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1429
|
+
/* @__PURE__ */ jsx5("div", { style: styles.panelHeading, children: chrome.contentBlocks }),
|
|
1430
|
+
/* @__PURE__ */ jsx5("div", { style: styles.paletteList, children: contentTypes.map((f) => {
|
|
1431
|
+
const Icon = f.icon;
|
|
1432
|
+
return /* @__PURE__ */ jsxs5("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
|
|
1433
|
+
/* @__PURE__ */ jsx5(Icon, { size: 16, color: "var(--fb-primary)" }),
|
|
1434
|
+
/* @__PURE__ */ jsx5("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
|
|
1435
|
+
/* @__PURE__ */ jsx5(Plus, { size: 13, color: "var(--fb-muted)", style: { marginLeft: "auto" } })
|
|
1436
|
+
] }, f.type);
|
|
1437
|
+
}) })
|
|
1438
|
+
] }),
|
|
1439
|
+
formTypes.length > 0 && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
1440
|
+
/* @__PURE__ */ jsx5("div", { style: { ...styles.panelHeading, marginTop: 16 }, children: chrome.formFields }),
|
|
1441
|
+
/* @__PURE__ */ jsx5("div", { style: styles.paletteList, children: formTypes.map((f) => {
|
|
1442
|
+
const Icon = f.icon;
|
|
1443
|
+
return /* @__PURE__ */ jsxs5("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
|
|
1444
|
+
/* @__PURE__ */ jsx5(Icon, { size: 16, color: "var(--fb-primary)" }),
|
|
1445
|
+
/* @__PURE__ */ jsx5("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
|
|
1446
|
+
/* @__PURE__ */ jsx5(Plus, { size: 13, color: "var(--fb-muted)", style: { marginLeft: "auto" } })
|
|
1447
|
+
] }, f.type);
|
|
1448
|
+
}) })
|
|
1449
|
+
] })
|
|
1389
1450
|
] })
|
|
1390
1451
|
] });
|
|
1391
1452
|
}
|
|
@@ -1538,7 +1599,7 @@ function FieldBlock({ field, lang, onFieldChange, strings, chrome, error, isBuil
|
|
|
1538
1599
|
return /* @__PURE__ */ jsxs6("div", { children: [
|
|
1539
1600
|
/* @__PURE__ */ jsxs6("div", { style: { display: "flex", flexDirection: isInline ? "row" : "column", alignItems: isInline ? "center" : "stretch", gap: isInline ? 10 : 6 }, children: [
|
|
1540
1601
|
showLabel && /* @__PURE__ */ jsxs6("label", { style: { ...styles.previewLabel, marginBottom: isInline ? 0 : 6, flexShrink: 0, width: isInline ? 120 : "auto", display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
1541
|
-
IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "
|
|
1602
|
+
IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "var(--fb-muted)" }),
|
|
1542
1603
|
labelText || (isBuild ? /* @__PURE__ */ jsx8("span", { style: { fontStyle: "italic", color: "var(--fb-muted)" }, children: chrome?.untitledField || "Untitled field" }) : ""),
|
|
1543
1604
|
field.required && /* @__PURE__ */ jsx8("span", { style: { color: "var(--fb-danger)" }, children: " *" })
|
|
1544
1605
|
] }),
|
|
@@ -1603,14 +1664,14 @@ function renderInteractive(field, lang, onFieldChange, IconComp, hasError, strin
|
|
|
1603
1664
|
case "checkbox":
|
|
1604
1665
|
return /* @__PURE__ */ jsxs6("label", { style: styles.previewRadio, children: [
|
|
1605
1666
|
/* @__PURE__ */ jsx8("input", { type: "checkbox", checked: !!value, onChange: (e) => set(e.target.checked), style: { accentColor: "var(--fb-primary)" } }),
|
|
1606
|
-
IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "
|
|
1667
|
+
IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "var(--fb-muted)" }),
|
|
1607
1668
|
t(field.label, lang),
|
|
1608
1669
|
field.required && /* @__PURE__ */ jsx8("span", { style: { color: "var(--fb-danger)" }, children: " *" })
|
|
1609
1670
|
] });
|
|
1610
1671
|
case "toggle":
|
|
1611
1672
|
return /* @__PURE__ */ jsxs6("label", { style: styles.previewRadio, children: [
|
|
1612
1673
|
/* @__PURE__ */ jsx8("input", { type: "checkbox", checked: !!value, onChange: (e) => set(e.target.checked), style: { accentColor: "var(--fb-primary)" } }),
|
|
1613
|
-
IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "
|
|
1674
|
+
IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "var(--fb-muted)" }),
|
|
1614
1675
|
t(field.label, lang)
|
|
1615
1676
|
] });
|
|
1616
1677
|
default:
|
|
@@ -1628,6 +1689,7 @@ function FieldTicket({
|
|
|
1628
1689
|
chrome,
|
|
1629
1690
|
strings,
|
|
1630
1691
|
language,
|
|
1692
|
+
dragEnabled,
|
|
1631
1693
|
onSelect,
|
|
1632
1694
|
onFieldChange,
|
|
1633
1695
|
onMoveField,
|
|
@@ -1657,7 +1719,7 @@ function FieldTicket({
|
|
|
1657
1719
|
/* @__PURE__ */ jsx9("div", { style: styles.ticketPerforation }),
|
|
1658
1720
|
/* @__PURE__ */ jsxs7("div", { style: styles.ticketBody, children: [
|
|
1659
1721
|
/* @__PURE__ */ jsxs7("div", { style: styles.ticketTop, children: [
|
|
1660
|
-
/* @__PURE__ */ jsx9("span", { ...dragHandleProps, style: { cursor: "grab", display: "flex" }, children: /* @__PURE__ */ jsx9(GripVertical, { size: 14, color: "
|
|
1722
|
+
dragEnabled && /* @__PURE__ */ jsx9("span", { ...dragHandleProps, style: { cursor: "grab", display: "flex" }, children: /* @__PURE__ */ jsx9(GripVertical, { size: 14, color: "var(--fb-muted)" }) }),
|
|
1661
1723
|
/* @__PURE__ */ jsx9(Icon, { size: 13, color: "var(--fb-primary)" }),
|
|
1662
1724
|
/* @__PURE__ */ jsxs7("span", { style: styles.typeBadge, children: [
|
|
1663
1725
|
chrome[FIELD_TYPE_CHROME_KEY[field.type]] || field.type,
|
|
@@ -1689,7 +1751,7 @@ function FieldTicket({
|
|
|
1689
1751
|
}
|
|
1690
1752
|
|
|
1691
1753
|
// src/components/SectionCard.tsx
|
|
1692
|
-
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1754
|
+
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1693
1755
|
function SectionCard({
|
|
1694
1756
|
section,
|
|
1695
1757
|
sIdx,
|
|
@@ -1700,6 +1762,7 @@ function SectionCard({
|
|
|
1700
1762
|
chrome,
|
|
1701
1763
|
strings,
|
|
1702
1764
|
language,
|
|
1765
|
+
features,
|
|
1703
1766
|
onActivate,
|
|
1704
1767
|
onToggleCollapse,
|
|
1705
1768
|
onUpdateTitle,
|
|
@@ -1739,14 +1802,16 @@ function SectionCard({
|
|
|
1739
1802
|
),
|
|
1740
1803
|
section.collapsed && /* @__PURE__ */ jsx10("span", { style: styles.miniBadge, children: chrome.fieldsCount(section.fields.length) }),
|
|
1741
1804
|
/* @__PURE__ */ jsxs8("div", { style: styles.sectionHeaderActions, onClick: (e) => e.stopPropagation(), children: [
|
|
1742
|
-
!section.collapsed && /* @__PURE__ */ jsxs8("div", { style: styles.swatchRow, children: [
|
|
1805
|
+
features.sections && !section.collapsed && /* @__PURE__ */ jsxs8("div", { style: styles.swatchRow, children: [
|
|
1743
1806
|
SECTION_BG_SWATCHES.map((c) => /* @__PURE__ */ jsx10("button", { type: "button", title: c || chrome.none, style: { ...styles.swatchBtn, background: c || "var(--fb-canvas)", ...section.background === c ? styles.swatchBtnActive : {} }, onClick: () => onUpdateBackground(c) }, c || "none")),
|
|
1744
1807
|
/* @__PURE__ */ jsx10("input", { type: "color", title: chrome.customColor, value: /^#/.test(section.background) ? section.background : "#ffffff", onChange: (e) => onUpdateBackground(e.target.value), style: styles.colorPickerInput })
|
|
1745
1808
|
] }),
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1809
|
+
features.sections && /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
1810
|
+
/* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.duplicate, onClick: onDuplicateSection, children: /* @__PURE__ */ jsx10(Copy2, { size: 13 }) }),
|
|
1811
|
+
/* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.moveUp, disabled: sIdx === 0, onClick: () => onMoveSection(-1), children: /* @__PURE__ */ jsx10(ArrowUp2, { size: 13 }) }),
|
|
1812
|
+
/* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.moveDown, disabled: sIdx === sectionsLength - 1, onClick: () => onMoveSection(1), children: /* @__PURE__ */ jsx10(ArrowDown2, { size: 13 }) }),
|
|
1813
|
+
/* @__PURE__ */ jsx10("button", { style: { ...styles.iconBtn, ...styles.iconBtnDanger }, title: chrome.deleteSection, disabled: sectionsLength <= 1, onClick: onDeleteSection, children: /* @__PURE__ */ jsx10(Trash22, { size: 13 }) })
|
|
1814
|
+
] })
|
|
1750
1815
|
] })
|
|
1751
1816
|
] }),
|
|
1752
1817
|
!section.collapsed && (section.fields.length === 0 ? /* @__PURE__ */ jsx10("div", { style: styles.sectionEmpty, children: chrome.noFieldsInSection }) : /* @__PURE__ */ jsx10("div", { style: styles.fieldList, children: section.fields.map((field, idx) => /* @__PURE__ */ jsx10(
|
|
@@ -1760,6 +1825,7 @@ function SectionCard({
|
|
|
1760
1825
|
chrome,
|
|
1761
1826
|
strings,
|
|
1762
1827
|
language,
|
|
1828
|
+
dragEnabled: features.dragReorder,
|
|
1763
1829
|
onSelect: () => onSelectField(field.id),
|
|
1764
1830
|
onFieldChange,
|
|
1765
1831
|
onMoveField,
|
|
@@ -1785,6 +1851,7 @@ function Canvas({
|
|
|
1785
1851
|
chrome,
|
|
1786
1852
|
strings,
|
|
1787
1853
|
language,
|
|
1854
|
+
features,
|
|
1788
1855
|
onActivateSection,
|
|
1789
1856
|
onToggleSectionCollapse,
|
|
1790
1857
|
onUpdateSectionTitle,
|
|
@@ -1801,7 +1868,7 @@ function Canvas({
|
|
|
1801
1868
|
getDropZoneHandlers,
|
|
1802
1869
|
getDragHandleProps
|
|
1803
1870
|
}) {
|
|
1804
|
-
return /* @__PURE__ */ jsxs9("div", { style: styles.canvas, children: [
|
|
1871
|
+
return /* @__PURE__ */ jsxs9("div", { className: "fb-canvas", style: styles.canvas, children: [
|
|
1805
1872
|
sections.map((section, sIdx) => /* @__PURE__ */ jsx11(
|
|
1806
1873
|
SectionCard,
|
|
1807
1874
|
{
|
|
@@ -1814,6 +1881,7 @@ function Canvas({
|
|
|
1814
1881
|
chrome,
|
|
1815
1882
|
strings,
|
|
1816
1883
|
language,
|
|
1884
|
+
features,
|
|
1817
1885
|
onActivate: () => onActivateSection(section.id),
|
|
1818
1886
|
onToggleCollapse: () => onToggleSectionCollapse(section.id),
|
|
1819
1887
|
onUpdateTitle: (value) => onUpdateSectionTitle(section.id, value),
|
|
@@ -1831,7 +1899,7 @@ function Canvas({
|
|
|
1831
1899
|
},
|
|
1832
1900
|
section.id
|
|
1833
1901
|
)),
|
|
1834
|
-
/* @__PURE__ */ jsxs9("button", { style: styles.addSectionBtn, onClick: onAddSection, children: [
|
|
1902
|
+
features.sections && /* @__PURE__ */ jsxs9("button", { style: styles.addSectionBtn, onClick: onAddSection, children: [
|
|
1835
1903
|
/* @__PURE__ */ jsx11(Layers, { size: 14 }),
|
|
1836
1904
|
" ",
|
|
1837
1905
|
chrome.addSection
|
|
@@ -1843,22 +1911,22 @@ function Canvas({
|
|
|
1843
1911
|
import { Bold, Italic, X, Plus as Plus2, Trash2 as Trash23 } from "lucide-react";
|
|
1844
1912
|
|
|
1845
1913
|
// src/components/fields/DefaultValueEditor.tsx
|
|
1846
|
-
import { Fragment as
|
|
1914
|
+
import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1847
1915
|
function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
|
|
1848
1916
|
if (meta.isContent) return null;
|
|
1849
1917
|
const f = field;
|
|
1850
1918
|
if (meta.boolean) {
|
|
1851
|
-
return /* @__PURE__ */ jsxs10(
|
|
1919
|
+
return /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
1852
1920
|
/* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultValue }),
|
|
1853
1921
|
/* @__PURE__ */ jsxs10("button", { style: styles.toggleRow, onClick: () => onChange({ defaultValue: !f.defaultValue }), children: [
|
|
1854
1922
|
/* @__PURE__ */ jsx12("span", { style: { ...styles.toggleTrack, background: f.defaultValue ? "var(--fb-primary)" : "var(--fb-border)" }, children: /* @__PURE__ */ jsx12("span", { style: { ...styles.toggleThumb, transform: f.defaultValue ? "translateX(16px)" : "translateX(0)" } }) }),
|
|
1855
|
-
/* @__PURE__ */ jsx12("span", { style: { fontSize: 13, color: "
|
|
1923
|
+
/* @__PURE__ */ jsx12("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: f.defaultValue ? chrome.checked : chrome.unchecked })
|
|
1856
1924
|
] })
|
|
1857
1925
|
] });
|
|
1858
1926
|
}
|
|
1859
1927
|
if (meta.multiValue) {
|
|
1860
1928
|
const selectedVals = f.defaultValue || [];
|
|
1861
|
-
return /* @__PURE__ */ jsxs10(
|
|
1929
|
+
return /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
1862
1930
|
/* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultChecked }),
|
|
1863
1931
|
/* @__PURE__ */ jsx12("div", { style: styles.optionList, children: (f.options || []).map((o) => {
|
|
1864
1932
|
const checked = selectedVals.includes(o.value);
|
|
@@ -1873,7 +1941,7 @@ function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
|
|
|
1873
1941
|
] });
|
|
1874
1942
|
}
|
|
1875
1943
|
if (meta.options) {
|
|
1876
|
-
return /* @__PURE__ */ jsxs10(
|
|
1944
|
+
return /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
1877
1945
|
/* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultValue }),
|
|
1878
1946
|
/* @__PURE__ */ jsxs10("select", { style: styles.propInput, value: f.defaultValue || "", onChange: (e) => onChange({ defaultValue: e.target.value }), children: [
|
|
1879
1947
|
/* @__PURE__ */ jsx12("option", { value: "", children: chrome.none }),
|
|
@@ -1882,16 +1950,16 @@ function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
|
|
|
1882
1950
|
] });
|
|
1883
1951
|
}
|
|
1884
1952
|
const htmlType = field.type === "input" && field.inputType === "number" ? "number" : field.type === "input" && field.inputType === "date" ? "date" : field.type === "input" && field.inputType === "time" ? "time" : "text";
|
|
1885
|
-
return /* @__PURE__ */ jsxs10(
|
|
1953
|
+
return /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
1886
1954
|
/* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultValue }),
|
|
1887
1955
|
/* @__PURE__ */ jsx12("input", { type: htmlType, style: styles.propInput, value: f.defaultValue || "", onChange: (e) => onChange({ defaultValue: e.target.value }) })
|
|
1888
1956
|
] });
|
|
1889
1957
|
}
|
|
1890
1958
|
|
|
1891
1959
|
// src/components/Inspector.tsx
|
|
1892
|
-
import { Fragment as
|
|
1893
|
-
function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
|
|
1894
|
-
return /* @__PURE__ */ jsxs11("div", { style: styles.inspector, children: [
|
|
1960
|
+
import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1961
|
+
function Inspector({ selected, language, chrome, features, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
|
|
1962
|
+
return /* @__PURE__ */ jsxs11("div", { className: "fb-inspector", style: styles.inspector, children: [
|
|
1895
1963
|
/* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.properties }),
|
|
1896
1964
|
!selected ? /* @__PURE__ */ jsx13("div", { style: styles.inspectorEmpty, children: chrome.selectFieldHint }) : /* @__PURE__ */ jsx13(
|
|
1897
1965
|
InspectorBody,
|
|
@@ -1899,6 +1967,7 @@ function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, o
|
|
|
1899
1967
|
selected,
|
|
1900
1968
|
language,
|
|
1901
1969
|
chrome,
|
|
1970
|
+
features,
|
|
1902
1971
|
onUpdateField,
|
|
1903
1972
|
onDeleteField,
|
|
1904
1973
|
onUpdateOption,
|
|
@@ -1908,45 +1977,47 @@ function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, o
|
|
|
1908
1977
|
)
|
|
1909
1978
|
] });
|
|
1910
1979
|
}
|
|
1911
|
-
function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
|
|
1980
|
+
function InspectorBody({ selected, language, chrome, features, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
|
|
1912
1981
|
const meta = getMeta(selected.type);
|
|
1913
1982
|
const f = selected;
|
|
1914
1983
|
return /* @__PURE__ */ jsxs11("div", { style: styles.inspectorBody, children: [
|
|
1915
|
-
(!meta.isContent || selected.type === "button") && /* @__PURE__ */ jsxs11(
|
|
1984
|
+
(!meta.isContent || selected.type === "button") && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
1916
1985
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: selected.type === "button" ? chrome.buttonText : chrome.label }),
|
|
1917
1986
|
/* @__PURE__ */ jsx13("input", { style: styles.propInput, value: t(selected.label, language), onChange: (e) => onUpdateField({ label: withLang(selected.label, language, e.target.value) }) }),
|
|
1918
1987
|
!meta.isContent && /* @__PURE__ */ jsxs11("label", { style: styles.toggleRow, children: [
|
|
1919
1988
|
/* @__PURE__ */ jsx13("input", { type: "checkbox", checked: !!selected.hideLabel, onChange: (e) => onUpdateField({ hideLabel: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
|
|
1920
|
-
/* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "
|
|
1989
|
+
/* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.hideLabel })
|
|
1921
1990
|
] })
|
|
1922
1991
|
] }),
|
|
1923
|
-
meta.hasSubtype && /* @__PURE__ */ jsxs11(
|
|
1992
|
+
meta.hasSubtype && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
1924
1993
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.inputType }),
|
|
1925
1994
|
/* @__PURE__ */ jsx13("select", { style: styles.propInput, value: f.inputType || "text", onChange: (e) => onUpdateField({ inputType: e.target.value }), children: INPUT_SUBTYPES.map((s) => /* @__PURE__ */ jsx13("option", { value: s, children: chrome[INPUT_SUBTYPE_CHROME_KEY[s]] }, s)) })
|
|
1926
1995
|
] }),
|
|
1927
|
-
selected.type === "paragraph" && /* @__PURE__ */ jsxs11(
|
|
1996
|
+
selected.type === "paragraph" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
1928
1997
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.content }),
|
|
1929
1998
|
/* @__PURE__ */ jsx13("textarea", { style: { ...styles.propInput, minHeight: 70, resize: "vertical" }, value: t(selected.content, language), onChange: (e) => onUpdateField({ content: withLang(selected.content, language, e.target.value) }) }),
|
|
1930
|
-
/* @__PURE__ */
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
/* @__PURE__ */
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1999
|
+
features.blockStyling && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
2000
|
+
/* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
|
|
2001
|
+
/* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.typography }),
|
|
2002
|
+
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.headingStyle }),
|
|
2003
|
+
/* @__PURE__ */ jsx13(Segmented, { options: PARAGRAPH_TAG_OPTIONS.map((v) => ({ value: v, label: TAG_CHROME_KEY[v] ? chrome[TAG_CHROME_KEY[v]] : v.toUpperCase() })), value: selected.tag || "p", onChange: (v) => onUpdateField({ tag: v, ...TAG_PRESETS[v] }) }),
|
|
2004
|
+
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.width }),
|
|
2005
|
+
/* @__PURE__ */ jsx13(Segmented, { options: FONT_SIZE_OPTIONS, value: selected.fontSize || "md", onChange: (v) => onUpdateField({ fontSize: v }) }),
|
|
2006
|
+
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.style }),
|
|
2007
|
+
/* @__PURE__ */ jsxs11("div", { style: styles.styleToggleRow, children: [
|
|
2008
|
+
/* @__PURE__ */ jsx13("button", { type: "button", style: selected.fontWeight === "bold" ? styles.styleToggleActive : styles.styleToggle, onClick: () => onUpdateField({ fontWeight: selected.fontWeight === "bold" ? "normal" : "bold" }), children: /* @__PURE__ */ jsx13(Bold, { size: 14 }) }),
|
|
2009
|
+
/* @__PURE__ */ jsx13("button", { type: "button", style: selected.fontStyle === "italic" ? styles.styleToggleActive : styles.styleToggle, onClick: () => onUpdateField({ fontStyle: selected.fontStyle === "italic" ? "normal" : "italic" }), children: /* @__PURE__ */ jsx13(Italic, { size: 14 }) })
|
|
2010
|
+
] }),
|
|
2011
|
+
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.align }),
|
|
2012
|
+
/* @__PURE__ */ jsx13(Segmented, { options: TEXT_ALIGN_OPTIONS, value: selected.textAlign || "left", onChange: (v) => onUpdateField({ textAlign: v }) }),
|
|
2013
|
+
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.color }),
|
|
2014
|
+
/* @__PURE__ */ jsxs11("div", { style: styles.swatchRow, children: [
|
|
2015
|
+
COLOR_SWATCHES.map((c) => /* @__PURE__ */ jsx13("button", { type: "button", title: c || chrome.none, style: { ...styles.swatchBtn, background: c || "var(--fb-ink)", ...selected.color === c ? styles.swatchBtnActive : {} }, onClick: () => onUpdateField({ color: c }) }, c || "default")),
|
|
2016
|
+
/* @__PURE__ */ jsx13("input", { type: "color", value: selected.color || "#1B1E24", onChange: (e) => onUpdateField({ color: e.target.value }), style: styles.colorPickerInput })
|
|
2017
|
+
] })
|
|
1947
2018
|
] })
|
|
1948
2019
|
] }),
|
|
1949
|
-
selected.type === "image" && /* @__PURE__ */ jsxs11(
|
|
2020
|
+
selected.type === "image" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
1950
2021
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.imageUrl }),
|
|
1951
2022
|
/* @__PURE__ */ jsx13("input", { style: styles.propInput, placeholder: "https://...", value: selected.src || "", onChange: (e) => onUpdateField({ src: e.target.value }) }),
|
|
1952
2023
|
/* @__PURE__ */ jsx13("p", { style: styles.helperText, children: chrome.imageUrlHelper }),
|
|
@@ -1958,47 +2029,49 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
|
|
|
1958
2029
|
/* @__PURE__ */ jsx13(Segmented, { options: IMAGE_SHAPES.map((v) => ({ value: v, label: chrome[IMAGE_SHAPE_CHROME_KEY[v]] })), value: selected.shape || "square", onChange: (v) => onUpdateField({ shape: v }) }),
|
|
1959
2030
|
/* @__PURE__ */ jsx13("p", { style: styles.helperText, children: "Fills the field's own width (set below under Layout) and scales height automatically \u2014 always responsive, never overflows." })
|
|
1960
2031
|
] }),
|
|
1961
|
-
selected.type === "button" && /* @__PURE__ */ jsxs11(
|
|
2032
|
+
selected.type === "button" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
1962
2033
|
/* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
|
|
1963
2034
|
/* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.buttonActionTitle }),
|
|
1964
2035
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.buttonAction }),
|
|
1965
2036
|
/* @__PURE__ */ jsx13(Segmented, { options: [{ value: "link", label: chrome.actionLink }, { value: "submit", label: chrome.actionSubmit }], value: selected.action || "submit", onChange: (v) => onUpdateField({ action: v }) }),
|
|
1966
|
-
selected.action === "link" ? /* @__PURE__ */ jsxs11(
|
|
2037
|
+
selected.action === "link" ? /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
1967
2038
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.linkOptional }),
|
|
1968
2039
|
/* @__PURE__ */ jsx13("input", { style: styles.propInput, placeholder: "https://...", value: selected.href || "", onChange: (e) => onUpdateField({ href: e.target.value }) }),
|
|
1969
2040
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.openIn }),
|
|
1970
2041
|
/* @__PURE__ */ jsx13(Segmented, { options: [{ value: "_self", label: chrome.sameTab }, { value: "_blank", label: chrome.newTab }], value: selected.target || "_self", onChange: (v) => onUpdateField({ target: v }) })
|
|
1971
|
-
] }) : /* @__PURE__ */ jsxs11(
|
|
2042
|
+
] }) : /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
1972
2043
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.submitScope }),
|
|
1973
2044
|
/* @__PURE__ */ jsx13(Segmented, { options: [{ value: "section", label: chrome.thisSection }, { value: "form", label: chrome.wholeForm }], value: selected.submitScope || "form", onChange: (v) => onUpdateField({ submitScope: v }) })
|
|
1974
2045
|
] }),
|
|
1975
|
-
/* @__PURE__ */
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
2046
|
+
features.blockStyling && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
2047
|
+
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.color }),
|
|
2048
|
+
/* @__PURE__ */ jsxs11("div", { style: styles.swatchRow, children: [
|
|
2049
|
+
BUTTON_COLOR_SWATCHES.map((c) => /* @__PURE__ */ jsx13("button", { type: "button", title: c || chrome.none, style: { ...styles.swatchBtn, background: c || "var(--fb-primary)", ...(selected.buttonStyle?.color || "") === c ? styles.swatchBtnActive : {} }, onClick: () => onUpdateField({ buttonStyle: { ...selected.buttonStyle, color: c } }) }, c || "default")),
|
|
2050
|
+
/* @__PURE__ */ jsx13("input", { type: "color", value: selected.buttonStyle?.color || "#5B5FEF", onChange: (e) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, color: e.target.value } }), style: styles.colorPickerInput })
|
|
2051
|
+
] }),
|
|
2052
|
+
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.buttonSize }),
|
|
2053
|
+
/* @__PURE__ */ jsx13(Segmented, { options: SUBMIT_SIZE_OPTIONS, value: selected.buttonStyle?.size || "md", onChange: (v) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, size: v } }) })
|
|
2054
|
+
] })
|
|
1982
2055
|
] }),
|
|
1983
|
-
meta.placeholder && /* @__PURE__ */ jsxs11(
|
|
2056
|
+
meta.placeholder && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
1984
2057
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.placeholder }),
|
|
1985
2058
|
/* @__PURE__ */ jsx13("input", { style: styles.propInput, value: t(f.placeholder, language), onChange: (e) => onUpdateField({ placeholder: withLang(f.placeholder, language, e.target.value) }) })
|
|
1986
2059
|
] }),
|
|
1987
|
-
selected.type === "input" && (selected.inputType === "text" || selected.inputType === "password" || !selected.inputType) && /* @__PURE__ */ jsxs11(
|
|
2060
|
+
selected.type === "input" && (selected.inputType === "text" || selected.inputType === "password" || !selected.inputType) && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
1988
2061
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.maxLength }),
|
|
1989
2062
|
/* @__PURE__ */ jsx13("input", { type: "number", style: styles.propInput, placeholder: chrome.noLimit, value: selected.maxLength || "", onChange: (e) => onUpdateField({ maxLength: e.target.value ? Number(e.target.value) : null }) })
|
|
1990
2063
|
] }),
|
|
1991
|
-
selected.type === "input" && selected.inputType === "number" && /* @__PURE__ */ jsxs11(
|
|
2064
|
+
selected.type === "input" && selected.inputType === "number" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
1992
2065
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.minValue }),
|
|
1993
2066
|
/* @__PURE__ */ jsx13("input", { type: "number", style: styles.propInput, value: selected.min ?? "", onChange: (e) => onUpdateField({ min: e.target.value === "" ? null : Number(e.target.value) }) }),
|
|
1994
2067
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.maxValue }),
|
|
1995
2068
|
/* @__PURE__ */ jsx13("input", { type: "number", style: styles.propInput, value: selected.max ?? "", onChange: (e) => onUpdateField({ max: e.target.value === "" ? null : Number(e.target.value) }) })
|
|
1996
2069
|
] }),
|
|
1997
|
-
selected.type === "textarea" && /* @__PURE__ */ jsxs11(
|
|
2070
|
+
selected.type === "textarea" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
1998
2071
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.maxLength }),
|
|
1999
2072
|
/* @__PURE__ */ jsx13("input", { type: "number", style: styles.propInput, placeholder: chrome.noLimit, value: selected.maxLength || "", onChange: (e) => onUpdateField({ maxLength: e.target.value ? Number(e.target.value) : null }) })
|
|
2000
2073
|
] }),
|
|
2001
|
-
meta.options && /* @__PURE__ */ jsxs11(
|
|
2074
|
+
meta.options && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
2002
2075
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.options }),
|
|
2003
2076
|
/* @__PURE__ */ jsxs11("div", { style: styles.optionList, children: [
|
|
2004
2077
|
(f.options || []).map((opt, i) => /* @__PURE__ */ jsxs11("div", { style: styles.optionRow, children: [
|
|
@@ -2015,7 +2088,7 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
|
|
|
2015
2088
|
/* @__PURE__ */ jsx13(DefaultValueEditor, { field: selected, meta, lang: language, chrome, onChange: onUpdateField }),
|
|
2016
2089
|
!meta.isContent && /* @__PURE__ */ jsxs11("label", { style: styles.toggleRow, children: [
|
|
2017
2090
|
/* @__PURE__ */ jsx13("input", { type: "checkbox", checked: !!selected.required, onChange: (e) => onUpdateField({ required: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
|
|
2018
|
-
/* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "
|
|
2091
|
+
/* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.requiredField })
|
|
2019
2092
|
] }),
|
|
2020
2093
|
/* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
|
|
2021
2094
|
/* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.layout }),
|
|
@@ -2023,16 +2096,16 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
|
|
|
2023
2096
|
/* @__PURE__ */ jsx13(Segmented, { options: WIDTH_OPTIONS.map((o) => ({ ...o, label: o.labelKey ? chrome[o.labelKey] : o.label || "" })), value: selected.width || "1/1", onChange: (v) => onUpdateField({ width: v }) }),
|
|
2024
2097
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.verticalAlign }),
|
|
2025
2098
|
/* @__PURE__ */ jsx13(Segmented, { options: [{ value: "top", label: chrome.top }, { value: "middle", label: chrome.middle }, { value: "bottom", label: chrome.bottom }], value: selected.verticalAlign || "top", onChange: (v) => onUpdateField({ verticalAlign: v }) }),
|
|
2026
|
-
!meta.boolean && !meta.isContent && /* @__PURE__ */ jsxs11(
|
|
2099
|
+
!meta.boolean && !meta.isContent && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
2027
2100
|
/* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.labelPosition }),
|
|
2028
2101
|
/* @__PURE__ */ jsx13(Segmented, { options: [{ value: "top", label: chrome.above }, { value: "inline", label: chrome.inline }], value: selected.labelPosition || "top", onChange: (v) => onUpdateField({ labelPosition: v }) })
|
|
2029
2102
|
] }),
|
|
2030
|
-
!meta.isContent && /* @__PURE__ */ jsxs11(
|
|
2103
|
+
!meta.isContent && /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
2031
2104
|
/* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
|
|
2032
2105
|
/* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.icon }),
|
|
2033
2106
|
/* @__PURE__ */ jsxs11("label", { style: styles.toggleRow, children: [
|
|
2034
2107
|
/* @__PURE__ */ jsx13("input", { type: "checkbox", checked: !!selected.showIcon, onChange: (e) => onUpdateField({ showIcon: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
|
|
2035
|
-
/* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "
|
|
2108
|
+
/* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.showIcon })
|
|
2036
2109
|
] }),
|
|
2037
2110
|
selected.showIcon && /* @__PURE__ */ jsx13("div", { style: styles.iconGrid, children: Object.keys(ICON_LIBRARY).map((key) => {
|
|
2038
2111
|
const IconComp = ICON_LIBRARY[key];
|
|
@@ -2184,7 +2257,7 @@ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome
|
|
|
2184
2257
|
})
|
|
2185
2258
|
] })
|
|
2186
2259
|
] }),
|
|
2187
|
-
submitted && /* @__PURE__ */ jsx14("div", { style: styles.modalOverlay, onClick: () => setSubmitted(null), children: /* @__PURE__ */ jsxs12("div", { style: { ...styles.modal,
|
|
2260
|
+
submitted && /* @__PURE__ */ jsx14("div", { style: styles.modalOverlay, onClick: () => setSubmitted(null), children: /* @__PURE__ */ jsxs12("div", { style: { ...styles.modal, maxWidth: 420 }, onClick: (e) => e.stopPropagation(), children: [
|
|
2188
2261
|
/* @__PURE__ */ jsxs12("div", { style: styles.modalHeader, children: [
|
|
2189
2262
|
/* @__PURE__ */ jsxs12("span", { style: { fontWeight: 600, fontSize: 14, display: "flex", alignItems: "center", gap: 7 }, children: [
|
|
2190
2263
|
/* @__PURE__ */ jsx14(PartyPopper, { size: 15, color: "var(--fb-primary)" }),
|
|
@@ -2259,7 +2332,7 @@ import { Save as Save2, X as X5 } from "lucide-react";
|
|
|
2259
2332
|
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2260
2333
|
function SaveAsModal({ chrome, suggestedName, onSave, onClose }) {
|
|
2261
2334
|
const [name, setName] = useState7(suggestedName);
|
|
2262
|
-
return /* @__PURE__ */ jsx17("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ jsxs15("div", { style: { ...styles.modal,
|
|
2335
|
+
return /* @__PURE__ */ jsx17("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ jsxs15("div", { style: { ...styles.modal, maxWidth: 380 }, onClick: (e) => e.stopPropagation(), children: [
|
|
2263
2336
|
/* @__PURE__ */ jsxs15("div", { style: styles.modalHeader, children: [
|
|
2264
2337
|
/* @__PURE__ */ jsx17("span", { style: { fontWeight: 600, fontSize: 14 }, children: chrome.saveForm }),
|
|
2265
2338
|
/* @__PURE__ */ jsx17("button", { style: styles.iconBtn, onClick: onClose, children: /* @__PURE__ */ jsx17(X5, { size: 16 }) })
|
|
@@ -2289,6 +2362,36 @@ var css = `
|
|
|
2289
2362
|
that support it (mobile browser chrome resizing the viewport), and is
|
|
2290
2363
|
simply ignored by ones that don't. */
|
|
2291
2364
|
.fb-root { max-height: 100vh; max-height: 100dvh; }
|
|
2365
|
+
|
|
2366
|
+
/* Below this width the fixed 200px Palette + 270px Inspector columns
|
|
2367
|
+
don't leave room for a usable Canvas, so instead of stacking all
|
|
2368
|
+
three in flow (which buries Canvas under a tall Palette), Palette
|
|
2369
|
+
and Inspector become narrow drawers over Canvas (which stays
|
|
2370
|
+
partially visible behind them), toggled by .fb-mobile-bar's two
|
|
2371
|
+
buttons, tracked by .fb-work-area's data-mobile-panel attribute,
|
|
2372
|
+
and dismissible via .fb-mobile-backdrop. */
|
|
2373
|
+
.fb-mobile-bar { display: none; align-items: center; gap: 6px; padding: 6px 10px; border-bottom: 1px solid var(--fb-border); background: var(--fb-surface); flex-shrink: 0; }
|
|
2374
|
+
.fb-mobile-btn { display: flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 7px; border: 1px solid var(--fb-border); background: var(--fb-surface); color: var(--fb-muted); font-size: 12.5px; font-weight: 600; }
|
|
2375
|
+
.fb-mobile-btn[aria-pressed="true"] { border-color: var(--fb-primary); background: var(--fb-primary-soft); color: var(--fb-primary); }
|
|
2376
|
+
.fb-mobile-backdrop { display: none; }
|
|
2377
|
+
@media (max-width: 720px) {
|
|
2378
|
+
.fb-mobile-bar { display: flex; }
|
|
2379
|
+
.fb-work-area { flex-direction: column !important; min-height: 0; }
|
|
2380
|
+
.fb-canvas-area { position: relative; overflow: hidden; }
|
|
2381
|
+
.fb-canvas { width: 100%; }
|
|
2382
|
+
.fb-mobile-backdrop { display: block; position: absolute; inset: 0; z-index: 6; background: rgba(15,16,20,0.35); }
|
|
2383
|
+
.fb-palette, .fb-inspector {
|
|
2384
|
+
position: absolute; top: 0; bottom: 0; z-index: 7;
|
|
2385
|
+
width: min(260px, 80vw) !important; max-height: none !important;
|
|
2386
|
+
border: none !important;
|
|
2387
|
+
box-shadow: 0 0 24px rgba(0,0,0,0.18);
|
|
2388
|
+
transition: transform 0.18s ease;
|
|
2389
|
+
}
|
|
2390
|
+
.fb-palette { left: 0; transform: translateX(-100%); }
|
|
2391
|
+
.fb-inspector { right: 0; transform: translateX(100%); }
|
|
2392
|
+
.fb-work-area[data-mobile-panel="palette"] .fb-palette,
|
|
2393
|
+
.fb-work-area[data-mobile-panel="inspector"] .fb-inspector { transform: translateX(0); }
|
|
2394
|
+
}
|
|
2292
2395
|
`;
|
|
2293
2396
|
|
|
2294
2397
|
// src/FormBuilder.tsx
|
|
@@ -2299,11 +2402,12 @@ var FormBuilder = forwardRef(function FormBuilder2({
|
|
|
2299
2402
|
languages = DEFAULT_LANGUAGES,
|
|
2300
2403
|
strings: stringsOverride,
|
|
2301
2404
|
chrome: chromeOverride,
|
|
2302
|
-
|
|
2405
|
+
features: featuresProp,
|
|
2303
2406
|
storage: storageProp,
|
|
2304
2407
|
onSubmit,
|
|
2305
2408
|
initialDocument
|
|
2306
2409
|
}, ref) {
|
|
2410
|
+
const features = resolveFeatures(featuresProp);
|
|
2307
2411
|
const storage = storageProp ?? localStorageAdapter;
|
|
2308
2412
|
const { theme, updateThemeColor, updateThemeLayout, resetTheme, replaceThemeOverrides, themeOverrides } = useTheme(themeOverrideProp);
|
|
2309
2413
|
const [language, setLanguage] = useState8(languageOverride || languages[0]?.code || "en");
|
|
@@ -2315,8 +2419,10 @@ var FormBuilder = forwardRef(function FormBuilder2({
|
|
|
2315
2419
|
const [showJson, setShowJson] = useState8(false);
|
|
2316
2420
|
const [showLibrary, setShowLibrary] = useState8(false);
|
|
2317
2421
|
const [copied, setCopied] = useState8(false);
|
|
2422
|
+
const [mobilePanel, setMobilePanel] = useState8("none");
|
|
2318
2423
|
const persistence = usePersistence({
|
|
2319
2424
|
storage,
|
|
2425
|
+
autosave: features.autosave,
|
|
2320
2426
|
language,
|
|
2321
2427
|
chrome,
|
|
2322
2428
|
document: { title: doc.title, themeOverrides, sections: doc.sections },
|
|
@@ -2370,6 +2476,7 @@ var FormBuilder = forwardRef(function FormBuilder2({
|
|
|
2370
2476
|
"--fb-surface": theme.surface,
|
|
2371
2477
|
"--fb-canvas": theme.canvas,
|
|
2372
2478
|
"--fb-page-bg": theme.pageBackground,
|
|
2479
|
+
"--fb-surface-2": mixHex(theme.surface, theme.ink, 0.06),
|
|
2373
2480
|
"--fb-space-page": `${theme.layout.pagePadding}px`,
|
|
2374
2481
|
"--fb-space-canvas": `${theme.layout.canvasPadding}px`,
|
|
2375
2482
|
"--fb-space-section": `${theme.layout.sectionGap}px`,
|
|
@@ -2389,6 +2496,7 @@ var FormBuilder = forwardRef(function FormBuilder2({
|
|
|
2389
2496
|
mode,
|
|
2390
2497
|
saveState: persistence.saveState,
|
|
2391
2498
|
chrome,
|
|
2499
|
+
features,
|
|
2392
2500
|
savedFormsCount: persistence.savedForms.length,
|
|
2393
2501
|
onTitleChange: doc.updateTitle,
|
|
2394
2502
|
onLanguageChange: setLanguage,
|
|
@@ -2402,63 +2510,102 @@ var FormBuilder = forwardRef(function FormBuilder2({
|
|
|
2402
2510
|
persistence.loadingDraft ? /* @__PURE__ */ jsxs16("div", { style: styles.loadingScreen, children: [
|
|
2403
2511
|
/* @__PURE__ */ jsx18(Loader22, { size: 20, className: "spin" }),
|
|
2404
2512
|
/* @__PURE__ */ jsx18("span", { style: { marginTop: 8, fontSize: 13, color: "var(--fb-muted)" }, children: chrome.loadingDraft })
|
|
2405
|
-
] }) : mode === "build" ? /* @__PURE__ */ jsxs16("div", { style: styles.workArea, children: [
|
|
2406
|
-
/* @__PURE__ */
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2513
|
+
] }) : mode === "build" ? /* @__PURE__ */ jsxs16("div", { className: "fb-work-area", style: styles.workArea, "data-mobile-panel": mobilePanel, children: [
|
|
2514
|
+
/* @__PURE__ */ jsxs16("div", { className: "fb-mobile-bar", children: [
|
|
2515
|
+
/* @__PURE__ */ jsxs16(
|
|
2516
|
+
"button",
|
|
2517
|
+
{
|
|
2518
|
+
type: "button",
|
|
2519
|
+
className: "fb-mobile-btn",
|
|
2520
|
+
"aria-pressed": mobilePanel === "palette",
|
|
2521
|
+
onClick: () => setMobilePanel((p) => p === "palette" ? "none" : "palette"),
|
|
2522
|
+
children: [
|
|
2523
|
+
/* @__PURE__ */ jsx18(Menu, { size: 14 }),
|
|
2524
|
+
" ",
|
|
2525
|
+
chrome.paletteTabBlocks
|
|
2526
|
+
]
|
|
2527
|
+
}
|
|
2528
|
+
),
|
|
2529
|
+
/* @__PURE__ */ jsxs16(
|
|
2530
|
+
"button",
|
|
2531
|
+
{
|
|
2532
|
+
type: "button",
|
|
2533
|
+
className: "fb-mobile-btn",
|
|
2534
|
+
"aria-pressed": mobilePanel === "inspector",
|
|
2535
|
+
onClick: () => setMobilePanel((p) => p === "inspector" ? "none" : "inspector"),
|
|
2536
|
+
children: [
|
|
2537
|
+
/* @__PURE__ */ jsx18(SlidersHorizontal, { size: 14 }),
|
|
2538
|
+
" ",
|
|
2539
|
+
chrome.properties
|
|
2540
|
+
]
|
|
2541
|
+
}
|
|
2542
|
+
)
|
|
2543
|
+
] }),
|
|
2544
|
+
/* @__PURE__ */ jsxs16("div", { className: "fb-canvas-area", style: styles.workArea, children: [
|
|
2545
|
+
mobilePanel !== "none" && /* @__PURE__ */ jsx18("div", { className: "fb-mobile-backdrop", onClick: () => setMobilePanel("none") }),
|
|
2546
|
+
/* @__PURE__ */ jsx18(
|
|
2547
|
+
Palette,
|
|
2548
|
+
{
|
|
2549
|
+
activeSectionLabel,
|
|
2550
|
+
chrome,
|
|
2551
|
+
onAddField: (type) => {
|
|
2552
|
+
doc.addField(type);
|
|
2553
|
+
setMobilePanel("none");
|
|
2554
|
+
},
|
|
2555
|
+
features,
|
|
2556
|
+
theme,
|
|
2557
|
+
updateThemeColor,
|
|
2558
|
+
updateThemeLayout,
|
|
2559
|
+
resetTheme
|
|
2560
|
+
}
|
|
2561
|
+
),
|
|
2562
|
+
/* @__PURE__ */ jsx18(
|
|
2563
|
+
Canvas,
|
|
2564
|
+
{
|
|
2565
|
+
sections: doc.sections,
|
|
2566
|
+
activeSectionId: doc.activeSectionId,
|
|
2567
|
+
selectedId: doc.selectedId,
|
|
2568
|
+
dragOverKey: drag.dragOverKey,
|
|
2569
|
+
chrome,
|
|
2570
|
+
strings,
|
|
2571
|
+
language,
|
|
2572
|
+
features,
|
|
2573
|
+
onActivateSection: doc.setActiveSectionId,
|
|
2574
|
+
onToggleSectionCollapse: doc.toggleSectionCollapse,
|
|
2575
|
+
onUpdateSectionTitle: doc.updateSectionTitle,
|
|
2576
|
+
onUpdateSectionBackground: doc.updateSectionBackground,
|
|
2577
|
+
onDuplicateSection: doc.duplicateSection,
|
|
2578
|
+
onMoveSection: doc.moveSection,
|
|
2579
|
+
onDeleteSection: doc.deleteSection,
|
|
2580
|
+
onAddSection: doc.addSection,
|
|
2581
|
+
onSelectField: (sectionId, fieldId) => {
|
|
2582
|
+
doc.setSelectedId(fieldId);
|
|
2583
|
+
doc.setActiveSectionId(sectionId);
|
|
2584
|
+
setMobilePanel("inspector");
|
|
2585
|
+
},
|
|
2586
|
+
onFieldChange: doc.updateField,
|
|
2587
|
+
onMoveField: doc.moveField,
|
|
2588
|
+
onDuplicateField: doc.duplicateField,
|
|
2589
|
+
onDeleteField: doc.deleteField,
|
|
2590
|
+
getDropZoneHandlers: drag.getDropZoneHandlers,
|
|
2591
|
+
getDragHandleProps: drag.getDragHandleProps
|
|
2592
|
+
}
|
|
2593
|
+
),
|
|
2594
|
+
/* @__PURE__ */ jsx18(
|
|
2595
|
+
Inspector,
|
|
2596
|
+
{
|
|
2597
|
+
selected: doc.selected,
|
|
2598
|
+
language,
|
|
2599
|
+
chrome,
|
|
2600
|
+
features,
|
|
2601
|
+
onUpdateField: (patch) => doc.selected && doc.updateField(doc.selected.id, patch),
|
|
2602
|
+
onDeleteField: () => doc.selected && doc.deleteField(doc.selected.id),
|
|
2603
|
+
onUpdateOption: (optIdx, patch) => doc.selected && doc.updateOption(doc.selected.id, optIdx, patch),
|
|
2604
|
+
onAddOption: () => doc.selected && doc.addOption(doc.selected.id),
|
|
2605
|
+
onRemoveOption: (optIdx) => doc.selected && doc.removeOption(doc.selected.id, optIdx)
|
|
2606
|
+
}
|
|
2607
|
+
)
|
|
2608
|
+
] })
|
|
2462
2609
|
] }) : /* @__PURE__ */ jsx18(
|
|
2463
2610
|
PreviewPane,
|
|
2464
2611
|
{
|
|
@@ -2499,7 +2646,24 @@ var FormBuilder = forwardRef(function FormBuilder2({
|
|
|
2499
2646
|
] });
|
|
2500
2647
|
});
|
|
2501
2648
|
var FormBuilder_default = FormBuilder;
|
|
2649
|
+
|
|
2650
|
+
// src/theme/darkTheme.ts
|
|
2651
|
+
var DARK_THEME = {
|
|
2652
|
+
primary: "#8B8FF5",
|
|
2653
|
+
primarySoft: "#262A45",
|
|
2654
|
+
danger: "#F0715B",
|
|
2655
|
+
dangerSoft: "#3A2420",
|
|
2656
|
+
ink: "#EDEEF2",
|
|
2657
|
+
muted: "#9096A8",
|
|
2658
|
+
border: "#2E313D",
|
|
2659
|
+
surface: "#1A1B23",
|
|
2660
|
+
canvas: "#121319",
|
|
2661
|
+
pageBackground: "#1A1B23",
|
|
2662
|
+
layout: DEFAULT_THEME.layout
|
|
2663
|
+
};
|
|
2502
2664
|
export {
|
|
2665
|
+
DARK_THEME,
|
|
2666
|
+
DEFAULT_THEME,
|
|
2503
2667
|
FormBuilder_default as FormBuilder,
|
|
2504
2668
|
FormBuilder_default as default,
|
|
2505
2669
|
localStorageAdapter
|