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.js CHANGED
@@ -1,8 +1,69 @@
1
1
  "use client";
2
2
 
3
3
  // src/FormBuilder.tsx
4
- import { forwardRef, useImperativeHandle, useState as useState8 } from "react";
5
- import { Loader2 as Loader22 } from "lucide-react";
4
+ import { forwardRef, useEffect as useEffect2, useImperativeHandle, useState as useState8 } from "react";
5
+ import { Loader2 as Loader22, Menu, SlidersHorizontal } from "lucide-react";
6
+
7
+ // src/constants/fieldTypes.ts
8
+ import {
9
+ Type,
10
+ AlignLeft,
11
+ ChevronDown,
12
+ Circle,
13
+ ListChecks,
14
+ CheckSquare,
15
+ ToggleLeft,
16
+ FileText,
17
+ Image as ImageIcon,
18
+ MousePointerClick
19
+ } from "lucide-react";
20
+ var FIELD_TYPES = [
21
+ { type: "paragraph", icon: FileText, isContent: true, defaultIcon: "FileText" },
22
+ { type: "image", icon: ImageIcon, isContent: true, isImage: true, defaultIcon: "Type" },
23
+ { type: "button", icon: MousePointerClick, isContent: true, defaultIcon: "Type" },
24
+ { type: "input", icon: Type, placeholder: true, hasSubtype: true, defaultIcon: "Type" },
25
+ { type: "textarea", icon: AlignLeft, placeholder: true, defaultIcon: "AlignLeft" },
26
+ { type: "select", icon: ChevronDown, options: true, defaultIcon: "ChevronDown" },
27
+ { type: "radio", icon: Circle, options: true, defaultIcon: "Circle" },
28
+ { type: "checkboxGroup", icon: ListChecks, options: true, multiValue: true, defaultIcon: "ListChecks" },
29
+ { type: "checkbox", icon: CheckSquare, boolean: true, defaultIcon: "CheckSquare" },
30
+ { type: "toggle", icon: ToggleLeft, boolean: true, defaultIcon: "ToggleLeft" }
31
+ ];
32
+ var TYPE_MAP = Object.fromEntries(FIELD_TYPES.map((f) => [f.type, f]));
33
+ var CONTENT_TYPES = FIELD_TYPES.filter((f) => f.isContent);
34
+ var FORM_TYPES = FIELD_TYPES.filter((f) => !f.isContent);
35
+ function getMeta(type) {
36
+ return TYPE_MAP[type] || TYPE_MAP.input;
37
+ }
38
+ var LEGACY_INPUT_TYPES = ["text", "email", "phone", "number", "password", "date"];
39
+ var INPUT_SUBTYPES = ["text", "email", "phone", "number", "password", "date", "time"];
40
+ var IMAGE_SHAPES = ["square", "circle", "banner"];
41
+ var FIELD_TYPE_CHROME_KEY = {
42
+ paragraph: "fieldTypeParagraph",
43
+ image: "fieldTypeImage",
44
+ button: "fieldTypeButton",
45
+ input: "fieldTypeInput",
46
+ textarea: "fieldTypeTextarea",
47
+ select: "fieldTypeSelect",
48
+ radio: "fieldTypeRadio",
49
+ checkboxGroup: "fieldTypeCheckboxGroup",
50
+ checkbox: "fieldTypeCheckbox",
51
+ toggle: "fieldTypeToggle"
52
+ };
53
+ var INPUT_SUBTYPE_CHROME_KEY = {
54
+ text: "subtypeText",
55
+ email: "subtypeEmail",
56
+ phone: "subtypePhone",
57
+ number: "subtypeNumber",
58
+ password: "subtypePassword",
59
+ date: "subtypeDate",
60
+ time: "subtypeTime"
61
+ };
62
+ var IMAGE_SHAPE_CHROME_KEY = {
63
+ square: "shapeSquare",
64
+ circle: "shapeCircle",
65
+ banner: "shapeBanner"
66
+ };
6
67
 
7
68
  // src/i18n/languages.ts
8
69
  var DEFAULT_LANGUAGES = [
@@ -333,6 +394,22 @@ function withLang(val, lang, value) {
333
394
  return { ...base, [lang]: value };
334
395
  }
335
396
 
397
+ // src/lib/color.ts
398
+ function mixHex(a, b, t2) {
399
+ const pa = parseHex(a);
400
+ const pb = parseHex(b);
401
+ if (!pa || !pb) return a;
402
+ const mix = (x, y) => Math.round(x + (y - x) * t2);
403
+ const toHex = (n) => n.toString(16).padStart(2, "0");
404
+ return `#${toHex(mix(pa[0], pb[0]))}${toHex(mix(pa[1], pb[1]))}${toHex(mix(pa[2], pb[2]))}`;
405
+ }
406
+ function parseHex(hex) {
407
+ const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());
408
+ if (!m) return null;
409
+ const n = parseInt(m[1], 16);
410
+ return [n >> 16 & 255, n >> 8 & 255, n & 255];
411
+ }
412
+
336
413
  // src/lib/storage/compress.ts
337
414
  import { compressToUTF16, decompressFromUTF16 } from "lz-string";
338
415
  function compress(raw) {
@@ -375,67 +452,6 @@ var localStorageAdapter = {
375
452
  }
376
453
  };
377
454
 
378
- // src/constants/fieldTypes.ts
379
- import {
380
- Type,
381
- AlignLeft,
382
- ChevronDown,
383
- Circle,
384
- ListChecks,
385
- CheckSquare,
386
- ToggleLeft,
387
- FileText,
388
- Image as ImageIcon,
389
- MousePointerClick
390
- } from "lucide-react";
391
- var FIELD_TYPES = [
392
- { type: "paragraph", icon: FileText, isContent: true, defaultIcon: "FileText" },
393
- { type: "image", icon: ImageIcon, isContent: true, isImage: true, defaultIcon: "Type" },
394
- { type: "button", icon: MousePointerClick, isContent: true, defaultIcon: "Type" },
395
- { type: "input", icon: Type, placeholder: true, hasSubtype: true, defaultIcon: "Type" },
396
- { type: "textarea", icon: AlignLeft, placeholder: true, defaultIcon: "AlignLeft" },
397
- { type: "select", icon: ChevronDown, options: true, defaultIcon: "ChevronDown" },
398
- { type: "radio", icon: Circle, options: true, defaultIcon: "Circle" },
399
- { type: "checkboxGroup", icon: ListChecks, options: true, multiValue: true, defaultIcon: "ListChecks" },
400
- { type: "checkbox", icon: CheckSquare, boolean: true, defaultIcon: "CheckSquare" },
401
- { type: "toggle", icon: ToggleLeft, boolean: true, defaultIcon: "ToggleLeft" }
402
- ];
403
- var TYPE_MAP = Object.fromEntries(FIELD_TYPES.map((f) => [f.type, f]));
404
- var CONTENT_TYPES = FIELD_TYPES.filter((f) => f.isContent);
405
- var FORM_TYPES = FIELD_TYPES.filter((f) => !f.isContent);
406
- function getMeta(type) {
407
- return TYPE_MAP[type] || TYPE_MAP.input;
408
- }
409
- var LEGACY_INPUT_TYPES = ["text", "email", "phone", "number", "password", "date"];
410
- var INPUT_SUBTYPES = ["text", "email", "phone", "number", "password", "date", "time"];
411
- var IMAGE_SHAPES = ["square", "circle", "banner"];
412
- var FIELD_TYPE_CHROME_KEY = {
413
- paragraph: "fieldTypeParagraph",
414
- image: "fieldTypeImage",
415
- button: "fieldTypeButton",
416
- input: "fieldTypeInput",
417
- textarea: "fieldTypeTextarea",
418
- select: "fieldTypeSelect",
419
- radio: "fieldTypeRadio",
420
- checkboxGroup: "fieldTypeCheckboxGroup",
421
- checkbox: "fieldTypeCheckbox",
422
- toggle: "fieldTypeToggle"
423
- };
424
- var INPUT_SUBTYPE_CHROME_KEY = {
425
- text: "subtypeText",
426
- email: "subtypeEmail",
427
- phone: "subtypePhone",
428
- number: "subtypeNumber",
429
- password: "subtypePassword",
430
- date: "subtypeDate",
431
- time: "subtypeTime"
432
- };
433
- var IMAGE_SHAPE_CHROME_KEY = {
434
- square: "shapeSquare",
435
- circle: "shapeCircle",
436
- banner: "shapeBanner"
437
- };
438
-
439
455
  // src/lib/id.ts
440
456
  var genFormId = () => `form_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`;
441
457
  var genSectionId = () => `section_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`;
@@ -599,6 +615,38 @@ 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
+ deviceToggle: true
634
+ };
635
+ function resolveFeatures(features) {
636
+ return {
637
+ ...DEFAULT_FEATURES,
638
+ ...features,
639
+ contentBlocks: Array.isArray(features?.contentBlocks) ? new Set(features.contentBlocks) : features?.contentBlocks ?? DEFAULT_FEATURES.contentBlocks,
640
+ fieldTypes: Array.isArray(features?.fieldTypes) ? new Set(features.fieldTypes) : features?.fieldTypes ?? DEFAULT_FEATURES.fieldTypes
641
+ };
642
+ }
643
+ function isContentBlockEnabled(features, type) {
644
+ return features.contentBlocks === true || features.contentBlocks instanceof Set && features.contentBlocks.has(type);
645
+ }
646
+ function isFieldTypeEnabled(features, type) {
647
+ return features.fieldTypes === true || features.fieldTypes instanceof Set && features.fieldTypes.has(type);
648
+ }
649
+
602
650
  // src/hooks/useTheme.ts
603
651
  import { useState } from "react";
604
652
 
@@ -833,6 +881,7 @@ var formKey = (id) => `form-page-builder:saved:${id}`;
833
881
  var MAX_TEMPLATES = 5;
834
882
  function usePersistence({
835
883
  storage,
884
+ autosave,
836
885
  language,
837
886
  chrome,
838
887
  document,
@@ -894,7 +943,7 @@ function usePersistence({
894
943
  refreshLibrary();
895
944
  }, []);
896
945
  useEffect(() => {
897
- if (!hasLoadedOnce.current) return;
946
+ if (!hasLoadedOnce.current || !autosave) return;
898
947
  setSaveState("saving");
899
948
  if (autosaveTimer.current) clearTimeout(autosaveTimer.current);
900
949
  autosaveTimer.current = setTimeout(async () => {
@@ -1033,15 +1082,15 @@ var styles = {
1033
1082
  titleInput: { border: "none", outline: "none", fontSize: 14, fontWeight: 600, background: "transparent", color: "var(--fb-ink)", padding: "4px 6px", borderRadius: 6, minWidth: 160 },
1034
1083
  toolbarRight: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" },
1035
1084
  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 },
1085
+ 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
1086
  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 },
1087
+ 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
1088
  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
1089
  saveStatus: { display: "flex", alignItems: "center", gap: 5, fontSize: 12, color: "var(--fb-muted)", minWidth: 60 },
1041
1090
  countBadge: { fontSize: 10.5, fontWeight: 700, background: "var(--fb-primary-soft)", color: "var(--fb-primary)", borderRadius: 9, padding: "1px 6px", marginLeft: 2 },
1042
1091
  loadingScreen: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
1043
1092
  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" },
1093
+ libraryRow: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10, padding: "10px 8px", borderRadius: 8, border: "1px solid var(--fb-border)" },
1045
1094
  libraryRowTitle: { fontSize: 13.5, fontWeight: 600, color: "var(--fb-ink)", display: "flex", alignItems: "center", gap: 8, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
1046
1095
  libraryRowMeta: { fontSize: 11.5, color: "var(--fb-muted)", marginTop: 2 },
1047
1096
  currentBadge: { fontSize: 10, fontWeight: 700, color: "var(--fb-primary)", background: "var(--fb-primary-soft)", padding: "2px 6px", borderRadius: 5, flexShrink: 0 },
@@ -1050,7 +1099,7 @@ var styles = {
1050
1099
  panelHeading: { fontSize: 11, fontWeight: 700, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--fb-muted)", marginBottom: 10 },
1051
1100
  activeSectionHint: { fontSize: 11.5, color: "var(--fb-muted)", marginBottom: 14, lineHeight: 1.4 },
1052
1101
  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" },
1102
+ 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
1103
  canvas: { flex: 1, padding: "var(--fb-space-canvas)", overflowY: "auto", background: "var(--fb-canvas)" },
1055
1104
  sectionBlock: { borderRadius: 12, padding: "var(--fb-space-panel)", marginBottom: "var(--fb-space-section)", transition: "border-color 0.12s" },
1056
1105
  sectionHeader: { display: "flex", alignItems: "center", gap: 8, marginBottom: 12, flexWrap: "wrap" },
@@ -1060,7 +1109,7 @@ var styles = {
1060
1109
  sectionHeaderActions: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap", marginLeft: "auto" },
1061
1110
  sectionEmpty: { fontSize: 12.5, color: "var(--fb-muted)", padding: "18px 4px", textAlign: "center", border: "1px dashed var(--fb-border)", borderRadius: 8 },
1062
1111
  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 },
1112
+ 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
1113
  swatchRow: { display: "flex", alignItems: "center", gap: 5, flexWrap: "wrap" },
1065
1114
  swatchBtn: { width: 20, height: 20, borderRadius: "50%", border: "1px solid var(--fb-border)", padding: 0 },
1066
1115
  swatchBtnActive: { border: "2px solid var(--fb-primary)" },
@@ -1069,56 +1118,56 @@ var styles = {
1069
1118
  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
1119
  ticketSelected: { borderColor: "var(--fb-primary)", boxShadow: "0 0 0 3px var(--fb-primary-soft)" },
1071
1120
  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 },
1121
+ ticketIndex: { fontFamily: "'JetBrains Mono', monospace", fontSize: 13, fontWeight: 700, color: "var(--fb-border)", width: 34, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 },
1073
1122
  ticketPerforation: { width: 0, borderLeft: "1px dashed var(--fb-border)" },
1074
1123
  ticketBody: { flex: 1, padding: "10px var(--fb-space-ticket)", minWidth: 0 },
1075
1124
  ticketTop: { display: "flex", alignItems: "center", gap: 7, marginBottom: 4 },
1076
1125
  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" },
1126
+ 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
1127
  chipRow: { display: "flex", gap: 5, marginBottom: 7, flexWrap: "wrap" },
1079
1128
  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 },
1129
+ langToggleTrack: { position: "relative", display: "flex", gap: 3, background: "var(--fb-surface-2)", padding: 3, borderRadius: 20 },
1081
1130
  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" },
1131
+ 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
1132
  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)" },
1133
+ segmented: { display: "flex", gap: 3, background: "var(--fb-surface-2)", padding: 3, borderRadius: 8, marginBottom: 4 },
1134
+ 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 },
1135
+ 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
1136
  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" },
1137
+ 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
1138
  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
1139
  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)" },
1140
+ 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
1141
  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" },
1142
+ 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" },
1143
+ previewRadio: { display: "flex", alignItems: "center", gap: 6, fontSize: 13, color: "var(--fb-ink)" },
1144
+ ticketActions: { display: "flex", flexDirection: "column", gap: 3, padding: 8, borderLeft: "1px solid var(--fb-border)" },
1145
+ 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
1146
  iconBtnDanger: { color: "var(--fb-danger)" },
1098
1147
  inspector: { width: 270, borderLeft: "1px solid var(--fb-border)", background: "var(--fb-surface)", padding: "var(--fb-space-panel)", overflowY: "auto" },
1099
1148
  inspectorEmpty: { fontSize: 13, color: "var(--fb-muted)", lineHeight: 1.5, marginTop: 6 },
1100
1149
  inspectorBody: { display: "flex", flexDirection: "column", gap: 4 },
1101
1150
  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" },
1151
+ propLabel: { fontSize: 11.5, fontWeight: 600, color: "var(--fb-muted)", marginTop: 12, marginBottom: 5 },
1152
+ 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
1153
  optionList: { display: "flex", flexDirection: "column", gap: 6 },
1105
1154
  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 },
1155
+ 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" },
1156
+ 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
1157
  toggleRow: { display: "flex", alignItems: "center", gap: 8, background: "transparent", border: "none", padding: "8px 0" },
1109
1158
  toggleTrack: { width: 30, height: 17, borderRadius: 20, position: "relative", transition: "background 0.15s", display: "inline-block" },
1110
1159
  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
1160
  inspectorDivider: { height: 1, background: "var(--fb-border)", margin: "14px 0 10px" },
1112
1161
  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)" },
1162
+ 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" },
1163
+ 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
1164
  modalHeader: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "12px 16px", borderBottom: "1px solid var(--fb-border)" },
1116
1165
  jsonPre: { margin: 0, padding: 16, fontSize: 12, lineHeight: 1.6, overflow: "auto", background: "#14171C", color: "#D6D8E0", fontFamily: "'JetBrains Mono', monospace" },
1117
1166
  previewWrap: { flex: 1, display: "flex", justifyContent: "center", padding: "var(--fb-space-page) 20px", overflowY: "auto", background: "var(--fb-canvas)" },
1118
1167
  previewToolbar: { width: "100%", display: "flex", gap: 10, marginBottom: 16, justifyContent: "center" },
1119
1168
  previewCard: { width: "100%", maxWidth: 480, background: "var(--fb-page-bg)", border: "1px solid var(--fb-border)", borderRadius: 12, padding: "var(--fb-space-page)" },
1120
1169
  previewTitle: { fontSize: 19, fontWeight: 700, margin: "0 0 20px" },
1121
- previewLabel: { display: "block", fontSize: 13, fontWeight: 600, color: "#33353E", marginBottom: 6 },
1170
+ previewLabel: { display: "block", fontSize: 13, fontWeight: 600, color: "var(--fb-ink)", marginBottom: 6 },
1122
1171
  previewGrid: { display: "flex", flexWrap: "wrap", gap: "var(--fb-space-field)" },
1123
1172
  sectionRuntimeTitle: { fontSize: 15, fontWeight: 700, margin: "0 0 12px", color: "var(--fb-ink)" },
1124
1173
  imagePlaceholder: { display: "flex", alignItems: "center", justifyContent: "center", border: "1px dashed var(--fb-border)" },
@@ -1128,13 +1177,13 @@ var styles = {
1128
1177
  submittedRow: { display: "flex", justifyContent: "space-between", gap: 12, fontSize: 13, padding: "6px 0", borderBottom: "1px solid var(--fb-border)" },
1129
1178
  submittedLabel: { color: "var(--fb-muted)", flexShrink: 0 },
1130
1179
  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" },
1180
+ 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
1181
  realInputError: { borderColor: "var(--fb-danger)" },
1133
1182
  submitBtn: { marginTop: 8, color: "#fff", border: "none", borderRadius: 8, fontWeight: 600, width: "100%" },
1134
1183
  layoutPanelHeader: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 4 },
1135
1184
  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" }
1185
+ spacingLabel: { fontSize: 12, color: "var(--fb-ink)" },
1186
+ 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
1187
  };
1139
1188
 
1140
1189
  // src/components/LanguageToggle.tsx
@@ -1175,6 +1224,7 @@ function Toolbar({
1175
1224
  mode,
1176
1225
  saveState,
1177
1226
  chrome,
1227
+ features,
1178
1228
  savedFormsCount,
1179
1229
  onTitleChange,
1180
1230
  onLanguageChange,
@@ -1187,7 +1237,7 @@ function Toolbar({
1187
1237
  return /* @__PURE__ */ jsxs2("div", { style: styles.toolbar, children: [
1188
1238
  /* @__PURE__ */ jsxs2("div", { style: styles.toolbarLeft, children: [
1189
1239
  /* @__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" })
1240
+ 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
1241
  ] }),
1192
1242
  /* @__PURE__ */ jsxs2("div", { style: styles.toolbarRight, children: [
1193
1243
  /* @__PURE__ */ jsxs2("span", { style: styles.saveStatus, children: [
@@ -1203,37 +1253,43 @@ function Toolbar({
1203
1253
  chrome.saveFailed
1204
1254
  ] })
1205
1255
  ] }),
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
1256
+ features.languageSwitcher && /* @__PURE__ */ jsxs2(Fragment, { children: [
1257
+ /* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
1258
+ /* @__PURE__ */ jsx2(LanguageToggle, { languages, value: language, onChange: onLanguageChange })
1213
1259
  ] }),
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
1260
+ features.previewMode && /* @__PURE__ */ jsxs2(Fragment, { children: [
1261
+ /* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
1262
+ /* @__PURE__ */ jsxs2("button", { style: mode === "build" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("build"), children: [
1263
+ /* @__PURE__ */ jsx2(Pencil, { size: 14 }),
1264
+ " ",
1265
+ chrome.build
1266
+ ] }),
1267
+ /* @__PURE__ */ jsxs2("button", { style: mode === "preview" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("preview"), children: [
1268
+ /* @__PURE__ */ jsx2(Eye, { size: 14 }),
1269
+ " ",
1270
+ chrome.preview
1271
+ ] })
1218
1272
  ] }),
1219
- /* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
1220
- /* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onNewForm, title: chrome.startNewForm, children: [
1273
+ (features.newForm || features.templates) && /* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
1274
+ features.newForm && /* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onNewForm, title: chrome.startNewForm, children: [
1221
1275
  /* @__PURE__ */ jsx2(FilePlus2, { size: 14 }),
1222
1276
  " ",
1223
1277
  chrome.newForm
1224
1278
  ] }),
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
1279
+ features.templates && /* @__PURE__ */ jsxs2(Fragment, { children: [
1280
+ /* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onOpenLibrary, title: chrome.openTemplatesTitle, children: [
1281
+ /* @__PURE__ */ jsx2(FolderOpen, { size: 14 }),
1282
+ " ",
1283
+ chrome.templates,
1284
+ savedFormsCount > 0 && /* @__PURE__ */ jsx2("span", { style: styles.countBadge, children: savedFormsCount })
1285
+ ] }),
1286
+ /* @__PURE__ */ jsxs2("button", { style: styles.primaryBtn, onClick: onSaveExisting, title: chrome.saveToLibraryTitle, children: [
1287
+ /* @__PURE__ */ jsx2(Save, { size: 14 }),
1288
+ " ",
1289
+ chrome.save
1290
+ ] })
1235
1291
  ] }),
1236
- /* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onOpenJson, children: [
1292
+ features.jsonView && /* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onOpenJson, children: [
1237
1293
  /* @__PURE__ */ jsx2(Code2, { size: 14 }),
1238
1294
  " ",
1239
1295
  chrome.viewJson
@@ -1334,15 +1390,19 @@ function Palette({
1334
1390
  activeSectionLabel,
1335
1391
  chrome,
1336
1392
  onAddField,
1337
- themeEditable,
1393
+ features,
1338
1394
  theme,
1339
1395
  updateThemeColor,
1340
1396
  updateThemeLayout,
1341
- resetTheme
1397
+ resetTheme,
1398
+ fieldCount
1342
1399
  }) {
1343
1400
  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(
1401
+ const contentTypes = CONTENT_TYPES.filter((f) => isContentBlockEnabled(features, f.type));
1402
+ const formTypes = FORM_TYPES.filter((f) => isFieldTypeEnabled(features, f.type));
1403
+ const atFieldCap = typeof features.maxFields === "number" && fieldCount >= features.maxFields;
1404
+ return /* @__PURE__ */ jsxs5("div", { className: "fb-palette", style: styles.palette, children: [
1405
+ features.design && /* @__PURE__ */ jsx5("div", { style: { marginBottom: 14 }, children: /* @__PURE__ */ jsx5(
1346
1406
  Segmented,
1347
1407
  {
1348
1408
  options: [
@@ -1353,7 +1413,7 @@ function Palette({
1353
1413
  onChange: setTab
1354
1414
  }
1355
1415
  ) }),
1356
- tab === "design" && themeEditable ? /* @__PURE__ */ jsx5(
1416
+ tab === "design" && features.design ? /* @__PURE__ */ jsx5(
1357
1417
  DesignPanel,
1358
1418
  {
1359
1419
  chrome,
@@ -1368,24 +1428,29 @@ function Palette({
1368
1428
  " ",
1369
1429
  /* @__PURE__ */ jsx5("strong", { children: activeSectionLabel })
1370
1430
  ] }),
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
- }) })
1431
+ contentTypes.length > 0 && /* @__PURE__ */ jsxs5(Fragment2, { children: [
1432
+ /* @__PURE__ */ jsx5("div", { style: styles.panelHeading, children: chrome.contentBlocks }),
1433
+ /* @__PURE__ */ jsx5("div", { style: styles.paletteList, children: contentTypes.map((f) => {
1434
+ const Icon = f.icon;
1435
+ return /* @__PURE__ */ jsxs5("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1436
+ /* @__PURE__ */ jsx5(Icon, { size: 16, color: "var(--fb-primary)" }),
1437
+ /* @__PURE__ */ jsx5("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1438
+ /* @__PURE__ */ jsx5(Plus, { size: 13, color: "var(--fb-muted)", style: { marginLeft: "auto" } })
1439
+ ] }, f.type);
1440
+ }) })
1441
+ ] }),
1442
+ formTypes.length > 0 && /* @__PURE__ */ jsxs5(Fragment2, { children: [
1443
+ /* @__PURE__ */ jsx5("div", { style: { ...styles.panelHeading, marginTop: 16 }, children: chrome.formFields }),
1444
+ /* @__PURE__ */ jsx5("div", { style: styles.paletteList, children: formTypes.map((f) => {
1445
+ const Icon = f.icon;
1446
+ const itemStyle = atFieldCap ? { ...styles.paletteItem, opacity: 0.45, cursor: "not-allowed" } : styles.paletteItem;
1447
+ return /* @__PURE__ */ jsxs5("button", { type: "button", disabled: atFieldCap, style: itemStyle, onClick: () => onAddField(f.type), children: [
1448
+ /* @__PURE__ */ jsx5(Icon, { size: 16, color: "var(--fb-primary)" }),
1449
+ /* @__PURE__ */ jsx5("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1450
+ /* @__PURE__ */ jsx5(Plus, { size: 13, color: "var(--fb-muted)", style: { marginLeft: "auto" } })
1451
+ ] }, f.type);
1452
+ }) })
1453
+ ] })
1389
1454
  ] })
1390
1455
  ] });
1391
1456
  }
@@ -1538,7 +1603,7 @@ function FieldBlock({ field, lang, onFieldChange, strings, chrome, error, isBuil
1538
1603
  return /* @__PURE__ */ jsxs6("div", { children: [
1539
1604
  /* @__PURE__ */ jsxs6("div", { style: { display: "flex", flexDirection: isInline ? "row" : "column", alignItems: isInline ? "center" : "stretch", gap: isInline ? 10 : 6 }, children: [
1540
1605
  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" }),
1606
+ IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "var(--fb-muted)" }),
1542
1607
  labelText || (isBuild ? /* @__PURE__ */ jsx8("span", { style: { fontStyle: "italic", color: "var(--fb-muted)" }, children: chrome?.untitledField || "Untitled field" }) : ""),
1543
1608
  field.required && /* @__PURE__ */ jsx8("span", { style: { color: "var(--fb-danger)" }, children: " *" })
1544
1609
  ] }),
@@ -1603,14 +1668,14 @@ function renderInteractive(field, lang, onFieldChange, IconComp, hasError, strin
1603
1668
  case "checkbox":
1604
1669
  return /* @__PURE__ */ jsxs6("label", { style: styles.previewRadio, children: [
1605
1670
  /* @__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" }),
1671
+ IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "var(--fb-muted)" }),
1607
1672
  t(field.label, lang),
1608
1673
  field.required && /* @__PURE__ */ jsx8("span", { style: { color: "var(--fb-danger)" }, children: " *" })
1609
1674
  ] });
1610
1675
  case "toggle":
1611
1676
  return /* @__PURE__ */ jsxs6("label", { style: styles.previewRadio, children: [
1612
1677
  /* @__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" }),
1678
+ IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "var(--fb-muted)" }),
1614
1679
  t(field.label, lang)
1615
1680
  ] });
1616
1681
  default:
@@ -1628,6 +1693,7 @@ function FieldTicket({
1628
1693
  chrome,
1629
1694
  strings,
1630
1695
  language,
1696
+ dragEnabled,
1631
1697
  onSelect,
1632
1698
  onFieldChange,
1633
1699
  onMoveField,
@@ -1657,7 +1723,7 @@ function FieldTicket({
1657
1723
  /* @__PURE__ */ jsx9("div", { style: styles.ticketPerforation }),
1658
1724
  /* @__PURE__ */ jsxs7("div", { style: styles.ticketBody, children: [
1659
1725
  /* @__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" }) }),
1726
+ dragEnabled && /* @__PURE__ */ jsx9("span", { ...dragHandleProps, style: { cursor: "grab", display: "flex" }, children: /* @__PURE__ */ jsx9(GripVertical, { size: 14, color: "var(--fb-muted)" }) }),
1661
1727
  /* @__PURE__ */ jsx9(Icon, { size: 13, color: "var(--fb-primary)" }),
1662
1728
  /* @__PURE__ */ jsxs7("span", { style: styles.typeBadge, children: [
1663
1729
  chrome[FIELD_TYPE_CHROME_KEY[field.type]] || field.type,
@@ -1689,7 +1755,7 @@ function FieldTicket({
1689
1755
  }
1690
1756
 
1691
1757
  // src/components/SectionCard.tsx
1692
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1758
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1693
1759
  function SectionCard({
1694
1760
  section,
1695
1761
  sIdx,
@@ -1700,6 +1766,7 @@ function SectionCard({
1700
1766
  chrome,
1701
1767
  strings,
1702
1768
  language,
1769
+ features,
1703
1770
  onActivate,
1704
1771
  onToggleCollapse,
1705
1772
  onUpdateTitle,
@@ -1739,14 +1806,16 @@ function SectionCard({
1739
1806
  ),
1740
1807
  section.collapsed && /* @__PURE__ */ jsx10("span", { style: styles.miniBadge, children: chrome.fieldsCount(section.fields.length) }),
1741
1808
  /* @__PURE__ */ jsxs8("div", { style: styles.sectionHeaderActions, onClick: (e) => e.stopPropagation(), children: [
1742
- !section.collapsed && /* @__PURE__ */ jsxs8("div", { style: styles.swatchRow, children: [
1809
+ features.sections && !section.collapsed && /* @__PURE__ */ jsxs8("div", { style: styles.swatchRow, children: [
1743
1810
  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
1811
  /* @__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
1812
  ] }),
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 }) })
1813
+ features.sections && /* @__PURE__ */ jsxs8(Fragment3, { children: [
1814
+ /* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.duplicate, onClick: onDuplicateSection, children: /* @__PURE__ */ jsx10(Copy2, { size: 13 }) }),
1815
+ /* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.moveUp, disabled: sIdx === 0, onClick: () => onMoveSection(-1), children: /* @__PURE__ */ jsx10(ArrowUp2, { size: 13 }) }),
1816
+ /* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.moveDown, disabled: sIdx === sectionsLength - 1, onClick: () => onMoveSection(1), children: /* @__PURE__ */ jsx10(ArrowDown2, { size: 13 }) }),
1817
+ /* @__PURE__ */ jsx10("button", { style: { ...styles.iconBtn, ...styles.iconBtnDanger }, title: chrome.deleteSection, disabled: sectionsLength <= 1, onClick: onDeleteSection, children: /* @__PURE__ */ jsx10(Trash22, { size: 13 }) })
1818
+ ] })
1750
1819
  ] })
1751
1820
  ] }),
1752
1821
  !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 +1829,7 @@ function SectionCard({
1760
1829
  chrome,
1761
1830
  strings,
1762
1831
  language,
1832
+ dragEnabled: features.dragReorder,
1763
1833
  onSelect: () => onSelectField(field.id),
1764
1834
  onFieldChange,
1765
1835
  onMoveField,
@@ -1785,6 +1855,7 @@ function Canvas({
1785
1855
  chrome,
1786
1856
  strings,
1787
1857
  language,
1858
+ features,
1788
1859
  onActivateSection,
1789
1860
  onToggleSectionCollapse,
1790
1861
  onUpdateSectionTitle,
@@ -1801,7 +1872,7 @@ function Canvas({
1801
1872
  getDropZoneHandlers,
1802
1873
  getDragHandleProps
1803
1874
  }) {
1804
- return /* @__PURE__ */ jsxs9("div", { style: styles.canvas, children: [
1875
+ return /* @__PURE__ */ jsxs9("div", { className: "fb-canvas", style: styles.canvas, children: [
1805
1876
  sections.map((section, sIdx) => /* @__PURE__ */ jsx11(
1806
1877
  SectionCard,
1807
1878
  {
@@ -1814,6 +1885,7 @@ function Canvas({
1814
1885
  chrome,
1815
1886
  strings,
1816
1887
  language,
1888
+ features,
1817
1889
  onActivate: () => onActivateSection(section.id),
1818
1890
  onToggleCollapse: () => onToggleSectionCollapse(section.id),
1819
1891
  onUpdateTitle: (value) => onUpdateSectionTitle(section.id, value),
@@ -1831,7 +1903,7 @@ function Canvas({
1831
1903
  },
1832
1904
  section.id
1833
1905
  )),
1834
- /* @__PURE__ */ jsxs9("button", { style: styles.addSectionBtn, onClick: onAddSection, children: [
1906
+ features.sections && /* @__PURE__ */ jsxs9("button", { style: styles.addSectionBtn, onClick: onAddSection, children: [
1835
1907
  /* @__PURE__ */ jsx11(Layers, { size: 14 }),
1836
1908
  " ",
1837
1909
  chrome.addSection
@@ -1843,22 +1915,22 @@ function Canvas({
1843
1915
  import { Bold, Italic, X, Plus as Plus2, Trash2 as Trash23 } from "lucide-react";
1844
1916
 
1845
1917
  // src/components/fields/DefaultValueEditor.tsx
1846
- import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1918
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1847
1919
  function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
1848
1920
  if (meta.isContent) return null;
1849
1921
  const f = field;
1850
1922
  if (meta.boolean) {
1851
- return /* @__PURE__ */ jsxs10(Fragment3, { children: [
1923
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
1852
1924
  /* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultValue }),
1853
1925
  /* @__PURE__ */ jsxs10("button", { style: styles.toggleRow, onClick: () => onChange({ defaultValue: !f.defaultValue }), children: [
1854
1926
  /* @__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 })
1927
+ /* @__PURE__ */ jsx12("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: f.defaultValue ? chrome.checked : chrome.unchecked })
1856
1928
  ] })
1857
1929
  ] });
1858
1930
  }
1859
1931
  if (meta.multiValue) {
1860
1932
  const selectedVals = f.defaultValue || [];
1861
- return /* @__PURE__ */ jsxs10(Fragment3, { children: [
1933
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
1862
1934
  /* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultChecked }),
1863
1935
  /* @__PURE__ */ jsx12("div", { style: styles.optionList, children: (f.options || []).map((o) => {
1864
1936
  const checked = selectedVals.includes(o.value);
@@ -1873,7 +1945,7 @@ function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
1873
1945
  ] });
1874
1946
  }
1875
1947
  if (meta.options) {
1876
- return /* @__PURE__ */ jsxs10(Fragment3, { children: [
1948
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
1877
1949
  /* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultValue }),
1878
1950
  /* @__PURE__ */ jsxs10("select", { style: styles.propInput, value: f.defaultValue || "", onChange: (e) => onChange({ defaultValue: e.target.value }), children: [
1879
1951
  /* @__PURE__ */ jsx12("option", { value: "", children: chrome.none }),
@@ -1882,16 +1954,16 @@ function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
1882
1954
  ] });
1883
1955
  }
1884
1956
  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: [
1957
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
1886
1958
  /* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultValue }),
1887
1959
  /* @__PURE__ */ jsx12("input", { type: htmlType, style: styles.propInput, value: f.defaultValue || "", onChange: (e) => onChange({ defaultValue: e.target.value }) })
1888
1960
  ] });
1889
1961
  }
1890
1962
 
1891
1963
  // 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: [
1964
+ import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1965
+ function Inspector({ selected, language, chrome, features, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1966
+ return /* @__PURE__ */ jsxs11("div", { className: "fb-inspector", style: styles.inspector, children: [
1895
1967
  /* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.properties }),
1896
1968
  !selected ? /* @__PURE__ */ jsx13("div", { style: styles.inspectorEmpty, children: chrome.selectFieldHint }) : /* @__PURE__ */ jsx13(
1897
1969
  InspectorBody,
@@ -1899,6 +1971,7 @@ function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, o
1899
1971
  selected,
1900
1972
  language,
1901
1973
  chrome,
1974
+ features,
1902
1975
  onUpdateField,
1903
1976
  onDeleteField,
1904
1977
  onUpdateOption,
@@ -1908,45 +1981,47 @@ function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, o
1908
1981
  )
1909
1982
  ] });
1910
1983
  }
1911
- function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1984
+ function InspectorBody({ selected, language, chrome, features, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1912
1985
  const meta = getMeta(selected.type);
1913
1986
  const f = selected;
1914
1987
  return /* @__PURE__ */ jsxs11("div", { style: styles.inspectorBody, children: [
1915
- (!meta.isContent || selected.type === "button") && /* @__PURE__ */ jsxs11(Fragment4, { children: [
1988
+ (!meta.isContent || selected.type === "button") && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1916
1989
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: selected.type === "button" ? chrome.buttonText : chrome.label }),
1917
1990
  /* @__PURE__ */ jsx13("input", { style: styles.propInput, value: t(selected.label, language), onChange: (e) => onUpdateField({ label: withLang(selected.label, language, e.target.value) }) }),
1918
1991
  !meta.isContent && /* @__PURE__ */ jsxs11("label", { style: styles.toggleRow, children: [
1919
1992
  /* @__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 })
1993
+ /* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.hideLabel })
1921
1994
  ] })
1922
1995
  ] }),
1923
- meta.hasSubtype && /* @__PURE__ */ jsxs11(Fragment4, { children: [
1996
+ meta.hasSubtype && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1924
1997
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.inputType }),
1925
1998
  /* @__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
1999
  ] }),
1927
- selected.type === "paragraph" && /* @__PURE__ */ jsxs11(Fragment4, { children: [
2000
+ selected.type === "paragraph" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1928
2001
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.content }),
1929
2002
  /* @__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 })
2003
+ features.blockStyling && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2004
+ /* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
2005
+ /* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.typography }),
2006
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.headingStyle }),
2007
+ /* @__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] }) }),
2008
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.width }),
2009
+ /* @__PURE__ */ jsx13(Segmented, { options: FONT_SIZE_OPTIONS, value: selected.fontSize || "md", onChange: (v) => onUpdateField({ fontSize: v }) }),
2010
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.style }),
2011
+ /* @__PURE__ */ jsxs11("div", { style: styles.styleToggleRow, children: [
2012
+ /* @__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 }) }),
2013
+ /* @__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 }) })
2014
+ ] }),
2015
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.align }),
2016
+ /* @__PURE__ */ jsx13(Segmented, { options: TEXT_ALIGN_OPTIONS, value: selected.textAlign || "left", onChange: (v) => onUpdateField({ textAlign: v }) }),
2017
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.color }),
2018
+ /* @__PURE__ */ jsxs11("div", { style: styles.swatchRow, children: [
2019
+ 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")),
2020
+ /* @__PURE__ */ jsx13("input", { type: "color", value: selected.color || "#1B1E24", onChange: (e) => onUpdateField({ color: e.target.value }), style: styles.colorPickerInput })
2021
+ ] })
1947
2022
  ] })
1948
2023
  ] }),
1949
- selected.type === "image" && /* @__PURE__ */ jsxs11(Fragment4, { children: [
2024
+ selected.type === "image" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1950
2025
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.imageUrl }),
1951
2026
  /* @__PURE__ */ jsx13("input", { style: styles.propInput, placeholder: "https://...", value: selected.src || "", onChange: (e) => onUpdateField({ src: e.target.value }) }),
1952
2027
  /* @__PURE__ */ jsx13("p", { style: styles.helperText, children: chrome.imageUrlHelper }),
@@ -1958,47 +2033,49 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
1958
2033
  /* @__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
2034
  /* @__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
2035
  ] }),
1961
- selected.type === "button" && /* @__PURE__ */ jsxs11(Fragment4, { children: [
2036
+ selected.type === "button" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1962
2037
  /* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
1963
2038
  /* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.buttonActionTitle }),
1964
2039
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.buttonAction }),
1965
2040
  /* @__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: [
2041
+ selected.action === "link" ? /* @__PURE__ */ jsxs11(Fragment5, { children: [
1967
2042
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.linkOptional }),
1968
2043
  /* @__PURE__ */ jsx13("input", { style: styles.propInput, placeholder: "https://...", value: selected.href || "", onChange: (e) => onUpdateField({ href: e.target.value }) }),
1969
2044
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.openIn }),
1970
2045
  /* @__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: [
2046
+ ] }) : /* @__PURE__ */ jsxs11(Fragment5, { children: [
1972
2047
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.submitScope }),
1973
2048
  /* @__PURE__ */ jsx13(Segmented, { options: [{ value: "section", label: chrome.thisSection }, { value: "form", label: chrome.wholeForm }], value: selected.submitScope || "form", onChange: (v) => onUpdateField({ submitScope: v }) })
1974
2049
  ] }),
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 } }) })
2050
+ features.blockStyling && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2051
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.color }),
2052
+ /* @__PURE__ */ jsxs11("div", { style: styles.swatchRow, children: [
2053
+ 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")),
2054
+ /* @__PURE__ */ jsx13("input", { type: "color", value: selected.buttonStyle?.color || "#5B5FEF", onChange: (e) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, color: e.target.value } }), style: styles.colorPickerInput })
2055
+ ] }),
2056
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.buttonSize }),
2057
+ /* @__PURE__ */ jsx13(Segmented, { options: SUBMIT_SIZE_OPTIONS, value: selected.buttonStyle?.size || "md", onChange: (v) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, size: v } }) })
2058
+ ] })
1982
2059
  ] }),
1983
- meta.placeholder && /* @__PURE__ */ jsxs11(Fragment4, { children: [
2060
+ meta.placeholder && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1984
2061
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.placeholder }),
1985
2062
  /* @__PURE__ */ jsx13("input", { style: styles.propInput, value: t(f.placeholder, language), onChange: (e) => onUpdateField({ placeholder: withLang(f.placeholder, language, e.target.value) }) })
1986
2063
  ] }),
1987
- selected.type === "input" && (selected.inputType === "text" || selected.inputType === "password" || !selected.inputType) && /* @__PURE__ */ jsxs11(Fragment4, { children: [
2064
+ selected.type === "input" && (selected.inputType === "text" || selected.inputType === "password" || !selected.inputType) && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1988
2065
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.maxLength }),
1989
2066
  /* @__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
2067
  ] }),
1991
- selected.type === "input" && selected.inputType === "number" && /* @__PURE__ */ jsxs11(Fragment4, { children: [
2068
+ selected.type === "input" && selected.inputType === "number" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1992
2069
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.minValue }),
1993
2070
  /* @__PURE__ */ jsx13("input", { type: "number", style: styles.propInput, value: selected.min ?? "", onChange: (e) => onUpdateField({ min: e.target.value === "" ? null : Number(e.target.value) }) }),
1994
2071
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.maxValue }),
1995
2072
  /* @__PURE__ */ jsx13("input", { type: "number", style: styles.propInput, value: selected.max ?? "", onChange: (e) => onUpdateField({ max: e.target.value === "" ? null : Number(e.target.value) }) })
1996
2073
  ] }),
1997
- selected.type === "textarea" && /* @__PURE__ */ jsxs11(Fragment4, { children: [
2074
+ selected.type === "textarea" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1998
2075
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.maxLength }),
1999
2076
  /* @__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
2077
  ] }),
2001
- meta.options && /* @__PURE__ */ jsxs11(Fragment4, { children: [
2078
+ meta.options && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2002
2079
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.options }),
2003
2080
  /* @__PURE__ */ jsxs11("div", { style: styles.optionList, children: [
2004
2081
  (f.options || []).map((opt, i) => /* @__PURE__ */ jsxs11("div", { style: styles.optionRow, children: [
@@ -2015,7 +2092,7 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
2015
2092
  /* @__PURE__ */ jsx13(DefaultValueEditor, { field: selected, meta, lang: language, chrome, onChange: onUpdateField }),
2016
2093
  !meta.isContent && /* @__PURE__ */ jsxs11("label", { style: styles.toggleRow, children: [
2017
2094
  /* @__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 })
2095
+ /* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.requiredField })
2019
2096
  ] }),
2020
2097
  /* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
2021
2098
  /* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.layout }),
@@ -2023,16 +2100,16 @@ function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteFiel
2023
2100
  /* @__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
2101
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.verticalAlign }),
2025
2102
  /* @__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: [
2103
+ !meta.boolean && !meta.isContent && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2027
2104
  /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.labelPosition }),
2028
2105
  /* @__PURE__ */ jsx13(Segmented, { options: [{ value: "top", label: chrome.above }, { value: "inline", label: chrome.inline }], value: selected.labelPosition || "top", onChange: (v) => onUpdateField({ labelPosition: v }) })
2029
2106
  ] }),
2030
- !meta.isContent && /* @__PURE__ */ jsxs11(Fragment4, { children: [
2107
+ !meta.isContent && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2031
2108
  /* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
2032
2109
  /* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.icon }),
2033
2110
  /* @__PURE__ */ jsxs11("label", { style: styles.toggleRow, children: [
2034
2111
  /* @__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 })
2112
+ /* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.showIcon })
2036
2113
  ] }),
2037
2114
  selected.showIcon && /* @__PURE__ */ jsx13("div", { style: styles.iconGrid, children: Object.keys(ICON_LIBRARY).map((key) => {
2038
2115
  const IconComp = ICON_LIBRARY[key];
@@ -2098,7 +2175,7 @@ function collectFieldValues(fields) {
2098
2175
 
2099
2176
  // src/components/PreviewPane.tsx
2100
2177
  import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2101
- function PreviewPane({ title, sections, onFieldChange, language, strings, chrome, baseMaxWidth, onSubmit }) {
2178
+ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome, baseMaxWidth, features, onSubmit }) {
2102
2179
  const [device, setDevice] = useState6("laptop");
2103
2180
  const [errors, setErrors] = useState6({});
2104
2181
  const [submitted, setSubmitted] = useState6(null);
@@ -2161,7 +2238,7 @@ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome
2161
2238
  }
2162
2239
  return /* @__PURE__ */ jsxs12("div", { style: styles.previewWrap, children: [
2163
2240
  /* @__PURE__ */ jsxs12("div", { style: { width: "100%", maxWidth, display: "flex", flexDirection: "column", alignItems: "center" }, children: [
2164
- /* @__PURE__ */ jsx14("div", { style: styles.previewToolbar, children: /* @__PURE__ */ jsx14(Segmented, { options: deviceOptions, value: device, onChange: setDevice }) }),
2241
+ features.deviceToggle && /* @__PURE__ */ jsx14("div", { style: styles.previewToolbar, children: /* @__PURE__ */ jsx14(Segmented, { options: deviceOptions, value: device, onChange: setDevice }) }),
2165
2242
  /* @__PURE__ */ jsxs12("div", { style: { ...styles.previewCard, maxWidth, width: "100%" }, children: [
2166
2243
  /* @__PURE__ */ jsx14("h2", { style: styles.previewTitle, children: t(title, language) }),
2167
2244
  allFields.length === 0 && /* @__PURE__ */ jsx14("p", { style: { color: "var(--fb-muted)", fontSize: 14 }, children: strings.addFieldsHint }),
@@ -2184,7 +2261,7 @@ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome
2184
2261
  })
2185
2262
  ] })
2186
2263
  ] }),
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: [
2264
+ 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
2265
  /* @__PURE__ */ jsxs12("div", { style: styles.modalHeader, children: [
2189
2266
  /* @__PURE__ */ jsxs12("span", { style: { fontWeight: 600, fontSize: 14, display: "flex", alignItems: "center", gap: 7 }, children: [
2190
2267
  /* @__PURE__ */ jsx14(PartyPopper, { size: 15, color: "var(--fb-primary)" }),
@@ -2259,7 +2336,7 @@ import { Save as Save2, X as X5 } from "lucide-react";
2259
2336
  import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
2260
2337
  function SaveAsModal({ chrome, suggestedName, onSave, onClose }) {
2261
2338
  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: [
2339
+ return /* @__PURE__ */ jsx17("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ jsxs15("div", { style: { ...styles.modal, maxWidth: 380 }, onClick: (e) => e.stopPropagation(), children: [
2263
2340
  /* @__PURE__ */ jsxs15("div", { style: styles.modalHeader, children: [
2264
2341
  /* @__PURE__ */ jsx17("span", { style: { fontWeight: 600, fontSize: 14 }, children: chrome.saveForm }),
2265
2342
  /* @__PURE__ */ jsx17("button", { style: styles.iconBtn, onClick: onClose, children: /* @__PURE__ */ jsx17(X5, { size: 16 }) })
@@ -2289,6 +2366,36 @@ var css = `
2289
2366
  that support it (mobile browser chrome resizing the viewport), and is
2290
2367
  simply ignored by ones that don't. */
2291
2368
  .fb-root { max-height: 100vh; max-height: 100dvh; }
2369
+
2370
+ /* Below this width the fixed 200px Palette + 270px Inspector columns
2371
+ don't leave room for a usable Canvas, so instead of stacking all
2372
+ three in flow (which buries Canvas under a tall Palette), Palette
2373
+ and Inspector become narrow drawers over Canvas (which stays
2374
+ partially visible behind them), toggled by .fb-mobile-bar's two
2375
+ buttons, tracked by .fb-work-area's data-mobile-panel attribute,
2376
+ and dismissible via .fb-mobile-backdrop. */
2377
+ .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; }
2378
+ .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; }
2379
+ .fb-mobile-btn[aria-pressed="true"] { border-color: var(--fb-primary); background: var(--fb-primary-soft); color: var(--fb-primary); }
2380
+ .fb-mobile-backdrop { display: none; }
2381
+ @media (max-width: 720px) {
2382
+ .fb-mobile-bar { display: flex; }
2383
+ .fb-work-area { flex-direction: column !important; min-height: 0; }
2384
+ .fb-canvas-area { position: relative; overflow: hidden; }
2385
+ .fb-canvas { width: 100%; }
2386
+ .fb-mobile-backdrop { display: block; position: absolute; inset: 0; z-index: 6; background: rgba(15,16,20,0.35); }
2387
+ .fb-palette, .fb-inspector {
2388
+ position: absolute; top: 0; bottom: 0; z-index: 7;
2389
+ width: min(260px, 80vw) !important; max-height: none !important;
2390
+ border: none !important;
2391
+ box-shadow: 0 0 24px rgba(0,0,0,0.18);
2392
+ transition: transform 0.18s ease;
2393
+ }
2394
+ .fb-palette { left: 0; transform: translateX(-100%); }
2395
+ .fb-inspector { right: 0; transform: translateX(100%); }
2396
+ .fb-work-area[data-mobile-panel="palette"] .fb-palette,
2397
+ .fb-work-area[data-mobile-panel="inspector"] .fb-inspector { transform: translateX(0); }
2398
+ }
2292
2399
  `;
2293
2400
 
2294
2401
  // src/FormBuilder.tsx
@@ -2299,11 +2406,14 @@ var FormBuilder = forwardRef(function FormBuilder2({
2299
2406
  languages = DEFAULT_LANGUAGES,
2300
2407
  strings: stringsOverride,
2301
2408
  chrome: chromeOverride,
2302
- themeEditable = false,
2409
+ features: featuresProp,
2303
2410
  storage: storageProp,
2304
2411
  onSubmit,
2305
- initialDocument
2412
+ initialDocument,
2413
+ initialMode,
2414
+ onModeChange
2306
2415
  }, ref) {
2416
+ const features = resolveFeatures(featuresProp);
2307
2417
  const storage = storageProp ?? localStorageAdapter;
2308
2418
  const { theme, updateThemeColor, updateThemeLayout, resetTheme, replaceThemeOverrides, themeOverrides } = useTheme(themeOverrideProp);
2309
2419
  const [language, setLanguage] = useState8(languageOverride || languages[0]?.code || "en");
@@ -2311,12 +2421,21 @@ var FormBuilder = forwardRef(function FormBuilder2({
2311
2421
  const chrome = { ...CHROME[language] || CHROME.en, ...chromeOverride && chromeOverride[language] || {} };
2312
2422
  const doc = useFormDocument({ language, chrome });
2313
2423
  const drag = useDragReorder(doc.reorderWithinSection);
2314
- const [mode, setMode] = useState8("build");
2424
+ const [mode, setModeState] = useState8(initialMode ?? "build");
2425
+ const setMode = (next) => {
2426
+ setModeState(next);
2427
+ onModeChange?.(next);
2428
+ };
2429
+ useEffect2(() => {
2430
+ onModeChange?.(mode);
2431
+ }, []);
2315
2432
  const [showJson, setShowJson] = useState8(false);
2316
2433
  const [showLibrary, setShowLibrary] = useState8(false);
2317
2434
  const [copied, setCopied] = useState8(false);
2435
+ const [mobilePanel, setMobilePanel] = useState8("none");
2318
2436
  const persistence = usePersistence({
2319
2437
  storage,
2438
+ autosave: features.autosave,
2320
2439
  language,
2321
2440
  chrome,
2322
2441
  document: { title: doc.title, themeOverrides, sections: doc.sections },
@@ -2356,6 +2475,7 @@ var FormBuilder = forwardRef(function FormBuilder2({
2356
2475
  }
2357
2476
  // eslint-disable-next-line react-hooks/exhaustive-deps
2358
2477
  }), [jsonDoc, jsonString]);
2478
+ const fieldCount = doc.sections.reduce((n, s) => n + s.fields.filter((f) => !getMeta(f.type).isContent).length, 0);
2359
2479
  const activeSectionIdx = doc.sections.findIndex((s) => s.id === doc.activeSection?.id);
2360
2480
  const activeSectionLabel = t(doc.activeSection?.title, language) || `#${activeSectionIdx + 1}`;
2361
2481
  const rootStyle = {
@@ -2370,6 +2490,7 @@ var FormBuilder = forwardRef(function FormBuilder2({
2370
2490
  "--fb-surface": theme.surface,
2371
2491
  "--fb-canvas": theme.canvas,
2372
2492
  "--fb-page-bg": theme.pageBackground,
2493
+ "--fb-surface-2": mixHex(theme.surface, theme.ink, 0.06),
2373
2494
  "--fb-space-page": `${theme.layout.pagePadding}px`,
2374
2495
  "--fb-space-canvas": `${theme.layout.canvasPadding}px`,
2375
2496
  "--fb-space-section": `${theme.layout.sectionGap}px`,
@@ -2389,6 +2510,7 @@ var FormBuilder = forwardRef(function FormBuilder2({
2389
2510
  mode,
2390
2511
  saveState: persistence.saveState,
2391
2512
  chrome,
2513
+ features,
2392
2514
  savedFormsCount: persistence.savedForms.length,
2393
2515
  onTitleChange: doc.updateTitle,
2394
2516
  onLanguageChange: setLanguage,
@@ -2402,63 +2524,103 @@ var FormBuilder = forwardRef(function FormBuilder2({
2402
2524
  persistence.loadingDraft ? /* @__PURE__ */ jsxs16("div", { style: styles.loadingScreen, children: [
2403
2525
  /* @__PURE__ */ jsx18(Loader22, { size: 20, className: "spin" }),
2404
2526
  /* @__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
- )
2527
+ ] }) : mode === "build" ? /* @__PURE__ */ jsxs16("div", { className: "fb-work-area", style: styles.workArea, "data-mobile-panel": mobilePanel, children: [
2528
+ /* @__PURE__ */ jsxs16("div", { className: "fb-mobile-bar", children: [
2529
+ /* @__PURE__ */ jsxs16(
2530
+ "button",
2531
+ {
2532
+ type: "button",
2533
+ className: "fb-mobile-btn",
2534
+ "aria-pressed": mobilePanel === "palette",
2535
+ onClick: () => setMobilePanel((p) => p === "palette" ? "none" : "palette"),
2536
+ children: [
2537
+ /* @__PURE__ */ jsx18(Menu, { size: 14 }),
2538
+ " ",
2539
+ chrome.paletteTabBlocks
2540
+ ]
2541
+ }
2542
+ ),
2543
+ /* @__PURE__ */ jsxs16(
2544
+ "button",
2545
+ {
2546
+ type: "button",
2547
+ className: "fb-mobile-btn",
2548
+ "aria-pressed": mobilePanel === "inspector",
2549
+ onClick: () => setMobilePanel((p) => p === "inspector" ? "none" : "inspector"),
2550
+ children: [
2551
+ /* @__PURE__ */ jsx18(SlidersHorizontal, { size: 14 }),
2552
+ " ",
2553
+ chrome.properties
2554
+ ]
2555
+ }
2556
+ )
2557
+ ] }),
2558
+ /* @__PURE__ */ jsxs16("div", { className: "fb-canvas-area", style: styles.workArea, children: [
2559
+ mobilePanel !== "none" && /* @__PURE__ */ jsx18("div", { className: "fb-mobile-backdrop", onClick: () => setMobilePanel("none") }),
2560
+ /* @__PURE__ */ jsx18(
2561
+ Palette,
2562
+ {
2563
+ activeSectionLabel,
2564
+ chrome,
2565
+ onAddField: (type) => {
2566
+ doc.addField(type);
2567
+ setMobilePanel("none");
2568
+ },
2569
+ features,
2570
+ fieldCount,
2571
+ theme,
2572
+ updateThemeColor,
2573
+ updateThemeLayout,
2574
+ resetTheme
2575
+ }
2576
+ ),
2577
+ /* @__PURE__ */ jsx18(
2578
+ Canvas,
2579
+ {
2580
+ sections: doc.sections,
2581
+ activeSectionId: doc.activeSectionId,
2582
+ selectedId: doc.selectedId,
2583
+ dragOverKey: drag.dragOverKey,
2584
+ chrome,
2585
+ strings,
2586
+ language,
2587
+ features,
2588
+ onActivateSection: doc.setActiveSectionId,
2589
+ onToggleSectionCollapse: doc.toggleSectionCollapse,
2590
+ onUpdateSectionTitle: doc.updateSectionTitle,
2591
+ onUpdateSectionBackground: doc.updateSectionBackground,
2592
+ onDuplicateSection: doc.duplicateSection,
2593
+ onMoveSection: doc.moveSection,
2594
+ onDeleteSection: doc.deleteSection,
2595
+ onAddSection: doc.addSection,
2596
+ onSelectField: (sectionId, fieldId) => {
2597
+ doc.setSelectedId(fieldId);
2598
+ doc.setActiveSectionId(sectionId);
2599
+ setMobilePanel("inspector");
2600
+ },
2601
+ onFieldChange: doc.updateField,
2602
+ onMoveField: doc.moveField,
2603
+ onDuplicateField: doc.duplicateField,
2604
+ onDeleteField: doc.deleteField,
2605
+ getDropZoneHandlers: drag.getDropZoneHandlers,
2606
+ getDragHandleProps: drag.getDragHandleProps
2607
+ }
2608
+ ),
2609
+ /* @__PURE__ */ jsx18(
2610
+ Inspector,
2611
+ {
2612
+ selected: doc.selected,
2613
+ language,
2614
+ chrome,
2615
+ features,
2616
+ onUpdateField: (patch) => doc.selected && doc.updateField(doc.selected.id, patch),
2617
+ onDeleteField: () => doc.selected && doc.deleteField(doc.selected.id),
2618
+ onUpdateOption: (optIdx, patch) => doc.selected && doc.updateOption(doc.selected.id, optIdx, patch),
2619
+ onAddOption: () => doc.selected && doc.addOption(doc.selected.id),
2620
+ onRemoveOption: (optIdx) => doc.selected && doc.removeOption(doc.selected.id, optIdx)
2621
+ }
2622
+ )
2623
+ ] })
2462
2624
  ] }) : /* @__PURE__ */ jsx18(
2463
2625
  PreviewPane,
2464
2626
  {
@@ -2469,6 +2631,7 @@ var FormBuilder = forwardRef(function FormBuilder2({
2469
2631
  strings,
2470
2632
  chrome,
2471
2633
  baseMaxWidth: theme.layout.maxWidth,
2634
+ features,
2472
2635
  onSubmit
2473
2636
  }
2474
2637
  ),
@@ -2499,7 +2662,24 @@ var FormBuilder = forwardRef(function FormBuilder2({
2499
2662
  ] });
2500
2663
  });
2501
2664
  var FormBuilder_default = FormBuilder;
2665
+
2666
+ // src/theme/darkTheme.ts
2667
+ var DARK_THEME = {
2668
+ primary: "#8B8FF5",
2669
+ primarySoft: "#262A45",
2670
+ danger: "#F0715B",
2671
+ dangerSoft: "#3A2420",
2672
+ ink: "#EDEEF2",
2673
+ muted: "#9096A8",
2674
+ border: "#2E313D",
2675
+ surface: "#1A1B23",
2676
+ canvas: "#121319",
2677
+ pageBackground: "#1A1B23",
2678
+ layout: DEFAULT_THEME.layout
2679
+ };
2502
2680
  export {
2681
+ DARK_THEME,
2682
+ DEFAULT_THEME,
2503
2683
  FormBuilder_default as FormBuilder,
2504
2684
  FormBuilder_default as default,
2505
2685
  localStorageAdapter