form-page-builder 1.0.0 → 2.1.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
@@ -31,6 +33,56 @@ module.exports = __toCommonJS(index_exports);
31
33
  var import_react8 = require("react");
32
34
  var import_lucide_react18 = require("lucide-react");
33
35
 
36
+ // src/constants/fieldTypes.ts
37
+ var import_lucide_react = require("lucide-react");
38
+ var FIELD_TYPES = [
39
+ { type: "paragraph", icon: import_lucide_react.FileText, isContent: true, defaultIcon: "FileText" },
40
+ { type: "image", icon: import_lucide_react.Image, isContent: true, isImage: true, defaultIcon: "Type" },
41
+ { type: "button", icon: import_lucide_react.MousePointerClick, isContent: true, defaultIcon: "Type" },
42
+ { type: "input", icon: import_lucide_react.Type, placeholder: true, hasSubtype: true, defaultIcon: "Type" },
43
+ { type: "textarea", icon: import_lucide_react.AlignLeft, placeholder: true, defaultIcon: "AlignLeft" },
44
+ { type: "select", icon: import_lucide_react.ChevronDown, options: true, defaultIcon: "ChevronDown" },
45
+ { type: "radio", icon: import_lucide_react.Circle, options: true, defaultIcon: "Circle" },
46
+ { type: "checkboxGroup", icon: import_lucide_react.ListChecks, options: true, multiValue: true, defaultIcon: "ListChecks" },
47
+ { type: "checkbox", icon: import_lucide_react.CheckSquare, boolean: true, defaultIcon: "CheckSquare" },
48
+ { type: "toggle", icon: import_lucide_react.ToggleLeft, boolean: true, defaultIcon: "ToggleLeft" }
49
+ ];
50
+ var TYPE_MAP = Object.fromEntries(FIELD_TYPES.map((f) => [f.type, f]));
51
+ var CONTENT_TYPES = FIELD_TYPES.filter((f) => f.isContent);
52
+ var FORM_TYPES = FIELD_TYPES.filter((f) => !f.isContent);
53
+ function getMeta(type) {
54
+ return TYPE_MAP[type] || TYPE_MAP.input;
55
+ }
56
+ var LEGACY_INPUT_TYPES = ["text", "email", "phone", "number", "password", "date"];
57
+ var INPUT_SUBTYPES = ["text", "email", "phone", "number", "password", "date", "time"];
58
+ var IMAGE_SHAPES = ["square", "circle", "banner"];
59
+ var FIELD_TYPE_CHROME_KEY = {
60
+ paragraph: "fieldTypeParagraph",
61
+ image: "fieldTypeImage",
62
+ button: "fieldTypeButton",
63
+ input: "fieldTypeInput",
64
+ textarea: "fieldTypeTextarea",
65
+ select: "fieldTypeSelect",
66
+ radio: "fieldTypeRadio",
67
+ checkboxGroup: "fieldTypeCheckboxGroup",
68
+ checkbox: "fieldTypeCheckbox",
69
+ toggle: "fieldTypeToggle"
70
+ };
71
+ var INPUT_SUBTYPE_CHROME_KEY = {
72
+ text: "subtypeText",
73
+ email: "subtypeEmail",
74
+ phone: "subtypePhone",
75
+ number: "subtypeNumber",
76
+ password: "subtypePassword",
77
+ date: "subtypeDate",
78
+ time: "subtypeTime"
79
+ };
80
+ var IMAGE_SHAPE_CHROME_KEY = {
81
+ square: "shapeSquare",
82
+ circle: "shapeCircle",
83
+ banner: "shapeBanner"
84
+ };
85
+
34
86
  // src/i18n/languages.ts
35
87
  var DEFAULT_LANGUAGES = [
36
88
  { code: "en", label: "EN" },
@@ -360,6 +412,22 @@ function withLang(val, lang, value) {
360
412
  return { ...base, [lang]: value };
361
413
  }
362
414
 
415
+ // src/lib/color.ts
416
+ function mixHex(a, b, t2) {
417
+ const pa = parseHex(a);
418
+ const pb = parseHex(b);
419
+ if (!pa || !pb) return a;
420
+ const mix = (x, y) => Math.round(x + (y - x) * t2);
421
+ const toHex = (n) => n.toString(16).padStart(2, "0");
422
+ return `#${toHex(mix(pa[0], pb[0]))}${toHex(mix(pa[1], pb[1]))}${toHex(mix(pa[2], pb[2]))}`;
423
+ }
424
+ function parseHex(hex) {
425
+ const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());
426
+ if (!m) return null;
427
+ const n = parseInt(m[1], 16);
428
+ return [n >> 16 & 255, n >> 8 & 255, n & 255];
429
+ }
430
+
363
431
  // src/lib/storage/compress.ts
364
432
  var import_lz_string = require("lz-string");
365
433
  function compress(raw) {
@@ -402,56 +470,6 @@ var localStorageAdapter = {
402
470
  }
403
471
  };
404
472
 
405
- // src/constants/fieldTypes.ts
406
- var import_lucide_react = require("lucide-react");
407
- var FIELD_TYPES = [
408
- { type: "paragraph", icon: import_lucide_react.FileText, isContent: true, defaultIcon: "FileText" },
409
- { type: "image", icon: import_lucide_react.Image, isContent: true, isImage: true, defaultIcon: "Type" },
410
- { type: "button", icon: import_lucide_react.MousePointerClick, isContent: true, defaultIcon: "Type" },
411
- { type: "input", icon: import_lucide_react.Type, placeholder: true, hasSubtype: true, defaultIcon: "Type" },
412
- { type: "textarea", icon: import_lucide_react.AlignLeft, placeholder: true, defaultIcon: "AlignLeft" },
413
- { type: "select", icon: import_lucide_react.ChevronDown, options: true, defaultIcon: "ChevronDown" },
414
- { type: "radio", icon: import_lucide_react.Circle, options: true, defaultIcon: "Circle" },
415
- { type: "checkboxGroup", icon: import_lucide_react.ListChecks, options: true, multiValue: true, defaultIcon: "ListChecks" },
416
- { type: "checkbox", icon: import_lucide_react.CheckSquare, boolean: true, defaultIcon: "CheckSquare" },
417
- { type: "toggle", icon: import_lucide_react.ToggleLeft, boolean: true, defaultIcon: "ToggleLeft" }
418
- ];
419
- var TYPE_MAP = Object.fromEntries(FIELD_TYPES.map((f) => [f.type, f]));
420
- var CONTENT_TYPES = FIELD_TYPES.filter((f) => f.isContent);
421
- var FORM_TYPES = FIELD_TYPES.filter((f) => !f.isContent);
422
- function getMeta(type) {
423
- return TYPE_MAP[type] || TYPE_MAP.input;
424
- }
425
- var LEGACY_INPUT_TYPES = ["text", "email", "phone", "number", "password", "date"];
426
- var INPUT_SUBTYPES = ["text", "email", "phone", "number", "password", "date", "time"];
427
- var IMAGE_SHAPES = ["square", "circle", "banner"];
428
- var FIELD_TYPE_CHROME_KEY = {
429
- paragraph: "fieldTypeParagraph",
430
- image: "fieldTypeImage",
431
- button: "fieldTypeButton",
432
- input: "fieldTypeInput",
433
- textarea: "fieldTypeTextarea",
434
- select: "fieldTypeSelect",
435
- radio: "fieldTypeRadio",
436
- checkboxGroup: "fieldTypeCheckboxGroup",
437
- checkbox: "fieldTypeCheckbox",
438
- toggle: "fieldTypeToggle"
439
- };
440
- var INPUT_SUBTYPE_CHROME_KEY = {
441
- text: "subtypeText",
442
- email: "subtypeEmail",
443
- phone: "subtypePhone",
444
- number: "subtypeNumber",
445
- password: "subtypePassword",
446
- date: "subtypeDate",
447
- time: "subtypeTime"
448
- };
449
- var IMAGE_SHAPE_CHROME_KEY = {
450
- square: "shapeSquare",
451
- circle: "shapeCircle",
452
- banner: "shapeBanner"
453
- };
454
-
455
473
  // src/lib/id.ts
456
474
  var genFormId = () => `form_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`;
457
475
  var genSectionId = () => `section_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`;
@@ -615,6 +633,38 @@ 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
+ deviceToggle: true
652
+ };
653
+ function resolveFeatures(features) {
654
+ return {
655
+ ...DEFAULT_FEATURES,
656
+ ...features,
657
+ contentBlocks: Array.isArray(features?.contentBlocks) ? new Set(features.contentBlocks) : features?.contentBlocks ?? DEFAULT_FEATURES.contentBlocks,
658
+ fieldTypes: Array.isArray(features?.fieldTypes) ? new Set(features.fieldTypes) : features?.fieldTypes ?? DEFAULT_FEATURES.fieldTypes
659
+ };
660
+ }
661
+ function isContentBlockEnabled(features, type) {
662
+ return features.contentBlocks === true || features.contentBlocks instanceof Set && features.contentBlocks.has(type);
663
+ }
664
+ function isFieldTypeEnabled(features, type) {
665
+ return features.fieldTypes === true || features.fieldTypes instanceof Set && features.fieldTypes.has(type);
666
+ }
667
+
618
668
  // src/hooks/useTheme.ts
619
669
  var import_react = require("react");
620
670
 
@@ -849,6 +899,7 @@ var formKey = (id) => `form-page-builder:saved:${id}`;
849
899
  var MAX_TEMPLATES = 5;
850
900
  function usePersistence({
851
901
  storage,
902
+ autosave,
852
903
  language,
853
904
  chrome,
854
905
  document,
@@ -910,7 +961,7 @@ function usePersistence({
910
961
  refreshLibrary();
911
962
  }, []);
912
963
  (0, import_react3.useEffect)(() => {
913
- if (!hasLoadedOnce.current) return;
964
+ if (!hasLoadedOnce.current || !autosave) return;
914
965
  setSaveState("saving");
915
966
  if (autosaveTimer.current) clearTimeout(autosaveTimer.current);
916
967
  autosaveTimer.current = setTimeout(async () => {
@@ -1049,15 +1100,15 @@ var styles = {
1049
1100
  titleInput: { border: "none", outline: "none", fontSize: 14, fontWeight: 600, background: "transparent", color: "var(--fb-ink)", padding: "4px 6px", borderRadius: 6, minWidth: 160 },
1050
1101
  toolbarRight: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" },
1051
1102
  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 },
1103
+ 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
1104
  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 },
1105
+ 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
1106
  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
1107
  saveStatus: { display: "flex", alignItems: "center", gap: 5, fontSize: 12, color: "var(--fb-muted)", minWidth: 60 },
1057
1108
  countBadge: { fontSize: 10.5, fontWeight: 700, background: "var(--fb-primary-soft)", color: "var(--fb-primary)", borderRadius: 9, padding: "1px 6px", marginLeft: 2 },
1058
1109
  loadingScreen: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
1059
1110
  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" },
1111
+ libraryRow: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10, padding: "10px 8px", borderRadius: 8, border: "1px solid var(--fb-border)" },
1061
1112
  libraryRowTitle: { fontSize: 13.5, fontWeight: 600, color: "var(--fb-ink)", display: "flex", alignItems: "center", gap: 8, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
1062
1113
  libraryRowMeta: { fontSize: 11.5, color: "var(--fb-muted)", marginTop: 2 },
1063
1114
  currentBadge: { fontSize: 10, fontWeight: 700, color: "var(--fb-primary)", background: "var(--fb-primary-soft)", padding: "2px 6px", borderRadius: 5, flexShrink: 0 },
@@ -1066,7 +1117,7 @@ var styles = {
1066
1117
  panelHeading: { fontSize: 11, fontWeight: 700, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--fb-muted)", marginBottom: 10 },
1067
1118
  activeSectionHint: { fontSize: 11.5, color: "var(--fb-muted)", marginBottom: 14, lineHeight: 1.4 },
1068
1119
  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" },
1120
+ 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
1121
  canvas: { flex: 1, padding: "var(--fb-space-canvas)", overflowY: "auto", background: "var(--fb-canvas)" },
1071
1122
  sectionBlock: { borderRadius: 12, padding: "var(--fb-space-panel)", marginBottom: "var(--fb-space-section)", transition: "border-color 0.12s" },
1072
1123
  sectionHeader: { display: "flex", alignItems: "center", gap: 8, marginBottom: 12, flexWrap: "wrap" },
@@ -1076,7 +1127,7 @@ var styles = {
1076
1127
  sectionHeaderActions: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap", marginLeft: "auto" },
1077
1128
  sectionEmpty: { fontSize: 12.5, color: "var(--fb-muted)", padding: "18px 4px", textAlign: "center", border: "1px dashed var(--fb-border)", borderRadius: 8 },
1078
1129
  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 },
1130
+ 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
1131
  swatchRow: { display: "flex", alignItems: "center", gap: 5, flexWrap: "wrap" },
1081
1132
  swatchBtn: { width: 20, height: 20, borderRadius: "50%", border: "1px solid var(--fb-border)", padding: 0 },
1082
1133
  swatchBtnActive: { border: "2px solid var(--fb-primary)" },
@@ -1085,56 +1136,56 @@ var styles = {
1085
1136
  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
1137
  ticketSelected: { borderColor: "var(--fb-primary)", boxShadow: "0 0 0 3px var(--fb-primary-soft)" },
1087
1138
  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 },
1139
+ ticketIndex: { fontFamily: "'JetBrains Mono', monospace", fontSize: 13, fontWeight: 700, color: "var(--fb-border)", width: 34, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 },
1089
1140
  ticketPerforation: { width: 0, borderLeft: "1px dashed var(--fb-border)" },
1090
1141
  ticketBody: { flex: 1, padding: "10px var(--fb-space-ticket)", minWidth: 0 },
1091
1142
  ticketTop: { display: "flex", alignItems: "center", gap: 7, marginBottom: 4 },
1092
1143
  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" },
1144
+ 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
1145
  chipRow: { display: "flex", gap: 5, marginBottom: 7, flexWrap: "wrap" },
1095
1146
  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 },
1147
+ langToggleTrack: { position: "relative", display: "flex", gap: 3, background: "var(--fb-surface-2)", padding: 3, borderRadius: 20 },
1097
1148
  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" },
1149
+ 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
1150
  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)" },
1151
+ segmented: { display: "flex", gap: 3, background: "var(--fb-surface-2)", padding: 3, borderRadius: 8, marginBottom: 4 },
1152
+ 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 },
1153
+ 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
1154
  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" },
1155
+ 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
1156
  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
1157
  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)" },
1158
+ 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
1159
  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" },
1160
+ 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" },
1161
+ previewRadio: { display: "flex", alignItems: "center", gap: 6, fontSize: 13, color: "var(--fb-ink)" },
1162
+ ticketActions: { display: "flex", flexDirection: "column", gap: 3, padding: 8, borderLeft: "1px solid var(--fb-border)" },
1163
+ 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
1164
  iconBtnDanger: { color: "var(--fb-danger)" },
1114
1165
  inspector: { width: 270, borderLeft: "1px solid var(--fb-border)", background: "var(--fb-surface)", padding: "var(--fb-space-panel)", overflowY: "auto" },
1115
1166
  inspectorEmpty: { fontSize: 13, color: "var(--fb-muted)", lineHeight: 1.5, marginTop: 6 },
1116
1167
  inspectorBody: { display: "flex", flexDirection: "column", gap: 4 },
1117
1168
  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" },
1169
+ propLabel: { fontSize: 11.5, fontWeight: 600, color: "var(--fb-muted)", marginTop: 12, marginBottom: 5 },
1170
+ 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
1171
  optionList: { display: "flex", flexDirection: "column", gap: 6 },
1121
1172
  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 },
1173
+ 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" },
1174
+ 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
1175
  toggleRow: { display: "flex", alignItems: "center", gap: 8, background: "transparent", border: "none", padding: "8px 0" },
1125
1176
  toggleTrack: { width: 30, height: 17, borderRadius: 20, position: "relative", transition: "background 0.15s", display: "inline-block" },
1126
1177
  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
1178
  inspectorDivider: { height: 1, background: "var(--fb-border)", margin: "14px 0 10px" },
1128
1179
  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)" },
1180
+ 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" },
1181
+ 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
1182
  modalHeader: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "12px 16px", borderBottom: "1px solid var(--fb-border)" },
1132
1183
  jsonPre: { margin: 0, padding: 16, fontSize: 12, lineHeight: 1.6, overflow: "auto", background: "#14171C", color: "#D6D8E0", fontFamily: "'JetBrains Mono', monospace" },
1133
1184
  previewWrap: { flex: 1, display: "flex", justifyContent: "center", padding: "var(--fb-space-page) 20px", overflowY: "auto", background: "var(--fb-canvas)" },
1134
1185
  previewToolbar: { width: "100%", display: "flex", gap: 10, marginBottom: 16, justifyContent: "center" },
1135
1186
  previewCard: { width: "100%", maxWidth: 480, background: "var(--fb-page-bg)", border: "1px solid var(--fb-border)", borderRadius: 12, padding: "var(--fb-space-page)" },
1136
1187
  previewTitle: { fontSize: 19, fontWeight: 700, margin: "0 0 20px" },
1137
- previewLabel: { display: "block", fontSize: 13, fontWeight: 600, color: "#33353E", marginBottom: 6 },
1188
+ previewLabel: { display: "block", fontSize: 13, fontWeight: 600, color: "var(--fb-ink)", marginBottom: 6 },
1138
1189
  previewGrid: { display: "flex", flexWrap: "wrap", gap: "var(--fb-space-field)" },
1139
1190
  sectionRuntimeTitle: { fontSize: 15, fontWeight: 700, margin: "0 0 12px", color: "var(--fb-ink)" },
1140
1191
  imagePlaceholder: { display: "flex", alignItems: "center", justifyContent: "center", border: "1px dashed var(--fb-border)" },
@@ -1144,13 +1195,13 @@ var styles = {
1144
1195
  submittedRow: { display: "flex", justifyContent: "space-between", gap: 12, fontSize: 13, padding: "6px 0", borderBottom: "1px solid var(--fb-border)" },
1145
1196
  submittedLabel: { color: "var(--fb-muted)", flexShrink: 0 },
1146
1197
  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" },
1198
+ 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
1199
  realInputError: { borderColor: "var(--fb-danger)" },
1149
1200
  submitBtn: { marginTop: 8, color: "#fff", border: "none", borderRadius: 8, fontWeight: 600, width: "100%" },
1150
1201
  layoutPanelHeader: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 4 },
1151
1202
  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" }
1203
+ spacingLabel: { fontSize: 12, color: "var(--fb-ink)" },
1204
+ 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
1205
  };
1155
1206
 
1156
1207
  // src/components/LanguageToggle.tsx
@@ -1191,6 +1242,7 @@ function Toolbar({
1191
1242
  mode,
1192
1243
  saveState,
1193
1244
  chrome,
1245
+ features,
1194
1246
  savedFormsCount,
1195
1247
  onTitleChange,
1196
1248
  onLanguageChange,
@@ -1203,7 +1255,7 @@ function Toolbar({
1203
1255
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.toolbar, children: [
1204
1256
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.toolbarLeft, children: [
1205
1257
  /* @__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" })
1258
+ 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
1259
  ] }),
1208
1260
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles.toolbarRight, children: [
1209
1261
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles.saveStatus, children: [
@@ -1219,37 +1271,43 @@ function Toolbar({
1219
1271
  chrome.saveFailed
1220
1272
  ] })
1221
1273
  ] }),
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
1274
+ features.languageSwitcher && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1275
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.toolbarDivider }),
1276
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LanguageToggle, { languages, value: language, onChange: onLanguageChange })
1229
1277
  ] }),
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
1278
+ features.previewMode && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1279
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.toolbarDivider }),
1280
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: mode === "build" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("build"), children: [
1281
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Pencil, { size: 14 }),
1282
+ " ",
1283
+ chrome.build
1284
+ ] }),
1285
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: mode === "preview" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("preview"), children: [
1286
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Eye, { size: 14 }),
1287
+ " ",
1288
+ chrome.preview
1289
+ ] })
1234
1290
  ] }),
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: [
1291
+ (features.newForm || features.templates) && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles.toolbarDivider }),
1292
+ features.newForm && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.ghostBtn, onClick: onNewForm, title: chrome.startNewForm, children: [
1237
1293
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.FilePlus2, { size: 14 }),
1238
1294
  " ",
1239
1295
  chrome.newForm
1240
1296
  ] }),
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
1297
+ features.templates && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1298
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.ghostBtn, onClick: onOpenLibrary, title: chrome.openTemplatesTitle, children: [
1299
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.FolderOpen, { size: 14 }),
1300
+ " ",
1301
+ chrome.templates,
1302
+ savedFormsCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: styles.countBadge, children: savedFormsCount })
1303
+ ] }),
1304
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.primaryBtn, onClick: onSaveExisting, title: chrome.saveToLibraryTitle, children: [
1305
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Save, { size: 14 }),
1306
+ " ",
1307
+ chrome.save
1308
+ ] })
1251
1309
  ] }),
1252
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.ghostBtn, onClick: onOpenJson, children: [
1310
+ features.jsonView && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { style: styles.ghostBtn, onClick: onOpenJson, children: [
1253
1311
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Code2, { size: 14 }),
1254
1312
  " ",
1255
1313
  chrome.viewJson
@@ -1350,15 +1408,19 @@ function Palette({
1350
1408
  activeSectionLabel,
1351
1409
  chrome,
1352
1410
  onAddField,
1353
- themeEditable,
1411
+ features,
1354
1412
  theme,
1355
1413
  updateThemeColor,
1356
1414
  updateThemeLayout,
1357
- resetTheme
1415
+ resetTheme,
1416
+ fieldCount
1358
1417
  }) {
1359
1418
  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)(
1419
+ const contentTypes = CONTENT_TYPES.filter((f) => isContentBlockEnabled(features, f.type));
1420
+ const formTypes = FORM_TYPES.filter((f) => isFieldTypeEnabled(features, f.type));
1421
+ const atFieldCap = typeof features.maxFields === "number" && fieldCount >= features.maxFields;
1422
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "fb-palette", style: styles.palette, children: [
1423
+ features.design && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { marginBottom: 14 }, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1362
1424
  Segmented,
1363
1425
  {
1364
1426
  options: [
@@ -1369,7 +1431,7 @@ function Palette({
1369
1431
  onChange: setTab
1370
1432
  }
1371
1433
  ) }),
1372
- tab === "design" && themeEditable ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1434
+ tab === "design" && features.design ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1373
1435
  DesignPanel,
1374
1436
  {
1375
1437
  chrome,
@@ -1384,24 +1446,29 @@ function Palette({
1384
1446
  " ",
1385
1447
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: activeSectionLabel })
1386
1448
  ] }),
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
- }) })
1449
+ contentTypes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1450
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.panelHeading, children: chrome.contentBlocks }),
1451
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.paletteList, children: contentTypes.map((f) => {
1452
+ const Icon = f.icon;
1453
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1454
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { size: 16, color: "var(--fb-primary)" }),
1455
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1456
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Plus, { size: 13, color: "var(--fb-muted)", style: { marginLeft: "auto" } })
1457
+ ] }, f.type);
1458
+ }) })
1459
+ ] }),
1460
+ formTypes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
1461
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { ...styles.panelHeading, marginTop: 16 }, children: chrome.formFields }),
1462
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: styles.paletteList, children: formTypes.map((f) => {
1463
+ const Icon = f.icon;
1464
+ const itemStyle = atFieldCap ? { ...styles.paletteItem, opacity: 0.45, cursor: "not-allowed" } : styles.paletteItem;
1465
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("button", { type: "button", disabled: atFieldCap, style: itemStyle, onClick: () => onAddField(f.type), children: [
1466
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { size: 16, color: "var(--fb-primary)" }),
1467
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1468
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react5.Plus, { size: 13, color: "var(--fb-muted)", style: { marginLeft: "auto" } })
1469
+ ] }, f.type);
1470
+ }) })
1471
+ ] })
1405
1472
  ] })
1406
1473
  ] });
1407
1474
  }
@@ -1530,7 +1597,7 @@ function FieldBlock({ field, lang, onFieldChange, strings, chrome, error, isBuil
1530
1597
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1531
1598
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", flexDirection: isInline ? "row" : "column", alignItems: isInline ? "center" : "stretch", gap: isInline ? 10 : 6 }, children: [
1532
1599
  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" }),
1600
+ IconComp && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconComp, { size: 14, color: "var(--fb-muted)" }),
1534
1601
  labelText || (isBuild ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontStyle: "italic", color: "var(--fb-muted)" }, children: chrome?.untitledField || "Untitled field" }) : ""),
1535
1602
  field.required && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { color: "var(--fb-danger)" }, children: " *" })
1536
1603
  ] }),
@@ -1595,14 +1662,14 @@ function renderInteractive(field, lang, onFieldChange, IconComp, hasError, strin
1595
1662
  case "checkbox":
1596
1663
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: styles.previewRadio, children: [
1597
1664
  /* @__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" }),
1665
+ IconComp && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconComp, { size: 14, color: "var(--fb-muted)" }),
1599
1666
  t(field.label, lang),
1600
1667
  field.required && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { color: "var(--fb-danger)" }, children: " *" })
1601
1668
  ] });
1602
1669
  case "toggle":
1603
1670
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { style: styles.previewRadio, children: [
1604
1671
  /* @__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" }),
1672
+ IconComp && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconComp, { size: 14, color: "var(--fb-muted)" }),
1606
1673
  t(field.label, lang)
1607
1674
  ] });
1608
1675
  default:
@@ -1620,6 +1687,7 @@ function FieldTicket({
1620
1687
  chrome,
1621
1688
  strings,
1622
1689
  language,
1690
+ dragEnabled,
1623
1691
  onSelect,
1624
1692
  onFieldChange,
1625
1693
  onMoveField,
@@ -1649,7 +1717,7 @@ function FieldTicket({
1649
1717
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style: styles.ticketPerforation }),
1650
1718
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: styles.ticketBody, children: [
1651
1719
  /* @__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" }) }),
1720
+ 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
1721
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Icon, { size: 13, color: "var(--fb-primary)" }),
1654
1722
  /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { style: styles.typeBadge, children: [
1655
1723
  chrome[FIELD_TYPE_CHROME_KEY[field.type]] || field.type,
@@ -1692,6 +1760,7 @@ function SectionCard({
1692
1760
  chrome,
1693
1761
  strings,
1694
1762
  language,
1763
+ features,
1695
1764
  onActivate,
1696
1765
  onToggleCollapse,
1697
1766
  onUpdateTitle,
@@ -1731,14 +1800,16 @@ function SectionCard({
1731
1800
  ),
1732
1801
  section.collapsed && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: styles.miniBadge, children: chrome.fieldsCount(section.fields.length) }),
1733
1802
  /* @__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: [
1803
+ features.sections && !section.collapsed && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: styles.swatchRow, children: [
1735
1804
  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
1805
  /* @__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
1806
  ] }),
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 }) })
1807
+ features.sections && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1808
+ /* @__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 }) }),
1809
+ /* @__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 }) }),
1810
+ /* @__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 }) }),
1811
+ /* @__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 }) })
1812
+ ] })
1742
1813
  ] })
1743
1814
  ] }),
1744
1815
  !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 +1823,7 @@ function SectionCard({
1752
1823
  chrome,
1753
1824
  strings,
1754
1825
  language,
1826
+ dragEnabled: features.dragReorder,
1755
1827
  onSelect: () => onSelectField(field.id),
1756
1828
  onFieldChange,
1757
1829
  onMoveField,
@@ -1777,6 +1849,7 @@ function Canvas({
1777
1849
  chrome,
1778
1850
  strings,
1779
1851
  language,
1852
+ features,
1780
1853
  onActivateSection,
1781
1854
  onToggleSectionCollapse,
1782
1855
  onUpdateSectionTitle,
@@ -1793,7 +1866,7 @@ function Canvas({
1793
1866
  getDropZoneHandlers,
1794
1867
  getDragHandleProps
1795
1868
  }) {
1796
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.canvas, children: [
1869
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "fb-canvas", style: styles.canvas, children: [
1797
1870
  sections.map((section, sIdx) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1798
1871
  SectionCard,
1799
1872
  {
@@ -1806,6 +1879,7 @@ function Canvas({
1806
1879
  chrome,
1807
1880
  strings,
1808
1881
  language,
1882
+ features,
1809
1883
  onActivate: () => onActivateSection(section.id),
1810
1884
  onToggleCollapse: () => onToggleSectionCollapse(section.id),
1811
1885
  onUpdateTitle: (value) => onUpdateSectionTitle(section.id, value),
@@ -1823,7 +1897,7 @@ function Canvas({
1823
1897
  },
1824
1898
  section.id
1825
1899
  )),
1826
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("button", { style: styles.addSectionBtn, onClick: onAddSection, children: [
1900
+ features.sections && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("button", { style: styles.addSectionBtn, onClick: onAddSection, children: [
1827
1901
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react12.Layers, { size: 14 }),
1828
1902
  " ",
1829
1903
  chrome.addSection
@@ -1844,7 +1918,7 @@ function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
1844
1918
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("label", { style: styles.propLabel, children: chrome.defaultValue }),
1845
1919
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { style: styles.toggleRow, onClick: () => onChange({ defaultValue: !f.defaultValue }), children: [
1846
1920
  /* @__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 })
1921
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: f.defaultValue ? chrome.checked : chrome.unchecked })
1848
1922
  ] })
1849
1923
  ] });
1850
1924
  }
@@ -1882,8 +1956,8 @@ function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
1882
1956
 
1883
1957
  // src/components/Inspector.tsx
1884
1958
  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: [
1959
+ function Inspector({ selected, language, chrome, features, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1960
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "fb-inspector", style: styles.inspector, children: [
1887
1961
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.panelHeading, children: chrome.properties }),
1888
1962
  !selected ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.inspectorEmpty, children: chrome.selectFieldHint }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1889
1963
  InspectorBody,
@@ -1891,6 +1965,7 @@ function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, o
1891
1965
  selected,
1892
1966
  language,
1893
1967
  chrome,
1968
+ features,
1894
1969
  onUpdateField,
1895
1970
  onDeleteField,
1896
1971
  onUpdateOption,
@@ -1900,7 +1975,7 @@ function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, o
1900
1975
  )
1901
1976
  ] });
1902
1977
  }
1903
- function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1978
+ function InspectorBody({ selected, language, chrome, features, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1904
1979
  const meta = getMeta(selected.type);
1905
1980
  const f = selected;
1906
1981
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.inspectorBody, children: [
@@ -1909,7 +1984,7 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
1909
1984
  /* @__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
1985
  !meta.isContent && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: styles.toggleRow, children: [
1911
1986
  /* @__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 })
1987
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.hideLabel })
1913
1988
  ] })
1914
1989
  ] }),
1915
1990
  meta.hasSubtype && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
@@ -1919,23 +1994,25 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
1919
1994
  selected.type === "paragraph" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1920
1995
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.content }),
1921
1996
  /* @__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 })
1997
+ features.blockStyling && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1998
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.inspectorDivider }),
1999
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.panelHeading, children: chrome.typography }),
2000
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.headingStyle }),
2001
+ /* @__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] }) }),
2002
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.width }),
2003
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Segmented, { options: FONT_SIZE_OPTIONS, value: selected.fontSize || "md", onChange: (v) => onUpdateField({ fontSize: v }) }),
2004
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.style }),
2005
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.styleToggleRow, children: [
2006
+ /* @__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 }) }),
2007
+ /* @__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 }) })
2008
+ ] }),
2009
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.align }),
2010
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Segmented, { options: TEXT_ALIGN_OPTIONS, value: selected.textAlign || "left", onChange: (v) => onUpdateField({ textAlign: v }) }),
2011
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.color }),
2012
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.swatchRow, children: [
2013
+ 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")),
2014
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "color", value: selected.color || "#1B1E24", onChange: (e) => onUpdateField({ color: e.target.value }), style: styles.colorPickerInput })
2015
+ ] })
1939
2016
  ] })
1940
2017
  ] }),
1941
2018
  selected.type === "image" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
@@ -1964,13 +2041,15 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
1964
2041
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.submitScope }),
1965
2042
  /* @__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
2043
  ] }),
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 } }) })
2044
+ features.blockStyling && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
2045
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.color }),
2046
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.swatchRow, children: [
2047
+ 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")),
2048
+ /* @__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 })
2049
+ ] }),
2050
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.buttonSize }),
2051
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Segmented, { options: SUBMIT_SIZE_OPTIONS, value: selected.buttonStyle?.size || "md", onChange: (v) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, size: v } }) })
2052
+ ] })
1974
2053
  ] }),
1975
2054
  meta.placeholder && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1976
2055
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { style: styles.propLabel, children: chrome.placeholder }),
@@ -2007,7 +2086,7 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
2007
2086
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DefaultValueEditor, { field: selected, meta, lang: language, chrome, onChange: onUpdateField }),
2008
2087
  !meta.isContent && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: styles.toggleRow, children: [
2009
2088
  /* @__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 })
2089
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.requiredField })
2011
2090
  ] }),
2012
2091
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.inspectorDivider }),
2013
2092
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.panelHeading, children: chrome.layout }),
@@ -2024,7 +2103,7 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
2024
2103
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.panelHeading, children: chrome.icon }),
2025
2104
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { style: styles.toggleRow, children: [
2026
2105
  /* @__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 })
2106
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.showIcon })
2028
2107
  ] }),
2029
2108
  selected.showIcon && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: styles.iconGrid, children: Object.keys(ICON_LIBRARY).map((key) => {
2030
2109
  const IconComp = ICON_LIBRARY[key];
@@ -2090,7 +2169,7 @@ function collectFieldValues(fields) {
2090
2169
 
2091
2170
  // src/components/PreviewPane.tsx
2092
2171
  var import_jsx_runtime14 = require("react/jsx-runtime");
2093
- function PreviewPane({ title, sections, onFieldChange, language, strings, chrome, baseMaxWidth, onSubmit }) {
2172
+ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome, baseMaxWidth, features, onSubmit }) {
2094
2173
  const [device, setDevice] = (0, import_react6.useState)("laptop");
2095
2174
  const [errors, setErrors] = (0, import_react6.useState)({});
2096
2175
  const [submitted, setSubmitted] = (0, import_react6.useState)(null);
@@ -2153,7 +2232,7 @@ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome
2153
2232
  }
2154
2233
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: styles.previewWrap, children: [
2155
2234
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { width: "100%", maxWidth, display: "flex", flexDirection: "column", alignItems: "center" }, children: [
2156
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: styles.previewToolbar, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Segmented, { options: deviceOptions, value: device, onChange: setDevice }) }),
2235
+ features.deviceToggle && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { style: styles.previewToolbar, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Segmented, { options: deviceOptions, value: device, onChange: setDevice }) }),
2157
2236
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { ...styles.previewCard, maxWidth, width: "100%" }, children: [
2158
2237
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h2", { style: styles.previewTitle, children: t(title, language) }),
2159
2238
  allFields.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: { color: "var(--fb-muted)", fontSize: 14 }, children: strings.addFieldsHint }),
@@ -2176,7 +2255,7 @@ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome
2176
2255
  })
2177
2256
  ] })
2178
2257
  ] }),
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: [
2258
+ 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
2259
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: styles.modalHeader, children: [
2181
2260
  /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { style: { fontWeight: 600, fontSize: 14, display: "flex", alignItems: "center", gap: 7 }, children: [
2182
2261
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react14.PartyPopper, { size: 15, color: "var(--fb-primary)" }),
@@ -2251,7 +2330,7 @@ var import_lucide_react17 = require("lucide-react");
2251
2330
  var import_jsx_runtime17 = require("react/jsx-runtime");
2252
2331
  function SaveAsModal({ chrome, suggestedName, onSave, onClose }) {
2253
2332
  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: [
2333
+ 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
2334
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { style: styles.modalHeader, children: [
2256
2335
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { fontWeight: 600, fontSize: 14 }, children: chrome.saveForm }),
2257
2336
  /* @__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 +2360,36 @@ var css = `
2281
2360
  that support it (mobile browser chrome resizing the viewport), and is
2282
2361
  simply ignored by ones that don't. */
2283
2362
  .fb-root { max-height: 100vh; max-height: 100dvh; }
2363
+
2364
+ /* Below this width the fixed 200px Palette + 270px Inspector columns
2365
+ don't leave room for a usable Canvas, so instead of stacking all
2366
+ three in flow (which buries Canvas under a tall Palette), Palette
2367
+ and Inspector become narrow drawers over Canvas (which stays
2368
+ partially visible behind them), toggled by .fb-mobile-bar's two
2369
+ buttons, tracked by .fb-work-area's data-mobile-panel attribute,
2370
+ and dismissible via .fb-mobile-backdrop. */
2371
+ .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; }
2372
+ .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; }
2373
+ .fb-mobile-btn[aria-pressed="true"] { border-color: var(--fb-primary); background: var(--fb-primary-soft); color: var(--fb-primary); }
2374
+ .fb-mobile-backdrop { display: none; }
2375
+ @media (max-width: 720px) {
2376
+ .fb-mobile-bar { display: flex; }
2377
+ .fb-work-area { flex-direction: column !important; min-height: 0; }
2378
+ .fb-canvas-area { position: relative; overflow: hidden; }
2379
+ .fb-canvas { width: 100%; }
2380
+ .fb-mobile-backdrop { display: block; position: absolute; inset: 0; z-index: 6; background: rgba(15,16,20,0.35); }
2381
+ .fb-palette, .fb-inspector {
2382
+ position: absolute; top: 0; bottom: 0; z-index: 7;
2383
+ width: min(260px, 80vw) !important; max-height: none !important;
2384
+ border: none !important;
2385
+ box-shadow: 0 0 24px rgba(0,0,0,0.18);
2386
+ transition: transform 0.18s ease;
2387
+ }
2388
+ .fb-palette { left: 0; transform: translateX(-100%); }
2389
+ .fb-inspector { right: 0; transform: translateX(100%); }
2390
+ .fb-work-area[data-mobile-panel="palette"] .fb-palette,
2391
+ .fb-work-area[data-mobile-panel="inspector"] .fb-inspector { transform: translateX(0); }
2392
+ }
2284
2393
  `;
2285
2394
 
2286
2395
  // src/FormBuilder.tsx
@@ -2291,11 +2400,14 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2291
2400
  languages = DEFAULT_LANGUAGES,
2292
2401
  strings: stringsOverride,
2293
2402
  chrome: chromeOverride,
2294
- themeEditable = false,
2403
+ features: featuresProp,
2295
2404
  storage: storageProp,
2296
2405
  onSubmit,
2297
- initialDocument
2406
+ initialDocument,
2407
+ initialMode,
2408
+ onModeChange
2298
2409
  }, ref) {
2410
+ const features = resolveFeatures(featuresProp);
2299
2411
  const storage = storageProp ?? localStorageAdapter;
2300
2412
  const { theme, updateThemeColor, updateThemeLayout, resetTheme, replaceThemeOverrides, themeOverrides } = useTheme(themeOverrideProp);
2301
2413
  const [language, setLanguage] = (0, import_react8.useState)(languageOverride || languages[0]?.code || "en");
@@ -2303,12 +2415,21 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2303
2415
  const chrome = { ...CHROME[language] || CHROME.en, ...chromeOverride && chromeOverride[language] || {} };
2304
2416
  const doc = useFormDocument({ language, chrome });
2305
2417
  const drag = useDragReorder(doc.reorderWithinSection);
2306
- const [mode, setMode] = (0, import_react8.useState)("build");
2418
+ const [mode, setModeState] = (0, import_react8.useState)(initialMode ?? "build");
2419
+ const setMode = (next) => {
2420
+ setModeState(next);
2421
+ onModeChange?.(next);
2422
+ };
2423
+ (0, import_react8.useEffect)(() => {
2424
+ onModeChange?.(mode);
2425
+ }, []);
2307
2426
  const [showJson, setShowJson] = (0, import_react8.useState)(false);
2308
2427
  const [showLibrary, setShowLibrary] = (0, import_react8.useState)(false);
2309
2428
  const [copied, setCopied] = (0, import_react8.useState)(false);
2429
+ const [mobilePanel, setMobilePanel] = (0, import_react8.useState)("none");
2310
2430
  const persistence = usePersistence({
2311
2431
  storage,
2432
+ autosave: features.autosave,
2312
2433
  language,
2313
2434
  chrome,
2314
2435
  document: { title: doc.title, themeOverrides, sections: doc.sections },
@@ -2348,6 +2469,7 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2348
2469
  }
2349
2470
  // eslint-disable-next-line react-hooks/exhaustive-deps
2350
2471
  }), [jsonDoc, jsonString]);
2472
+ const fieldCount = doc.sections.reduce((n, s) => n + s.fields.filter((f) => !getMeta(f.type).isContent).length, 0);
2351
2473
  const activeSectionIdx = doc.sections.findIndex((s) => s.id === doc.activeSection?.id);
2352
2474
  const activeSectionLabel = t(doc.activeSection?.title, language) || `#${activeSectionIdx + 1}`;
2353
2475
  const rootStyle = {
@@ -2362,6 +2484,7 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2362
2484
  "--fb-surface": theme.surface,
2363
2485
  "--fb-canvas": theme.canvas,
2364
2486
  "--fb-page-bg": theme.pageBackground,
2487
+ "--fb-surface-2": mixHex(theme.surface, theme.ink, 0.06),
2365
2488
  "--fb-space-page": `${theme.layout.pagePadding}px`,
2366
2489
  "--fb-space-canvas": `${theme.layout.canvasPadding}px`,
2367
2490
  "--fb-space-section": `${theme.layout.sectionGap}px`,
@@ -2381,6 +2504,7 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2381
2504
  mode,
2382
2505
  saveState: persistence.saveState,
2383
2506
  chrome,
2507
+ features,
2384
2508
  savedFormsCount: persistence.savedForms.length,
2385
2509
  onTitleChange: doc.updateTitle,
2386
2510
  onLanguageChange: setLanguage,
@@ -2394,63 +2518,103 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2394
2518
  persistence.loadingDraft ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { style: styles.loadingScreen, children: [
2395
2519
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react18.Loader2, { size: 20, className: "spin" }),
2396
2520
  /* @__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
- )
2521
+ ] }) : mode === "build" ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "fb-work-area", style: styles.workArea, "data-mobile-panel": mobilePanel, children: [
2522
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "fb-mobile-bar", children: [
2523
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2524
+ "button",
2525
+ {
2526
+ type: "button",
2527
+ className: "fb-mobile-btn",
2528
+ "aria-pressed": mobilePanel === "palette",
2529
+ onClick: () => setMobilePanel((p) => p === "palette" ? "none" : "palette"),
2530
+ children: [
2531
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react18.Menu, { size: 14 }),
2532
+ " ",
2533
+ chrome.paletteTabBlocks
2534
+ ]
2535
+ }
2536
+ ),
2537
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2538
+ "button",
2539
+ {
2540
+ type: "button",
2541
+ className: "fb-mobile-btn",
2542
+ "aria-pressed": mobilePanel === "inspector",
2543
+ onClick: () => setMobilePanel((p) => p === "inspector" ? "none" : "inspector"),
2544
+ children: [
2545
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react18.SlidersHorizontal, { size: 14 }),
2546
+ " ",
2547
+ chrome.properties
2548
+ ]
2549
+ }
2550
+ )
2551
+ ] }),
2552
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "fb-canvas-area", style: styles.workArea, children: [
2553
+ mobilePanel !== "none" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "fb-mobile-backdrop", onClick: () => setMobilePanel("none") }),
2554
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2555
+ Palette,
2556
+ {
2557
+ activeSectionLabel,
2558
+ chrome,
2559
+ onAddField: (type) => {
2560
+ doc.addField(type);
2561
+ setMobilePanel("none");
2562
+ },
2563
+ features,
2564
+ fieldCount,
2565
+ theme,
2566
+ updateThemeColor,
2567
+ updateThemeLayout,
2568
+ resetTheme
2569
+ }
2570
+ ),
2571
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2572
+ Canvas,
2573
+ {
2574
+ sections: doc.sections,
2575
+ activeSectionId: doc.activeSectionId,
2576
+ selectedId: doc.selectedId,
2577
+ dragOverKey: drag.dragOverKey,
2578
+ chrome,
2579
+ strings,
2580
+ language,
2581
+ features,
2582
+ onActivateSection: doc.setActiveSectionId,
2583
+ onToggleSectionCollapse: doc.toggleSectionCollapse,
2584
+ onUpdateSectionTitle: doc.updateSectionTitle,
2585
+ onUpdateSectionBackground: doc.updateSectionBackground,
2586
+ onDuplicateSection: doc.duplicateSection,
2587
+ onMoveSection: doc.moveSection,
2588
+ onDeleteSection: doc.deleteSection,
2589
+ onAddSection: doc.addSection,
2590
+ onSelectField: (sectionId, fieldId) => {
2591
+ doc.setSelectedId(fieldId);
2592
+ doc.setActiveSectionId(sectionId);
2593
+ setMobilePanel("inspector");
2594
+ },
2595
+ onFieldChange: doc.updateField,
2596
+ onMoveField: doc.moveField,
2597
+ onDuplicateField: doc.duplicateField,
2598
+ onDeleteField: doc.deleteField,
2599
+ getDropZoneHandlers: drag.getDropZoneHandlers,
2600
+ getDragHandleProps: drag.getDragHandleProps
2601
+ }
2602
+ ),
2603
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2604
+ Inspector,
2605
+ {
2606
+ selected: doc.selected,
2607
+ language,
2608
+ chrome,
2609
+ features,
2610
+ onUpdateField: (patch) => doc.selected && doc.updateField(doc.selected.id, patch),
2611
+ onDeleteField: () => doc.selected && doc.deleteField(doc.selected.id),
2612
+ onUpdateOption: (optIdx, patch) => doc.selected && doc.updateOption(doc.selected.id, optIdx, patch),
2613
+ onAddOption: () => doc.selected && doc.addOption(doc.selected.id),
2614
+ onRemoveOption: (optIdx) => doc.selected && doc.removeOption(doc.selected.id, optIdx)
2615
+ }
2616
+ )
2617
+ ] })
2454
2618
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2455
2619
  PreviewPane,
2456
2620
  {
@@ -2461,6 +2625,7 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2461
2625
  strings,
2462
2626
  chrome,
2463
2627
  baseMaxWidth: theme.layout.maxWidth,
2628
+ features,
2464
2629
  onSubmit
2465
2630
  }
2466
2631
  ),
@@ -2491,8 +2656,25 @@ var FormBuilder = (0, import_react8.forwardRef)(function FormBuilder2({
2491
2656
  ] });
2492
2657
  });
2493
2658
  var FormBuilder_default = FormBuilder;
2659
+
2660
+ // src/theme/darkTheme.ts
2661
+ var DARK_THEME = {
2662
+ primary: "#8B8FF5",
2663
+ primarySoft: "#262A45",
2664
+ danger: "#F0715B",
2665
+ dangerSoft: "#3A2420",
2666
+ ink: "#EDEEF2",
2667
+ muted: "#9096A8",
2668
+ border: "#2E313D",
2669
+ surface: "#1A1B23",
2670
+ canvas: "#121319",
2671
+ pageBackground: "#1A1B23",
2672
+ layout: DEFAULT_THEME.layout
2673
+ };
2494
2674
  // Annotate the CommonJS export names for ESM import in node:
2495
2675
  0 && (module.exports = {
2676
+ DARK_THEME,
2677
+ DEFAULT_THEME,
2496
2678
  FormBuilder,
2497
2679
  localStorageAdapter
2498
2680
  });