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.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: "#6B6E79", fontSize: 13, fontWeight: 500 },
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: "#4A4D57", fontSize: 13, fontWeight: 500 },
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 #F0F1F4" },
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: "#33353E", textAlign: "left" },
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 #C7C9D6", background: "transparent", color: "var(--fb-primary)", fontSize: 13, fontWeight: 600 },
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: "#C7C9D6", width: 34, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 },
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: "#B4522F", background: "var(--fb-danger-soft)", padding: "2px 6px", borderRadius: 5, letterSpacing: "0.02em", marginLeft: "auto" },
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: "#F0F1F4", padding: 3, borderRadius: 20 },
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: "#6B6E79", fontSize: 12.5, fontWeight: 600, whiteSpace: "nowrap" },
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: "#F0F1F4", padding: 3, borderRadius: 8, marginBottom: 4 },
1085
- 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 },
1086
- 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)" },
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: "#fff", display: "flex", alignItems: "center", justifyContent: "center", color: "#6B6E79" },
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: "#fff", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
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 #E9EAEE", borderRadius: 7, padding: "7px 10px", fontSize: 13, color: "var(--fb-muted)", background: "#FBFBFD", display: "flex", alignItems: "center", justifyContent: "space-between" },
1094
- previewRadio: { display: "flex", alignItems: "center", gap: 6, fontSize: 13, color: "#4A4D57" },
1095
- ticketActions: { display: "flex", flexDirection: "column", gap: 3, padding: 8, borderLeft: "1px solid #F0F1F4" },
1096
- iconBtn: { width: 24, height: 24, borderRadius: 6, border: "1px solid #E9EAEE", background: "#fff", display: "flex", alignItems: "center", justifyContent: "center", color: "#6B6E79" },
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: "#6B6E79", marginTop: 12, marginBottom: 5 },
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 #C7C9D6", borderRadius: 7, padding: "6px 8px", justifyContent: "center", marginTop: 2 },
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: "#fff", borderRadius: 12, width: 520, maxHeight: "70vh", display: "flex", flexDirection: "column", overflow: "hidden", boxShadow: "0 20px 60px rgba(0,0,0,0.25)" },
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: "#33353E", marginBottom: 6 },
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: "#4A4D57" },
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__ */ jsx2("div", { style: styles.toolbarDivider }),
1207
- /* @__PURE__ */ jsx2(LanguageToggle, { languages, value: language, onChange: onLanguageChange }),
1208
- /* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
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("button", { style: mode === "preview" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("preview"), children: [
1215
- /* @__PURE__ */ jsx2(Eye, { size: 14 }),
1216
- " ",
1217
- chrome.preview
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("button", { style: styles.ghostBtn, onClick: onOpenLibrary, title: chrome.openTemplatesTitle, children: [
1226
- /* @__PURE__ */ jsx2(FolderOpen, { size: 14 }),
1227
- " ",
1228
- chrome.templates,
1229
- savedFormsCount > 0 && /* @__PURE__ */ jsx2("span", { style: styles.countBadge, children: savedFormsCount })
1230
- ] }),
1231
- /* @__PURE__ */ jsxs2("button", { style: styles.primaryBtn, onClick: onSaveExisting, title: chrome.saveToLibraryTitle, children: [
1232
- /* @__PURE__ */ jsx2(Save, { size: 14 }),
1233
- " ",
1234
- chrome.save
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
- themeEditable,
1392
+ features,
1338
1393
  theme,
1339
1394
  updateThemeColor,
1340
1395
  updateThemeLayout,
1341
1396
  resetTheme
1342
1397
  }) {
1343
1398
  const [tab, setTab] = useState5("blocks");
1344
- return /* @__PURE__ */ jsxs5("div", { style: styles.palette, children: [
1345
- themeEditable && /* @__PURE__ */ jsx5("div", { style: { marginBottom: 14 }, children: /* @__PURE__ */ jsx5(
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" && themeEditable ? /* @__PURE__ */ jsx5(
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__ */ jsx5("div", { style: styles.panelHeading, children: chrome.contentBlocks }),
1372
- /* @__PURE__ */ jsx5("div", { style: styles.paletteList, children: CONTENT_TYPES.map((f) => {
1373
- const Icon = f.icon;
1374
- return /* @__PURE__ */ jsxs5("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1375
- /* @__PURE__ */ jsx5(Icon, { size: 16, color: "var(--fb-primary)" }),
1376
- /* @__PURE__ */ jsx5("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1377
- /* @__PURE__ */ jsx5(Plus, { size: 13, color: "#A6A8B3", style: { marginLeft: "auto" } })
1378
- ] }, f.type);
1379
- }) }),
1380
- /* @__PURE__ */ jsx5("div", { style: { ...styles.panelHeading, marginTop: 16 }, children: chrome.formFields }),
1381
- /* @__PURE__ */ jsx5("div", { style: styles.paletteList, children: FORM_TYPES.map((f) => {
1382
- const Icon = f.icon;
1383
- return /* @__PURE__ */ jsxs5("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1384
- /* @__PURE__ */ jsx5(Icon, { size: 16, color: "var(--fb-primary)" }),
1385
- /* @__PURE__ */ jsx5("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1386
- /* @__PURE__ */ jsx5(Plus, { size: 13, color: "#A6A8B3", style: { marginLeft: "auto" } })
1387
- ] }, f.type);
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: "#6B6E79" }),
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: "#6B6E79" }),
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: "#6B6E79" }),
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: "#C4C6D0" }) }),
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
- /* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.duplicate, onClick: onDuplicateSection, children: /* @__PURE__ */ jsx10(Copy2, { size: 13 }) }),
1747
- /* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.moveUp, disabled: sIdx === 0, onClick: () => onMoveSection(-1), children: /* @__PURE__ */ jsx10(ArrowUp2, { size: 13 }) }),
1748
- /* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.moveDown, disabled: sIdx === sectionsLength - 1, onClick: () => onMoveSection(1), children: /* @__PURE__ */ jsx10(ArrowDown2, { size: 13 }) }),
1749
- /* @__PURE__ */ jsx10("button", { style: { ...styles.iconBtn, ...styles.iconBtnDanger }, title: chrome.deleteSection, disabled: sectionsLength <= 1, onClick: onDeleteSection, children: /* @__PURE__ */ jsx10(Trash22, { size: 13 }) })
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 Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
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(Fragment3, { children: [
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: "#4A4D57" }, children: f.defaultValue ? chrome.checked : chrome.unchecked })
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(Fragment3, { children: [
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(Fragment3, { children: [
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(Fragment3, { children: [
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 Fragment4, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
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(Fragment4, { children: [
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: "#4A4D57" }, children: chrome.hideLabel })
1989
+ /* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.hideLabel })
1921
1990
  ] })
1922
1991
  ] }),
1923
- meta.hasSubtype && /* @__PURE__ */ jsxs11(Fragment4, { children: [
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(Fragment4, { children: [
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__ */ jsx13("div", { style: styles.inspectorDivider }),
1931
- /* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.typography }),
1932
- /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.headingStyle }),
1933
- /* @__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] }) }),
1934
- /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.width }),
1935
- /* @__PURE__ */ jsx13(Segmented, { options: FONT_SIZE_OPTIONS, value: selected.fontSize || "md", onChange: (v) => onUpdateField({ fontSize: v }) }),
1936
- /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.style }),
1937
- /* @__PURE__ */ jsxs11("div", { style: styles.styleToggleRow, children: [
1938
- /* @__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 }) }),
1939
- /* @__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 }) })
1940
- ] }),
1941
- /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.align }),
1942
- /* @__PURE__ */ jsx13(Segmented, { options: TEXT_ALIGN_OPTIONS, value: selected.textAlign || "left", onChange: (v) => onUpdateField({ textAlign: v }) }),
1943
- /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.color }),
1944
- /* @__PURE__ */ jsxs11("div", { style: styles.swatchRow, children: [
1945
- 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")),
1946
- /* @__PURE__ */ jsx13("input", { type: "color", value: selected.color || "#1B1E24", onChange: (e) => onUpdateField({ color: e.target.value }), style: styles.colorPickerInput })
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(Fragment4, { children: [
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(Fragment4, { children: [
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(Fragment4, { children: [
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(Fragment4, { children: [
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__ */ jsx13("label", { style: styles.propLabel, children: chrome.color }),
1976
- /* @__PURE__ */ jsxs11("div", { style: styles.swatchRow, children: [
1977
- 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")),
1978
- /* @__PURE__ */ jsx13("input", { type: "color", value: selected.buttonStyle?.color || "#5B5FEF", onChange: (e) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, color: e.target.value } }), style: styles.colorPickerInput })
1979
- ] }),
1980
- /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.buttonSize }),
1981
- /* @__PURE__ */ jsx13(Segmented, { options: SUBMIT_SIZE_OPTIONS, value: selected.buttonStyle?.size || "md", onChange: (v) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, size: v } }) })
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(Fragment4, { children: [
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(Fragment4, { children: [
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(Fragment4, { children: [
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(Fragment4, { children: [
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(Fragment4, { children: [
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: "#4A4D57" }, children: chrome.requiredField })
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(Fragment4, { children: [
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(Fragment4, { children: [
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: "#4A4D57" }, children: chrome.showIcon })
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, width: 420 }, onClick: (e) => e.stopPropagation(), children: [
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, width: 380 }, onClick: (e) => e.stopPropagation(), children: [
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
- themeEditable = false,
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__ */ jsx18(
2407
- Palette,
2408
- {
2409
- activeSectionLabel,
2410
- chrome,
2411
- onAddField: doc.addField,
2412
- themeEditable,
2413
- theme,
2414
- updateThemeColor,
2415
- updateThemeLayout,
2416
- resetTheme
2417
- }
2418
- ),
2419
- /* @__PURE__ */ jsx18(
2420
- Canvas,
2421
- {
2422
- sections: doc.sections,
2423
- activeSectionId: doc.activeSectionId,
2424
- selectedId: doc.selectedId,
2425
- dragOverKey: drag.dragOverKey,
2426
- chrome,
2427
- strings,
2428
- language,
2429
- onActivateSection: doc.setActiveSectionId,
2430
- onToggleSectionCollapse: doc.toggleSectionCollapse,
2431
- onUpdateSectionTitle: doc.updateSectionTitle,
2432
- onUpdateSectionBackground: doc.updateSectionBackground,
2433
- onDuplicateSection: doc.duplicateSection,
2434
- onMoveSection: doc.moveSection,
2435
- onDeleteSection: doc.deleteSection,
2436
- onAddSection: doc.addSection,
2437
- onSelectField: (sectionId, fieldId) => {
2438
- doc.setSelectedId(fieldId);
2439
- doc.setActiveSectionId(sectionId);
2440
- },
2441
- onFieldChange: doc.updateField,
2442
- onMoveField: doc.moveField,
2443
- onDuplicateField: doc.duplicateField,
2444
- onDeleteField: doc.deleteField,
2445
- getDropZoneHandlers: drag.getDropZoneHandlers,
2446
- getDragHandleProps: drag.getDragHandleProps
2447
- }
2448
- ),
2449
- /* @__PURE__ */ jsx18(
2450
- Inspector,
2451
- {
2452
- selected: doc.selected,
2453
- language,
2454
- chrome,
2455
- onUpdateField: (patch) => doc.selected && doc.updateField(doc.selected.id, patch),
2456
- onDeleteField: () => doc.selected && doc.deleteField(doc.selected.id),
2457
- onUpdateOption: (optIdx, patch) => doc.selected && doc.updateOption(doc.selected.id, optIdx, patch),
2458
- onAddOption: () => doc.selected && doc.addOption(doc.selected.id),
2459
- onRemoveOption: (optIdx) => doc.selected && doc.removeOption(doc.selected.id, optIdx)
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