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/dist/index.cjs CHANGED
@@ -21,6 +21,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  // src/index.ts
22
22
  var index_exports = {};
23
23
  __export(index_exports, {
24
+ DARK_THEME: () => DARK_THEME,
25
+ DEFAULT_THEME: () => DEFAULT_THEME,
24
26
  FormBuilder: () => FormBuilder_default,
25
27
  default: () => FormBuilder_default,
26
28
  localStorageAdapter: () => localStorageAdapter
@@ -360,6 +362,22 @@ function withLang(val, lang, value) {
360
362
  return { ...base, [lang]: value };
361
363
  }
362
364
 
365
+ // src/lib/color.ts
366
+ function mixHex(a, b, t2) {
367
+ const pa = parseHex(a);
368
+ const pb = parseHex(b);
369
+ if (!pa || !pb) return a;
370
+ const mix = (x, y) => Math.round(x + (y - x) * t2);
371
+ const toHex = (n) => n.toString(16).padStart(2, "0");
372
+ return `#${toHex(mix(pa[0], pb[0]))}${toHex(mix(pa[1], pb[1]))}${toHex(mix(pa[2], pb[2]))}`;
373
+ }
374
+ function parseHex(hex) {
375
+ const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());
376
+ if (!m) return null;
377
+ const n = parseInt(m[1], 16);
378
+ return [n >> 16 & 255, n >> 8 & 255, n & 255];
379
+ }
380
+
363
381
  // src/lib/storage/compress.ts
364
382
  var import_lz_string = require("lz-string");
365
383
  function compress(raw) {
@@ -615,6 +633,37 @@ function migrateDocument(raw) {
615
633
  return { title, themeOverrides, sections };
616
634
  }
617
635
 
636
+ // src/lib/features.ts
637
+ var DEFAULT_FEATURES = {
638
+ naming: true,
639
+ templates: true,
640
+ newForm: true,
641
+ autosave: true,
642
+ jsonView: true,
643
+ previewMode: true,
644
+ languageSwitcher: true,
645
+ design: false,
646
+ blockStyling: true,
647
+ contentBlocks: true,
648
+ fieldTypes: true,
649
+ sections: true,
650
+ dragReorder: true
651
+ };
652
+ function resolveFeatures(features) {
653
+ return {
654
+ ...DEFAULT_FEATURES,
655
+ ...features,
656
+ contentBlocks: Array.isArray(features?.contentBlocks) ? new Set(features.contentBlocks) : features?.contentBlocks ?? DEFAULT_FEATURES.contentBlocks,
657
+ fieldTypes: Array.isArray(features?.fieldTypes) ? new Set(features.fieldTypes) : features?.fieldTypes ?? DEFAULT_FEATURES.fieldTypes
658
+ };
659
+ }
660
+ function isContentBlockEnabled(features, type) {
661
+ return features.contentBlocks === true || features.contentBlocks instanceof Set && features.contentBlocks.has(type);
662
+ }
663
+ function isFieldTypeEnabled(features, type) {
664
+ return features.fieldTypes === true || features.fieldTypes instanceof Set && features.fieldTypes.has(type);
665
+ }
666
+
618
667
  // src/hooks/useTheme.ts
619
668
  var import_react = require("react");
620
669
 
@@ -849,6 +898,7 @@ var formKey = (id) => `form-page-builder:saved:${id}`;
849
898
  var MAX_TEMPLATES = 5;
850
899
  function usePersistence({
851
900
  storage,
901
+ autosave,
852
902
  language,
853
903
  chrome,
854
904
  document,
@@ -910,7 +960,7 @@ function usePersistence({
910
960
  refreshLibrary();
911
961
  }, []);
912
962
  (0, import_react3.useEffect)(() => {
913
- if (!hasLoadedOnce.current) return;
963
+ if (!hasLoadedOnce.current || !autosave) return;
914
964
  setSaveState("saving");
915
965
  if (autosaveTimer.current) clearTimeout(autosaveTimer.current);
916
966
  autosaveTimer.current = setTimeout(async () => {
@@ -1049,15 +1099,15 @@ var styles = {
1049
1099
  titleInput: { border: "none", outline: "none", fontSize: 14, fontWeight: 600, background: "transparent", color: "var(--fb-ink)", padding: "4px 6px", borderRadius: 6, minWidth: 160 },
1050
1100
  toolbarRight: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" },
1051
1101
  toolbarDivider: { width: 1, height: 20, background: "var(--fb-border)", margin: "0 4px" },
1052
- tabBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid transparent", background: "transparent", color: "#6B6E79", fontSize: 13, fontWeight: 500 },
1102
+ 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 },
1053
1103
  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 },
1054
- ghostBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid var(--fb-border)", background: "var(--fb-surface)", color: "#4A4D57", fontSize: 13, fontWeight: 500 },
1104
+ 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 },
1055
1105
  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 },
1056
1106
  saveStatus: { display: "flex", alignItems: "center", gap: 5, fontSize: 12, color: "var(--fb-muted)", minWidth: 60 },
1057
1107
  countBadge: { fontSize: 10.5, fontWeight: 700, background: "var(--fb-primary-soft)", color: "var(--fb-primary)", borderRadius: 9, padding: "1px 6px", marginLeft: 2 },
1058
1108
  loadingScreen: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
1059
1109
  libraryBody: { padding: "var(--fb-space-panel)", overflowY: "auto", display: "flex", flexDirection: "column", gap: 4 },
1060
- libraryRow: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10, padding: "10px 8px", borderRadius: 8, border: "1px solid #F0F1F4" },
1110
+ libraryRow: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10, padding: "10px 8px", borderRadius: 8, border: "1px solid var(--fb-border)" },
1061
1111
  libraryRowTitle: { fontSize: 13.5, fontWeight: 600, color: "var(--fb-ink)", display: "flex", alignItems: "center", gap: 8, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
1062
1112
  libraryRowMeta: { fontSize: 11.5, color: "var(--fb-muted)", marginTop: 2 },
1063
1113
  currentBadge: { fontSize: 10, fontWeight: 700, color: "var(--fb-primary)", background: "var(--fb-primary-soft)", padding: "2px 6px", borderRadius: 5, flexShrink: 0 },
@@ -1066,7 +1116,7 @@ var styles = {
1066
1116
  panelHeading: { fontSize: 11, fontWeight: 700, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--fb-muted)", marginBottom: 10 },
1067
1117
  activeSectionHint: { fontSize: 11.5, color: "var(--fb-muted)", marginBottom: 14, lineHeight: 1.4 },
1068
1118
  paletteList: { display: "flex", flexDirection: "column", gap: 4 },
1069
- paletteItem: { display: "flex", alignItems: "center", gap: 9, padding: "8px 9px", borderRadius: 8, border: "1px solid transparent", background: "transparent", fontSize: 13, color: "#33353E", textAlign: "left" },
1119
+ 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" },
1070
1120
  canvas: { flex: 1, padding: "var(--fb-space-canvas)", overflowY: "auto", background: "var(--fb-canvas)" },
1071
1121
  sectionBlock: { borderRadius: 12, padding: "var(--fb-space-panel)", marginBottom: "var(--fb-space-section)", transition: "border-color 0.12s" },
1072
1122
  sectionHeader: { display: "flex", alignItems: "center", gap: 8, marginBottom: 12, flexWrap: "wrap" },
@@ -1076,7 +1126,7 @@ var styles = {
1076
1126
  sectionHeaderActions: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap", marginLeft: "auto" },
1077
1127
  sectionEmpty: { fontSize: 12.5, color: "var(--fb-muted)", padding: "18px 4px", textAlign: "center", border: "1px dashed var(--fb-border)", borderRadius: 8 },
1078
1128
  resetLinkBtn: { display: "flex", alignItems: "center", gap: 3, fontSize: 11, color: "var(--fb-muted)", background: "transparent", border: "none", padding: "2px 4px" },
1079
- addSectionBtn: { display: "flex", alignItems: "center", justifyContent: "center", gap: 6, width: "100%", padding: "10px", borderRadius: 10, border: "1px dashed #C7C9D6", background: "transparent", color: "var(--fb-primary)", fontSize: 13, fontWeight: 600 },
1129
+ 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 },
1080
1130
  swatchRow: { display: "flex", alignItems: "center", gap: 5, flexWrap: "wrap" },
1081
1131
  swatchBtn: { width: 20, height: 20, borderRadius: "50%", border: "1px solid var(--fb-border)", padding: 0 },
1082
1132
  swatchBtnActive: { border: "2px solid var(--fb-primary)" },
@@ -1085,56 +1135,56 @@ var styles = {
1085
1135
  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" },
1086
1136
  ticketSelected: { borderColor: "var(--fb-primary)", boxShadow: "0 0 0 3px var(--fb-primary-soft)" },
1087
1137
  ticketDragOver: { borderColor: "var(--fb-muted)" },
1088
- ticketIndex: { fontFamily: "'JetBrains Mono', monospace", fontSize: 13, fontWeight: 700, color: "#C7C9D6", width: 34, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 },
1138
+ ticketIndex: { fontFamily: "'JetBrains Mono', monospace", fontSize: 13, fontWeight: 700, color: "var(--fb-border)", width: 34, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 },
1089
1139
  ticketPerforation: { width: 0, borderLeft: "1px dashed var(--fb-border)" },
1090
1140
  ticketBody: { flex: 1, padding: "10px var(--fb-space-ticket)", minWidth: 0 },
1091
1141
  ticketTop: { display: "flex", alignItems: "center", gap: 7, marginBottom: 4 },
1092
1142
  typeBadge: { fontSize: 10.5, fontFamily: "'JetBrains Mono', monospace", color: "var(--fb-muted)" },
1093
- requiredBadge: { fontSize: 10, fontWeight: 700, color: "#B4522F", background: "var(--fb-danger-soft)", padding: "2px 6px", borderRadius: 5, letterSpacing: "0.02em", marginLeft: "auto" },
1143
+ requiredBadge: { fontSize: 10, fontWeight: 700, color: "var(--fb-danger)", background: "var(--fb-danger-soft)", padding: "2px 6px", borderRadius: 5, letterSpacing: "0.02em", marginLeft: "auto" },
1094
1144
  chipRow: { display: "flex", gap: 5, marginBottom: 7, flexWrap: "wrap" },
1095
1145
  miniBadge: { fontSize: 10, fontWeight: 600, color: "var(--fb-primary)", background: "var(--fb-primary-soft)", padding: "2px 6px", borderRadius: 5, letterSpacing: "0.02em" },
1096
- langToggleTrack: { position: "relative", display: "flex", gap: 3, background: "#F0F1F4", padding: 3, borderRadius: 20 },
1146
+ langToggleTrack: { position: "relative", display: "flex", gap: 3, background: "var(--fb-surface-2)", padding: 3, borderRadius: 20 },
1097
1147
  langToggleThumb: { position: "absolute", top: 3, left: 3, bottom: 3, background: "var(--fb-primary)", borderRadius: 17, transition: "transform 0.18s ease" },
1098
- langToggleBtn: { position: "relative", zIndex: 1, padding: "5px 12px", borderRadius: 17, border: "none", background: "transparent", color: "#6B6E79", fontSize: 12.5, fontWeight: 600, whiteSpace: "nowrap" },
1148
+ 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" },
1099
1149
  langToggleBtnActive: { position: "relative", zIndex: 1, padding: "5px 12px", borderRadius: 17, border: "none", background: "transparent", color: "#fff", fontSize: 12.5, fontWeight: 600, whiteSpace: "nowrap" },
1100
- segmented: { display: "flex", gap: 3, background: "#F0F1F4", padding: 3, borderRadius: 8, marginBottom: 4 },
1101
- segmentedBtn: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 5, padding: "6px 8px", borderRadius: 6, border: "none", background: "transparent", color: "#6B6E79", fontSize: 12.5, fontWeight: 500 },
1102
- segmentedBtnActive: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 5, padding: "6px 8px", borderRadius: 6, border: "none", background: "#fff", color: "var(--fb-ink)", fontSize: 12.5, fontWeight: 600, boxShadow: "0 1px 2px rgba(0,0,0,0.08)" },
1150
+ segmented: { display: "flex", gap: 3, background: "var(--fb-surface-2)", padding: 3, borderRadius: 8, marginBottom: 4 },
1151
+ 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 },
1152
+ 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)" },
1103
1153
  iconGrid: { display: "grid", gridTemplateColumns: "repeat(6, 1fr)", gap: 5, marginTop: 6 },
1104
- iconGridBtn: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-border)", background: "#fff", display: "flex", alignItems: "center", justifyContent: "center", color: "#6B6E79" },
1154
+ 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)" },
1105
1155
  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)" },
1106
1156
  styleToggleRow: { display: "flex", gap: 5, marginBottom: 4 },
1107
- styleToggle: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-border)", background: "#fff", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
1157
+ 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)" },
1108
1158
  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)" },
1109
- previewInput: { border: "1px solid #E9EAEE", borderRadius: 7, padding: "7px 10px", fontSize: 13, color: "var(--fb-muted)", background: "#FBFBFD", display: "flex", alignItems: "center", justifyContent: "space-between" },
1110
- previewRadio: { display: "flex", alignItems: "center", gap: 6, fontSize: 13, color: "#4A4D57" },
1111
- ticketActions: { display: "flex", flexDirection: "column", gap: 3, padding: 8, borderLeft: "1px solid #F0F1F4" },
1112
- iconBtn: { width: 24, height: 24, borderRadius: 6, border: "1px solid #E9EAEE", background: "#fff", display: "flex", alignItems: "center", justifyContent: "center", color: "#6B6E79" },
1159
+ 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" },
1160
+ previewRadio: { display: "flex", alignItems: "center", gap: 6, fontSize: 13, color: "var(--fb-ink)" },
1161
+ ticketActions: { display: "flex", flexDirection: "column", gap: 3, padding: 8, borderLeft: "1px solid var(--fb-border)" },
1162
+ 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)" },
1113
1163
  iconBtnDanger: { color: "var(--fb-danger)" },
1114
1164
  inspector: { width: 270, borderLeft: "1px solid var(--fb-border)", background: "var(--fb-surface)", padding: "var(--fb-space-panel)", overflowY: "auto" },
1115
1165
  inspectorEmpty: { fontSize: 13, color: "var(--fb-muted)", lineHeight: 1.5, marginTop: 6 },
1116
1166
  inspectorBody: { display: "flex", flexDirection: "column", gap: 4 },
1117
1167
  helperText: { fontSize: 11, color: "var(--fb-muted)", lineHeight: 1.4, margin: "2px 0 4px" },
1118
- propLabel: { fontSize: 11.5, fontWeight: 600, color: "#6B6E79", marginTop: 12, marginBottom: 5 },
1119
- 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" },
1168
+ propLabel: { fontSize: 11.5, fontWeight: 600, color: "var(--fb-muted)", marginTop: 12, marginBottom: 5 },
1169
+ 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" },
1120
1170
  optionList: { display: "flex", flexDirection: "column", gap: 6 },
1121
1171
  optionRow: { display: "flex", gap: 6, alignItems: "center" },
1122
- optionInput: { flex: 1, border: "1px solid var(--fb-border)", borderRadius: 6, padding: "6px 8px", fontSize: 12.5, outline: "none", minWidth: 0, boxSizing: "border-box" },
1123
- addOptionBtn: { display: "flex", alignItems: "center", gap: 5, fontSize: 12.5, color: "var(--fb-primary)", background: "transparent", border: "1px dashed #C7C9D6", borderRadius: 7, padding: "6px 8px", justifyContent: "center", marginTop: 2 },
1172
+ 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" },
1173
+ 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 },
1124
1174
  toggleRow: { display: "flex", alignItems: "center", gap: 8, background: "transparent", border: "none", padding: "8px 0" },
1125
1175
  toggleTrack: { width: 30, height: 17, borderRadius: 20, position: "relative", transition: "background 0.15s", display: "inline-block" },
1126
1176
  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)" },
1127
1177
  inspectorDivider: { height: 1, background: "var(--fb-border)", margin: "14px 0 10px" },
1128
1178
  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" },
1129
- modalOverlay: { position: "fixed", inset: 0, background: "rgba(20,22,28,0.45)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 50 },
1130
- modal: { background: "#fff", borderRadius: 12, width: 520, maxHeight: "70vh", display: "flex", flexDirection: "column", overflow: "hidden", boxShadow: "0 20px 60px rgba(0,0,0,0.25)" },
1179
+ 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" },
1180
+ 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" },
1131
1181
  modalHeader: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "12px 16px", borderBottom: "1px solid var(--fb-border)" },
1132
1182
  jsonPre: { margin: 0, padding: 16, fontSize: 12, lineHeight: 1.6, overflow: "auto", background: "#14171C", color: "#D6D8E0", fontFamily: "'JetBrains Mono', monospace" },
1133
1183
  previewWrap: { flex: 1, display: "flex", justifyContent: "center", padding: "var(--fb-space-page) 20px", overflowY: "auto", background: "var(--fb-canvas)" },
1134
1184
  previewToolbar: { width: "100%", display: "flex", gap: 10, marginBottom: 16, justifyContent: "center" },
1135
1185
  previewCard: { width: "100%", maxWidth: 480, background: "var(--fb-page-bg)", border: "1px solid var(--fb-border)", borderRadius: 12, padding: "var(--fb-space-page)" },
1136
1186
  previewTitle: { fontSize: 19, fontWeight: 700, margin: "0 0 20px" },
1137
- previewLabel: { display: "block", fontSize: 13, fontWeight: 600, color: "#33353E", marginBottom: 6 },
1187
+ previewLabel: { display: "block", fontSize: 13, fontWeight: 600, color: "var(--fb-ink)", marginBottom: 6 },
1138
1188
  previewGrid: { display: "flex", flexWrap: "wrap", gap: "var(--fb-space-field)" },
1139
1189
  sectionRuntimeTitle: { fontSize: 15, fontWeight: 700, margin: "0 0 12px", color: "var(--fb-ink)" },
1140
1190
  imagePlaceholder: { display: "flex", alignItems: "center", justifyContent: "center", border: "1px dashed var(--fb-border)" },
@@ -1144,13 +1194,13 @@ var styles = {
1144
1194
  submittedRow: { display: "flex", justifyContent: "space-between", gap: 12, fontSize: 13, padding: "6px 0", borderBottom: "1px solid var(--fb-border)" },
1145
1195
  submittedLabel: { color: "var(--fb-muted)", flexShrink: 0 },
1146
1196
  submittedValue: { color: "var(--fb-ink)", fontWeight: 600, textAlign: "right" },
1147
- 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" },
1197
+ 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" },
1148
1198
  realInputError: { borderColor: "var(--fb-danger)" },
1149
1199
  submitBtn: { marginTop: 8, color: "#fff", border: "none", borderRadius: 8, fontWeight: 600, width: "100%" },
1150
1200
  layoutPanelHeader: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 4 },
1151
1201
  spacingRow: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, padding: "4px 0" },
1152
- spacingLabel: { fontSize: 12, color: "#4A4D57" },
1153
- spacingInput: { width: 60, border: "1px solid var(--fb-border)", borderRadius: 6, padding: "4px 6px", fontSize: 12, textAlign: "right", outline: "none" }
1202
+ spacingLabel: { fontSize: 12, color: "var(--fb-ink)" },
1203
+ 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" }
1154
1204
  };
1155
1205
 
1156
1206
  // src/components/LanguageToggle.tsx
@@ -1191,6 +1241,7 @@ function Toolbar({
1191
1241
  mode,
1192
1242
  saveState,
1193
1243
  chrome,
1244
+ features,
1194
1245
  savedFormsCount,
1195
1246
  onTitleChange,
1196
1247
  onLanguageChange,
@@ -1203,7 +1254,7 @@ function Toolbar({
1203
1254
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.toolbar, children: [
1204
1255
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.toolbarLeft, children: [
1205
1256
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.logoMark, children: "FB" }),
1206
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { value: t(title, language), onChange: (e) => onTitleChange(e.target.value), style: styles.titleInput, "aria-label": "Form title" })
1257
+ features.naming ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("input", { value: t(title, language), onChange: (e) => onTitleChange(e.target.value), style: styles.titleInput, "aria-label": "Form title" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.titleInput, children: t(title, language) })
1207
1258
  ] }),
1208
1259
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.toolbarRight, children: [
1209
1260
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.saveStatus, children: [
@@ -1219,37 +1270,43 @@ function Toolbar({
1219
1270
  chrome.saveFailed
1220
1271
  ] })
1221
1272
  ] }),
1222
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.toolbarDivider }),
1223
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LanguageToggle, { languages, value: language, onChange: onLanguageChange }),
1224
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.toolbarDivider }),
1225
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: mode === "build" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("build"), children: [
1226
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Pencil, { size: 14 }),
1227
- " ",
1228
- chrome.build
1273
+ features.languageSwitcher && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1274
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.toolbarDivider }),
1275
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LanguageToggle, { languages, value: language, onChange: onLanguageChange })
1229
1276
  ] }),
1230
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: mode === "preview" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("preview"), children: [
1231
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Eye, { size: 14 }),
1232
- " ",
1233
- chrome.preview
1277
+ features.previewMode && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1278
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.toolbarDivider }),
1279
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: mode === "build" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("build"), children: [
1280
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Pencil, { size: 14 }),
1281
+ " ",
1282
+ chrome.build
1283
+ ] }),
1284
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: mode === "preview" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("preview"), children: [
1285
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Eye, { size: 14 }),
1286
+ " ",
1287
+ chrome.preview
1288
+ ] })
1234
1289
  ] }),
1235
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.toolbarDivider }),
1236
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.ghostBtn, onClick: onNewForm, title: chrome.startNewForm, children: [
1290
+ (features.newForm || features.templates) && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.toolbarDivider }),
1291
+ features.newForm && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.ghostBtn, onClick: onNewForm, title: chrome.startNewForm, children: [
1237
1292
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.FilePlus2, { size: 14 }),
1238
1293
  " ",
1239
1294
  chrome.newForm
1240
1295
  ] }),
1241
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.ghostBtn, onClick: onOpenLibrary, title: chrome.openTemplatesTitle, children: [
1242
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.FolderOpen, { size: 14 }),
1243
- " ",
1244
- chrome.templates,
1245
- savedFormsCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.countBadge, children: savedFormsCount })
1246
- ] }),
1247
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.primaryBtn, onClick: onSaveExisting, title: chrome.saveToLibraryTitle, children: [
1248
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Save, { size: 14 }),
1249
- " ",
1250
- chrome.save
1296
+ features.templates && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1297
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.ghostBtn, onClick: onOpenLibrary, title: chrome.openTemplatesTitle, children: [
1298
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.FolderOpen, { size: 14 }),
1299
+ " ",
1300
+ chrome.templates,
1301
+ savedFormsCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.countBadge, children: savedFormsCount })
1302
+ ] }),
1303
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.primaryBtn, onClick: onSaveExisting, title: chrome.saveToLibraryTitle, children: [
1304
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Save, { size: 14 }),
1305
+ " ",
1306
+ chrome.save
1307
+ ] })
1251
1308
  ] }),
1252
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.ghostBtn, onClick: onOpenJson, children: [
1309
+ features.jsonView && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.ghostBtn, onClick: onOpenJson, children: [
1253
1310
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Code2, { size: 14 }),
1254
1311
  " ",
1255
1312
  chrome.viewJson
@@ -1350,15 +1407,17 @@ function Palette({
1350
1407
  activeSectionLabel,
1351
1408
  chrome,
1352
1409
  onAddField,
1353
- themeEditable,
1410
+ features,
1354
1411
  theme,
1355
1412
  updateThemeColor,
1356
1413
  updateThemeLayout,
1357
1414
  resetTheme
1358
1415
  }) {
1359
1416
  const [tab, setTab] = (0, import_react5.useState)("blocks");
1360
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: styles.palette, children: [
1361
- themeEditable && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { marginBottom: 14 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1417
+ const contentTypes = CONTENT_TYPES.filter((f) => isContentBlockEnabled(features, f.type));
1418
+ const formTypes = FORM_TYPES.filter((f) => isFieldTypeEnabled(features, f.type));
1419
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "fb-palette", style: styles.palette, children: [
1420
+ features.design && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { marginBottom: 14 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1362
1421
  Segmented,
1363
1422
  {
1364
1423
  options: [
@@ -1369,7 +1428,7 @@ function Palette({
1369
1428
  onChange: setTab
1370
1429
  }
1371
1430
  ) }),
1372
- tab === "design" && themeEditable ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1431
+ tab === "design" && features.design ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1373
1432
  DesignPanel,
1374
1433
  {
1375
1434
  chrome,
@@ -1384,24 +1443,28 @@ function Palette({
1384
1443
  " ",
1385
1444
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: activeSectionLabel })
1386
1445
  ] }),
1387
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.panelHeading, children: chrome.contentBlocks }),
1388
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.paletteList, children: CONTENT_TYPES.map((f) => {
1389
- const Icon = f.icon;
1390
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1391
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { size: 16, color: "var(--fb-primary)" }),
1392
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1393
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Plus, { size: 13, color: "#A6A8B3", style: { marginLeft: "auto" } })
1394
- ] }, f.type);
1395
- }) }),
1396
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { ...styles.panelHeading, marginTop: 16 }, children: chrome.formFields }),
1397
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.paletteList, children: FORM_TYPES.map((f) => {
1398
- const Icon = f.icon;
1399
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1400
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { size: 16, color: "var(--fb-primary)" }),
1401
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1402
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Plus, { size: 13, color: "#A6A8B3", style: { marginLeft: "auto" } })
1403
- ] }, f.type);
1404
- }) })
1446
+ contentTypes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1447
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.panelHeading, children: chrome.contentBlocks }),
1448
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.paletteList, children: contentTypes.map((f) => {
1449
+ const Icon = f.icon;
1450
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1451
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { size: 16, color: "var(--fb-primary)" }),
1452
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1453
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Plus, { size: 13, color: "var(--fb-muted)", style: { marginLeft: "auto" } })
1454
+ ] }, f.type);
1455
+ }) })
1456
+ ] }),
1457
+ formTypes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1458
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { ...styles.panelHeading, marginTop: 16 }, children: chrome.formFields }),
1459
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.paletteList, children: formTypes.map((f) => {
1460
+ const Icon = f.icon;
1461
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1462
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { size: 16, color: "var(--fb-primary)" }),
1463
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1464
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Plus, { size: 13, color: "var(--fb-muted)", style: { marginLeft: "auto" } })
1465
+ ] }, f.type);
1466
+ }) })
1467
+ ] })
1405
1468
  ] })
1406
1469
  ] });
1407
1470
  }
@@ -1530,7 +1593,7 @@ function FieldBlock({ field, lang, onFieldChange, strings, chrome, error, isBuil
1530
1593
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1531
1594
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: isInline ? "row" : "column", alignItems: isInline ? "center" : "stretch", gap: isInline ? 10 : 6 }, children: [
1532
1595
  showLabel && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: { ...styles.previewLabel, marginBottom: isInline ? 0 : 6, flexShrink: 0, width: isInline ? 120 : "auto", display: "flex", alignItems: "center", gap: 6 }, children: [
1533
- IconComp && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconComp, { size: 14, color: "#6B6E79" }),
1596
+ IconComp && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconComp, { size: 14, color: "var(--fb-muted)" }),
1534
1597
  labelText || (isBuild ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontStyle: "italic", color: "var(--fb-muted)" }, children: chrome?.untitledField || "Untitled field" }) : ""),
1535
1598
  field.required && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { color: "var(--fb-danger)" }, children: " *" })
1536
1599
  ] }),
@@ -1595,14 +1658,14 @@ function renderInteractive(field, lang, onFieldChange, IconComp, hasError, strin
1595
1658
  case "checkbox":
1596
1659
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: styles.previewRadio, children: [
1597
1660
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "checkbox", checked: !!value, onChange: (e) => set(e.target.checked), style: { accentColor: "var(--fb-primary)" } }),
1598
- IconComp && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconComp, { size: 14, color: "#6B6E79" }),
1661
+ IconComp && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconComp, { size: 14, color: "var(--fb-muted)" }),
1599
1662
  t(field.label, lang),
1600
1663
  field.required && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { color: "var(--fb-danger)" }, children: " *" })
1601
1664
  ] });
1602
1665
  case "toggle":
1603
1666
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: styles.previewRadio, children: [
1604
1667
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "checkbox", checked: !!value, onChange: (e) => set(e.target.checked), style: { accentColor: "var(--fb-primary)" } }),
1605
- IconComp && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconComp, { size: 14, color: "#6B6E79" }),
1668
+ IconComp && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconComp, { size: 14, color: "var(--fb-muted)" }),
1606
1669
  t(field.label, lang)
1607
1670
  ] });
1608
1671
  default:
@@ -1620,6 +1683,7 @@ function FieldTicket({
1620
1683
  chrome,
1621
1684
  strings,
1622
1685
  language,
1686
+ dragEnabled,
1623
1687
  onSelect,
1624
1688
  onFieldChange,
1625
1689
  onMoveField,
@@ -1649,7 +1713,7 @@ function FieldTicket({
1649
1713
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.ticketPerforation }),
1650
1714
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.ticketBody, children: [
1651
1715
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.ticketTop, children: [
1652
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { ...dragHandleProps, style: { cursor: "grab", display: "flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react10.GripVertical, { size: 14, color: "#C4C6D0" }) }),
1716
+ dragEnabled && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { ...dragHandleProps, style: { cursor: "grab", display: "flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react10.GripVertical, { size: 14, color: "var(--fb-muted)" }) }),
1653
1717
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Icon, { size: 13, color: "var(--fb-primary)" }),
1654
1718
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { style: styles.typeBadge, children: [
1655
1719
  chrome[FIELD_TYPE_CHROME_KEY[field.type]] || field.type,
@@ -1692,6 +1756,7 @@ function SectionCard({
1692
1756
  chrome,
1693
1757
  strings,
1694
1758
  language,
1759
+ features,
1695
1760
  onActivate,
1696
1761
  onToggleCollapse,
1697
1762
  onUpdateTitle,
@@ -1731,14 +1796,16 @@ function SectionCard({
1731
1796
  ),
1732
1797
  section.collapsed && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: styles.miniBadge, children: chrome.fieldsCount(section.fields.length) }),
1733
1798
  /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: styles.sectionHeaderActions, onClick: (e) => e.stopPropagation(), children: [
1734
- !section.collapsed && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: styles.swatchRow, children: [
1799
+ features.sections && !section.collapsed && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: styles.swatchRow, children: [
1735
1800
  SECTION_BG_SWATCHES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("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")),
1736
1801
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("input", { type: "color", title: chrome.customColor, value: /^#/.test(section.background) ? section.background : "#ffffff", onChange: (e) => onUpdateBackground(e.target.value), style: styles.colorPickerInput })
1737
1802
  ] }),
1738
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { style: styles.iconBtn, title: chrome.duplicate, onClick: onDuplicateSection, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react11.Copy, { size: 13 }) }),
1739
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { style: styles.iconBtn, title: chrome.moveUp, disabled: sIdx === 0, onClick: () => onMoveSection(-1), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react11.ArrowUp, { size: 13 }) }),
1740
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { style: styles.iconBtn, title: chrome.moveDown, disabled: sIdx === sectionsLength - 1, onClick: () => onMoveSection(1), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react11.ArrowDown, { size: 13 }) }),
1741
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { style: { ...styles.iconBtn, ...styles.iconBtnDanger }, title: chrome.deleteSection, disabled: sectionsLength <= 1, onClick: onDeleteSection, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react11.Trash2, { size: 13 }) })
1803
+ features.sections && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1804
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { style: styles.iconBtn, title: chrome.duplicate, onClick: onDuplicateSection, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react11.Copy, { size: 13 }) }),
1805
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { style: styles.iconBtn, title: chrome.moveUp, disabled: sIdx === 0, onClick: () => onMoveSection(-1), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react11.ArrowUp, { size: 13 }) }),
1806
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { style: styles.iconBtn, title: chrome.moveDown, disabled: sIdx === sectionsLength - 1, onClick: () => onMoveSection(1), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react11.ArrowDown, { size: 13 }) }),
1807
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { style: { ...styles.iconBtn, ...styles.iconBtnDanger }, title: chrome.deleteSection, disabled: sectionsLength <= 1, onClick: onDeleteSection, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react11.Trash2, { size: 13 }) })
1808
+ ] })
1742
1809
  ] })
1743
1810
  ] }),
1744
1811
  !section.collapsed && (section.fields.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: styles.sectionEmpty, children: chrome.noFieldsInSection }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: styles.fieldList, children: section.fields.map((field, idx) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
@@ -1752,6 +1819,7 @@ function SectionCard({
1752
1819
  chrome,
1753
1820
  strings,
1754
1821
  language,
1822
+ dragEnabled: features.dragReorder,
1755
1823
  onSelect: () => onSelectField(field.id),
1756
1824
  onFieldChange,
1757
1825
  onMoveField,
@@ -1777,6 +1845,7 @@ function Canvas({
1777
1845
  chrome,
1778
1846
  strings,
1779
1847
  language,
1848
+ features,
1780
1849
  onActivateSection,
1781
1850
  onToggleSectionCollapse,
1782
1851
  onUpdateSectionTitle,
@@ -1793,7 +1862,7 @@ function Canvas({
1793
1862
  getDropZoneHandlers,
1794
1863
  getDragHandleProps
1795
1864
  }) {
1796
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.canvas, children: [
1865
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "fb-canvas", style: styles.canvas, children: [
1797
1866
  sections.map((section, sIdx) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1798
1867
  SectionCard,
1799
1868
  {
@@ -1806,6 +1875,7 @@ function Canvas({
1806
1875
  chrome,
1807
1876
  strings,
1808
1877
  language,
1878
+ features,
1809
1879
  onActivate: () => onActivateSection(section.id),
1810
1880
  onToggleCollapse: () => onToggleSectionCollapse(section.id),
1811
1881
  onUpdateTitle: (value) => onUpdateSectionTitle(section.id, value),
@@ -1823,7 +1893,7 @@ function Canvas({
1823
1893
  },
1824
1894
  section.id
1825
1895
  )),
1826
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("button", { style: styles.addSectionBtn, onClick: onAddSection, children: [
1896
+ features.sections && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("button", { style: styles.addSectionBtn, onClick: onAddSection, children: [
1827
1897
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react12.Layers, { size: 14 }),
1828
1898
  " ",
1829
1899
  chrome.addSection
@@ -1844,7 +1914,7 @@ function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
1844
1914
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("label", { style: styles.propLabel, children: chrome.defaultValue }),
1845
1915
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { style: styles.toggleRow, onClick: () => onChange({ defaultValue: !f.defaultValue }), children: [
1846
1916
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { ...styles.toggleTrack, background: f.defaultValue ? "var(--fb-primary)" : "var(--fb-border)" }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { ...styles.toggleThumb, transform: f.defaultValue ? "translateX(16px)" : "translateX(0)" } }) }),
1847
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { fontSize: 13, color: "#4A4D57" }, children: f.defaultValue ? chrome.checked : chrome.unchecked })
1917
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: f.defaultValue ? chrome.checked : chrome.unchecked })
1848
1918
  ] })
1849
1919
  ] });
1850
1920
  }
@@ -1882,8 +1952,8 @@ function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
1882
1952
 
1883
1953
  // src/components/Inspector.tsx
1884
1954
  var import_jsx_runtime13 = require("react/jsx-runtime");
1885
- function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1886
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.inspector, children: [
1955
+ function Inspector({ selected, language, chrome, features, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1956
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "fb-inspector", style: styles.inspector, children: [
1887
1957
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.panelHeading, children: chrome.properties }),
1888
1958
  !selected ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.inspectorEmpty, children: chrome.selectFieldHint }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1889
1959
  InspectorBody,
@@ -1891,6 +1961,7 @@ function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, o
1891
1961
  selected,
1892
1962
  language,
1893
1963
  chrome,
1964
+ features,
1894
1965
  onUpdateField,
1895
1966
  onDeleteField,
1896
1967
  onUpdateOption,
@@ -1900,7 +1971,7 @@ function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, o
1900
1971
  )
1901
1972
  ] });
1902
1973
  }
1903
- function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1974
+ function InspectorBody({ selected, language, chrome, features, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1904
1975
  const meta = getMeta(selected.type);
1905
1976
  const f = selected;
1906
1977
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.inspectorBody, children: [
@@ -1909,7 +1980,7 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
1909
1980
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { style: styles.propInput, value: t(selected.label, language), onChange: (e) => onUpdateField({ label: withLang(selected.label, language, e.target.value) }) }),
1910
1981
  !meta.isContent && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: styles.toggleRow, children: [
1911
1982
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "checkbox", checked: !!selected.hideLabel, onChange: (e) => onUpdateField({ hideLabel: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
1912
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 13, color: "#4A4D57" }, children: chrome.hideLabel })
1983
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.hideLabel })
1913
1984
  ] })
1914
1985
  ] }),
1915
1986
  meta.hasSubtype && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
@@ -1919,23 +1990,25 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
1919
1990
  selected.type === "paragraph" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1920
1991
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.content }),
1921
1992
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("textarea", { style: { ...styles.propInput, minHeight: 70, resize: "vertical" }, value: t(selected.content, language), onChange: (e) => onUpdateField({ content: withLang(selected.content, language, e.target.value) }) }),
1922
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.inspectorDivider }),
1923
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.panelHeading, children: chrome.typography }),
1924
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.headingStyle }),
1925
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(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] }) }),
1926
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.width }),
1927
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Segmented, { options: FONT_SIZE_OPTIONS, value: selected.fontSize || "md", onChange: (v) => onUpdateField({ fontSize: v }) }),
1928
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.style }),
1929
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.styleToggleRow, children: [
1930
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", style: selected.fontWeight === "bold" ? styles.styleToggleActive : styles.styleToggle, onClick: () => onUpdateField({ fontWeight: selected.fontWeight === "bold" ? "normal" : "bold" }), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react13.Bold, { size: 14 }) }),
1931
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", style: selected.fontStyle === "italic" ? styles.styleToggleActive : styles.styleToggle, onClick: () => onUpdateField({ fontStyle: selected.fontStyle === "italic" ? "normal" : "italic" }), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react13.Italic, { size: 14 }) })
1932
- ] }),
1933
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.align }),
1934
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Segmented, { options: TEXT_ALIGN_OPTIONS, value: selected.textAlign || "left", onChange: (v) => onUpdateField({ textAlign: v }) }),
1935
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.color }),
1936
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.swatchRow, children: [
1937
- COLOR_SWATCHES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("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")),
1938
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "color", value: selected.color || "#1B1E24", onChange: (e) => onUpdateField({ color: e.target.value }), style: styles.colorPickerInput })
1993
+ features.blockStyling && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1994
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.inspectorDivider }),
1995
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.panelHeading, children: chrome.typography }),
1996
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.headingStyle }),
1997
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(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] }) }),
1998
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.width }),
1999
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Segmented, { options: FONT_SIZE_OPTIONS, value: selected.fontSize || "md", onChange: (v) => onUpdateField({ fontSize: v }) }),
2000
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.style }),
2001
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.styleToggleRow, children: [
2002
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", style: selected.fontWeight === "bold" ? styles.styleToggleActive : styles.styleToggle, onClick: () => onUpdateField({ fontWeight: selected.fontWeight === "bold" ? "normal" : "bold" }), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react13.Bold, { size: 14 }) }),
2003
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", style: selected.fontStyle === "italic" ? styles.styleToggleActive : styles.styleToggle, onClick: () => onUpdateField({ fontStyle: selected.fontStyle === "italic" ? "normal" : "italic" }), children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react13.Italic, { size: 14 }) })
2004
+ ] }),
2005
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.align }),
2006
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Segmented, { options: TEXT_ALIGN_OPTIONS, value: selected.textAlign || "left", onChange: (v) => onUpdateField({ textAlign: v }) }),
2007
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.color }),
2008
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.swatchRow, children: [
2009
+ COLOR_SWATCHES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("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")),
2010
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "color", value: selected.color || "#1B1E24", onChange: (e) => onUpdateField({ color: e.target.value }), style: styles.colorPickerInput })
2011
+ ] })
1939
2012
  ] })
1940
2013
  ] }),
1941
2014
  selected.type === "image" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
@@ -1964,13 +2037,15 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
1964
2037
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.submitScope }),
1965
2038
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Segmented, { options: [{ value: "section", label: chrome.thisSection }, { value: "form", label: chrome.wholeForm }], value: selected.submitScope || "form", onChange: (v) => onUpdateField({ submitScope: v }) })
1966
2039
  ] }),
1967
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.color }),
1968
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.swatchRow, children: [
1969
- BUTTON_COLOR_SWATCHES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("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")),
1970
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "color", value: selected.buttonStyle?.color || "#5B5FEF", onChange: (e) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, color: e.target.value } }), style: styles.colorPickerInput })
1971
- ] }),
1972
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.buttonSize }),
1973
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Segmented, { options: SUBMIT_SIZE_OPTIONS, value: selected.buttonStyle?.size || "md", onChange: (v) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, size: v } }) })
2040
+ features.blockStyling && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
2041
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.color }),
2042
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.swatchRow, children: [
2043
+ BUTTON_COLOR_SWATCHES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("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")),
2044
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "color", value: selected.buttonStyle?.color || "#5B5FEF", onChange: (e) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, color: e.target.value } }), style: styles.colorPickerInput })
2045
+ ] }),
2046
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.buttonSize }),
2047
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Segmented, { options: SUBMIT_SIZE_OPTIONS, value: selected.buttonStyle?.size || "md", onChange: (v) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, size: v } }) })
2048
+ ] })
1974
2049
  ] }),
1975
2050
  meta.placeholder && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1976
2051
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.placeholder }),
@@ -2007,7 +2082,7 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
2007
2082
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DefaultValueEditor, { field: selected, meta, lang: language, chrome, onChange: onUpdateField }),
2008
2083
  !meta.isContent && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: styles.toggleRow, children: [
2009
2084
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "checkbox", checked: !!selected.required, onChange: (e) => onUpdateField({ required: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
2010
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 13, color: "#4A4D57" }, children: chrome.requiredField })
2085
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.requiredField })
2011
2086
  ] }),
2012
2087
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.inspectorDivider }),
2013
2088
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.panelHeading, children: chrome.layout }),
@@ -2024,7 +2099,7 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
2024
2099
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.panelHeading, children: chrome.icon }),
2025
2100
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: styles.toggleRow, children: [
2026
2101
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "checkbox", checked: !!selected.showIcon, onChange: (e) => onUpdateField({ showIcon: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
2027
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 13, color: "#4A4D57" }, children: chrome.showIcon })
2102
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.showIcon })
2028
2103
  ] }),
2029
2104
  selected.showIcon && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.iconGrid, children: Object.keys(ICON_LIBRARY).map((key) => {
2030
2105
  const IconComp = ICON_LIBRARY[key];
@@ -2176,7 +2251,7 @@ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome
2176
2251
  })
2177
2252
  ] })
2178
2253
  ] }),
2179
- submitted && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: styles.modalOverlay, onClick: () => setSubmitted(null), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { ...styles.modal, width: 420 }, onClick: (e) => e.stopPropagation(), children: [
2254
+ submitted && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: styles.modalOverlay, onClick: () => setSubmitted(null), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { ...styles.modal, maxWidth: 420 }, onClick: (e) => e.stopPropagation(), children: [
2180
2255
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: styles.modalHeader, children: [
2181
2256
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { style: { fontWeight: 600, fontSize: 14, display: "flex", alignItems: "center", gap: 7 }, children: [
2182
2257
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react14.PartyPopper, { size: 15, color: "var(--fb-primary)" }),
@@ -2251,7 +2326,7 @@ var import_lucide_react17 = require("lucide-react");
2251
2326
  var import_jsx_runtime17 = require("react/jsx-runtime");
2252
2327
  function SaveAsModal({ chrome, suggestedName, onSave, onClose }) {
2253
2328
  const [name, setName] = (0, import_react7.useState)(suggestedName);
2254
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: { ...styles.modal, width: 380 }, onClick: (e) => e.stopPropagation(), children: [
2329
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: { ...styles.modal, maxWidth: 380 }, onClick: (e) => e.stopPropagation(), children: [
2255
2330
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: styles.modalHeader, children: [
2256
2331
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { fontWeight: 600, fontSize: 14 }, children: chrome.saveForm }),
2257
2332
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { style: styles.iconBtn, onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react17.X, { size: 16 }) })
@@ -2281,6 +2356,36 @@ var css = `
2281
2356
  that support it (mobile browser chrome resizing the viewport), and is
2282
2357
  simply ignored by ones that don't. */
2283
2358
  .fb-root { max-height: 100vh; max-height: 100dvh; }
2359
+
2360
+ /* Below this width the fixed 200px Palette + 270px Inspector columns
2361
+ don't leave room for a usable Canvas, so instead of stacking all
2362
+ three in flow (which buries Canvas under a tall Palette), Palette
2363
+ and Inspector become narrow drawers over Canvas (which stays
2364
+ partially visible behind them), toggled by .fb-mobile-bar's two
2365
+ buttons, tracked by .fb-work-area's data-mobile-panel attribute,
2366
+ and dismissible via .fb-mobile-backdrop. */
2367
+ .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; }
2368
+ .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; }
2369
+ .fb-mobile-btn[aria-pressed="true"] { border-color: var(--fb-primary); background: var(--fb-primary-soft); color: var(--fb-primary); }
2370
+ .fb-mobile-backdrop { display: none; }
2371
+ @media (max-width: 720px) {
2372
+ .fb-mobile-bar { display: flex; }
2373
+ .fb-work-area { flex-direction: column !important; min-height: 0; }
2374
+ .fb-canvas-area { position: relative; overflow: hidden; }
2375
+ .fb-canvas { width: 100%; }
2376
+ .fb-mobile-backdrop { display: block; position: absolute; inset: 0; z-index: 6; background: rgba(15,16,20,0.35); }
2377
+ .fb-palette, .fb-inspector {
2378
+ position: absolute; top: 0; bottom: 0; z-index: 7;
2379
+ width: min(260px, 80vw) !important; max-height: none !important;
2380
+ border: none !important;
2381
+ box-shadow: 0 0 24px rgba(0,0,0,0.18);
2382
+ transition: transform 0.18s ease;
2383
+ }
2384
+ .fb-palette { left: 0; transform: translateX(-100%); }
2385
+ .fb-inspector { right: 0; transform: translateX(100%); }
2386
+ .fb-work-area[data-mobile-panel="palette"] .fb-palette,
2387
+ .fb-work-area[data-mobile-panel="inspector"] .fb-inspector { transform: translateX(0); }
2388
+ }
2284
2389
  `;
2285
2390
 
2286
2391
  // src/FormBuilder.tsx
@@ -2291,11 +2396,12 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2291
2396
  languages = DEFAULT_LANGUAGES,
2292
2397
  strings: stringsOverride,
2293
2398
  chrome: chromeOverride,
2294
- themeEditable = false,
2399
+ features: featuresProp,
2295
2400
  storage: storageProp,
2296
2401
  onSubmit,
2297
2402
  initialDocument
2298
2403
  }, ref) {
2404
+ const features = resolveFeatures(featuresProp);
2299
2405
  const storage = storageProp ?? localStorageAdapter;
2300
2406
  const { theme, updateThemeColor, updateThemeLayout, resetTheme, replaceThemeOverrides, themeOverrides } = useTheme(themeOverrideProp);
2301
2407
  const [language, setLanguage] = (0, import_react8.useState)(languageOverride || languages[0]?.code || "en");
@@ -2307,8 +2413,10 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2307
2413
  const [showJson, setShowJson] = (0, import_react8.useState)(false);
2308
2414
  const [showLibrary, setShowLibrary] = (0, import_react8.useState)(false);
2309
2415
  const [copied, setCopied] = (0, import_react8.useState)(false);
2416
+ const [mobilePanel, setMobilePanel] = (0, import_react8.useState)("none");
2310
2417
  const persistence = usePersistence({
2311
2418
  storage,
2419
+ autosave: features.autosave,
2312
2420
  language,
2313
2421
  chrome,
2314
2422
  document: { title: doc.title, themeOverrides, sections: doc.sections },
@@ -2362,6 +2470,7 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2362
2470
  "--fb-surface": theme.surface,
2363
2471
  "--fb-canvas": theme.canvas,
2364
2472
  "--fb-page-bg": theme.pageBackground,
2473
+ "--fb-surface-2": mixHex(theme.surface, theme.ink, 0.06),
2365
2474
  "--fb-space-page": `${theme.layout.pagePadding}px`,
2366
2475
  "--fb-space-canvas": `${theme.layout.canvasPadding}px`,
2367
2476
  "--fb-space-section": `${theme.layout.sectionGap}px`,
@@ -2381,6 +2490,7 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2381
2490
  mode,
2382
2491
  saveState: persistence.saveState,
2383
2492
  chrome,
2493
+ features,
2384
2494
  savedFormsCount: persistence.savedForms.length,
2385
2495
  onTitleChange: doc.updateTitle,
2386
2496
  onLanguageChange: setLanguage,
@@ -2394,63 +2504,102 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2394
2504
  persistence.loadingDraft ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: styles.loadingScreen, children: [
2395
2505
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react18.Loader2, { size: 20, className: "spin" }),
2396
2506
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { style: { marginTop: 8, fontSize: 13, color: "var(--fb-muted)" }, children: chrome.loadingDraft })
2397
- ] }) : mode === "build" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: styles.workArea, children: [
2398
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2399
- Palette,
2400
- {
2401
- activeSectionLabel,
2402
- chrome,
2403
- onAddField: doc.addField,
2404
- themeEditable,
2405
- theme,
2406
- updateThemeColor,
2407
- updateThemeLayout,
2408
- resetTheme
2409
- }
2410
- ),
2411
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2412
- Canvas,
2413
- {
2414
- sections: doc.sections,
2415
- activeSectionId: doc.activeSectionId,
2416
- selectedId: doc.selectedId,
2417
- dragOverKey: drag.dragOverKey,
2418
- chrome,
2419
- strings,
2420
- language,
2421
- onActivateSection: doc.setActiveSectionId,
2422
- onToggleSectionCollapse: doc.toggleSectionCollapse,
2423
- onUpdateSectionTitle: doc.updateSectionTitle,
2424
- onUpdateSectionBackground: doc.updateSectionBackground,
2425
- onDuplicateSection: doc.duplicateSection,
2426
- onMoveSection: doc.moveSection,
2427
- onDeleteSection: doc.deleteSection,
2428
- onAddSection: doc.addSection,
2429
- onSelectField: (sectionId, fieldId) => {
2430
- doc.setSelectedId(fieldId);
2431
- doc.setActiveSectionId(sectionId);
2432
- },
2433
- onFieldChange: doc.updateField,
2434
- onMoveField: doc.moveField,
2435
- onDuplicateField: doc.duplicateField,
2436
- onDeleteField: doc.deleteField,
2437
- getDropZoneHandlers: drag.getDropZoneHandlers,
2438
- getDragHandleProps: drag.getDragHandleProps
2439
- }
2440
- ),
2441
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2442
- Inspector,
2443
- {
2444
- selected: doc.selected,
2445
- language,
2446
- chrome,
2447
- onUpdateField: (patch) => doc.selected && doc.updateField(doc.selected.id, patch),
2448
- onDeleteField: () => doc.selected && doc.deleteField(doc.selected.id),
2449
- onUpdateOption: (optIdx, patch) => doc.selected && doc.updateOption(doc.selected.id, optIdx, patch),
2450
- onAddOption: () => doc.selected && doc.addOption(doc.selected.id),
2451
- onRemoveOption: (optIdx) => doc.selected && doc.removeOption(doc.selected.id, optIdx)
2452
- }
2453
- )
2507
+ ] }) : mode === "build" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "fb-work-area", style: styles.workArea, "data-mobile-panel": mobilePanel, children: [
2508
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "fb-mobile-bar", children: [
2509
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2510
+ "button",
2511
+ {
2512
+ type: "button",
2513
+ className: "fb-mobile-btn",
2514
+ "aria-pressed": mobilePanel === "palette",
2515
+ onClick: () => setMobilePanel((p) => p === "palette" ? "none" : "palette"),
2516
+ children: [
2517
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react18.Menu, { size: 14 }),
2518
+ " ",
2519
+ chrome.paletteTabBlocks
2520
+ ]
2521
+ }
2522
+ ),
2523
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2524
+ "button",
2525
+ {
2526
+ type: "button",
2527
+ className: "fb-mobile-btn",
2528
+ "aria-pressed": mobilePanel === "inspector",
2529
+ onClick: () => setMobilePanel((p) => p === "inspector" ? "none" : "inspector"),
2530
+ children: [
2531
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react18.SlidersHorizontal, { size: 14 }),
2532
+ " ",
2533
+ chrome.properties
2534
+ ]
2535
+ }
2536
+ )
2537
+ ] }),
2538
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "fb-canvas-area", style: styles.workArea, children: [
2539
+ mobilePanel !== "none" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "fb-mobile-backdrop", onClick: () => setMobilePanel("none") }),
2540
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2541
+ Palette,
2542
+ {
2543
+ activeSectionLabel,
2544
+ chrome,
2545
+ onAddField: (type) => {
2546
+ doc.addField(type);
2547
+ setMobilePanel("none");
2548
+ },
2549
+ features,
2550
+ theme,
2551
+ updateThemeColor,
2552
+ updateThemeLayout,
2553
+ resetTheme
2554
+ }
2555
+ ),
2556
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2557
+ Canvas,
2558
+ {
2559
+ sections: doc.sections,
2560
+ activeSectionId: doc.activeSectionId,
2561
+ selectedId: doc.selectedId,
2562
+ dragOverKey: drag.dragOverKey,
2563
+ chrome,
2564
+ strings,
2565
+ language,
2566
+ features,
2567
+ onActivateSection: doc.setActiveSectionId,
2568
+ onToggleSectionCollapse: doc.toggleSectionCollapse,
2569
+ onUpdateSectionTitle: doc.updateSectionTitle,
2570
+ onUpdateSectionBackground: doc.updateSectionBackground,
2571
+ onDuplicateSection: doc.duplicateSection,
2572
+ onMoveSection: doc.moveSection,
2573
+ onDeleteSection: doc.deleteSection,
2574
+ onAddSection: doc.addSection,
2575
+ onSelectField: (sectionId, fieldId) => {
2576
+ doc.setSelectedId(fieldId);
2577
+ doc.setActiveSectionId(sectionId);
2578
+ setMobilePanel("inspector");
2579
+ },
2580
+ onFieldChange: doc.updateField,
2581
+ onMoveField: doc.moveField,
2582
+ onDuplicateField: doc.duplicateField,
2583
+ onDeleteField: doc.deleteField,
2584
+ getDropZoneHandlers: drag.getDropZoneHandlers,
2585
+ getDragHandleProps: drag.getDragHandleProps
2586
+ }
2587
+ ),
2588
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2589
+ Inspector,
2590
+ {
2591
+ selected: doc.selected,
2592
+ language,
2593
+ chrome,
2594
+ features,
2595
+ onUpdateField: (patch) => doc.selected && doc.updateField(doc.selected.id, patch),
2596
+ onDeleteField: () => doc.selected && doc.deleteField(doc.selected.id),
2597
+ onUpdateOption: (optIdx, patch) => doc.selected && doc.updateOption(doc.selected.id, optIdx, patch),
2598
+ onAddOption: () => doc.selected && doc.addOption(doc.selected.id),
2599
+ onRemoveOption: (optIdx) => doc.selected && doc.removeOption(doc.selected.id, optIdx)
2600
+ }
2601
+ )
2602
+ ] })
2454
2603
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2455
2604
  PreviewPane,
2456
2605
  {
@@ -2491,8 +2640,25 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2491
2640
  ] });
2492
2641
  });
2493
2642
  var FormBuilder_default = FormBuilder;
2643
+
2644
+ // src/theme/darkTheme.ts
2645
+ var DARK_THEME = {
2646
+ primary: "#8B8FF5",
2647
+ primarySoft: "#262A45",
2648
+ danger: "#F0715B",
2649
+ dangerSoft: "#3A2420",
2650
+ ink: "#EDEEF2",
2651
+ muted: "#9096A8",
2652
+ border: "#2E313D",
2653
+ surface: "#1A1B23",
2654
+ canvas: "#121319",
2655
+ pageBackground: "#1A1B23",
2656
+ layout: DEFAULT_THEME.layout
2657
+ };
2494
2658
  // Annotate the CommonJS export names for ESM import in node:
2495
2659
  0 && (module.exports = {
2660
+ DARK_THEME,
2661
+ DEFAULT_THEME,
2496
2662
  FormBuilder,
2497
2663
  localStorageAdapter
2498
2664
  });