form-page-builder 0.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
 
3
3
  // src/FormBuilder.tsx
4
- import { useState as useState8 } from "react";
5
- import { Loader2 as Loader22 } from "lucide-react";
4
+ import { forwardRef, useImperativeHandle, useState as useState8 } from "react";
5
+ import { Loader2 as Loader22, Menu, SlidersHorizontal } from "lucide-react";
6
6
 
7
7
  // src/i18n/languages.ts
8
8
  var DEFAULT_LANGUAGES = [
@@ -50,6 +50,8 @@ var CHROME = {
50
50
  contentBlocks: "Content",
51
51
  formFields: "Form Fields",
52
52
  addingTo: "Adding to",
53
+ paletteTabBlocks: "Blocks",
54
+ paletteTabDesign: "Design",
53
55
  properties: "Properties",
54
56
  selectFieldHint: "Select a field to edit its properties.",
55
57
  label: "Label",
@@ -95,15 +97,15 @@ var CHROME = {
95
97
  build: "Build",
96
98
  preview: "Preview",
97
99
  newForm: "New",
98
- myForms: "My forms",
100
+ templates: "Templates",
99
101
  save: "Save",
100
102
  viewJson: "View JSON",
101
103
  saving: "Saving...",
102
104
  saved: "Saved",
103
105
  saveFailed: "Save failed",
104
106
  startNewForm: "Start a new form",
105
- openSavedForm: "Open a saved form",
106
- saveToLibraryTitle: "Save this form to your library",
107
+ openTemplatesTitle: "Open a saved template",
108
+ saveToLibraryTitle: "Save this form as a template",
107
109
  sectionTitlePlaceholder: (n) => `Section ${n} title (optional)`,
108
110
  noFieldsInSection: "No fields in this section yet \u2014 pick a field type on the left.",
109
111
  addSection: "Add section",
@@ -116,22 +118,17 @@ var CHROME = {
116
118
  formJson: "Form JSON",
117
119
  copy: "Copy",
118
120
  copied: "Copied",
119
- nothingSaved: 'Nothing saved yet. Click "Save" in the toolbar to store this form here.',
121
+ noTemplates: 'No templates saved yet. Click "Save" in the toolbar to store this form here.',
120
122
  updated: "Updated",
121
123
  open: "Open",
122
- saveForm: "Save form",
123
- formName: "Form name",
124
- saveToLibrary: "Save to library",
124
+ saveForm: "Save as template",
125
+ formName: "Template name",
126
+ saveToLibrary: "Save template",
125
127
  loadingDraft: "Loading your draft...",
128
+ templatesLimitReached: "You can save up to 5 templates. Delete one to save another.",
126
129
  current: "current",
127
130
  customColor: "Custom color",
128
131
  fieldsCount: (n) => `${n} field${n === 1 ? "" : "s"}`,
129
- formSettings: "Form settings",
130
- submitLabel: "Submit button text",
131
- submitMode: "Submit button",
132
- combined: "Combined (one button)",
133
- perSection: "Per section",
134
- settings: "Form settings",
135
132
  fieldTypeInput: "Input",
136
133
  fieldTypeTextarea: "Textarea",
137
134
  fieldTypeSelect: "Select",
@@ -141,6 +138,7 @@ var CHROME = {
141
138
  fieldTypeToggle: "Toggle",
142
139
  fieldTypeParagraph: "Paragraph",
143
140
  fieldTypeImage: "Image",
141
+ fieldTypeButton: "Button",
144
142
  subtypeText: "Text",
145
143
  subtypeEmail: "Email",
146
144
  subtypePhone: "Phone",
@@ -153,8 +151,17 @@ var CHROME = {
153
151
  shapeBanner: "Banner",
154
152
  tagBody: "Body",
155
153
  tagCaption: "Caption",
156
- submitSectionTitle: "Submit",
157
- submitStyle: "Submit button style",
154
+ buttonText: "Button text",
155
+ buttonActionTitle: "Action",
156
+ buttonAction: "When clicked",
157
+ actionLink: "Open link",
158
+ actionSubmit: "Submit",
159
+ openIn: "Open in",
160
+ sameTab: "Same tab",
161
+ newTab: "New tab",
162
+ submitScope: "Submits",
163
+ thisSection: "This section",
164
+ wholeForm: "Whole form",
158
165
  buttonSize: "Size",
159
166
  theme: "Theme",
160
167
  primaryColor: "Primary color",
@@ -179,6 +186,8 @@ var CHROME = {
179
186
  contentBlocks: "\u30B3\u30F3\u30C6\u30F3\u30C4",
180
187
  formFields: "\u30D5\u30A9\u30FC\u30E0\u9805\u76EE",
181
188
  addingTo: "\u8FFD\u52A0\u5148",
189
+ paletteTabBlocks: "\u30D6\u30ED\u30C3\u30AF",
190
+ paletteTabDesign: "\u30C7\u30B6\u30A4\u30F3",
182
191
  properties: "\u30D7\u30ED\u30D1\u30C6\u30A3",
183
192
  selectFieldHint: "\u7DE8\u96C6\u3059\u308B\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
184
193
  label: "\u30E9\u30D9\u30EB",
@@ -224,15 +233,15 @@ var CHROME = {
224
233
  build: "\u4F5C\u6210",
225
234
  preview: "\u30D7\u30EC\u30D3\u30E5\u30FC",
226
235
  newForm: "\u65B0\u898F",
227
- myForms: "\u30DE\u30A4\u30D5\u30A9\u30FC\u30E0",
236
+ templates: "\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8",
228
237
  save: "\u4FDD\u5B58",
229
238
  viewJson: "JSON\u3092\u8868\u793A",
230
239
  saving: "\u4FDD\u5B58\u4E2D...",
231
240
  saved: "\u4FDD\u5B58\u6E08\u307F",
232
241
  saveFailed: "\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
233
242
  startNewForm: "\u65B0\u3057\u3044\u30D5\u30A9\u30FC\u30E0\u3092\u4F5C\u6210",
234
- openSavedForm: "\u4FDD\u5B58\u6E08\u307F\u30D5\u30A9\u30FC\u30E0\u3092\u958B\u304F",
235
- saveToLibraryTitle: "\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u3092\u30E9\u30A4\u30D6\u30E9\u30EA\u306B\u4FDD\u5B58",
243
+ openTemplatesTitle: "\u4FDD\u5B58\u6E08\u307F\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u3092\u958B\u304F",
244
+ saveToLibraryTitle: "\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u3092\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u3068\u3057\u3066\u4FDD\u5B58",
236
245
  sectionTitlePlaceholder: (n) => `\u30BB\u30AF\u30B7\u30E7\u30F3${n}\u306E\u30BF\u30A4\u30C8\u30EB\uFF08\u4EFB\u610F\uFF09`,
237
246
  noFieldsInSection: "\u3053\u306E\u30BB\u30AF\u30B7\u30E7\u30F3\u306B\u306F\u307E\u3060\u30D5\u30A3\u30FC\u30EB\u30C9\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u5DE6\u306E\u30D1\u30CD\u30EB\u304B\u3089\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u9078\u3093\u3067\u304F\u3060\u3055\u3044\u3002",
238
247
  addSection: "\u30BB\u30AF\u30B7\u30E7\u30F3\u3092\u8FFD\u52A0",
@@ -245,22 +254,17 @@ var CHROME = {
245
254
  formJson: "\u30D5\u30A9\u30FC\u30E0JSON",
246
255
  copy: "\u30B3\u30D4\u30FC",
247
256
  copied: "\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F",
248
- nothingSaved: "\u307E\u3060\u4FDD\u5B58\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u30C4\u30FC\u30EB\u30D0\u30FC\u306E\u300C\u4FDD\u5B58\u300D\u3092\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
257
+ noTemplates: "\u307E\u3060\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u30C4\u30FC\u30EB\u30D0\u30FC\u306E\u300C\u4FDD\u5B58\u300D\u3092\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
249
258
  updated: "\u66F4\u65B0\u65E5\u6642",
250
259
  open: "\u958B\u304F",
251
- saveForm: "\u30D5\u30A9\u30FC\u30E0\u3092\u4FDD\u5B58",
252
- formName: "\u30D5\u30A9\u30FC\u30E0\u540D",
253
- saveToLibrary: "\u30E9\u30A4\u30D6\u30E9\u30EA\u306B\u4FDD\u5B58",
260
+ saveForm: "\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u3068\u3057\u3066\u4FDD\u5B58",
261
+ formName: "\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u540D",
262
+ saveToLibrary: "\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u3092\u4FDD\u5B58",
254
263
  loadingDraft: "\u4E0B\u66F8\u304D\u3092\u8AAD\u307F\u8FBC\u3093\u3067\u3044\u307E\u3059...",
264
+ templatesLimitReached: "\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u306F5\u4EF6\u307E\u3067\u4FDD\u5B58\u3067\u304D\u307E\u3059\u30021\u4EF6\u524A\u9664\u3057\u3066\u304B\u3089\u4FDD\u5B58\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
255
265
  current: "\u73FE\u5728\u7DE8\u96C6\u4E2D",
256
266
  customColor: "\u30AB\u30B9\u30BF\u30E0\u30AB\u30E9\u30FC",
257
267
  fieldsCount: (n) => `${n}\u4EF6\u306E\u30D5\u30A3\u30FC\u30EB\u30C9`,
258
- formSettings: "\u30D5\u30A9\u30FC\u30E0\u8A2D\u5B9A",
259
- submitLabel: "\u9001\u4FE1\u30DC\u30BF\u30F3\u306E\u30C6\u30AD\u30B9\u30C8",
260
- submitMode: "\u9001\u4FE1\u30DC\u30BF\u30F3\u306E\u8868\u793A",
261
- combined: "\u307E\u3068\u3081\u30661\u3064",
262
- perSection: "\u30BB\u30AF\u30B7\u30E7\u30F3\u3054\u3068",
263
- settings: "\u30D5\u30A9\u30FC\u30E0\u8A2D\u5B9A",
264
268
  fieldTypeInput: "\u5165\u529B",
265
269
  fieldTypeTextarea: "\u30C6\u30AD\u30B9\u30C8\u30A8\u30EA\u30A2",
266
270
  fieldTypeSelect: "\u30BB\u30EC\u30AF\u30C8",
@@ -270,6 +274,7 @@ var CHROME = {
270
274
  fieldTypeToggle: "\u30C8\u30B0\u30EB",
271
275
  fieldTypeParagraph: "\u6BB5\u843D",
272
276
  fieldTypeImage: "\u753B\u50CF",
277
+ fieldTypeButton: "\u30DC\u30BF\u30F3",
273
278
  subtypeText: "\u30C6\u30AD\u30B9\u30C8",
274
279
  subtypeEmail: "\u30E1\u30FC\u30EB",
275
280
  subtypePhone: "\u96FB\u8A71\u756A\u53F7",
@@ -282,8 +287,17 @@ var CHROME = {
282
287
  shapeBanner: "\u30D0\u30CA\u30FC",
283
288
  tagBody: "\u672C\u6587",
284
289
  tagCaption: "\u30AD\u30E3\u30D7\u30B7\u30E7\u30F3",
285
- submitSectionTitle: "\u9001\u4FE1",
286
- submitStyle: "\u9001\u4FE1\u30DC\u30BF\u30F3\u306E\u30B9\u30BF\u30A4\u30EB",
290
+ buttonText: "\u30DC\u30BF\u30F3\u306E\u30C6\u30AD\u30B9\u30C8",
291
+ buttonActionTitle: "\u30A2\u30AF\u30B7\u30E7\u30F3",
292
+ buttonAction: "\u30AF\u30EA\u30C3\u30AF\u6642\u306E\u52D5\u4F5C",
293
+ actionLink: "\u30EA\u30F3\u30AF\u3092\u958B\u304F",
294
+ actionSubmit: "\u9001\u4FE1",
295
+ openIn: "\u958B\u304D\u65B9",
296
+ sameTab: "\u540C\u3058\u30BF\u30D6",
297
+ newTab: "\u65B0\u3057\u3044\u30BF\u30D6",
298
+ submitScope: "\u9001\u4FE1\u7BC4\u56F2",
299
+ thisSection: "\u3053\u306E\u30BB\u30AF\u30B7\u30E7\u30F3",
300
+ wholeForm: "\u30D5\u30A9\u30FC\u30E0\u5168\u4F53",
287
301
  buttonSize: "\u30B5\u30A4\u30BA",
288
302
  theme: "\u30C6\u30FC\u30DE",
289
303
  primaryColor: "\u30E1\u30A4\u30F3\u30AB\u30E9\u30FC",
@@ -319,6 +333,35 @@ function withLang(val, lang, value) {
319
333
  return { ...base, [lang]: value };
320
334
  }
321
335
 
336
+ // src/lib/color.ts
337
+ function mixHex(a, b, t2) {
338
+ const pa = parseHex(a);
339
+ const pb = parseHex(b);
340
+ if (!pa || !pb) return a;
341
+ const mix = (x, y) => Math.round(x + (y - x) * t2);
342
+ const toHex = (n) => n.toString(16).padStart(2, "0");
343
+ return `#${toHex(mix(pa[0], pb[0]))}${toHex(mix(pa[1], pb[1]))}${toHex(mix(pa[2], pb[2]))}`;
344
+ }
345
+ function parseHex(hex) {
346
+ const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());
347
+ if (!m) return null;
348
+ const n = parseInt(m[1], 16);
349
+ return [n >> 16 & 255, n >> 8 & 255, n & 255];
350
+ }
351
+
352
+ // src/lib/storage/compress.ts
353
+ import { compressToUTF16, decompressFromUTF16 } from "lz-string";
354
+ function compress(raw) {
355
+ return compressToUTF16(raw);
356
+ }
357
+ function decompress(value) {
358
+ try {
359
+ return decompressFromUTF16(value);
360
+ } catch {
361
+ return null;
362
+ }
363
+ }
364
+
322
365
  // src/lib/storage/localStorageAdapter.ts
323
366
  function hasLocalStorage() {
324
367
  return typeof window !== "undefined" && !!window.localStorage;
@@ -326,11 +369,21 @@ function hasLocalStorage() {
326
369
  var localStorageAdapter = {
327
370
  async get(key) {
328
371
  if (!hasLocalStorage()) return null;
329
- return window.localStorage.getItem(key);
372
+ const raw = window.localStorage.getItem(key);
373
+ if (raw == null) return null;
374
+ const decompressed = decompress(raw);
375
+ if (decompressed != null) {
376
+ try {
377
+ JSON.parse(decompressed);
378
+ return decompressed;
379
+ } catch {
380
+ }
381
+ }
382
+ return raw;
330
383
  },
331
384
  async set(key, value) {
332
385
  if (!hasLocalStorage()) return;
333
- window.localStorage.setItem(key, value);
386
+ window.localStorage.setItem(key, compress(value));
334
387
  },
335
388
  async delete(key) {
336
389
  if (!hasLocalStorage()) return;
@@ -338,55 +391,6 @@ var localStorageAdapter = {
338
391
  }
339
392
  };
340
393
 
341
- // src/hooks/useTheme.ts
342
- import { useState } from "react";
343
-
344
- // src/theme/defaultTheme.ts
345
- var DEFAULT_THEME = {
346
- primary: "#5B5FEF",
347
- primarySoft: "#EEF0FF",
348
- danger: "#C4432E",
349
- dangerSoft: "#FDECE4",
350
- ink: "#1B1E24",
351
- muted: "#9296A3",
352
- border: "#E2E4E9",
353
- surface: "#FFFFFF",
354
- canvas: "#F5F6F8",
355
- pageBackground: "#FFFFFF",
356
- layout: { maxWidth: 640, pagePadding: 28, canvasPadding: 20, sectionGap: 20, fieldGap: 16, toolbarPadding: 10, panelPadding: 14, ticketPadding: 14 }
357
- };
358
-
359
- // src/hooks/useTheme.ts
360
- function useTheme(themeOverrideProp) {
361
- const baseTheme = {
362
- ...DEFAULT_THEME,
363
- ...themeOverrideProp || {},
364
- layout: { ...DEFAULT_THEME.layout, ...themeOverrideProp && themeOverrideProp.layout || {} }
365
- };
366
- const [themeOverrides, setThemeOverrides] = useState({});
367
- const theme = {
368
- ...baseTheme,
369
- ...themeOverrides,
370
- layout: { ...baseTheme.layout, ...themeOverrides.layout || {} }
371
- };
372
- function updateThemeColor(key, value) {
373
- setThemeOverrides((prev) => ({ ...prev, [key]: value }));
374
- }
375
- function updateThemeLayout(key, value) {
376
- setThemeOverrides((prev) => ({ ...prev, layout: { ...prev.layout, [key]: value } }));
377
- }
378
- function resetTheme() {
379
- setThemeOverrides({});
380
- }
381
- function replaceThemeOverrides(overrides) {
382
- setThemeOverrides(overrides);
383
- }
384
- return { theme, themeOverrides, updateThemeColor, updateThemeLayout, resetTheme, replaceThemeOverrides };
385
- }
386
-
387
- // src/hooks/useFormDocument.ts
388
- import { useState as useState2 } from "react";
389
-
390
394
  // src/constants/fieldTypes.ts
391
395
  import {
392
396
  Type,
@@ -397,11 +401,13 @@ import {
397
401
  CheckSquare,
398
402
  ToggleLeft,
399
403
  FileText,
400
- Image as ImageIcon
404
+ Image as ImageIcon,
405
+ MousePointerClick
401
406
  } from "lucide-react";
402
407
  var FIELD_TYPES = [
403
408
  { type: "paragraph", icon: FileText, isContent: true, defaultIcon: "FileText" },
404
409
  { type: "image", icon: ImageIcon, isContent: true, isImage: true, defaultIcon: "Type" },
410
+ { type: "button", icon: MousePointerClick, isContent: true, defaultIcon: "Type" },
405
411
  { type: "input", icon: Type, placeholder: true, hasSubtype: true, defaultIcon: "Type" },
406
412
  { type: "textarea", icon: AlignLeft, placeholder: true, defaultIcon: "AlignLeft" },
407
413
  { type: "select", icon: ChevronDown, options: true, defaultIcon: "ChevronDown" },
@@ -422,6 +428,7 @@ var IMAGE_SHAPES = ["square", "circle", "banner"];
422
428
  var FIELD_TYPE_CHROME_KEY = {
423
429
  paragraph: "fieldTypeParagraph",
424
430
  image: "fieldTypeImage",
431
+ button: "fieldTypeButton",
425
432
  input: "fieldTypeInput",
426
433
  textarea: "fieldTypeTextarea",
427
434
  select: "fieldTypeSelect",
@@ -500,21 +507,195 @@ function defaultFieldFor(type, language, chrome) {
500
507
  base.fontStyle = "normal";
501
508
  base.textAlign = "left";
502
509
  base.color = "";
510
+ } else if (type === "button") {
511
+ base.action = "submit";
512
+ base.submitScope = "form";
513
+ base.buttonStyle = { color: "", size: "md" };
514
+ base.href = "";
515
+ base.target = "_self";
503
516
  } else {
504
517
  base.defaultValue = "";
505
518
  }
506
519
  return base;
507
520
  }
508
521
  function defaultSection(titleEn = "") {
509
- return { id: genSectionId(), title: bi(titleEn, ""), background: "", collapsed: false, submitStyle: null, fields: [] };
522
+ return { id: genSectionId(), title: bi(titleEn, ""), background: "", collapsed: false, fields: [] };
523
+ }
524
+
525
+ // src/lib/submittable.ts
526
+ function sectionHasFormFields(section) {
527
+ return section.fields.some((f) => !getMeta(f.type).isContent);
528
+ }
529
+
530
+ // src/lib/migrate.ts
531
+ function migrateField(field) {
532
+ let f = { ...field };
533
+ if (LEGACY_INPUT_TYPES.includes(f.type)) f = { ...f, type: "input", inputType: f.type };
534
+ f.label = typeof f.label === "string" ? bi(f.label) : f.label || bi();
535
+ f.hideLabel = !!f.hideLabel;
536
+ if ("placeholder" in f) f.placeholder = typeof f.placeholder === "string" ? bi(f.placeholder) : f.placeholder || bi();
537
+ if ("content" in f) f.content = typeof f.content === "string" ? bi(f.content) : f.content || bi();
538
+ if ("alt" in f) f.alt = typeof f.alt === "string" ? bi(f.alt) : f.alt || bi();
539
+ if (f.options) f.options = f.options.map((o) => ({ ...o, label: typeof o.label === "string" ? bi(o.label) : o.label || bi() }));
540
+ if (f.type === "paragraph") {
541
+ f.tag = f.tag || "p";
542
+ f.fontSize = f.fontSize || "md";
543
+ f.fontWeight = f.fontWeight || "normal";
544
+ f.fontStyle = f.fontStyle || "normal";
545
+ f.textAlign = f.textAlign || "left";
546
+ f.color = f.color || "";
547
+ }
548
+ if (f.type === "button") {
549
+ f.action = f.action === "link" ? "link" : "submit";
550
+ f.buttonStyle = f.buttonStyle || { color: "", size: "md" };
551
+ f.href = f.href || "";
552
+ f.target = f.target === "_blank" ? "_blank" : "_self";
553
+ f.submitScope = f.submitScope === "section" ? "section" : "form";
554
+ }
555
+ f.verticalAlign = f.verticalAlign || "top";
556
+ return f;
557
+ }
558
+ function migrateFields(fields) {
559
+ return (fields || []).map(migrateField);
560
+ }
561
+ function synthesizeButtonField(label, style, scope) {
562
+ const resolvedLabel = typeof label === "string" && label ? bi(label) : label && typeof label === "object" && (label.en || label.ja) ? label : bi("Submit", "");
563
+ return {
564
+ id: nextId(),
565
+ type: "button",
566
+ label: resolvedLabel,
567
+ hideLabel: false,
568
+ width: "1/1",
569
+ verticalAlign: "top",
570
+ labelPosition: "top",
571
+ showIcon: false,
572
+ displayIcon: "Type",
573
+ action: "submit",
574
+ submitScope: scope,
575
+ buttonStyle: style || { color: "", size: "md" },
576
+ href: "",
577
+ target: "_self"
578
+ };
579
+ }
580
+ function migrateDocument(raw) {
581
+ if (!raw) return null;
582
+ const title = typeof raw.title === "string" ? bi(raw.title) : raw.title || bi();
583
+ const themeOverrides = raw.themeOverrides || {};
584
+ let sections;
585
+ if (raw.sections) {
586
+ sections = raw.sections.map((s) => ({
587
+ id: s.id || genSectionId(),
588
+ title: typeof s.title === "string" ? bi(s.title) : s.title || bi(),
589
+ background: s.background || "",
590
+ collapsed: !!s.collapsed,
591
+ fields: migrateFields(s.fields || [])
592
+ }));
593
+ } else {
594
+ sections = [{ ...defaultSection(), fields: migrateFields(raw.fields || []) }];
595
+ }
596
+ const legacy = raw.version === void 0 || raw.version < 5;
597
+ if (legacy) {
598
+ resyncIdCounter(sections.flatMap((s) => s.fields));
599
+ const submitMode = raw.submitMode === "perSection" ? "perSection" : "combined";
600
+ const submitLabel = raw.submitLabel;
601
+ const submitStyle = raw.submitStyle || { color: "", size: "md" };
602
+ if (submitMode === "perSection" && raw.sections) {
603
+ sections = sections.map((s, i) => {
604
+ if (!sectionHasFormFields(s)) return s;
605
+ const rawSection = raw.sections[i] || {};
606
+ const label = rawSection.submitLabel || submitLabel;
607
+ const style = rawSection.submitStyle || submitStyle;
608
+ return { ...s, fields: [...s.fields, synthesizeButtonField(label, style, "section")] };
609
+ });
610
+ } else if (sections.some(sectionHasFormFields)) {
611
+ const lastIdx = sections.length - 1;
612
+ sections = sections.map((s, i) => i === lastIdx ? { ...s, fields: [...s.fields, synthesizeButtonField(submitLabel, submitStyle, "form")] } : s);
613
+ }
614
+ }
615
+ return { title, themeOverrides, sections };
616
+ }
617
+
618
+ // src/lib/features.ts
619
+ var DEFAULT_FEATURES = {
620
+ naming: true,
621
+ templates: true,
622
+ newForm: true,
623
+ autosave: true,
624
+ jsonView: true,
625
+ previewMode: true,
626
+ languageSwitcher: true,
627
+ design: false,
628
+ blockStyling: true,
629
+ contentBlocks: true,
630
+ fieldTypes: true,
631
+ sections: true,
632
+ dragReorder: true
633
+ };
634
+ function resolveFeatures(features) {
635
+ return {
636
+ ...DEFAULT_FEATURES,
637
+ ...features,
638
+ contentBlocks: Array.isArray(features?.contentBlocks) ? new Set(features.contentBlocks) : features?.contentBlocks ?? DEFAULT_FEATURES.contentBlocks,
639
+ fieldTypes: Array.isArray(features?.fieldTypes) ? new Set(features.fieldTypes) : features?.fieldTypes ?? DEFAULT_FEATURES.fieldTypes
640
+ };
641
+ }
642
+ function isContentBlockEnabled(features, type) {
643
+ return features.contentBlocks === true || features.contentBlocks instanceof Set && features.contentBlocks.has(type);
644
+ }
645
+ function isFieldTypeEnabled(features, type) {
646
+ return features.fieldTypes === true || features.fieldTypes instanceof Set && features.fieldTypes.has(type);
647
+ }
648
+
649
+ // src/hooks/useTheme.ts
650
+ import { useState } from "react";
651
+
652
+ // src/theme/defaultTheme.ts
653
+ var DEFAULT_THEME = {
654
+ primary: "#5B5FEF",
655
+ primarySoft: "#EEF0FF",
656
+ danger: "#C4432E",
657
+ dangerSoft: "#FDECE4",
658
+ ink: "#1B1E24",
659
+ muted: "#9296A3",
660
+ border: "#E2E4E9",
661
+ surface: "#FFFFFF",
662
+ canvas: "#F5F6F8",
663
+ pageBackground: "#FFFFFF",
664
+ layout: { maxWidth: 1200, pagePadding: 28, canvasPadding: 20, sectionGap: 20, fieldGap: 16, toolbarPadding: 10, panelPadding: 14, ticketPadding: 14 }
665
+ };
666
+
667
+ // src/hooks/useTheme.ts
668
+ function useTheme(themeOverrideProp) {
669
+ const baseTheme = {
670
+ ...DEFAULT_THEME,
671
+ ...themeOverrideProp || {},
672
+ layout: { ...DEFAULT_THEME.layout, ...themeOverrideProp && themeOverrideProp.layout || {} }
673
+ };
674
+ const [themeOverrides, setThemeOverrides] = useState({});
675
+ const theme = {
676
+ ...baseTheme,
677
+ ...themeOverrides,
678
+ layout: { ...baseTheme.layout, ...themeOverrides.layout || {} }
679
+ };
680
+ function updateThemeColor(key, value) {
681
+ setThemeOverrides((prev) => ({ ...prev, [key]: value }));
682
+ }
683
+ function updateThemeLayout(key, value) {
684
+ setThemeOverrides((prev) => ({ ...prev, layout: { ...prev.layout, [key]: value } }));
685
+ }
686
+ function resetTheme() {
687
+ setThemeOverrides({});
688
+ }
689
+ function replaceThemeOverrides(overrides) {
690
+ setThemeOverrides(overrides);
691
+ }
692
+ return { theme, themeOverrides, updateThemeColor, updateThemeLayout, resetTheme, replaceThemeOverrides };
510
693
  }
511
694
 
512
695
  // src/hooks/useFormDocument.ts
696
+ import { useState as useState2 } from "react";
513
697
  function useFormDocument({ language, chrome }) {
514
698
  const [title, setTitle] = useState2(bi("Untitled form", ""));
515
- const [submitLabel, setSubmitLabelState] = useState2(bi());
516
- const [submitMode, setSubmitMode] = useState2("combined");
517
- const [submitStyle, setSubmitStyleState] = useState2({ color: "", size: "md" });
518
699
  const [sections, setSections] = useState2([defaultSection()]);
519
700
  const [activeSectionId, setActiveSectionId] = useState2(null);
520
701
  const [selectedId, setSelectedId] = useState2(null);
@@ -524,12 +705,6 @@ function useFormDocument({ language, chrome }) {
524
705
  function updateTitle(value) {
525
706
  setTitle((prev) => withLang(prev, language, value));
526
707
  }
527
- function updateSubmitLabel(value) {
528
- setSubmitLabelState((prev) => withLang(prev, language, value));
529
- }
530
- function updateSubmitStyle(patch) {
531
- setSubmitStyleState((prev) => ({ ...prev, ...patch }));
532
- }
533
708
  function addSection() {
534
709
  const s = defaultSection();
535
710
  setSections((prev) => [...prev, s]);
@@ -574,12 +749,6 @@ function useFormDocument({ language, chrome }) {
574
749
  function toggleSectionCollapse(sectionId) {
575
750
  setSections((prev) => prev.map((s) => s.id === sectionId ? { ...s, collapsed: !s.collapsed } : s));
576
751
  }
577
- function updateSectionSubmitStyle(sectionId, patch) {
578
- setSections((prev) => prev.map((s) => s.id === sectionId ? { ...s, submitStyle: { ...s.submitStyle || submitStyle, ...patch } } : s));
579
- }
580
- function clearSectionSubmitStyle(sectionId) {
581
- setSections((prev) => prev.map((s) => s.id === sectionId ? { ...s, submitStyle: null } : s));
582
- }
583
752
  function addField(type) {
584
753
  const field = defaultFieldFor(type, language, chrome);
585
754
  const targetId = activeSectionId || sections[0]?.id;
@@ -657,9 +826,6 @@ function useFormDocument({ language, chrome }) {
657
826
  setSections(doc.sections);
658
827
  setActiveSectionId(doc.sections[0]?.id || null);
659
828
  setTitle(doc.title);
660
- setSubmitLabelState(doc.submitLabel);
661
- setSubmitMode(doc.submitMode);
662
- setSubmitStyleState(doc.submitStyle);
663
829
  setSelectedId(null);
664
830
  }
665
831
  function resetToBlank() {
@@ -667,16 +833,10 @@ function useFormDocument({ language, chrome }) {
667
833
  setSections([s]);
668
834
  setActiveSectionId(s.id);
669
835
  setTitle(bi("Untitled form", ""));
670
- setSubmitLabelState(bi());
671
- setSubmitMode("combined");
672
- setSubmitStyleState({ color: "", size: "md" });
673
836
  setSelectedId(null);
674
837
  }
675
838
  return {
676
839
  title,
677
- submitLabel,
678
- submitMode,
679
- submitStyle,
680
840
  sections,
681
841
  activeSectionId,
682
842
  selectedId,
@@ -685,11 +845,8 @@ function useFormDocument({ language, chrome }) {
685
845
  activeSection,
686
846
  setActiveSectionId,
687
847
  setSelectedId,
688
- setSubmitMode,
689
848
  setTitle,
690
849
  updateTitle,
691
- updateSubmitLabel,
692
- updateSubmitStyle,
693
850
  addSection,
694
851
  duplicateSection,
695
852
  deleteSection,
@@ -697,8 +854,6 @@ function useFormDocument({ language, chrome }) {
697
854
  updateSectionTitle,
698
855
  updateSectionBackground,
699
856
  toggleSectionCollapse,
700
- updateSectionSubmitStyle,
701
- clearSectionSubmitStyle,
702
857
  addField,
703
858
  updateField,
704
859
  deleteField,
@@ -721,62 +876,15 @@ var DRAFT_KEY = "form-page-builder:draft";
721
876
  var INDEX_KEY = "form-page-builder:index";
722
877
  var formKey = (id) => `form-page-builder:saved:${id}`;
723
878
 
724
- // src/lib/migrate.ts
725
- function migrateField(field) {
726
- let f = { ...field };
727
- if (LEGACY_INPUT_TYPES.includes(f.type)) f = { ...f, type: "input", inputType: f.type };
728
- f.label = typeof f.label === "string" ? bi(f.label) : f.label || bi();
729
- f.hideLabel = !!f.hideLabel;
730
- if ("placeholder" in f) f.placeholder = typeof f.placeholder === "string" ? bi(f.placeholder) : f.placeholder || bi();
731
- if ("content" in f) f.content = typeof f.content === "string" ? bi(f.content) : f.content || bi();
732
- if ("alt" in f) f.alt = typeof f.alt === "string" ? bi(f.alt) : f.alt || bi();
733
- if (f.options) f.options = f.options.map((o) => ({ ...o, label: typeof o.label === "string" ? bi(o.label) : o.label || bi() }));
734
- if (f.type === "paragraph") {
735
- f.tag = f.tag || "p";
736
- f.fontSize = f.fontSize || "md";
737
- f.fontWeight = f.fontWeight || "normal";
738
- f.fontStyle = f.fontStyle || "normal";
739
- f.textAlign = f.textAlign || "left";
740
- f.color = f.color || "";
741
- }
742
- f.verticalAlign = f.verticalAlign || "top";
743
- return f;
744
- }
745
- function migrateFields(fields) {
746
- return (fields || []).map(migrateField);
747
- }
748
- function migrateDocument(raw) {
749
- if (!raw) return null;
750
- const title = typeof raw.title === "string" ? bi(raw.title) : raw.title || bi();
751
- const submitLabel = typeof raw.submitLabel === "string" ? bi(raw.submitLabel) : raw.submitLabel || bi();
752
- const submitMode = raw.submitMode === "perSection" ? "perSection" : "combined";
753
- const submitStyle = raw.submitStyle || { color: "", size: "md" };
754
- const themeOverrides = raw.themeOverrides || {};
755
- if (raw.sections) {
756
- return {
757
- title,
758
- submitLabel,
759
- submitMode,
760
- submitStyle,
761
- themeOverrides,
762
- sections: raw.sections.map((s) => ({
763
- id: s.id || genSectionId(),
764
- title: typeof s.title === "string" ? bi(s.title) : s.title || bi(),
765
- background: s.background || "",
766
- collapsed: !!s.collapsed,
767
- submitStyle: s.submitStyle || null,
768
- fields: migrateFields(s.fields || [])
769
- }))
770
- };
771
- }
772
- return { title, submitLabel, submitMode, submitStyle, themeOverrides, sections: [{ ...defaultSection(), fields: migrateFields(raw.fields || []) }] };
773
- }
774
-
775
879
  // src/hooks/usePersistence.ts
880
+ var MAX_TEMPLATES = 5;
776
881
  function usePersistence({
777
882
  storage,
883
+ autosave,
778
884
  language,
885
+ chrome,
779
886
  document,
887
+ initialDocument,
780
888
  onLoadDocument,
781
889
  onLoadThemeOverrides,
782
890
  onTitleChange,
@@ -802,17 +910,27 @@ function usePersistence({
802
910
  useEffect(() => {
803
911
  (async () => {
804
912
  try {
805
- const raw = await storage.get(DRAFT_KEY);
806
- if (raw) {
807
- const parsed = JSON.parse(raw);
808
- const doc = migrateDocument(parsed);
913
+ if (initialDocument) {
914
+ const doc = migrateDocument(initialDocument);
809
915
  if (doc) {
810
916
  onLoadDocument(doc);
811
917
  onLoadThemeOverrides(doc.themeOverrides);
918
+ } else {
919
+ ensureActiveSection();
812
920
  }
813
- if (parsed.currentFormId) setCurrentFormId(parsed.currentFormId);
814
921
  } else {
815
- ensureActiveSection();
922
+ const raw = await storage.get(DRAFT_KEY);
923
+ if (raw) {
924
+ const parsed = JSON.parse(raw);
925
+ const doc = migrateDocument(parsed);
926
+ if (doc) {
927
+ onLoadDocument(doc);
928
+ onLoadThemeOverrides(doc.themeOverrides);
929
+ }
930
+ if (parsed.currentFormId) setCurrentFormId(parsed.currentFormId);
931
+ } else {
932
+ ensureActiveSection();
933
+ }
816
934
  }
817
935
  } catch (err) {
818
936
  ensureActiveSection();
@@ -824,7 +942,7 @@ function usePersistence({
824
942
  refreshLibrary();
825
943
  }, []);
826
944
  useEffect(() => {
827
- if (!hasLoadedOnce.current) return;
945
+ if (!hasLoadedOnce.current || !autosave) return;
828
946
  setSaveState("saving");
829
947
  if (autosaveTimer.current) clearTimeout(autosaveTimer.current);
830
948
  autosaveTimer.current = setTimeout(async () => {
@@ -838,8 +956,12 @@ function usePersistence({
838
956
  return () => {
839
957
  if (autosaveTimer.current) clearTimeout(autosaveTimer.current);
840
958
  };
841
- }, [document.title, document.submitLabel, document.submitMode, document.submitStyle, document.themeOverrides, document.sections, currentFormId]);
959
+ }, [document.title, document.themeOverrides, document.sections, currentFormId]);
842
960
  async function saveAs(name) {
961
+ if (savedForms.length >= MAX_TEMPLATES) {
962
+ alert(chrome.templatesLimitReached);
963
+ return;
964
+ }
843
965
  const id = genFormId();
844
966
  const now = Date.now();
845
967
  try {
@@ -948,26 +1070,26 @@ function useDragReorder(reorderWithinSection) {
948
1070
  }
949
1071
 
950
1072
  // src/components/Toolbar.tsx
951
- import { Loader2, AlertCircle, Languages, Pencil, Eye, Settings, FilePlus2, FolderOpen, Save, Code2 } from "lucide-react";
1073
+ import { Loader2, AlertCircle, Pencil, Eye, FilePlus2, FolderOpen, Save, Code2 } from "lucide-react";
952
1074
 
953
1075
  // src/styles/styles.ts
954
1076
  var styles = {
955
- app: { fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, sans-serif", background: "var(--fb-canvas)", borderRadius: 12, overflow: "hidden", border: "1px solid var(--fb-border)", color: "var(--fb-ink)", minHeight: 640, maxHeight: "100vh", display: "flex", flexDirection: "column" },
1077
+ app: { fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, sans-serif", background: "var(--fb-canvas)", borderRadius: 12, overflow: "hidden", border: "1px solid var(--fb-border)", color: "var(--fb-ink)", display: "flex", flexDirection: "column" },
956
1078
  toolbar: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "var(--fb-space-toolbar) 16px", borderBottom: "1px solid var(--fb-border)", background: "var(--fb-surface)", flexWrap: "wrap", gap: 8, position: "relative" },
957
1079
  toolbarLeft: { display: "flex", alignItems: "center", gap: 10 },
958
1080
  logoMark: { width: 26, height: 26, borderRadius: 7, background: "var(--fb-primary)", color: "#fff", fontSize: 11, fontWeight: 700, display: "flex", alignItems: "center", justifyContent: "center", fontFamily: "'JetBrains Mono', monospace", letterSpacing: "-0.5px" },
959
1081
  titleInput: { border: "none", outline: "none", fontSize: 14, fontWeight: 600, background: "transparent", color: "var(--fb-ink)", padding: "4px 6px", borderRadius: 6, minWidth: 160 },
960
1082
  toolbarRight: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" },
961
1083
  toolbarDivider: { width: 1, height: 20, background: "var(--fb-border)", margin: "0 4px" },
962
- tabBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid transparent", background: "transparent", color: "#6B6E79", fontSize: 13, fontWeight: 500 },
1084
+ tabBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid transparent", background: "transparent", color: "var(--fb-muted)", fontSize: 13, fontWeight: 500 },
963
1085
  tabBtnActive: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid var(--fb-border)", background: "var(--fb-primary-soft)", color: "var(--fb-primary)", fontSize: 13, fontWeight: 600 },
964
- ghostBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid var(--fb-border)", background: "var(--fb-surface)", color: "#4A4D57", fontSize: 13, fontWeight: 500 },
1086
+ ghostBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 12px", borderRadius: 7, border: "1px solid var(--fb-border)", background: "var(--fb-surface)", color: "var(--fb-ink)", fontSize: 13, fontWeight: 500 },
965
1087
  primaryBtn: { display: "flex", alignItems: "center", gap: 6, padding: "6px 13px", borderRadius: 7, border: "1px solid var(--fb-primary)", background: "var(--fb-primary)", color: "#fff", fontSize: 13, fontWeight: 600 },
966
1088
  saveStatus: { display: "flex", alignItems: "center", gap: 5, fontSize: 12, color: "var(--fb-muted)", minWidth: 60 },
967
1089
  countBadge: { fontSize: 10.5, fontWeight: 700, background: "var(--fb-primary-soft)", color: "var(--fb-primary)", borderRadius: 9, padding: "1px 6px", marginLeft: 2 },
968
1090
  loadingScreen: { flex: 1, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
969
1091
  libraryBody: { padding: "var(--fb-space-panel)", overflowY: "auto", display: "flex", flexDirection: "column", gap: 4 },
970
- libraryRow: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10, padding: "10px 8px", borderRadius: 8, border: "1px solid #F0F1F4" },
1092
+ libraryRow: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10, padding: "10px 8px", borderRadius: 8, border: "1px solid var(--fb-border)" },
971
1093
  libraryRowTitle: { fontSize: 13.5, fontWeight: 600, color: "var(--fb-ink)", display: "flex", alignItems: "center", gap: 8, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
972
1094
  libraryRowMeta: { fontSize: 11.5, color: "var(--fb-muted)", marginTop: 2 },
973
1095
  currentBadge: { fontSize: 10, fontWeight: 700, color: "var(--fb-primary)", background: "var(--fb-primary-soft)", padding: "2px 6px", borderRadius: 5, flexShrink: 0 },
@@ -976,7 +1098,7 @@ var styles = {
976
1098
  panelHeading: { fontSize: 11, fontWeight: 700, letterSpacing: "0.06em", textTransform: "uppercase", color: "var(--fb-muted)", marginBottom: 10 },
977
1099
  activeSectionHint: { fontSize: 11.5, color: "var(--fb-muted)", marginBottom: 14, lineHeight: 1.4 },
978
1100
  paletteList: { display: "flex", flexDirection: "column", gap: 4 },
979
- paletteItem: { display: "flex", alignItems: "center", gap: 9, padding: "8px 9px", borderRadius: 8, border: "1px solid transparent", background: "transparent", fontSize: 13, color: "#33353E", textAlign: "left" },
1101
+ paletteItem: { display: "flex", alignItems: "center", gap: 9, padding: "8px 9px", borderRadius: 8, border: "1px solid transparent", background: "transparent", fontSize: 13, color: "var(--fb-ink)", textAlign: "left" },
980
1102
  canvas: { flex: 1, padding: "var(--fb-space-canvas)", overflowY: "auto", background: "var(--fb-canvas)" },
981
1103
  sectionBlock: { borderRadius: 12, padding: "var(--fb-space-panel)", marginBottom: "var(--fb-space-section)", transition: "border-color 0.12s" },
982
1104
  sectionHeader: { display: "flex", alignItems: "center", gap: 8, marginBottom: 12, flexWrap: "wrap" },
@@ -985,10 +1107,8 @@ var styles = {
985
1107
  sectionTitleInput: { border: "none", outline: "none", background: "transparent", fontSize: 14, fontWeight: 700, color: "var(--fb-ink)", padding: "2px 0", minWidth: 120, flex: 1 },
986
1108
  sectionHeaderActions: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap", marginLeft: "auto" },
987
1109
  sectionEmpty: { fontSize: 12.5, color: "var(--fb-muted)", padding: "18px 4px", textAlign: "center", border: "1px dashed var(--fb-border)", borderRadius: 8 },
988
- submitStyleRow: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", background: "#F7F8FA", border: "1px solid #F0F1F4", borderRadius: 8, padding: "6px 10px", marginBottom: 12 },
989
- miniLabel: { fontSize: 11, fontWeight: 600, color: "var(--fb-muted)" },
990
1110
  resetLinkBtn: { display: "flex", alignItems: "center", gap: 3, fontSize: 11, color: "var(--fb-muted)", background: "transparent", border: "none", padding: "2px 4px" },
991
- addSectionBtn: { display: "flex", alignItems: "center", justifyContent: "center", gap: 6, width: "100%", padding: "10px", borderRadius: 10, border: "1px dashed #C7C9D6", background: "transparent", color: "var(--fb-primary)", fontSize: 13, fontWeight: 600 },
1111
+ addSectionBtn: { display: "flex", alignItems: "center", justifyContent: "center", gap: 6, width: "100%", padding: "10px", borderRadius: 10, border: "1px dashed var(--fb-border)", background: "transparent", color: "var(--fb-primary)", fontSize: 13, fontWeight: 600 },
992
1112
  swatchRow: { display: "flex", alignItems: "center", gap: 5, flexWrap: "wrap" },
993
1113
  swatchBtn: { width: 20, height: 20, borderRadius: "50%", border: "1px solid var(--fb-border)", padding: 0 },
994
1114
  swatchBtnActive: { border: "2px solid var(--fb-primary)" },
@@ -997,52 +1117,56 @@ var styles = {
997
1117
  ticket: { display: "flex", alignItems: "stretch", background: "var(--fb-surface)", border: "1px solid var(--fb-border)", borderRadius: 10, position: "relative", transition: "border-color 0.12s, box-shadow 0.12s" },
998
1118
  ticketSelected: { borderColor: "var(--fb-primary)", boxShadow: "0 0 0 3px var(--fb-primary-soft)" },
999
1119
  ticketDragOver: { borderColor: "var(--fb-muted)" },
1000
- ticketIndex: { fontFamily: "'JetBrains Mono', monospace", fontSize: 13, fontWeight: 700, color: "#C7C9D6", width: 34, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 },
1120
+ ticketIndex: { fontFamily: "'JetBrains Mono', monospace", fontSize: 13, fontWeight: 700, color: "var(--fb-border)", width: 34, display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 },
1001
1121
  ticketPerforation: { width: 0, borderLeft: "1px dashed var(--fb-border)" },
1002
1122
  ticketBody: { flex: 1, padding: "10px var(--fb-space-ticket)", minWidth: 0 },
1003
1123
  ticketTop: { display: "flex", alignItems: "center", gap: 7, marginBottom: 4 },
1004
1124
  typeBadge: { fontSize: 10.5, fontFamily: "'JetBrains Mono', monospace", color: "var(--fb-muted)" },
1005
- requiredBadge: { fontSize: 10, fontWeight: 700, color: "#B4522F", background: "var(--fb-danger-soft)", padding: "2px 6px", borderRadius: 5, letterSpacing: "0.02em", marginLeft: "auto" },
1125
+ requiredBadge: { fontSize: 10, fontWeight: 700, color: "var(--fb-danger)", background: "var(--fb-danger-soft)", padding: "2px 6px", borderRadius: 5, letterSpacing: "0.02em", marginLeft: "auto" },
1006
1126
  chipRow: { display: "flex", gap: 5, marginBottom: 7, flexWrap: "wrap" },
1007
1127
  miniBadge: { fontSize: 10, fontWeight: 600, color: "var(--fb-primary)", background: "var(--fb-primary-soft)", padding: "2px 6px", borderRadius: 5, letterSpacing: "0.02em" },
1008
- segmented: { display: "flex", gap: 3, background: "#F0F1F4", padding: 3, borderRadius: 8, marginBottom: 4 },
1009
- 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 },
1010
- 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)" },
1128
+ langToggleTrack: { position: "relative", display: "flex", gap: 3, background: "var(--fb-surface-2)", padding: 3, borderRadius: 20 },
1129
+ langToggleThumb: { position: "absolute", top: 3, left: 3, bottom: 3, background: "var(--fb-primary)", borderRadius: 17, transition: "transform 0.18s ease" },
1130
+ langToggleBtn: { position: "relative", zIndex: 1, padding: "5px 12px", borderRadius: 17, border: "none", background: "transparent", color: "var(--fb-muted)", fontSize: 12.5, fontWeight: 600, whiteSpace: "nowrap" },
1131
+ langToggleBtnActive: { position: "relative", zIndex: 1, padding: "5px 12px", borderRadius: 17, border: "none", background: "transparent", color: "#fff", fontSize: 12.5, fontWeight: 600, whiteSpace: "nowrap" },
1132
+ segmented: { display: "flex", gap: 3, background: "var(--fb-surface-2)", padding: 3, borderRadius: 8, marginBottom: 4 },
1133
+ segmentedBtn: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 5, padding: "6px 8px", borderRadius: 6, border: "none", background: "transparent", color: "var(--fb-muted)", fontSize: 12.5, fontWeight: 500 },
1134
+ segmentedBtnActive: { flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 5, padding: "6px 8px", borderRadius: 6, border: "none", background: "var(--fb-surface)", color: "var(--fb-ink)", fontSize: 12.5, fontWeight: 600, boxShadow: "0 1px 2px rgba(0,0,0,0.08)" },
1011
1135
  iconGrid: { display: "grid", gridTemplateColumns: "repeat(6, 1fr)", gap: 5, marginTop: 6 },
1012
- iconGridBtn: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-border)", background: "#fff", display: "flex", alignItems: "center", justifyContent: "center", color: "#6B6E79" },
1136
+ iconGridBtn: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-border)", background: "var(--fb-surface)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
1013
1137
  iconGridBtnActive: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-primary)", background: "var(--fb-primary-soft)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-primary)" },
1014
1138
  styleToggleRow: { display: "flex", gap: 5, marginBottom: 4 },
1015
- styleToggle: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-border)", background: "#fff", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
1139
+ styleToggle: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-border)", background: "var(--fb-surface)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
1016
1140
  styleToggleActive: { width: 30, height: 30, borderRadius: 7, border: "1px solid var(--fb-primary)", background: "var(--fb-primary-soft)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-primary)" },
1017
- 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" },
1018
- previewRadio: { display: "flex", alignItems: "center", gap: 6, fontSize: 13, color: "#4A4D57" },
1019
- ticketActions: { display: "flex", flexDirection: "column", gap: 3, padding: 8, borderLeft: "1px solid #F0F1F4" },
1020
- iconBtn: { width: 24, height: 24, borderRadius: 6, border: "1px solid #E9EAEE", background: "#fff", display: "flex", alignItems: "center", justifyContent: "center", color: "#6B6E79" },
1141
+ previewInput: { border: "1px solid var(--fb-border)", borderRadius: 7, padding: "7px 10px", fontSize: 13, color: "var(--fb-muted)", background: "var(--fb-surface-2)", display: "flex", alignItems: "center", justifyContent: "space-between" },
1142
+ previewRadio: { display: "flex", alignItems: "center", gap: 6, fontSize: 13, color: "var(--fb-ink)" },
1143
+ ticketActions: { display: "flex", flexDirection: "column", gap: 3, padding: 8, borderLeft: "1px solid var(--fb-border)" },
1144
+ iconBtn: { width: 24, height: 24, borderRadius: 6, border: "1px solid var(--fb-border)", background: "var(--fb-surface)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--fb-muted)" },
1021
1145
  iconBtnDanger: { color: "var(--fb-danger)" },
1022
1146
  inspector: { width: 270, borderLeft: "1px solid var(--fb-border)", background: "var(--fb-surface)", padding: "var(--fb-space-panel)", overflowY: "auto" },
1023
1147
  inspectorEmpty: { fontSize: 13, color: "var(--fb-muted)", lineHeight: 1.5, marginTop: 6 },
1024
1148
  inspectorBody: { display: "flex", flexDirection: "column", gap: 4 },
1025
1149
  helperText: { fontSize: 11, color: "var(--fb-muted)", lineHeight: 1.4, margin: "2px 0 4px" },
1026
- propLabel: { fontSize: 11.5, fontWeight: 600, color: "#6B6E79", marginTop: 12, marginBottom: 5 },
1027
- propInput: { border: "1px solid var(--fb-border)", borderRadius: 7, padding: "7px 9px", fontSize: 13, color: "var(--fb-ink)", outline: "none", width: "100%", boxSizing: "border-box" },
1150
+ propLabel: { fontSize: 11.5, fontWeight: 600, color: "var(--fb-muted)", marginTop: 12, marginBottom: 5 },
1151
+ propInput: { border: "1px solid var(--fb-border)", borderRadius: 7, padding: "7px 9px", fontSize: 13, color: "var(--fb-ink)", background: "var(--fb-surface)", outline: "none", width: "100%", boxSizing: "border-box" },
1028
1152
  optionList: { display: "flex", flexDirection: "column", gap: 6 },
1029
1153
  optionRow: { display: "flex", gap: 6, alignItems: "center" },
1030
- optionInput: { flex: 1, border: "1px solid var(--fb-border)", borderRadius: 6, padding: "6px 8px", fontSize: 12.5, outline: "none", minWidth: 0, boxSizing: "border-box" },
1031
- addOptionBtn: { display: "flex", alignItems: "center", gap: 5, fontSize: 12.5, color: "var(--fb-primary)", background: "transparent", border: "1px dashed #C7C9D6", borderRadius: 7, padding: "6px 8px", justifyContent: "center", marginTop: 2 },
1154
+ optionInput: { flex: 1, border: "1px solid var(--fb-border)", borderRadius: 6, padding: "6px 8px", fontSize: 12.5, color: "var(--fb-ink)", background: "var(--fb-surface)", outline: "none", minWidth: 0, boxSizing: "border-box" },
1155
+ addOptionBtn: { display: "flex", alignItems: "center", gap: 5, fontSize: 12.5, color: "var(--fb-primary)", background: "transparent", border: "1px dashed var(--fb-border)", borderRadius: 7, padding: "6px 8px", justifyContent: "center", marginTop: 2 },
1032
1156
  toggleRow: { display: "flex", alignItems: "center", gap: 8, background: "transparent", border: "none", padding: "8px 0" },
1033
1157
  toggleTrack: { width: 30, height: 17, borderRadius: 20, position: "relative", transition: "background 0.15s", display: "inline-block" },
1034
1158
  toggleThumb: { position: "absolute", top: 2, left: 2, width: 13, height: 13, borderRadius: "50%", background: "#fff", transition: "transform 0.15s", boxShadow: "0 1px 2px rgba(0,0,0,0.2)" },
1035
1159
  inspectorDivider: { height: 1, background: "var(--fb-border)", margin: "14px 0 10px" },
1036
1160
  deleteFieldBtn: { display: "flex", alignItems: "center", gap: 6, fontSize: 12.5, color: "var(--fb-danger)", background: "var(--fb-danger-soft)", border: "none", borderRadius: 7, padding: "8px 10px", justifyContent: "center" },
1037
- modalOverlay: { position: "fixed", inset: 0, background: "rgba(20,22,28,0.45)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 50 },
1038
- modal: { background: "#fff", borderRadius: 12, width: 520, maxHeight: "70vh", display: "flex", flexDirection: "column", overflow: "hidden", boxShadow: "0 20px 60px rgba(0,0,0,0.25)" },
1161
+ modalOverlay: { position: "fixed", inset: 0, background: "rgba(20,22,28,0.45)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 50, padding: 16, boxSizing: "border-box" },
1162
+ modal: { background: "var(--fb-surface)", borderRadius: 12, width: "100%", maxWidth: 520, maxHeight: "70vh", display: "flex", flexDirection: "column", overflow: "hidden", boxShadow: "0 20px 60px rgba(0,0,0,0.25)", boxSizing: "border-box" },
1039
1163
  modalHeader: { display: "flex", alignItems: "center", justifyContent: "space-between", padding: "12px 16px", borderBottom: "1px solid var(--fb-border)" },
1040
1164
  jsonPre: { margin: 0, padding: 16, fontSize: 12, lineHeight: 1.6, overflow: "auto", background: "#14171C", color: "#D6D8E0", fontFamily: "'JetBrains Mono', monospace" },
1041
1165
  previewWrap: { flex: 1, display: "flex", justifyContent: "center", padding: "var(--fb-space-page) 20px", overflowY: "auto", background: "var(--fb-canvas)" },
1042
1166
  previewToolbar: { width: "100%", display: "flex", gap: 10, marginBottom: 16, justifyContent: "center" },
1043
1167
  previewCard: { width: "100%", maxWidth: 480, background: "var(--fb-page-bg)", border: "1px solid var(--fb-border)", borderRadius: 12, padding: "var(--fb-space-page)" },
1044
1168
  previewTitle: { fontSize: 19, fontWeight: 700, margin: "0 0 20px" },
1045
- previewLabel: { display: "block", fontSize: 13, fontWeight: 600, color: "#33353E", marginBottom: 6 },
1169
+ previewLabel: { display: "block", fontSize: 13, fontWeight: 600, color: "var(--fb-ink)", marginBottom: 6 },
1046
1170
  previewGrid: { display: "flex", flexWrap: "wrap", gap: "var(--fb-space-field)" },
1047
1171
  sectionRuntimeTitle: { fontSize: 15, fontWeight: 700, margin: "0 0 12px", color: "var(--fb-ink)" },
1048
1172
  imagePlaceholder: { display: "flex", alignItems: "center", justifyContent: "center", border: "1px dashed var(--fb-border)" },
@@ -1052,32 +1176,146 @@ var styles = {
1052
1176
  submittedRow: { display: "flex", justifyContent: "space-between", gap: 12, fontSize: 13, padding: "6px 0", borderBottom: "1px solid var(--fb-border)" },
1053
1177
  submittedLabel: { color: "var(--fb-muted)", flexShrink: 0 },
1054
1178
  submittedValue: { color: "var(--fb-ink)", fontWeight: 600, textAlign: "right" },
1055
- realInput: { width: "100%", border: "1px solid var(--fb-border)", borderRadius: 8, padding: "9px 11px", fontSize: 13.5, outline: "none", color: "var(--fb-ink)", boxSizing: "border-box" },
1179
+ realInput: { width: "100%", border: "1px solid var(--fb-border)", borderRadius: 8, padding: "9px 11px", fontSize: 13.5, outline: "none", color: "var(--fb-ink)", background: "var(--fb-surface)", boxSizing: "border-box" },
1056
1180
  realInputError: { borderColor: "var(--fb-danger)" },
1057
1181
  submitBtn: { marginTop: 8, color: "#fff", border: "none", borderRadius: 8, fontWeight: 600, width: "100%" },
1058
- layoutPanel: { position: "absolute", top: "calc(100% + 6px)", right: 0, width: 260, background: "#fff", border: "1px solid var(--fb-border)", borderRadius: 10, boxShadow: "0 12px 32px rgba(0,0,0,0.18)", padding: 14, zIndex: 60, maxHeight: "70vh", overflowY: "auto" },
1059
1182
  layoutPanelHeader: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 4 },
1060
1183
  spacingRow: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8, padding: "4px 0" },
1061
- spacingLabel: { fontSize: 12, color: "#4A4D57" },
1062
- spacingInput: { width: 60, border: "1px solid var(--fb-border)", borderRadius: 6, padding: "4px 6px", fontSize: 12, textAlign: "right", outline: "none" }
1184
+ spacingLabel: { fontSize: 12, color: "var(--fb-ink)" },
1185
+ spacingInput: { width: 60, border: "1px solid var(--fb-border)", borderRadius: 6, padding: "4px 6px", fontSize: 12, textAlign: "right", color: "var(--fb-ink)", background: "var(--fb-surface)", outline: "none" }
1063
1186
  };
1064
1187
 
1065
- // src/components/Segmented.tsx
1188
+ // src/components/LanguageToggle.tsx
1066
1189
  import { jsx, jsxs } from "react/jsx-runtime";
1190
+ function LanguageToggle({ languages, value, onChange }) {
1191
+ const activeIdx = Math.max(0, languages.findIndex((l) => l.code === value));
1192
+ const n = languages.length || 1;
1193
+ return /* @__PURE__ */ jsxs("div", { style: styles.langToggleTrack, children: [
1194
+ /* @__PURE__ */ jsx(
1195
+ "div",
1196
+ {
1197
+ style: {
1198
+ ...styles.langToggleThumb,
1199
+ width: `calc(${100 / n}% - 3px)`,
1200
+ transform: `translateX(calc(${activeIdx * 100}% + ${activeIdx * 3}px))`
1201
+ }
1202
+ }
1203
+ ),
1204
+ languages.map((l) => /* @__PURE__ */ jsx(
1205
+ "button",
1206
+ {
1207
+ type: "button",
1208
+ style: l.code === value ? styles.langToggleBtnActive : styles.langToggleBtn,
1209
+ onClick: () => onChange(l.code),
1210
+ children: l.label
1211
+ },
1212
+ l.code
1213
+ ))
1214
+ ] });
1215
+ }
1216
+
1217
+ // src/components/Toolbar.tsx
1218
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1219
+ function Toolbar({
1220
+ title,
1221
+ language,
1222
+ languages,
1223
+ mode,
1224
+ saveState,
1225
+ chrome,
1226
+ features,
1227
+ savedFormsCount,
1228
+ onTitleChange,
1229
+ onLanguageChange,
1230
+ onModeChange,
1231
+ onNewForm,
1232
+ onOpenLibrary,
1233
+ onSaveExisting,
1234
+ onOpenJson
1235
+ }) {
1236
+ return /* @__PURE__ */ jsxs2("div", { style: styles.toolbar, children: [
1237
+ /* @__PURE__ */ jsxs2("div", { style: styles.toolbarLeft, children: [
1238
+ /* @__PURE__ */ jsx2("div", { style: styles.logoMark, children: "FB" }),
1239
+ features.naming ? /* @__PURE__ */ jsx2("input", { value: t(title, language), onChange: (e) => onTitleChange(e.target.value), style: styles.titleInput, "aria-label": "Form title" }) : /* @__PURE__ */ jsx2("span", { style: styles.titleInput, children: t(title, language) })
1240
+ ] }),
1241
+ /* @__PURE__ */ jsxs2("div", { style: styles.toolbarRight, children: [
1242
+ /* @__PURE__ */ jsxs2("span", { style: styles.saveStatus, children: [
1243
+ saveState === "saving" && /* @__PURE__ */ jsxs2(Fragment, { children: [
1244
+ /* @__PURE__ */ jsx2(Loader2, { size: 12, className: "spin" }),
1245
+ " ",
1246
+ chrome.saving
1247
+ ] }),
1248
+ saveState === "saved" && chrome.saved,
1249
+ saveState === "error" && /* @__PURE__ */ jsxs2("span", { style: { color: "var(--fb-danger)", display: "flex", alignItems: "center", gap: 4 }, children: [
1250
+ /* @__PURE__ */ jsx2(AlertCircle, { size: 12 }),
1251
+ " ",
1252
+ chrome.saveFailed
1253
+ ] })
1254
+ ] }),
1255
+ features.languageSwitcher && /* @__PURE__ */ jsxs2(Fragment, { children: [
1256
+ /* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
1257
+ /* @__PURE__ */ jsx2(LanguageToggle, { languages, value: language, onChange: onLanguageChange })
1258
+ ] }),
1259
+ features.previewMode && /* @__PURE__ */ jsxs2(Fragment, { children: [
1260
+ /* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
1261
+ /* @__PURE__ */ jsxs2("button", { style: mode === "build" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("build"), children: [
1262
+ /* @__PURE__ */ jsx2(Pencil, { size: 14 }),
1263
+ " ",
1264
+ chrome.build
1265
+ ] }),
1266
+ /* @__PURE__ */ jsxs2("button", { style: mode === "preview" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("preview"), children: [
1267
+ /* @__PURE__ */ jsx2(Eye, { size: 14 }),
1268
+ " ",
1269
+ chrome.preview
1270
+ ] })
1271
+ ] }),
1272
+ (features.newForm || features.templates) && /* @__PURE__ */ jsx2("div", { style: styles.toolbarDivider }),
1273
+ features.newForm && /* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onNewForm, title: chrome.startNewForm, children: [
1274
+ /* @__PURE__ */ jsx2(FilePlus2, { size: 14 }),
1275
+ " ",
1276
+ chrome.newForm
1277
+ ] }),
1278
+ features.templates && /* @__PURE__ */ jsxs2(Fragment, { children: [
1279
+ /* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onOpenLibrary, title: chrome.openTemplatesTitle, children: [
1280
+ /* @__PURE__ */ jsx2(FolderOpen, { size: 14 }),
1281
+ " ",
1282
+ chrome.templates,
1283
+ savedFormsCount > 0 && /* @__PURE__ */ jsx2("span", { style: styles.countBadge, children: savedFormsCount })
1284
+ ] }),
1285
+ /* @__PURE__ */ jsxs2("button", { style: styles.primaryBtn, onClick: onSaveExisting, title: chrome.saveToLibraryTitle, children: [
1286
+ /* @__PURE__ */ jsx2(Save, { size: 14 }),
1287
+ " ",
1288
+ chrome.save
1289
+ ] })
1290
+ ] }),
1291
+ features.jsonView && /* @__PURE__ */ jsxs2("button", { style: styles.ghostBtn, onClick: onOpenJson, children: [
1292
+ /* @__PURE__ */ jsx2(Code2, { size: 14 }),
1293
+ " ",
1294
+ chrome.viewJson
1295
+ ] })
1296
+ ] })
1297
+ ] });
1298
+ }
1299
+
1300
+ // src/components/Palette.tsx
1301
+ import { useState as useState5 } from "react";
1302
+ import { Plus } from "lucide-react";
1303
+
1304
+ // src/components/Segmented.tsx
1305
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1067
1306
  function Segmented({ options, value, onChange }) {
1068
- return /* @__PURE__ */ jsx("div", { style: styles.segmented, children: options.map((opt) => {
1307
+ return /* @__PURE__ */ jsx3("div", { style: styles.segmented, children: options.map((opt) => {
1069
1308
  const Icon = opt.icon;
1070
1309
  const active = value === opt.value;
1071
- return /* @__PURE__ */ jsxs("button", { type: "button", style: active ? styles.segmentedBtnActive : styles.segmentedBtn, onClick: () => onChange(opt.value), children: [
1072
- Icon && /* @__PURE__ */ jsx(Icon, { size: 13 }),
1310
+ return /* @__PURE__ */ jsxs3("button", { type: "button", style: active ? styles.segmentedBtnActive : styles.segmentedBtn, onClick: () => onChange(opt.value), children: [
1311
+ Icon && /* @__PURE__ */ jsx3(Icon, { size: 13 }),
1073
1312
  opt.label
1074
1313
  ] }, opt.value);
1075
1314
  }) });
1076
1315
  }
1077
1316
 
1078
- // src/components/LayoutPopover.tsx
1079
- import { useState as useState5 } from "react";
1080
- import { Ruler, RotateCcw } from "lucide-react";
1317
+ // src/components/DesignPanel.tsx
1318
+ import { RotateCcw } from "lucide-react";
1081
1319
 
1082
1320
  // src/constants/colors.ts
1083
1321
  var COLOR_SWATCHES = ["", "#1B1E24", "#5B5FEF", "#C4432E", "#0EA5A4", "#D97706"];
@@ -1100,12 +1338,8 @@ function effectiveWidth(width, device) {
1100
1338
  }
1101
1339
  var SPACING_FIELDS = [
1102
1340
  { key: "pagePadding", labelKey: "spacingPagePadding" },
1103
- { key: "canvasPadding", labelKey: "spacingCanvasPadding" },
1104
1341
  { key: "sectionGap", labelKey: "spacingSectionGap" },
1105
- { key: "fieldGap", labelKey: "spacingFieldGap" },
1106
- { key: "toolbarPadding", labelKey: "spacingToolbarPadding" },
1107
- { key: "panelPadding", labelKey: "spacingPanelPadding" },
1108
- { key: "ticketPadding", labelKey: "spacingTicketPadding" }
1342
+ { key: "fieldGap", labelKey: "spacingFieldGap" }
1109
1343
  ];
1110
1344
  function buildDeviceOptions(baseMaxWidth, chrome) {
1111
1345
  const mw = Number(baseMaxWidth) > 0 ? baseMaxWidth : DEFAULT_THEME.layout.maxWidth;
@@ -1116,184 +1350,112 @@ function buildDeviceOptions(baseMaxWidth, chrome) {
1116
1350
  ];
1117
1351
  }
1118
1352
 
1119
- // src/components/LayoutPopover.tsx
1120
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1121
- function LayoutPopover({ chrome, theme, updateThemeColor, updateThemeLayout, resetTheme }) {
1122
- const [open, setOpen] = useState5(false);
1123
- return /* @__PURE__ */ jsxs2("div", { style: { position: "relative" }, children: [
1124
- /* @__PURE__ */ jsx2("button", { style: styles.iconBtn, title: chrome.spacing, onClick: () => setOpen((v) => !v), children: /* @__PURE__ */ jsx2(Ruler, { size: 14 }) }),
1125
- open && /* @__PURE__ */ jsxs2("div", { style: styles.layoutPanel, children: [
1126
- /* @__PURE__ */ jsxs2("div", { style: styles.layoutPanelHeader, children: [
1127
- /* @__PURE__ */ jsxs2("span", { style: { fontWeight: 600, fontSize: 13 }, children: [
1128
- chrome.theme,
1129
- " / ",
1130
- chrome.spacing
1131
- ] }),
1132
- /* @__PURE__ */ jsxs2("button", { type: "button", style: styles.resetLinkBtn, onClick: resetTheme, children: [
1133
- /* @__PURE__ */ jsx2(RotateCcw, { size: 11 }),
1134
- " ",
1135
- chrome.reset
1136
- ] })
1137
- ] }),
1138
- /* @__PURE__ */ jsx2("label", { style: styles.propLabel, children: chrome.primaryColor }),
1139
- /* @__PURE__ */ jsxs2("div", { style: styles.swatchRow, children: [
1140
- BUTTON_COLOR_SWATCHES.slice(1).map((c) => /* @__PURE__ */ jsx2("button", { type: "button", title: c, style: { ...styles.swatchBtn, background: c, ...theme.primary === c ? styles.swatchBtnActive : {} }, onClick: () => updateThemeColor("primary", c) }, c)),
1141
- /* @__PURE__ */ jsx2("input", { type: "color", value: theme.primary, onChange: (e) => updateThemeColor("primary", e.target.value), style: styles.colorPickerInput })
1142
- ] }),
1143
- /* @__PURE__ */ jsx2("label", { style: styles.propLabel, children: chrome.pageBackground }),
1144
- /* @__PURE__ */ jsxs2("div", { style: styles.swatchRow, children: [
1145
- SECTION_BG_SWATCHES.filter(Boolean).map((c) => /* @__PURE__ */ jsx2("button", { type: "button", title: c, style: { ...styles.swatchBtn, background: c, ...theme.pageBackground === c ? styles.swatchBtnActive : {} }, onClick: () => updateThemeColor("pageBackground", c) }, c)),
1146
- /* @__PURE__ */ jsx2("input", { type: "color", value: theme.pageBackground, onChange: (e) => updateThemeColor("pageBackground", e.target.value), style: styles.colorPickerInput })
1147
- ] }),
1148
- /* @__PURE__ */ jsx2("label", { style: styles.propLabel, children: chrome.maxWidthPx }),
1149
- /* @__PURE__ */ jsx2("input", { type: "number", style: styles.propInput, value: theme.layout.maxWidth, onChange: (e) => updateThemeLayout("maxWidth", Number(e.target.value) || DEFAULT_THEME.layout.maxWidth) }),
1150
- /* @__PURE__ */ jsx2("div", { style: styles.inspectorDivider }),
1151
- /* @__PURE__ */ jsx2("div", { style: styles.panelHeading, children: chrome.spacing }),
1152
- SPACING_FIELDS.map(({ key, labelKey }) => /* @__PURE__ */ jsxs2("div", { style: styles.spacingRow, children: [
1153
- /* @__PURE__ */ jsx2("span", { style: styles.spacingLabel, children: chrome[labelKey] }),
1154
- /* @__PURE__ */ jsx2("input", { type: "number", style: styles.spacingInput, value: theme.layout[key], onChange: (e) => updateThemeLayout(key, Number(e.target.value) || 0) })
1155
- ] }, key))
1156
- ] })
1353
+ // src/components/DesignPanel.tsx
1354
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1355
+ function DesignPanel({ chrome, theme, updateThemeColor, updateThemeLayout, resetTheme }) {
1356
+ return /* @__PURE__ */ jsxs4("div", { children: [
1357
+ /* @__PURE__ */ jsxs4("div", { style: styles.layoutPanelHeader, children: [
1358
+ /* @__PURE__ */ jsx4("span", { style: { fontWeight: 600, fontSize: 13 }, children: chrome.theme }),
1359
+ /* @__PURE__ */ jsxs4("button", { type: "button", style: styles.resetLinkBtn, onClick: resetTheme, children: [
1360
+ /* @__PURE__ */ jsx4(RotateCcw, { size: 11 }),
1361
+ " ",
1362
+ chrome.reset
1363
+ ] })
1364
+ ] }),
1365
+ /* @__PURE__ */ jsx4("label", { style: styles.propLabel, children: chrome.primaryColor }),
1366
+ /* @__PURE__ */ jsxs4("div", { style: styles.swatchRow, children: [
1367
+ BUTTON_COLOR_SWATCHES.slice(1).map((c) => /* @__PURE__ */ jsx4("button", { type: "button", title: c, style: { ...styles.swatchBtn, background: c, ...theme.primary === c ? styles.swatchBtnActive : {} }, onClick: () => updateThemeColor("primary", c) }, c)),
1368
+ /* @__PURE__ */ jsx4("input", { type: "color", value: theme.primary, onChange: (e) => updateThemeColor("primary", e.target.value), style: styles.colorPickerInput })
1369
+ ] }),
1370
+ /* @__PURE__ */ jsx4("label", { style: styles.propLabel, children: chrome.pageBackground }),
1371
+ /* @__PURE__ */ jsxs4("div", { style: styles.swatchRow, children: [
1372
+ SECTION_BG_SWATCHES.filter(Boolean).map((c) => /* @__PURE__ */ jsx4("button", { type: "button", title: c, style: { ...styles.swatchBtn, background: c, ...theme.pageBackground === c ? styles.swatchBtnActive : {} }, onClick: () => updateThemeColor("pageBackground", c) }, c)),
1373
+ /* @__PURE__ */ jsx4("input", { type: "color", value: theme.pageBackground, onChange: (e) => updateThemeColor("pageBackground", e.target.value), style: styles.colorPickerInput })
1374
+ ] }),
1375
+ /* @__PURE__ */ jsx4("label", { style: styles.propLabel, children: chrome.maxWidthPx }),
1376
+ /* @__PURE__ */ jsx4("input", { type: "number", style: styles.propInput, value: theme.layout.maxWidth, onChange: (e) => updateThemeLayout("maxWidth", Number(e.target.value) || DEFAULT_THEME.layout.maxWidth) }),
1377
+ /* @__PURE__ */ jsx4("div", { style: styles.inspectorDivider }),
1378
+ /* @__PURE__ */ jsx4("div", { style: styles.panelHeading, children: chrome.spacing }),
1379
+ SPACING_FIELDS.map(({ key, labelKey }) => /* @__PURE__ */ jsxs4("div", { style: styles.spacingRow, children: [
1380
+ /* @__PURE__ */ jsx4("span", { style: styles.spacingLabel, children: chrome[labelKey] }),
1381
+ /* @__PURE__ */ jsx4("input", { type: "number", style: styles.spacingInput, value: theme.layout[key], onChange: (e) => updateThemeLayout(key, Number(e.target.value) || 0) })
1382
+ ] }, key))
1157
1383
  ] });
1158
1384
  }
1159
1385
 
1160
- // src/components/Toolbar.tsx
1161
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1162
- function Toolbar({
1163
- title,
1164
- language,
1165
- languages,
1166
- mode,
1167
- saveState,
1386
+ // src/components/Palette.tsx
1387
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1388
+ function Palette({
1389
+ activeSectionLabel,
1168
1390
  chrome,
1169
- themeEditable,
1391
+ onAddField,
1392
+ features,
1170
1393
  theme,
1171
- savedFormsCount,
1172
- onTitleChange,
1173
- onLanguageChange,
1174
- onModeChange,
1175
- onOpenSettings,
1176
- onNewForm,
1177
- onOpenLibrary,
1178
- onSaveExisting,
1179
- onOpenJson,
1180
1394
  updateThemeColor,
1181
1395
  updateThemeLayout,
1182
1396
  resetTheme
1183
1397
  }) {
1184
- return /* @__PURE__ */ jsxs3("div", { style: styles.toolbar, children: [
1185
- /* @__PURE__ */ jsxs3("div", { style: styles.toolbarLeft, children: [
1186
- /* @__PURE__ */ jsx3("div", { style: styles.logoMark, children: "FB" }),
1187
- /* @__PURE__ */ jsx3("input", { value: t(title, language), onChange: (e) => onTitleChange(e.target.value), style: styles.titleInput, "aria-label": "Form title" })
1188
- ] }),
1189
- /* @__PURE__ */ jsxs3("div", { style: styles.toolbarRight, children: [
1190
- /* @__PURE__ */ jsxs3("span", { style: styles.saveStatus, children: [
1191
- saveState === "saving" && /* @__PURE__ */ jsxs3(Fragment, { children: [
1192
- /* @__PURE__ */ jsx3(Loader2, { size: 12, className: "spin" }),
1193
- " ",
1194
- chrome.saving
1195
- ] }),
1196
- saveState === "saved" && chrome.saved,
1197
- saveState === "error" && /* @__PURE__ */ jsxs3("span", { style: { color: "var(--fb-danger)", display: "flex", alignItems: "center", gap: 4 }, children: [
1198
- /* @__PURE__ */ jsx3(AlertCircle, { size: 12 }),
1199
- " ",
1200
- chrome.saveFailed
1201
- ] })
1202
- ] }),
1203
- /* @__PURE__ */ jsx3("div", { style: styles.toolbarDivider }),
1204
- /* @__PURE__ */ jsx3(Languages, { size: 14, color: "var(--fb-muted)" }),
1205
- /* @__PURE__ */ jsx3(Segmented, { options: languages.map((l) => ({ value: l.code, label: l.label })), value: language, onChange: onLanguageChange }),
1206
- /* @__PURE__ */ jsx3("div", { style: styles.toolbarDivider }),
1207
- /* @__PURE__ */ jsxs3("button", { style: mode === "build" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("build"), children: [
1208
- /* @__PURE__ */ jsx3(Pencil, { size: 14 }),
1209
- " ",
1210
- chrome.build
1211
- ] }),
1212
- /* @__PURE__ */ jsxs3("button", { style: mode === "preview" ? styles.tabBtnActive : styles.tabBtn, onClick: () => onModeChange("preview"), children: [
1213
- /* @__PURE__ */ jsx3(Eye, { size: 14 }),
1214
- " ",
1215
- chrome.preview
1216
- ] }),
1217
- /* @__PURE__ */ jsx3("div", { style: styles.toolbarDivider }),
1218
- themeEditable && /* @__PURE__ */ jsx3(LayoutPopover, { chrome, theme, updateThemeColor, updateThemeLayout, resetTheme }),
1219
- /* @__PURE__ */ jsx3("button", { style: styles.iconBtn, title: chrome.settings, onClick: onOpenSettings, children: /* @__PURE__ */ jsx3(Settings, { size: 14 }) }),
1220
- /* @__PURE__ */ jsxs3("button", { style: styles.ghostBtn, onClick: onNewForm, title: chrome.startNewForm, children: [
1221
- /* @__PURE__ */ jsx3(FilePlus2, { size: 14 }),
1222
- " ",
1223
- chrome.newForm
1224
- ] }),
1225
- /* @__PURE__ */ jsxs3("button", { style: styles.ghostBtn, onClick: onOpenLibrary, title: chrome.openSavedForm, children: [
1226
- /* @__PURE__ */ jsx3(FolderOpen, { size: 14 }),
1398
+ const [tab, setTab] = useState5("blocks");
1399
+ const contentTypes = CONTENT_TYPES.filter((f) => isContentBlockEnabled(features, f.type));
1400
+ const formTypes = FORM_TYPES.filter((f) => isFieldTypeEnabled(features, f.type));
1401
+ return /* @__PURE__ */ jsxs5("div", { className: "fb-palette", style: styles.palette, children: [
1402
+ features.design && /* @__PURE__ */ jsx5("div", { style: { marginBottom: 14 }, children: /* @__PURE__ */ jsx5(
1403
+ Segmented,
1404
+ {
1405
+ options: [
1406
+ { value: "blocks", label: chrome.paletteTabBlocks },
1407
+ { value: "design", label: chrome.paletteTabDesign }
1408
+ ],
1409
+ value: tab,
1410
+ onChange: setTab
1411
+ }
1412
+ ) }),
1413
+ tab === "design" && features.design ? /* @__PURE__ */ jsx5(
1414
+ DesignPanel,
1415
+ {
1416
+ chrome,
1417
+ theme,
1418
+ updateThemeColor,
1419
+ updateThemeLayout,
1420
+ resetTheme
1421
+ }
1422
+ ) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
1423
+ /* @__PURE__ */ jsxs5("div", { style: styles.activeSectionHint, children: [
1424
+ chrome.addingTo,
1227
1425
  " ",
1228
- chrome.myForms,
1229
- savedFormsCount > 0 && /* @__PURE__ */ jsx3("span", { style: styles.countBadge, children: savedFormsCount })
1426
+ /* @__PURE__ */ jsx5("strong", { children: activeSectionLabel })
1230
1427
  ] }),
1231
- /* @__PURE__ */ jsxs3("button", { style: styles.primaryBtn, onClick: onSaveExisting, title: chrome.saveToLibraryTitle, children: [
1232
- /* @__PURE__ */ jsx3(Save, { size: 14 }),
1233
- " ",
1234
- chrome.save
1428
+ contentTypes.length > 0 && /* @__PURE__ */ jsxs5(Fragment2, { children: [
1429
+ /* @__PURE__ */ jsx5("div", { style: styles.panelHeading, children: chrome.contentBlocks }),
1430
+ /* @__PURE__ */ jsx5("div", { style: styles.paletteList, children: contentTypes.map((f) => {
1431
+ const Icon = f.icon;
1432
+ return /* @__PURE__ */ jsxs5("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1433
+ /* @__PURE__ */ jsx5(Icon, { size: 16, color: "var(--fb-primary)" }),
1434
+ /* @__PURE__ */ jsx5("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1435
+ /* @__PURE__ */ jsx5(Plus, { size: 13, color: "var(--fb-muted)", style: { marginLeft: "auto" } })
1436
+ ] }, f.type);
1437
+ }) })
1235
1438
  ] }),
1236
- /* @__PURE__ */ jsxs3("button", { style: styles.ghostBtn, onClick: onOpenJson, children: [
1237
- /* @__PURE__ */ jsx3(Code2, { size: 14 }),
1238
- " ",
1239
- chrome.viewJson
1439
+ formTypes.length > 0 && /* @__PURE__ */ jsxs5(Fragment2, { children: [
1440
+ /* @__PURE__ */ jsx5("div", { style: { ...styles.panelHeading, marginTop: 16 }, children: chrome.formFields }),
1441
+ /* @__PURE__ */ jsx5("div", { style: styles.paletteList, children: formTypes.map((f) => {
1442
+ const Icon = f.icon;
1443
+ return /* @__PURE__ */ jsxs5("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1444
+ /* @__PURE__ */ jsx5(Icon, { size: 16, color: "var(--fb-primary)" }),
1445
+ /* @__PURE__ */ jsx5("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1446
+ /* @__PURE__ */ jsx5(Plus, { size: 13, color: "var(--fb-muted)", style: { marginLeft: "auto" } })
1447
+ ] }, f.type);
1448
+ }) })
1240
1449
  ] })
1241
1450
  ] })
1242
1451
  ] });
1243
1452
  }
1244
1453
 
1245
- // src/components/Palette.tsx
1246
- import { Plus } from "lucide-react";
1247
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1248
- function Palette({ activeSectionLabel, chrome, onAddField }) {
1249
- return /* @__PURE__ */ jsxs4("div", { style: styles.palette, children: [
1250
- /* @__PURE__ */ jsxs4("div", { style: styles.activeSectionHint, children: [
1251
- chrome.addingTo,
1252
- " ",
1253
- /* @__PURE__ */ jsx4("strong", { children: activeSectionLabel })
1254
- ] }),
1255
- /* @__PURE__ */ jsx4("div", { style: styles.panelHeading, children: chrome.contentBlocks }),
1256
- /* @__PURE__ */ jsx4("div", { style: styles.paletteList, children: CONTENT_TYPES.map((f) => {
1257
- const Icon = f.icon;
1258
- return /* @__PURE__ */ jsxs4("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1259
- /* @__PURE__ */ jsx4(Icon, { size: 16, color: "var(--fb-primary)" }),
1260
- /* @__PURE__ */ jsx4("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1261
- /* @__PURE__ */ jsx4(Plus, { size: 13, color: "#A6A8B3", style: { marginLeft: "auto" } })
1262
- ] }, f.type);
1263
- }) }),
1264
- /* @__PURE__ */ jsx4("div", { style: { ...styles.panelHeading, marginTop: 16 }, children: chrome.formFields }),
1265
- /* @__PURE__ */ jsx4("div", { style: styles.paletteList, children: FORM_TYPES.map((f) => {
1266
- const Icon = f.icon;
1267
- return /* @__PURE__ */ jsxs4("button", { style: styles.paletteItem, onClick: () => onAddField(f.type), children: [
1268
- /* @__PURE__ */ jsx4(Icon, { size: 16, color: "var(--fb-primary)" }),
1269
- /* @__PURE__ */ jsx4("span", { children: chrome[FIELD_TYPE_CHROME_KEY[f.type]] }),
1270
- /* @__PURE__ */ jsx4(Plus, { size: 13, color: "#A6A8B3", style: { marginLeft: "auto" } })
1271
- ] }, f.type);
1272
- }) })
1273
- ] });
1274
- }
1275
-
1276
1454
  // src/components/Canvas.tsx
1277
1455
  import { Layers } from "lucide-react";
1278
1456
 
1279
1457
  // src/components/SectionCard.tsx
1280
- import { ChevronDown as ChevronDown3, ChevronRight, Copy as Copy2, ArrowUp as ArrowUp2, ArrowDown as ArrowDown2, Trash2 as Trash22, RotateCcw as RotateCcw2 } from "lucide-react";
1281
-
1282
- // src/constants/submitStyle.ts
1283
- var SUBMIT_SIZE_OPTIONS = [
1284
- { value: "sm", label: "S" },
1285
- { value: "md", label: "M" },
1286
- { value: "lg", label: "L" }
1287
- ];
1288
- var SUBMIT_SIZE_STYLES = {
1289
- sm: { padding: "7px 12px", fontSize: 12.5 },
1290
- md: { padding: "10px 16px", fontSize: 13.5 },
1291
- lg: { padding: "13px 22px", fontSize: 15 }
1292
- };
1293
- function resolveSubmitStyle(style) {
1294
- const sizeStyle = SUBMIT_SIZE_STYLES[style?.size || "md"] || SUBMIT_SIZE_STYLES.md;
1295
- return { ...sizeStyle, background: style?.color || "var(--fb-primary)" };
1296
- }
1458
+ import { ChevronDown as ChevronDown3, ChevronRight, Copy as Copy2, ArrowUp as ArrowUp2, ArrowDown as ArrowDown2, Trash2 as Trash22 } from "lucide-react";
1297
1459
 
1298
1460
  // src/components/FieldTicket.tsx
1299
1461
  import { ArrowUp, ArrowDown, Copy, Trash2, GripVertical } from "lucide-react";
@@ -1379,7 +1541,7 @@ var ICON_LIBRARY = {
1379
1541
 
1380
1542
  // src/components/fields/ImageBlock.tsx
1381
1543
  import { Image as ImageIcon2 } from "lucide-react";
1382
- import { jsx as jsx5 } from "react/jsx-runtime";
1544
+ import { jsx as jsx6 } from "react/jsx-runtime";
1383
1545
  function buildImageStyle(field) {
1384
1546
  const aspectRatio = field.shape === "banner" ? "16 / 5" : "1 / 1";
1385
1547
  return {
@@ -1393,35 +1555,58 @@ function buildImageStyle(field) {
1393
1555
  }
1394
1556
  function ImageBlock({ field, lang }) {
1395
1557
  const shapeStyle = buildImageStyle(field);
1396
- const img = field.src ? /* @__PURE__ */ jsx5("img", { src: field.src, alt: t(field.alt, lang || "en"), style: shapeStyle }) : /* @__PURE__ */ jsx5("div", { style: { ...shapeStyle, ...styles.imagePlaceholder }, children: /* @__PURE__ */ jsx5(ImageIcon2, { size: 20, color: "var(--fb-muted)" }) });
1397
- return field.link ? /* @__PURE__ */ jsx5("a", { href: field.link, target: "_blank", rel: "noreferrer", style: { display: "block" }, children: img }) : img;
1558
+ const img = field.src ? /* @__PURE__ */ jsx6("img", { src: field.src, alt: t(field.alt, lang || "en"), style: shapeStyle }) : /* @__PURE__ */ jsx6("div", { style: { ...shapeStyle, ...styles.imagePlaceholder }, children: /* @__PURE__ */ jsx6(ImageIcon2, { size: 20, color: "var(--fb-muted)" }) });
1559
+ return field.link ? /* @__PURE__ */ jsx6("a", { href: field.link, target: "_blank", rel: "noreferrer", style: { display: "block" }, children: img }) : img;
1560
+ }
1561
+
1562
+ // src/constants/submitStyle.ts
1563
+ var SUBMIT_SIZE_OPTIONS = [
1564
+ { value: "sm", label: "S" },
1565
+ { value: "md", label: "M" },
1566
+ { value: "lg", label: "L" }
1567
+ ];
1568
+ var SUBMIT_SIZE_STYLES = {
1569
+ sm: { padding: "7px 12px", fontSize: 12.5 },
1570
+ md: { padding: "10px 16px", fontSize: 13.5 },
1571
+ lg: { padding: "13px 22px", fontSize: 15 }
1572
+ };
1573
+ function resolveSubmitStyle(style) {
1574
+ const sizeStyle = SUBMIT_SIZE_STYLES[style?.size || "md"] || SUBMIT_SIZE_STYLES.md;
1575
+ return { ...sizeStyle, background: style?.color || "var(--fb-primary)" };
1576
+ }
1577
+
1578
+ // src/components/fields/ButtonBlock.tsx
1579
+ import { jsx as jsx7 } from "react/jsx-runtime";
1580
+ function ButtonBlock({ field, lang, onAction }) {
1581
+ return /* @__PURE__ */ jsx7("button", { type: "button", style: { ...styles.submitBtn, ...resolveSubmitStyle(field.buttonStyle) }, onClick: () => onAction?.(field), children: t(field.label, lang) || "..." });
1398
1582
  }
1399
1583
 
1400
1584
  // src/components/fields/FieldBlock.tsx
1401
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1402
- function FieldBlock({ field, lang, onFieldChange, strings, chrome, error, isBuild }) {
1403
- if (field.type === "image") return /* @__PURE__ */ jsx6(ImageBlock, { field, lang });
1585
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
1586
+ function FieldBlock({ field, lang, onFieldChange, strings, chrome, error, isBuild, onButtonAction }) {
1587
+ if (field.type === "image") return /* @__PURE__ */ jsx8(ImageBlock, { field, lang });
1588
+ if (field.type === "button") return /* @__PURE__ */ jsx8(ButtonBlock, { field, lang, onAction: onButtonAction });
1404
1589
  if (field.type === "paragraph") {
1405
1590
  const fontPx = FONT_SIZE_OPTIONS.find((f) => f.value === field.fontSize)?.px || 14;
1406
1591
  const Tag = TAG_TO_ELEMENT[field.tag] || "p";
1407
- return /* @__PURE__ */ jsx6(Tag, { style: { margin: 0, whiteSpace: "pre-wrap", fontSize: fontPx, fontWeight: field.fontWeight === "bold" ? 700 : 400, fontStyle: field.fontStyle === "italic" ? "italic" : "normal", textAlign: field.textAlign || "left", color: field.color || "var(--fb-ink)", lineHeight: 1.6 }, children: t(field.content, lang) || "..." });
1592
+ return /* @__PURE__ */ jsx8(Tag, { style: { margin: 0, whiteSpace: "pre-wrap", fontSize: fontPx, fontWeight: field.fontWeight === "bold" ? 700 : 400, fontStyle: field.fontStyle === "italic" ? "italic" : "normal", textAlign: field.textAlign || "left", color: field.color || "var(--fb-ink)", lineHeight: 1.6 }, children: t(field.content, lang) || "..." });
1408
1593
  }
1409
1594
  const meta = getMeta(field.type);
1410
1595
  const IconComp = field.showIcon && field.displayIcon ? ICON_LIBRARY[field.displayIcon] : null;
1411
1596
  const isInline = field.labelPosition === "inline" && !meta.boolean;
1412
1597
  const labelText = t(field.label, lang);
1413
1598
  const showLabel = !meta.boolean && !field.hideLabel;
1414
- return /* @__PURE__ */ jsxs5("div", { children: [
1415
- /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: isInline ? "row" : "column", alignItems: isInline ? "center" : "stretch", gap: isInline ? 10 : 6 }, children: [
1416
- showLabel && /* @__PURE__ */ jsxs5("label", { style: { ...styles.previewLabel, marginBottom: isInline ? 0 : 6, flexShrink: 0, width: isInline ? 120 : "auto", display: "flex", alignItems: "center", gap: 6 }, children: [
1417
- IconComp && /* @__PURE__ */ jsx6(IconComp, { size: 14, color: "#6B6E79" }),
1418
- labelText || (isBuild ? /* @__PURE__ */ jsx6("span", { style: { fontStyle: "italic", color: "var(--fb-muted)" }, children: chrome?.untitledField || "Untitled field" }) : ""),
1419
- field.required && /* @__PURE__ */ jsx6("span", { style: { color: "var(--fb-danger)" }, children: " *" })
1599
+ return /* @__PURE__ */ jsxs6("div", { children: [
1600
+ /* @__PURE__ */ jsxs6("div", { style: { display: "flex", flexDirection: isInline ? "row" : "column", alignItems: isInline ? "center" : "stretch", gap: isInline ? 10 : 6 }, children: [
1601
+ showLabel && /* @__PURE__ */ jsxs6("label", { style: { ...styles.previewLabel, marginBottom: isInline ? 0 : 6, flexShrink: 0, width: isInline ? 120 : "auto", display: "flex", alignItems: "center", gap: 6 }, children: [
1602
+ IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "var(--fb-muted)" }),
1603
+ labelText || (isBuild ? /* @__PURE__ */ jsx8("span", { style: { fontStyle: "italic", color: "var(--fb-muted)" }, children: chrome?.untitledField || "Untitled field" }) : ""),
1604
+ field.required && /* @__PURE__ */ jsx8("span", { style: { color: "var(--fb-danger)" }, children: " *" })
1420
1605
  ] }),
1421
- /* @__PURE__ */ jsx6("div", { style: { flex: 1, minWidth: 0 }, children: renderInteractive(field, lang, onFieldChange, IconComp, !!error, strings) })
1606
+ /* @__PURE__ */ jsx8("div", { style: { flex: 1, minWidth: 0 }, children: renderInteractive(field, lang, onFieldChange, IconComp, !!error, strings) })
1422
1607
  ] }),
1423
- error && /* @__PURE__ */ jsxs5("div", { style: styles.fieldError, children: [
1424
- /* @__PURE__ */ jsx6(CircleAlert, { size: 12 }),
1608
+ error && /* @__PURE__ */ jsxs6("div", { style: styles.fieldError, children: [
1609
+ /* @__PURE__ */ jsx8(CircleAlert, { size: 12 }),
1425
1610
  " ",
1426
1611
  error
1427
1612
  ] })
@@ -1435,40 +1620,40 @@ function renderInteractive(field, lang, onFieldChange, IconComp, hasError, strin
1435
1620
  if (field.type === "input") {
1436
1621
  switch (field.inputType) {
1437
1622
  case "number":
1438
- return /* @__PURE__ */ jsx6("input", { type: "number", ...common, min: field.min ?? void 0, max: field.max ?? void 0 });
1623
+ return /* @__PURE__ */ jsx8("input", { type: "number", ...common, min: field.min ?? void 0, max: field.max ?? void 0 });
1439
1624
  case "email":
1440
- return /* @__PURE__ */ jsx6("input", { type: "email", ...common });
1625
+ return /* @__PURE__ */ jsx8("input", { type: "email", ...common });
1441
1626
  case "password":
1442
- return /* @__PURE__ */ jsx6("input", { type: "password", ...common, maxLength: field.maxLength || void 0 });
1627
+ return /* @__PURE__ */ jsx8("input", { type: "password", ...common, maxLength: field.maxLength || void 0 });
1443
1628
  case "phone":
1444
- return /* @__PURE__ */ jsx6("input", { type: "tel", ...common });
1629
+ return /* @__PURE__ */ jsx8("input", { type: "tel", ...common });
1445
1630
  case "date":
1446
- return /* @__PURE__ */ jsx6("input", { type: "date", ...common });
1631
+ return /* @__PURE__ */ jsx8("input", { type: "date", ...common });
1447
1632
  case "time":
1448
- return /* @__PURE__ */ jsx6("input", { type: "time", ...common });
1633
+ return /* @__PURE__ */ jsx8("input", { type: "time", ...common });
1449
1634
  default:
1450
- return /* @__PURE__ */ jsx6("input", { type: "text", ...common, maxLength: field.maxLength || void 0 });
1635
+ return /* @__PURE__ */ jsx8("input", { type: "text", ...common, maxLength: field.maxLength || void 0 });
1451
1636
  }
1452
1637
  }
1453
1638
  switch (field.type) {
1454
1639
  case "textarea":
1455
- return /* @__PURE__ */ jsx6("textarea", { ...common, rows: 3, maxLength: field.maxLength || void 0 });
1640
+ return /* @__PURE__ */ jsx8("textarea", { ...common, rows: 3, maxLength: field.maxLength || void 0 });
1456
1641
  case "select":
1457
- return /* @__PURE__ */ jsxs5("select", { style: inputStyle, value: value || "", onChange: (e) => set(e.target.value), children: [
1458
- /* @__PURE__ */ jsx6("option", { value: "", children: strings.selectPlaceholder }),
1459
- (field.options || []).map((o) => /* @__PURE__ */ jsx6("option", { value: o.value, children: t(o.label, lang) }, o.value))
1642
+ return /* @__PURE__ */ jsxs6("select", { style: inputStyle, value: value || "", onChange: (e) => set(e.target.value), children: [
1643
+ /* @__PURE__ */ jsx8("option", { value: "", children: strings.selectPlaceholder }),
1644
+ (field.options || []).map((o) => /* @__PURE__ */ jsx8("option", { value: o.value, children: t(o.label, lang) }, o.value))
1460
1645
  ] });
1461
1646
  case "radio":
1462
- return /* @__PURE__ */ jsx6("div", { style: { display: "flex", gap: 16, flexWrap: "wrap", marginTop: 4 }, children: (field.options || []).map((o) => /* @__PURE__ */ jsxs5("label", { style: styles.previewRadio, children: [
1463
- /* @__PURE__ */ jsx6("input", { type: "radio", name: field.id, value: o.value, checked: value === o.value, onChange: (e) => set(e.target.value) }),
1647
+ return /* @__PURE__ */ jsx8("div", { style: { display: "flex", gap: 16, flexWrap: "wrap", marginTop: 4 }, children: (field.options || []).map((o) => /* @__PURE__ */ jsxs6("label", { style: styles.previewRadio, children: [
1648
+ /* @__PURE__ */ jsx8("input", { type: "radio", name: field.id, value: o.value, checked: value === o.value, onChange: (e) => set(e.target.value) }),
1464
1649
  t(o.label, lang)
1465
1650
  ] }, o.value)) });
1466
1651
  case "checkboxGroup": {
1467
1652
  const vals = Array.isArray(value) ? value : [];
1468
- return /* @__PURE__ */ jsx6("div", { style: { display: "flex", gap: 16, flexWrap: "wrap", marginTop: 4 }, children: (field.options || []).map((o) => {
1653
+ return /* @__PURE__ */ jsx8("div", { style: { display: "flex", gap: 16, flexWrap: "wrap", marginTop: 4 }, children: (field.options || []).map((o) => {
1469
1654
  const checked = vals.includes(o.value);
1470
- return /* @__PURE__ */ jsxs5("label", { style: styles.previewRadio, children: [
1471
- /* @__PURE__ */ jsx6("input", { type: "checkbox", checked, onChange: (e) => {
1655
+ return /* @__PURE__ */ jsxs6("label", { style: styles.previewRadio, children: [
1656
+ /* @__PURE__ */ jsx8("input", { type: "checkbox", checked, onChange: (e) => {
1472
1657
  const next = e.target.checked ? [...vals, o.value] : vals.filter((v) => v !== o.value);
1473
1658
  set(next);
1474
1659
  }, style: { accentColor: "var(--fb-primary)" } }),
@@ -1477,25 +1662,25 @@ function renderInteractive(field, lang, onFieldChange, IconComp, hasError, strin
1477
1662
  }) });
1478
1663
  }
1479
1664
  case "checkbox":
1480
- return /* @__PURE__ */ jsxs5("label", { style: styles.previewRadio, children: [
1481
- /* @__PURE__ */ jsx6("input", { type: "checkbox", checked: !!value, onChange: (e) => set(e.target.checked), style: { accentColor: "var(--fb-primary)" } }),
1482
- IconComp && /* @__PURE__ */ jsx6(IconComp, { size: 14, color: "#6B6E79" }),
1665
+ return /* @__PURE__ */ jsxs6("label", { style: styles.previewRadio, children: [
1666
+ /* @__PURE__ */ jsx8("input", { type: "checkbox", checked: !!value, onChange: (e) => set(e.target.checked), style: { accentColor: "var(--fb-primary)" } }),
1667
+ IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "var(--fb-muted)" }),
1483
1668
  t(field.label, lang),
1484
- field.required && /* @__PURE__ */ jsx6("span", { style: { color: "var(--fb-danger)" }, children: " *" })
1669
+ field.required && /* @__PURE__ */ jsx8("span", { style: { color: "var(--fb-danger)" }, children: " *" })
1485
1670
  ] });
1486
1671
  case "toggle":
1487
- return /* @__PURE__ */ jsxs5("label", { style: styles.previewRadio, children: [
1488
- /* @__PURE__ */ jsx6("input", { type: "checkbox", checked: !!value, onChange: (e) => set(e.target.checked), style: { accentColor: "var(--fb-primary)" } }),
1489
- IconComp && /* @__PURE__ */ jsx6(IconComp, { size: 14, color: "#6B6E79" }),
1672
+ return /* @__PURE__ */ jsxs6("label", { style: styles.previewRadio, children: [
1673
+ /* @__PURE__ */ jsx8("input", { type: "checkbox", checked: !!value, onChange: (e) => set(e.target.checked), style: { accentColor: "var(--fb-primary)" } }),
1674
+ IconComp && /* @__PURE__ */ jsx8(IconComp, { size: 14, color: "var(--fb-muted)" }),
1490
1675
  t(field.label, lang)
1491
1676
  ] });
1492
1677
  default:
1493
- return /* @__PURE__ */ jsx6("input", { type: "text", ...common });
1678
+ return /* @__PURE__ */ jsx8("input", { type: "text", ...common });
1494
1679
  }
1495
1680
  }
1496
1681
 
1497
1682
  // src/components/FieldTicket.tsx
1498
- import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1683
+ import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1499
1684
  function FieldTicket({
1500
1685
  field,
1501
1686
  idx,
@@ -1504,6 +1689,7 @@ function FieldTicket({
1504
1689
  chrome,
1505
1690
  strings,
1506
1691
  language,
1692
+ dragEnabled,
1507
1693
  onSelect,
1508
1694
  onFieldChange,
1509
1695
  onMoveField,
@@ -1515,7 +1701,7 @@ function FieldTicket({
1515
1701
  const meta = getMeta(field.type);
1516
1702
  const Icon = meta.icon;
1517
1703
  const widthPct = WIDTH_PERCENT[field.width || "1/1"];
1518
- return /* @__PURE__ */ jsxs6(
1704
+ return /* @__PURE__ */ jsxs7(
1519
1705
  "div",
1520
1706
  {
1521
1707
  ...dropZoneHandlers,
@@ -1529,35 +1715,35 @@ function FieldTicket({
1529
1715
  ...isDragOver ? styles.ticketDragOver : {}
1530
1716
  },
1531
1717
  children: [
1532
- /* @__PURE__ */ jsx7("div", { style: styles.ticketIndex, children: String(idx + 1).padStart(2, "0") }),
1533
- /* @__PURE__ */ jsx7("div", { style: styles.ticketPerforation }),
1534
- /* @__PURE__ */ jsxs6("div", { style: styles.ticketBody, children: [
1535
- /* @__PURE__ */ jsxs6("div", { style: styles.ticketTop, children: [
1536
- /* @__PURE__ */ jsx7("span", { ...dragHandleProps, style: { cursor: "grab", display: "flex" }, children: /* @__PURE__ */ jsx7(GripVertical, { size: 14, color: "#C4C6D0" }) }),
1537
- /* @__PURE__ */ jsx7(Icon, { size: 13, color: "var(--fb-primary)" }),
1538
- /* @__PURE__ */ jsxs6("span", { style: styles.typeBadge, children: [
1718
+ /* @__PURE__ */ jsx9("div", { style: styles.ticketIndex, children: String(idx + 1).padStart(2, "0") }),
1719
+ /* @__PURE__ */ jsx9("div", { style: styles.ticketPerforation }),
1720
+ /* @__PURE__ */ jsxs7("div", { style: styles.ticketBody, children: [
1721
+ /* @__PURE__ */ jsxs7("div", { style: styles.ticketTop, children: [
1722
+ dragEnabled && /* @__PURE__ */ jsx9("span", { ...dragHandleProps, style: { cursor: "grab", display: "flex" }, children: /* @__PURE__ */ jsx9(GripVertical, { size: 14, color: "var(--fb-muted)" }) }),
1723
+ /* @__PURE__ */ jsx9(Icon, { size: 13, color: "var(--fb-primary)" }),
1724
+ /* @__PURE__ */ jsxs7("span", { style: styles.typeBadge, children: [
1539
1725
  chrome[FIELD_TYPE_CHROME_KEY[field.type]] || field.type,
1540
1726
  field.type === "input" && field.inputType && field.inputType !== "text" ? ` \xB7 ${chrome[INPUT_SUBTYPE_CHROME_KEY[field.inputType]]}` : ""
1541
1727
  ] }),
1542
- field.required && /* @__PURE__ */ jsx7("span", { style: styles.requiredBadge, children: chrome.required })
1728
+ field.required && /* @__PURE__ */ jsx9("span", { style: styles.requiredBadge, children: chrome.required })
1543
1729
  ] }),
1544
- field.width && field.width !== "1/1" || field.labelPosition === "inline" || field.verticalAlign !== "top" || field.hideLabel ? /* @__PURE__ */ jsxs6("div", { style: styles.chipRow, children: [
1545
- field.width && field.width !== "1/1" && /* @__PURE__ */ jsxs6("span", { style: styles.miniBadge, children: [
1730
+ field.width && field.width !== "1/1" || field.labelPosition === "inline" || field.verticalAlign !== "top" || field.hideLabel ? /* @__PURE__ */ jsxs7("div", { style: styles.chipRow, children: [
1731
+ field.width && field.width !== "1/1" && /* @__PURE__ */ jsxs7("span", { style: styles.miniBadge, children: [
1546
1732
  chrome.width,
1547
1733
  " ",
1548
1734
  field.width
1549
1735
  ] }),
1550
- field.labelPosition === "inline" && /* @__PURE__ */ jsx7("span", { style: styles.miniBadge, children: chrome.inline }),
1551
- field.verticalAlign !== "top" && /* @__PURE__ */ jsx7("span", { style: styles.miniBadge, children: chrome[field.verticalAlign] }),
1552
- field.hideLabel && /* @__PURE__ */ jsx7("span", { style: styles.miniBadge, children: chrome.hideLabel })
1736
+ field.labelPosition === "inline" && /* @__PURE__ */ jsx9("span", { style: styles.miniBadge, children: chrome.inline }),
1737
+ field.verticalAlign !== "top" && /* @__PURE__ */ jsx9("span", { style: styles.miniBadge, children: chrome[field.verticalAlign] }),
1738
+ field.hideLabel && /* @__PURE__ */ jsx9("span", { style: styles.miniBadge, children: chrome.hideLabel })
1553
1739
  ] }) : null,
1554
- /* @__PURE__ */ jsx7("div", { style: { marginTop: 8 }, children: /* @__PURE__ */ jsx7(FieldBlock, { field, lang: language, onFieldChange, strings, chrome, isBuild: true }) })
1740
+ /* @__PURE__ */ jsx9("div", { style: { marginTop: 8 }, children: /* @__PURE__ */ jsx9(FieldBlock, { field, lang: language, onFieldChange, strings, chrome, isBuild: true }) })
1555
1741
  ] }),
1556
- /* @__PURE__ */ jsxs6("div", { style: styles.ticketActions, onClick: (e) => e.stopPropagation(), children: [
1557
- /* @__PURE__ */ jsx7("button", { style: styles.iconBtn, title: chrome.moveUp, onClick: () => onMoveField(field.id, -1), children: /* @__PURE__ */ jsx7(ArrowUp, { size: 13 }) }),
1558
- /* @__PURE__ */ jsx7("button", { style: styles.iconBtn, title: chrome.moveDown, onClick: () => onMoveField(field.id, 1), children: /* @__PURE__ */ jsx7(ArrowDown, { size: 13 }) }),
1559
- /* @__PURE__ */ jsx7("button", { style: styles.iconBtn, title: chrome.duplicate, onClick: () => onDuplicateField(field.id), children: /* @__PURE__ */ jsx7(Copy, { size: 13 }) }),
1560
- /* @__PURE__ */ jsx7("button", { style: { ...styles.iconBtn, ...styles.iconBtnDanger }, title: chrome.delete, onClick: () => onDeleteField(field.id), children: /* @__PURE__ */ jsx7(Trash2, { size: 13 }) })
1742
+ /* @__PURE__ */ jsxs7("div", { style: styles.ticketActions, onClick: (e) => e.stopPropagation(), children: [
1743
+ /* @__PURE__ */ jsx9("button", { style: styles.iconBtn, title: chrome.moveUp, onClick: () => onMoveField(field.id, -1), children: /* @__PURE__ */ jsx9(ArrowUp, { size: 13 }) }),
1744
+ /* @__PURE__ */ jsx9("button", { style: styles.iconBtn, title: chrome.moveDown, onClick: () => onMoveField(field.id, 1), children: /* @__PURE__ */ jsx9(ArrowDown, { size: 13 }) }),
1745
+ /* @__PURE__ */ jsx9("button", { style: styles.iconBtn, title: chrome.duplicate, onClick: () => onDuplicateField(field.id), children: /* @__PURE__ */ jsx9(Copy, { size: 13 }) }),
1746
+ /* @__PURE__ */ jsx9("button", { style: { ...styles.iconBtn, ...styles.iconBtnDanger }, title: chrome.delete, onClick: () => onDeleteField(field.id), children: /* @__PURE__ */ jsx9(Trash2, { size: 13 }) })
1561
1747
  ] })
1562
1748
  ]
1563
1749
  }
@@ -1565,19 +1751,18 @@ function FieldTicket({
1565
1751
  }
1566
1752
 
1567
1753
  // src/components/SectionCard.tsx
1568
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1754
+ import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1569
1755
  function SectionCard({
1570
1756
  section,
1571
1757
  sIdx,
1572
1758
  sectionsLength,
1573
1759
  isActive,
1574
- submitMode,
1575
- submitStyle,
1576
1760
  selectedId,
1577
1761
  dragOverKey,
1578
1762
  chrome,
1579
1763
  strings,
1580
1764
  language,
1765
+ features,
1581
1766
  onActivate,
1582
1767
  onToggleCollapse,
1583
1768
  onUpdateTitle,
@@ -1585,8 +1770,6 @@ function SectionCard({
1585
1770
  onDuplicateSection,
1586
1771
  onMoveSection,
1587
1772
  onDeleteSection,
1588
- onUpdateSectionSubmitStyle,
1589
- onClearSectionSubmitStyle,
1590
1773
  onSelectField,
1591
1774
  onFieldChange,
1592
1775
  onMoveField,
@@ -1595,19 +1778,19 @@ function SectionCard({
1595
1778
  getDropZoneHandlers,
1596
1779
  getDragHandleProps
1597
1780
  }) {
1598
- return /* @__PURE__ */ jsxs7(
1781
+ return /* @__PURE__ */ jsxs8(
1599
1782
  "div",
1600
1783
  {
1601
1784
  style: { ...styles.sectionBlock, background: section.background || "transparent", border: isActive ? "1px solid var(--fb-primary)" : "1px dashed var(--fb-border)" },
1602
1785
  onClick: onActivate,
1603
1786
  children: [
1604
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeader, children: [
1605
- /* @__PURE__ */ jsx8("button", { style: styles.chevronBtn, onClick: (e) => {
1787
+ /* @__PURE__ */ jsxs8("div", { style: styles.sectionHeader, children: [
1788
+ /* @__PURE__ */ jsx10("button", { style: styles.chevronBtn, onClick: (e) => {
1606
1789
  e.stopPropagation();
1607
1790
  onToggleCollapse();
1608
- }, children: section.collapsed ? /* @__PURE__ */ jsx8(ChevronRight, { size: 15 }) : /* @__PURE__ */ jsx8(ChevronDown3, { size: 15 }) }),
1609
- /* @__PURE__ */ jsx8("span", { style: { ...styles.colorDot, background: section.background || "var(--fb-canvas)" } }),
1610
- /* @__PURE__ */ jsx8(
1791
+ }, children: section.collapsed ? /* @__PURE__ */ jsx10(ChevronRight, { size: 15 }) : /* @__PURE__ */ jsx10(ChevronDown3, { size: 15 }) }),
1792
+ /* @__PURE__ */ jsx10("span", { style: { ...styles.colorDot, background: section.background || "var(--fb-canvas)" } }),
1793
+ /* @__PURE__ */ jsx10(
1611
1794
  "input",
1612
1795
  {
1613
1796
  style: styles.sectionTitleInput,
@@ -1617,29 +1800,21 @@ function SectionCard({
1617
1800
  onClick: (e) => e.stopPropagation()
1618
1801
  }
1619
1802
  ),
1620
- section.collapsed && /* @__PURE__ */ jsx8("span", { style: styles.miniBadge, children: chrome.fieldsCount(section.fields.length) }),
1621
- /* @__PURE__ */ jsxs7("div", { style: styles.sectionHeaderActions, onClick: (e) => e.stopPropagation(), children: [
1622
- !section.collapsed && /* @__PURE__ */ jsxs7("div", { style: styles.swatchRow, children: [
1623
- SECTION_BG_SWATCHES.map((c) => /* @__PURE__ */ jsx8("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")),
1624
- /* @__PURE__ */ jsx8("input", { type: "color", title: chrome.customColor, value: /^#/.test(section.background) ? section.background : "#ffffff", onChange: (e) => onUpdateBackground(e.target.value), style: styles.colorPickerInput })
1803
+ section.collapsed && /* @__PURE__ */ jsx10("span", { style: styles.miniBadge, children: chrome.fieldsCount(section.fields.length) }),
1804
+ /* @__PURE__ */ jsxs8("div", { style: styles.sectionHeaderActions, onClick: (e) => e.stopPropagation(), children: [
1805
+ features.sections && !section.collapsed && /* @__PURE__ */ jsxs8("div", { style: styles.swatchRow, children: [
1806
+ SECTION_BG_SWATCHES.map((c) => /* @__PURE__ */ jsx10("button", { type: "button", title: c || chrome.none, style: { ...styles.swatchBtn, background: c || "var(--fb-canvas)", ...section.background === c ? styles.swatchBtnActive : {} }, onClick: () => onUpdateBackground(c) }, c || "none")),
1807
+ /* @__PURE__ */ jsx10("input", { type: "color", title: chrome.customColor, value: /^#/.test(section.background) ? section.background : "#ffffff", onChange: (e) => onUpdateBackground(e.target.value), style: styles.colorPickerInput })
1625
1808
  ] }),
1626
- /* @__PURE__ */ jsx8("button", { style: styles.iconBtn, title: chrome.duplicate, onClick: onDuplicateSection, children: /* @__PURE__ */ jsx8(Copy2, { size: 13 }) }),
1627
- /* @__PURE__ */ jsx8("button", { style: styles.iconBtn, title: chrome.moveUp, disabled: sIdx === 0, onClick: () => onMoveSection(-1), children: /* @__PURE__ */ jsx8(ArrowUp2, { size: 13 }) }),
1628
- /* @__PURE__ */ jsx8("button", { style: styles.iconBtn, title: chrome.moveDown, disabled: sIdx === sectionsLength - 1, onClick: () => onMoveSection(1), children: /* @__PURE__ */ jsx8(ArrowDown2, { size: 13 }) }),
1629
- /* @__PURE__ */ jsx8("button", { style: { ...styles.iconBtn, ...styles.iconBtnDanger }, title: chrome.deleteSection, disabled: sectionsLength <= 1, onClick: onDeleteSection, children: /* @__PURE__ */ jsx8(Trash22, { size: 13 }) })
1630
- ] })
1631
- ] }),
1632
- !section.collapsed && submitMode === "perSection" && /* @__PURE__ */ jsxs7("div", { style: styles.submitStyleRow, onClick: (e) => e.stopPropagation(), children: [
1633
- /* @__PURE__ */ jsx8("span", { style: styles.miniLabel, children: chrome.submitStyle }),
1634
- /* @__PURE__ */ jsx8("div", { style: styles.swatchRow, children: BUTTON_COLOR_SWATCHES.map((c) => /* @__PURE__ */ jsx8("button", { type: "button", title: c || chrome.none, style: { ...styles.swatchBtn, background: c || "var(--fb-primary)", ...(section.submitStyle?.color || "") === c ? styles.swatchBtnActive : {} }, onClick: () => onUpdateSectionSubmitStyle({ color: c }) }, c || "inherit")) }),
1635
- /* @__PURE__ */ jsx8(Segmented, { options: SUBMIT_SIZE_OPTIONS, value: section.submitStyle?.size || submitStyle.size, onChange: (v) => onUpdateSectionSubmitStyle({ size: v }) }),
1636
- section.submitStyle && /* @__PURE__ */ jsxs7("button", { type: "button", style: styles.resetLinkBtn, onClick: onClearSectionSubmitStyle, children: [
1637
- /* @__PURE__ */ jsx8(RotateCcw2, { size: 11 }),
1638
- " ",
1639
- chrome.reset
1809
+ features.sections && /* @__PURE__ */ jsxs8(Fragment3, { children: [
1810
+ /* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.duplicate, onClick: onDuplicateSection, children: /* @__PURE__ */ jsx10(Copy2, { size: 13 }) }),
1811
+ /* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.moveUp, disabled: sIdx === 0, onClick: () => onMoveSection(-1), children: /* @__PURE__ */ jsx10(ArrowUp2, { size: 13 }) }),
1812
+ /* @__PURE__ */ jsx10("button", { style: styles.iconBtn, title: chrome.moveDown, disabled: sIdx === sectionsLength - 1, onClick: () => onMoveSection(1), children: /* @__PURE__ */ jsx10(ArrowDown2, { size: 13 }) }),
1813
+ /* @__PURE__ */ jsx10("button", { style: { ...styles.iconBtn, ...styles.iconBtnDanger }, title: chrome.deleteSection, disabled: sectionsLength <= 1, onClick: onDeleteSection, children: /* @__PURE__ */ jsx10(Trash22, { size: 13 }) })
1814
+ ] })
1640
1815
  ] })
1641
1816
  ] }),
1642
- !section.collapsed && (section.fields.length === 0 ? /* @__PURE__ */ jsx8("div", { style: styles.sectionEmpty, children: chrome.noFieldsInSection }) : /* @__PURE__ */ jsx8("div", { style: styles.fieldList, children: section.fields.map((field, idx) => /* @__PURE__ */ jsx8(
1817
+ !section.collapsed && (section.fields.length === 0 ? /* @__PURE__ */ jsx10("div", { style: styles.sectionEmpty, children: chrome.noFieldsInSection }) : /* @__PURE__ */ jsx10("div", { style: styles.fieldList, children: section.fields.map((field, idx) => /* @__PURE__ */ jsx10(
1643
1818
  FieldTicket,
1644
1819
  {
1645
1820
  field,
@@ -1650,6 +1825,7 @@ function SectionCard({
1650
1825
  chrome,
1651
1826
  strings,
1652
1827
  language,
1828
+ dragEnabled: features.dragReorder,
1653
1829
  onSelect: () => onSelectField(field.id),
1654
1830
  onFieldChange,
1655
1831
  onMoveField,
@@ -1666,17 +1842,16 @@ function SectionCard({
1666
1842
  }
1667
1843
 
1668
1844
  // src/components/Canvas.tsx
1669
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1845
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1670
1846
  function Canvas({
1671
1847
  sections,
1672
1848
  activeSectionId,
1673
- submitMode,
1674
- submitStyle,
1675
1849
  selectedId,
1676
1850
  dragOverKey,
1677
1851
  chrome,
1678
1852
  strings,
1679
1853
  language,
1854
+ features,
1680
1855
  onActivateSection,
1681
1856
  onToggleSectionCollapse,
1682
1857
  onUpdateSectionTitle,
@@ -1684,8 +1859,6 @@ function Canvas({
1684
1859
  onDuplicateSection,
1685
1860
  onMoveSection,
1686
1861
  onDeleteSection,
1687
- onUpdateSectionSubmitStyle,
1688
- onClearSectionSubmitStyle,
1689
1862
  onAddSection,
1690
1863
  onSelectField,
1691
1864
  onFieldChange,
@@ -1695,21 +1868,20 @@ function Canvas({
1695
1868
  getDropZoneHandlers,
1696
1869
  getDragHandleProps
1697
1870
  }) {
1698
- return /* @__PURE__ */ jsxs8("div", { style: styles.canvas, children: [
1699
- sections.map((section, sIdx) => /* @__PURE__ */ jsx9(
1871
+ return /* @__PURE__ */ jsxs9("div", { className: "fb-canvas", style: styles.canvas, children: [
1872
+ sections.map((section, sIdx) => /* @__PURE__ */ jsx11(
1700
1873
  SectionCard,
1701
1874
  {
1702
1875
  section,
1703
1876
  sIdx,
1704
1877
  sectionsLength: sections.length,
1705
1878
  isActive: activeSectionId === section.id,
1706
- submitMode,
1707
- submitStyle,
1708
1879
  selectedId,
1709
1880
  dragOverKey,
1710
1881
  chrome,
1711
1882
  strings,
1712
1883
  language,
1884
+ features,
1713
1885
  onActivate: () => onActivateSection(section.id),
1714
1886
  onToggleCollapse: () => onToggleSectionCollapse(section.id),
1715
1887
  onUpdateTitle: (value) => onUpdateSectionTitle(section.id, value),
@@ -1717,8 +1889,6 @@ function Canvas({
1717
1889
  onDuplicateSection: () => onDuplicateSection(section.id),
1718
1890
  onMoveSection: (dir) => onMoveSection(section.id, dir),
1719
1891
  onDeleteSection: () => onDeleteSection(section.id),
1720
- onUpdateSectionSubmitStyle: (patch) => onUpdateSectionSubmitStyle(section.id, patch),
1721
- onClearSectionSubmitStyle: () => onClearSectionSubmitStyle(section.id),
1722
1892
  onSelectField: (fieldId) => onSelectField(section.id, fieldId),
1723
1893
  onFieldChange,
1724
1894
  onMoveField,
@@ -1729,8 +1899,8 @@ function Canvas({
1729
1899
  },
1730
1900
  section.id
1731
1901
  )),
1732
- /* @__PURE__ */ jsxs8("button", { style: styles.addSectionBtn, onClick: onAddSection, children: [
1733
- /* @__PURE__ */ jsx9(Layers, { size: 14 }),
1902
+ features.sections && /* @__PURE__ */ jsxs9("button", { style: styles.addSectionBtn, onClick: onAddSection, children: [
1903
+ /* @__PURE__ */ jsx11(Layers, { size: 14 }),
1734
1904
  " ",
1735
1905
  chrome.addSection
1736
1906
  ] })
@@ -1741,27 +1911,27 @@ function Canvas({
1741
1911
  import { Bold, Italic, X, Plus as Plus2, Trash2 as Trash23 } from "lucide-react";
1742
1912
 
1743
1913
  // src/components/fields/DefaultValueEditor.tsx
1744
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1914
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1745
1915
  function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
1746
1916
  if (meta.isContent) return null;
1747
1917
  const f = field;
1748
1918
  if (meta.boolean) {
1749
- return /* @__PURE__ */ jsxs9(Fragment2, { children: [
1750
- /* @__PURE__ */ jsx10("label", { style: styles.propLabel, children: chrome.defaultValue }),
1751
- /* @__PURE__ */ jsxs9("button", { style: styles.toggleRow, onClick: () => onChange({ defaultValue: !f.defaultValue }), children: [
1752
- /* @__PURE__ */ jsx10("span", { style: { ...styles.toggleTrack, background: f.defaultValue ? "var(--fb-primary)" : "var(--fb-border)" }, children: /* @__PURE__ */ jsx10("span", { style: { ...styles.toggleThumb, transform: f.defaultValue ? "translateX(16px)" : "translateX(0)" } }) }),
1753
- /* @__PURE__ */ jsx10("span", { style: { fontSize: 13, color: "#4A4D57" }, children: f.defaultValue ? chrome.checked : chrome.unchecked })
1919
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
1920
+ /* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultValue }),
1921
+ /* @__PURE__ */ jsxs10("button", { style: styles.toggleRow, onClick: () => onChange({ defaultValue: !f.defaultValue }), children: [
1922
+ /* @__PURE__ */ jsx12("span", { style: { ...styles.toggleTrack, background: f.defaultValue ? "var(--fb-primary)" : "var(--fb-border)" }, children: /* @__PURE__ */ jsx12("span", { style: { ...styles.toggleThumb, transform: f.defaultValue ? "translateX(16px)" : "translateX(0)" } }) }),
1923
+ /* @__PURE__ */ jsx12("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: f.defaultValue ? chrome.checked : chrome.unchecked })
1754
1924
  ] })
1755
1925
  ] });
1756
1926
  }
1757
1927
  if (meta.multiValue) {
1758
1928
  const selectedVals = f.defaultValue || [];
1759
- return /* @__PURE__ */ jsxs9(Fragment2, { children: [
1760
- /* @__PURE__ */ jsx10("label", { style: styles.propLabel, children: chrome.defaultChecked }),
1761
- /* @__PURE__ */ jsx10("div", { style: styles.optionList, children: (f.options || []).map((o) => {
1929
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
1930
+ /* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultChecked }),
1931
+ /* @__PURE__ */ jsx12("div", { style: styles.optionList, children: (f.options || []).map((o) => {
1762
1932
  const checked = selectedVals.includes(o.value);
1763
- return /* @__PURE__ */ jsxs9("label", { style: { ...styles.previewRadio, cursor: "pointer" }, children: [
1764
- /* @__PURE__ */ jsx10("input", { type: "checkbox", checked, onChange: (e) => {
1933
+ return /* @__PURE__ */ jsxs10("label", { style: { ...styles.previewRadio, cursor: "pointer" }, children: [
1934
+ /* @__PURE__ */ jsx12("input", { type: "checkbox", checked, onChange: (e) => {
1765
1935
  const next = e.target.checked ? [...selectedVals, o.value] : selectedVals.filter((v) => v !== o.value);
1766
1936
  onChange({ defaultValue: next });
1767
1937
  }, style: { accentColor: "var(--fb-primary)" } }),
@@ -1771,32 +1941,33 @@ function DefaultValueEditor({ field, meta, lang, chrome, onChange }) {
1771
1941
  ] });
1772
1942
  }
1773
1943
  if (meta.options) {
1774
- return /* @__PURE__ */ jsxs9(Fragment2, { children: [
1775
- /* @__PURE__ */ jsx10("label", { style: styles.propLabel, children: chrome.defaultValue }),
1776
- /* @__PURE__ */ jsxs9("select", { style: styles.propInput, value: f.defaultValue || "", onChange: (e) => onChange({ defaultValue: e.target.value }), children: [
1777
- /* @__PURE__ */ jsx10("option", { value: "", children: chrome.none }),
1778
- (f.options || []).map((o) => /* @__PURE__ */ jsx10("option", { value: o.value, children: t(o.label, lang) }, o.value))
1944
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
1945
+ /* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultValue }),
1946
+ /* @__PURE__ */ jsxs10("select", { style: styles.propInput, value: f.defaultValue || "", onChange: (e) => onChange({ defaultValue: e.target.value }), children: [
1947
+ /* @__PURE__ */ jsx12("option", { value: "", children: chrome.none }),
1948
+ (f.options || []).map((o) => /* @__PURE__ */ jsx12("option", { value: o.value, children: t(o.label, lang) }, o.value))
1779
1949
  ] })
1780
1950
  ] });
1781
1951
  }
1782
1952
  const htmlType = field.type === "input" && field.inputType === "number" ? "number" : field.type === "input" && field.inputType === "date" ? "date" : field.type === "input" && field.inputType === "time" ? "time" : "text";
1783
- return /* @__PURE__ */ jsxs9(Fragment2, { children: [
1784
- /* @__PURE__ */ jsx10("label", { style: styles.propLabel, children: chrome.defaultValue }),
1785
- /* @__PURE__ */ jsx10("input", { type: htmlType, style: styles.propInput, value: f.defaultValue || "", onChange: (e) => onChange({ defaultValue: e.target.value }) })
1953
+ return /* @__PURE__ */ jsxs10(Fragment4, { children: [
1954
+ /* @__PURE__ */ jsx12("label", { style: styles.propLabel, children: chrome.defaultValue }),
1955
+ /* @__PURE__ */ jsx12("input", { type: htmlType, style: styles.propInput, value: f.defaultValue || "", onChange: (e) => onChange({ defaultValue: e.target.value }) })
1786
1956
  ] });
1787
1957
  }
1788
1958
 
1789
1959
  // src/components/Inspector.tsx
1790
- import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1791
- function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1792
- return /* @__PURE__ */ jsxs10("div", { style: styles.inspector, children: [
1793
- /* @__PURE__ */ jsx11("div", { style: styles.panelHeading, children: chrome.properties }),
1794
- !selected ? /* @__PURE__ */ jsx11("div", { style: styles.inspectorEmpty, children: chrome.selectFieldHint }) : /* @__PURE__ */ jsx11(
1960
+ import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1961
+ function Inspector({ selected, language, chrome, features, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1962
+ return /* @__PURE__ */ jsxs11("div", { className: "fb-inspector", style: styles.inspector, children: [
1963
+ /* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.properties }),
1964
+ !selected ? /* @__PURE__ */ jsx13("div", { style: styles.inspectorEmpty, children: chrome.selectFieldHint }) : /* @__PURE__ */ jsx13(
1795
1965
  InspectorBody,
1796
1966
  {
1797
1967
  selected,
1798
1968
  language,
1799
1969
  chrome,
1970
+ features,
1800
1971
  onUpdateField,
1801
1972
  onDeleteField,
1802
1973
  onUpdateOption,
@@ -1806,119 +1977,145 @@ function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, o
1806
1977
  )
1807
1978
  ] });
1808
1979
  }
1809
- function InspectorBody({ selected, language, chrome, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1980
+ function InspectorBody({ selected, language, chrome, features, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
1810
1981
  const meta = getMeta(selected.type);
1811
1982
  const f = selected;
1812
- return /* @__PURE__ */ jsxs10("div", { style: styles.inspectorBody, children: [
1813
- !meta.isContent && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1814
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.label }),
1815
- /* @__PURE__ */ jsx11("input", { style: styles.propInput, value: t(selected.label, language), onChange: (e) => onUpdateField({ label: withLang(selected.label, language, e.target.value) }) }),
1816
- /* @__PURE__ */ jsxs10("label", { style: styles.toggleRow, children: [
1817
- /* @__PURE__ */ jsx11("input", { type: "checkbox", checked: !!selected.hideLabel, onChange: (e) => onUpdateField({ hideLabel: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
1818
- /* @__PURE__ */ jsx11("span", { style: { fontSize: 13, color: "#4A4D57" }, children: chrome.hideLabel })
1983
+ return /* @__PURE__ */ jsxs11("div", { style: styles.inspectorBody, children: [
1984
+ (!meta.isContent || selected.type === "button") && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1985
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: selected.type === "button" ? chrome.buttonText : chrome.label }),
1986
+ /* @__PURE__ */ jsx13("input", { style: styles.propInput, value: t(selected.label, language), onChange: (e) => onUpdateField({ label: withLang(selected.label, language, e.target.value) }) }),
1987
+ !meta.isContent && /* @__PURE__ */ jsxs11("label", { style: styles.toggleRow, children: [
1988
+ /* @__PURE__ */ jsx13("input", { type: "checkbox", checked: !!selected.hideLabel, onChange: (e) => onUpdateField({ hideLabel: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
1989
+ /* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.hideLabel })
1819
1990
  ] })
1820
1991
  ] }),
1821
- meta.hasSubtype && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1822
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.inputType }),
1823
- /* @__PURE__ */ jsx11("select", { style: styles.propInput, value: f.inputType || "text", onChange: (e) => onUpdateField({ inputType: e.target.value }), children: INPUT_SUBTYPES.map((s) => /* @__PURE__ */ jsx11("option", { value: s, children: chrome[INPUT_SUBTYPE_CHROME_KEY[s]] }, s)) })
1992
+ meta.hasSubtype && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1993
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.inputType }),
1994
+ /* @__PURE__ */ jsx13("select", { style: styles.propInput, value: f.inputType || "text", onChange: (e) => onUpdateField({ inputType: e.target.value }), children: INPUT_SUBTYPES.map((s) => /* @__PURE__ */ jsx13("option", { value: s, children: chrome[INPUT_SUBTYPE_CHROME_KEY[s]] }, s)) })
1824
1995
  ] }),
1825
- selected.type === "paragraph" && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1826
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.content }),
1827
- /* @__PURE__ */ jsx11("textarea", { style: { ...styles.propInput, minHeight: 70, resize: "vertical" }, value: t(selected.content, language), onChange: (e) => onUpdateField({ content: withLang(selected.content, language, e.target.value) }) }),
1828
- /* @__PURE__ */ jsx11("div", { style: styles.inspectorDivider }),
1829
- /* @__PURE__ */ jsx11("div", { style: styles.panelHeading, children: chrome.typography }),
1830
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.headingStyle }),
1831
- /* @__PURE__ */ jsx11(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] }) }),
1832
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.width }),
1833
- /* @__PURE__ */ jsx11(Segmented, { options: FONT_SIZE_OPTIONS, value: selected.fontSize || "md", onChange: (v) => onUpdateField({ fontSize: v }) }),
1834
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.style }),
1835
- /* @__PURE__ */ jsxs10("div", { style: styles.styleToggleRow, children: [
1836
- /* @__PURE__ */ jsx11("button", { type: "button", style: selected.fontWeight === "bold" ? styles.styleToggleActive : styles.styleToggle, onClick: () => onUpdateField({ fontWeight: selected.fontWeight === "bold" ? "normal" : "bold" }), children: /* @__PURE__ */ jsx11(Bold, { size: 14 }) }),
1837
- /* @__PURE__ */ jsx11("button", { type: "button", style: selected.fontStyle === "italic" ? styles.styleToggleActive : styles.styleToggle, onClick: () => onUpdateField({ fontStyle: selected.fontStyle === "italic" ? "normal" : "italic" }), children: /* @__PURE__ */ jsx11(Italic, { size: 14 }) })
1838
- ] }),
1839
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.align }),
1840
- /* @__PURE__ */ jsx11(Segmented, { options: TEXT_ALIGN_OPTIONS, value: selected.textAlign || "left", onChange: (v) => onUpdateField({ textAlign: v }) }),
1841
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.color }),
1842
- /* @__PURE__ */ jsxs10("div", { style: styles.swatchRow, children: [
1843
- COLOR_SWATCHES.map((c) => /* @__PURE__ */ jsx11("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")),
1844
- /* @__PURE__ */ jsx11("input", { type: "color", value: selected.color || "#1B1E24", onChange: (e) => onUpdateField({ color: e.target.value }), style: styles.colorPickerInput })
1996
+ selected.type === "paragraph" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
1997
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.content }),
1998
+ /* @__PURE__ */ jsx13("textarea", { style: { ...styles.propInput, minHeight: 70, resize: "vertical" }, value: t(selected.content, language), onChange: (e) => onUpdateField({ content: withLang(selected.content, language, e.target.value) }) }),
1999
+ features.blockStyling && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2000
+ /* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
2001
+ /* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.typography }),
2002
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.headingStyle }),
2003
+ /* @__PURE__ */ jsx13(Segmented, { options: PARAGRAPH_TAG_OPTIONS.map((v) => ({ value: v, label: TAG_CHROME_KEY[v] ? chrome[TAG_CHROME_KEY[v]] : v.toUpperCase() })), value: selected.tag || "p", onChange: (v) => onUpdateField({ tag: v, ...TAG_PRESETS[v] }) }),
2004
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.width }),
2005
+ /* @__PURE__ */ jsx13(Segmented, { options: FONT_SIZE_OPTIONS, value: selected.fontSize || "md", onChange: (v) => onUpdateField({ fontSize: v }) }),
2006
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.style }),
2007
+ /* @__PURE__ */ jsxs11("div", { style: styles.styleToggleRow, children: [
2008
+ /* @__PURE__ */ jsx13("button", { type: "button", style: selected.fontWeight === "bold" ? styles.styleToggleActive : styles.styleToggle, onClick: () => onUpdateField({ fontWeight: selected.fontWeight === "bold" ? "normal" : "bold" }), children: /* @__PURE__ */ jsx13(Bold, { size: 14 }) }),
2009
+ /* @__PURE__ */ jsx13("button", { type: "button", style: selected.fontStyle === "italic" ? styles.styleToggleActive : styles.styleToggle, onClick: () => onUpdateField({ fontStyle: selected.fontStyle === "italic" ? "normal" : "italic" }), children: /* @__PURE__ */ jsx13(Italic, { size: 14 }) })
2010
+ ] }),
2011
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.align }),
2012
+ /* @__PURE__ */ jsx13(Segmented, { options: TEXT_ALIGN_OPTIONS, value: selected.textAlign || "left", onChange: (v) => onUpdateField({ textAlign: v }) }),
2013
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.color }),
2014
+ /* @__PURE__ */ jsxs11("div", { style: styles.swatchRow, children: [
2015
+ COLOR_SWATCHES.map((c) => /* @__PURE__ */ jsx13("button", { type: "button", title: c || chrome.none, style: { ...styles.swatchBtn, background: c || "var(--fb-ink)", ...selected.color === c ? styles.swatchBtnActive : {} }, onClick: () => onUpdateField({ color: c }) }, c || "default")),
2016
+ /* @__PURE__ */ jsx13("input", { type: "color", value: selected.color || "#1B1E24", onChange: (e) => onUpdateField({ color: e.target.value }), style: styles.colorPickerInput })
2017
+ ] })
1845
2018
  ] })
1846
2019
  ] }),
1847
- selected.type === "image" && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1848
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.imageUrl }),
1849
- /* @__PURE__ */ jsx11("input", { style: styles.propInput, placeholder: "https://...", value: selected.src || "", onChange: (e) => onUpdateField({ src: e.target.value }) }),
1850
- /* @__PURE__ */ jsx11("p", { style: styles.helperText, children: chrome.imageUrlHelper }),
1851
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.altText }),
1852
- /* @__PURE__ */ jsx11("input", { style: styles.propInput, value: t(selected.alt, language), onChange: (e) => onUpdateField({ alt: withLang(selected.alt, language, e.target.value) }) }),
1853
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.linkOptional }),
1854
- /* @__PURE__ */ jsx11("input", { style: styles.propInput, placeholder: "https://...", value: selected.link || "", onChange: (e) => onUpdateField({ link: e.target.value }) }),
1855
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.shape }),
1856
- /* @__PURE__ */ jsx11(Segmented, { options: IMAGE_SHAPES.map((v) => ({ value: v, label: chrome[IMAGE_SHAPE_CHROME_KEY[v]] })), value: selected.shape || "square", onChange: (v) => onUpdateField({ shape: v }) }),
1857
- /* @__PURE__ */ jsx11("p", { style: styles.helperText, children: "Fills the field's own width (set below under Layout) and scales height automatically \u2014 always responsive, never overflows." })
2020
+ selected.type === "image" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2021
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.imageUrl }),
2022
+ /* @__PURE__ */ jsx13("input", { style: styles.propInput, placeholder: "https://...", value: selected.src || "", onChange: (e) => onUpdateField({ src: e.target.value }) }),
2023
+ /* @__PURE__ */ jsx13("p", { style: styles.helperText, children: chrome.imageUrlHelper }),
2024
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.altText }),
2025
+ /* @__PURE__ */ jsx13("input", { style: styles.propInput, value: t(selected.alt, language), onChange: (e) => onUpdateField({ alt: withLang(selected.alt, language, e.target.value) }) }),
2026
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.linkOptional }),
2027
+ /* @__PURE__ */ jsx13("input", { style: styles.propInput, placeholder: "https://...", value: selected.link || "", onChange: (e) => onUpdateField({ link: e.target.value }) }),
2028
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.shape }),
2029
+ /* @__PURE__ */ jsx13(Segmented, { options: IMAGE_SHAPES.map((v) => ({ value: v, label: chrome[IMAGE_SHAPE_CHROME_KEY[v]] })), value: selected.shape || "square", onChange: (v) => onUpdateField({ shape: v }) }),
2030
+ /* @__PURE__ */ jsx13("p", { style: styles.helperText, children: "Fills the field's own width (set below under Layout) and scales height automatically \u2014 always responsive, never overflows." })
1858
2031
  ] }),
1859
- meta.placeholder && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1860
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.placeholder }),
1861
- /* @__PURE__ */ jsx11("input", { style: styles.propInput, value: t(f.placeholder, language), onChange: (e) => onUpdateField({ placeholder: withLang(f.placeholder, language, e.target.value) }) })
2032
+ selected.type === "button" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2033
+ /* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
2034
+ /* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.buttonActionTitle }),
2035
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.buttonAction }),
2036
+ /* @__PURE__ */ jsx13(Segmented, { options: [{ value: "link", label: chrome.actionLink }, { value: "submit", label: chrome.actionSubmit }], value: selected.action || "submit", onChange: (v) => onUpdateField({ action: v }) }),
2037
+ selected.action === "link" ? /* @__PURE__ */ jsxs11(Fragment5, { children: [
2038
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.linkOptional }),
2039
+ /* @__PURE__ */ jsx13("input", { style: styles.propInput, placeholder: "https://...", value: selected.href || "", onChange: (e) => onUpdateField({ href: e.target.value }) }),
2040
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.openIn }),
2041
+ /* @__PURE__ */ jsx13(Segmented, { options: [{ value: "_self", label: chrome.sameTab }, { value: "_blank", label: chrome.newTab }], value: selected.target || "_self", onChange: (v) => onUpdateField({ target: v }) })
2042
+ ] }) : /* @__PURE__ */ jsxs11(Fragment5, { children: [
2043
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.submitScope }),
2044
+ /* @__PURE__ */ jsx13(Segmented, { options: [{ value: "section", label: chrome.thisSection }, { value: "form", label: chrome.wholeForm }], value: selected.submitScope || "form", onChange: (v) => onUpdateField({ submitScope: v }) })
2045
+ ] }),
2046
+ features.blockStyling && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2047
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.color }),
2048
+ /* @__PURE__ */ jsxs11("div", { style: styles.swatchRow, children: [
2049
+ BUTTON_COLOR_SWATCHES.map((c) => /* @__PURE__ */ jsx13("button", { type: "button", title: c || chrome.none, style: { ...styles.swatchBtn, background: c || "var(--fb-primary)", ...(selected.buttonStyle?.color || "") === c ? styles.swatchBtnActive : {} }, onClick: () => onUpdateField({ buttonStyle: { ...selected.buttonStyle, color: c } }) }, c || "default")),
2050
+ /* @__PURE__ */ jsx13("input", { type: "color", value: selected.buttonStyle?.color || "#5B5FEF", onChange: (e) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, color: e.target.value } }), style: styles.colorPickerInput })
2051
+ ] }),
2052
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.buttonSize }),
2053
+ /* @__PURE__ */ jsx13(Segmented, { options: SUBMIT_SIZE_OPTIONS, value: selected.buttonStyle?.size || "md", onChange: (v) => onUpdateField({ buttonStyle: { ...selected.buttonStyle, size: v } }) })
2054
+ ] })
1862
2055
  ] }),
1863
- selected.type === "input" && (selected.inputType === "text" || selected.inputType === "password" || !selected.inputType) && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1864
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.maxLength }),
1865
- /* @__PURE__ */ jsx11("input", { type: "number", style: styles.propInput, placeholder: chrome.noLimit, value: selected.maxLength || "", onChange: (e) => onUpdateField({ maxLength: e.target.value ? Number(e.target.value) : null }) })
2056
+ meta.placeholder && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2057
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.placeholder }),
2058
+ /* @__PURE__ */ jsx13("input", { style: styles.propInput, value: t(f.placeholder, language), onChange: (e) => onUpdateField({ placeholder: withLang(f.placeholder, language, e.target.value) }) })
1866
2059
  ] }),
1867
- selected.type === "input" && selected.inputType === "number" && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1868
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.minValue }),
1869
- /* @__PURE__ */ jsx11("input", { type: "number", style: styles.propInput, value: selected.min ?? "", onChange: (e) => onUpdateField({ min: e.target.value === "" ? null : Number(e.target.value) }) }),
1870
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.maxValue }),
1871
- /* @__PURE__ */ jsx11("input", { type: "number", style: styles.propInput, value: selected.max ?? "", onChange: (e) => onUpdateField({ max: e.target.value === "" ? null : Number(e.target.value) }) })
2060
+ selected.type === "input" && (selected.inputType === "text" || selected.inputType === "password" || !selected.inputType) && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2061
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.maxLength }),
2062
+ /* @__PURE__ */ jsx13("input", { type: "number", style: styles.propInput, placeholder: chrome.noLimit, value: selected.maxLength || "", onChange: (e) => onUpdateField({ maxLength: e.target.value ? Number(e.target.value) : null }) })
1872
2063
  ] }),
1873
- selected.type === "textarea" && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1874
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.maxLength }),
1875
- /* @__PURE__ */ jsx11("input", { type: "number", style: styles.propInput, placeholder: chrome.noLimit, value: selected.maxLength || "", onChange: (e) => onUpdateField({ maxLength: e.target.value ? Number(e.target.value) : null }) })
2064
+ selected.type === "input" && selected.inputType === "number" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2065
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.minValue }),
2066
+ /* @__PURE__ */ jsx13("input", { type: "number", style: styles.propInput, value: selected.min ?? "", onChange: (e) => onUpdateField({ min: e.target.value === "" ? null : Number(e.target.value) }) }),
2067
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.maxValue }),
2068
+ /* @__PURE__ */ jsx13("input", { type: "number", style: styles.propInput, value: selected.max ?? "", onChange: (e) => onUpdateField({ max: e.target.value === "" ? null : Number(e.target.value) }) })
1876
2069
  ] }),
1877
- meta.options && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1878
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.options }),
1879
- /* @__PURE__ */ jsxs10("div", { style: styles.optionList, children: [
1880
- (f.options || []).map((opt, i) => /* @__PURE__ */ jsxs10("div", { style: styles.optionRow, children: [
1881
- /* @__PURE__ */ jsx11("input", { style: styles.optionInput, value: t(opt.label, language), onChange: (e) => onUpdateOption(i, { label: withLang(opt.label, language, e.target.value) }) }),
1882
- /* @__PURE__ */ jsx11("button", { style: styles.iconBtn, onClick: () => onRemoveOption(i), disabled: (f.options || []).length <= 1, children: /* @__PURE__ */ jsx11(X, { size: 13 }) })
2070
+ selected.type === "textarea" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2071
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.maxLength }),
2072
+ /* @__PURE__ */ jsx13("input", { type: "number", style: styles.propInput, placeholder: chrome.noLimit, value: selected.maxLength || "", onChange: (e) => onUpdateField({ maxLength: e.target.value ? Number(e.target.value) : null }) })
2073
+ ] }),
2074
+ meta.options && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2075
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.options }),
2076
+ /* @__PURE__ */ jsxs11("div", { style: styles.optionList, children: [
2077
+ (f.options || []).map((opt, i) => /* @__PURE__ */ jsxs11("div", { style: styles.optionRow, children: [
2078
+ /* @__PURE__ */ jsx13("input", { style: styles.optionInput, value: t(opt.label, language), onChange: (e) => onUpdateOption(i, { label: withLang(opt.label, language, e.target.value) }) }),
2079
+ /* @__PURE__ */ jsx13("button", { style: styles.iconBtn, onClick: () => onRemoveOption(i), disabled: (f.options || []).length <= 1, children: /* @__PURE__ */ jsx13(X, { size: 13 }) })
1883
2080
  ] }, i)),
1884
- /* @__PURE__ */ jsxs10("button", { style: styles.addOptionBtn, onClick: onAddOption, children: [
1885
- /* @__PURE__ */ jsx11(Plus2, { size: 13 }),
2081
+ /* @__PURE__ */ jsxs11("button", { style: styles.addOptionBtn, onClick: onAddOption, children: [
2082
+ /* @__PURE__ */ jsx13(Plus2, { size: 13 }),
1886
2083
  " ",
1887
2084
  chrome.addOption
1888
2085
  ] })
1889
2086
  ] })
1890
2087
  ] }),
1891
- /* @__PURE__ */ jsx11(DefaultValueEditor, { field: selected, meta, lang: language, chrome, onChange: onUpdateField }),
1892
- !meta.isContent && /* @__PURE__ */ jsxs10("label", { style: styles.toggleRow, children: [
1893
- /* @__PURE__ */ jsx11("input", { type: "checkbox", checked: !!selected.required, onChange: (e) => onUpdateField({ required: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
1894
- /* @__PURE__ */ jsx11("span", { style: { fontSize: 13, color: "#4A4D57" }, children: chrome.requiredField })
2088
+ /* @__PURE__ */ jsx13(DefaultValueEditor, { field: selected, meta, lang: language, chrome, onChange: onUpdateField }),
2089
+ !meta.isContent && /* @__PURE__ */ jsxs11("label", { style: styles.toggleRow, children: [
2090
+ /* @__PURE__ */ jsx13("input", { type: "checkbox", checked: !!selected.required, onChange: (e) => onUpdateField({ required: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
2091
+ /* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.requiredField })
1895
2092
  ] }),
1896
- /* @__PURE__ */ jsx11("div", { style: styles.inspectorDivider }),
1897
- /* @__PURE__ */ jsx11("div", { style: styles.panelHeading, children: chrome.layout }),
1898
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.width }),
1899
- /* @__PURE__ */ jsx11(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 }) }),
1900
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.verticalAlign }),
1901
- /* @__PURE__ */ jsx11(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 }) }),
1902
- !meta.boolean && !meta.isContent && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1903
- /* @__PURE__ */ jsx11("label", { style: styles.propLabel, children: chrome.labelPosition }),
1904
- /* @__PURE__ */ jsx11(Segmented, { options: [{ value: "top", label: chrome.above }, { value: "inline", label: chrome.inline }], value: selected.labelPosition || "top", onChange: (v) => onUpdateField({ labelPosition: v }) })
2093
+ /* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
2094
+ /* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.layout }),
2095
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.width }),
2096
+ /* @__PURE__ */ jsx13(Segmented, { options: WIDTH_OPTIONS.map((o) => ({ ...o, label: o.labelKey ? chrome[o.labelKey] : o.label || "" })), value: selected.width || "1/1", onChange: (v) => onUpdateField({ width: v }) }),
2097
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.verticalAlign }),
2098
+ /* @__PURE__ */ jsx13(Segmented, { options: [{ value: "top", label: chrome.top }, { value: "middle", label: chrome.middle }, { value: "bottom", label: chrome.bottom }], value: selected.verticalAlign || "top", onChange: (v) => onUpdateField({ verticalAlign: v }) }),
2099
+ !meta.boolean && !meta.isContent && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2100
+ /* @__PURE__ */ jsx13("label", { style: styles.propLabel, children: chrome.labelPosition }),
2101
+ /* @__PURE__ */ jsx13(Segmented, { options: [{ value: "top", label: chrome.above }, { value: "inline", label: chrome.inline }], value: selected.labelPosition || "top", onChange: (v) => onUpdateField({ labelPosition: v }) })
1905
2102
  ] }),
1906
- !meta.isContent && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1907
- /* @__PURE__ */ jsx11("div", { style: styles.inspectorDivider }),
1908
- /* @__PURE__ */ jsx11("div", { style: styles.panelHeading, children: chrome.icon }),
1909
- /* @__PURE__ */ jsxs10("label", { style: styles.toggleRow, children: [
1910
- /* @__PURE__ */ jsx11("input", { type: "checkbox", checked: !!selected.showIcon, onChange: (e) => onUpdateField({ showIcon: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
1911
- /* @__PURE__ */ jsx11("span", { style: { fontSize: 13, color: "#4A4D57" }, children: chrome.showIcon })
2103
+ !meta.isContent && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2104
+ /* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
2105
+ /* @__PURE__ */ jsx13("div", { style: styles.panelHeading, children: chrome.icon }),
2106
+ /* @__PURE__ */ jsxs11("label", { style: styles.toggleRow, children: [
2107
+ /* @__PURE__ */ jsx13("input", { type: "checkbox", checked: !!selected.showIcon, onChange: (e) => onUpdateField({ showIcon: e.target.checked }), style: { width: 15, height: 15, accentColor: "var(--fb-primary)" } }),
2108
+ /* @__PURE__ */ jsx13("span", { style: { fontSize: 13, color: "var(--fb-ink)" }, children: chrome.showIcon })
1912
2109
  ] }),
1913
- selected.showIcon && /* @__PURE__ */ jsx11("div", { style: styles.iconGrid, children: Object.keys(ICON_LIBRARY).map((key) => {
2110
+ selected.showIcon && /* @__PURE__ */ jsx13("div", { style: styles.iconGrid, children: Object.keys(ICON_LIBRARY).map((key) => {
1914
2111
  const IconComp = ICON_LIBRARY[key];
1915
2112
  const active = selected.displayIcon === key;
1916
- return /* @__PURE__ */ jsx11("button", { type: "button", title: key, style: active ? styles.iconGridBtnActive : styles.iconGridBtn, onClick: () => onUpdateField({ displayIcon: key }), children: /* @__PURE__ */ jsx11(IconComp, { size: 15 }) }, key);
2113
+ return /* @__PURE__ */ jsx13("button", { type: "button", title: key, style: active ? styles.iconGridBtnActive : styles.iconGridBtn, onClick: () => onUpdateField({ displayIcon: key }), children: /* @__PURE__ */ jsx13(IconComp, { size: 15 }) }, key);
1917
2114
  }) })
1918
2115
  ] }),
1919
- /* @__PURE__ */ jsx11("div", { style: styles.inspectorDivider }),
1920
- /* @__PURE__ */ jsxs10("button", { style: styles.deleteFieldBtn, onClick: onDeleteField, children: [
1921
- /* @__PURE__ */ jsx11(Trash23, { size: 13 }),
2116
+ /* @__PURE__ */ jsx13("div", { style: styles.inspectorDivider }),
2117
+ /* @__PURE__ */ jsxs11("button", { style: styles.deleteFieldBtn, onClick: onDeleteField, children: [
2118
+ /* @__PURE__ */ jsx13(Trash23, { size: 13 }),
1922
2119
  " ",
1923
2120
  chrome.deleteField
1924
2121
  ] })
@@ -1962,17 +2159,26 @@ function formatValue(field, lang) {
1962
2159
  return String(v);
1963
2160
  }
1964
2161
 
2162
+ // src/lib/collectSubmission.ts
2163
+ function collectFieldValues(fields) {
2164
+ const values = {};
2165
+ fields.forEach((f) => {
2166
+ if (getMeta(f.type).isContent) return;
2167
+ values[f.id] = f.defaultValue;
2168
+ });
2169
+ return values;
2170
+ }
2171
+
1965
2172
  // src/components/PreviewPane.tsx
1966
- import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1967
- function PreviewPane({ title, sections, onFieldChange, language, strings, chrome, baseMaxWidth, submitLabel, submitMode, submitStyle }) {
2173
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2174
+ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome, baseMaxWidth, onSubmit }) {
1968
2175
  const [device, setDevice] = useState6("laptop");
1969
2176
  const [errors, setErrors] = useState6({});
1970
2177
  const [submitted, setSubmitted] = useState6(null);
2178
+ const [attemptedButtonId, setAttemptedButtonId] = useState6(null);
1971
2179
  const deviceOptions = buildDeviceOptions(baseMaxWidth, chrome);
1972
2180
  const maxWidth = (deviceOptions.find((d) => d.value === device) || deviceOptions[0]).maxWidth;
1973
2181
  const allFields = sections.flatMap((s) => s.fields);
1974
- const submitText = t(submitLabel, language) || strings.submit;
1975
- const overallHasFormFields = allFields.some((f) => !getMeta(f.type).isContent);
1976
2182
  function runValidation(fields) {
1977
2183
  const errs = {};
1978
2184
  fields.forEach((f) => {
@@ -1981,78 +2187,92 @@ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome
1981
2187
  });
1982
2188
  return errs;
1983
2189
  }
1984
- function handleSubmitAll() {
2190
+ function buildSectionsBreakdown() {
2191
+ return sections.map((s) => ({ sectionId: s.id, values: collectFieldValues(s.fields) }));
2192
+ }
2193
+ function handleSubmitAll(buttonId) {
1985
2194
  const errs = runValidation(allFields);
1986
2195
  setErrors(errs);
2196
+ setAttemptedButtonId(buttonId);
1987
2197
  if (Object.keys(errs).length > 0) {
1988
2198
  setSubmitted(null);
1989
2199
  return;
1990
2200
  }
1991
2201
  setSubmitted(allFields.filter((f) => !getMeta(f.type).isContent).map((f) => ({ label: t(f.label, language), value: formatValue(f, language) })));
2202
+ const sectionsBreakdown = buildSectionsBreakdown();
2203
+ const all = collectFieldValues(allFields);
2204
+ onSubmit?.({ buttonId, scope: "form", values: all, sections: sectionsBreakdown, all });
1992
2205
  }
1993
- function handleSubmitSection(section) {
2206
+ function handleSubmitSection(section, buttonId) {
1994
2207
  const errs = runValidation(section.fields);
1995
2208
  setErrors((prev) => {
1996
2209
  const next = { ...prev };
1997
2210
  section.fields.forEach((f) => delete next[f.id]);
1998
2211
  return { ...next, ...errs };
1999
2212
  });
2213
+ setAttemptedButtonId(buttonId);
2000
2214
  if (Object.keys(errs).length > 0) {
2001
2215
  setSubmitted(null);
2002
2216
  return;
2003
2217
  }
2004
2218
  setSubmitted(section.fields.filter((f) => !getMeta(f.type).isContent).map((f) => ({ label: t(f.label, language), value: formatValue(f, language) })));
2219
+ const sectionsBreakdown = buildSectionsBreakdown();
2220
+ const all = collectFieldValues(allFields);
2221
+ onSubmit?.({ buttonId, scope: "section", sectionId: section.id, values: collectFieldValues(section.fields), sections: sectionsBreakdown, all });
2222
+ }
2223
+ function handleButtonAction(field) {
2224
+ if (field.action === "link") {
2225
+ if (field.href) window.open(field.href, field.target === "_blank" ? "_blank" : "_self", field.target === "_blank" ? "noopener,noreferrer" : void 0);
2226
+ return;
2227
+ }
2228
+ if (field.submitScope === "section") {
2229
+ const section = sections.find((s) => s.fields.some((f) => f.id === field.id));
2230
+ if (section) handleSubmitSection(section, field.id);
2231
+ } else {
2232
+ handleSubmitAll(field.id);
2233
+ }
2005
2234
  }
2006
- return /* @__PURE__ */ jsxs11("div", { style: styles.previewWrap, children: [
2007
- /* @__PURE__ */ jsxs11("div", { style: { width: "100%", maxWidth, display: "flex", flexDirection: "column", alignItems: "center" }, children: [
2008
- /* @__PURE__ */ jsx12("div", { style: styles.previewToolbar, children: /* @__PURE__ */ jsx12(Segmented, { options: deviceOptions, value: device, onChange: setDevice }) }),
2009
- /* @__PURE__ */ jsxs11("div", { style: { ...styles.previewCard, maxWidth, width: "100%" }, children: [
2010
- /* @__PURE__ */ jsx12("h2", { style: styles.previewTitle, children: t(title, language) }),
2011
- allFields.length === 0 && /* @__PURE__ */ jsx12("p", { style: { color: "var(--fb-muted)", fontSize: 14 }, children: strings.addFieldsHint }),
2235
+ return /* @__PURE__ */ jsxs12("div", { style: styles.previewWrap, children: [
2236
+ /* @__PURE__ */ jsxs12("div", { style: { width: "100%", maxWidth, display: "flex", flexDirection: "column", alignItems: "center" }, children: [
2237
+ /* @__PURE__ */ jsx14("div", { style: styles.previewToolbar, children: /* @__PURE__ */ jsx14(Segmented, { options: deviceOptions, value: device, onChange: setDevice }) }),
2238
+ /* @__PURE__ */ jsxs12("div", { style: { ...styles.previewCard, maxWidth, width: "100%" }, children: [
2239
+ /* @__PURE__ */ jsx14("h2", { style: styles.previewTitle, children: t(title, language) }),
2240
+ allFields.length === 0 && /* @__PURE__ */ jsx14("p", { style: { color: "var(--fb-muted)", fontSize: 14 }, children: strings.addFieldsHint }),
2012
2241
  sections.map((section) => {
2013
- const sectionHasFormFields = section.fields.some((f) => !getMeta(f.type).isContent);
2014
- const sectionHasErrors = section.fields.some((f) => errors[f.id]);
2015
- return /* @__PURE__ */ jsxs11("div", { style: { background: section.background || "transparent", padding: section.background ? 16 : 0, borderRadius: section.background ? 10 : 0, marginBottom: "var(--fb-space-section)" }, children: [
2016
- t(section.title, language) && /* @__PURE__ */ jsx12("h3", { style: styles.sectionRuntimeTitle, children: t(section.title, language) }),
2017
- /* @__PURE__ */ jsx12("div", { style: styles.previewGrid, children: section.fields.map((field) => {
2242
+ return /* @__PURE__ */ jsxs12("div", { style: { background: section.background || "transparent", padding: section.background ? 16 : 0, borderRadius: section.background ? 10 : 0, marginBottom: "var(--fb-space-section)" }, children: [
2243
+ t(section.title, language) && /* @__PURE__ */ jsx14("h3", { style: styles.sectionRuntimeTitle, children: t(section.title, language) }),
2244
+ /* @__PURE__ */ jsx14("div", { style: styles.previewGrid, children: section.fields.map((field) => {
2018
2245
  const width = effectiveWidth(field.width, device);
2019
2246
  const flexBasis = `1 1 calc(${WIDTH_PERCENT[width]} - 14px)`;
2020
- return /* @__PURE__ */ jsx12("div", { style: { flex: flexBasis, minWidth: 0, alignSelf: ALIGN_MAP[field.verticalAlign || "top"] }, children: /* @__PURE__ */ jsx12(FieldBlock, { field, lang: language, onFieldChange, strings, chrome, error: errors[field.id] }) }, field.id);
2021
- }) }),
2022
- submitMode === "perSection" && sectionHasFormFields && /* @__PURE__ */ jsxs11(Fragment4, { children: [
2023
- /* @__PURE__ */ jsx12("button", { style: { ...styles.submitBtn, ...resolveSubmitStyle(section.submitStyle || submitStyle) }, onClick: () => handleSubmitSection(section), children: submitText }),
2024
- sectionHasErrors && /* @__PURE__ */ jsxs11("p", { style: styles.formErrorNote, children: [
2025
- /* @__PURE__ */ jsx12(CircleAlert2, { size: 13 }),
2026
- " ",
2027
- strings.fixErrors
2028
- ] })
2029
- ] })
2247
+ return /* @__PURE__ */ jsxs12("div", { style: { flex: flexBasis, minWidth: 0, alignSelf: ALIGN_MAP[field.verticalAlign || "top"] }, children: [
2248
+ /* @__PURE__ */ jsx14(FieldBlock, { field, lang: language, onFieldChange, strings, chrome, error: errors[field.id], onButtonAction: handleButtonAction }),
2249
+ field.type === "button" && field.id === attemptedButtonId && Object.keys(errors).length > 0 && /* @__PURE__ */ jsxs12("p", { style: styles.formErrorNote, children: [
2250
+ /* @__PURE__ */ jsx14(CircleAlert2, { size: 13 }),
2251
+ " ",
2252
+ strings.fixErrors
2253
+ ] })
2254
+ ] }, field.id);
2255
+ }) })
2030
2256
  ] }, section.id);
2031
- }),
2032
- submitMode === "combined" && overallHasFormFields && /* @__PURE__ */ jsx12("button", { style: { ...styles.submitBtn, ...resolveSubmitStyle(submitStyle) }, onClick: handleSubmitAll, children: submitText }),
2033
- submitMode === "combined" && Object.keys(errors).length > 0 && /* @__PURE__ */ jsxs11("p", { style: styles.formErrorNote, children: [
2034
- /* @__PURE__ */ jsx12(CircleAlert2, { size: 13 }),
2035
- " ",
2036
- strings.fixErrors
2037
- ] })
2257
+ })
2038
2258
  ] })
2039
2259
  ] }),
2040
- submitted && /* @__PURE__ */ jsx12("div", { style: styles.modalOverlay, onClick: () => setSubmitted(null), children: /* @__PURE__ */ jsxs11("div", { style: { ...styles.modal, width: 420 }, onClick: (e) => e.stopPropagation(), children: [
2041
- /* @__PURE__ */ jsxs11("div", { style: styles.modalHeader, children: [
2042
- /* @__PURE__ */ jsxs11("span", { style: { fontWeight: 600, fontSize: 14, display: "flex", alignItems: "center", gap: 7 }, children: [
2043
- /* @__PURE__ */ jsx12(PartyPopper, { size: 15, color: "var(--fb-primary)" }),
2260
+ submitted && /* @__PURE__ */ jsx14("div", { style: styles.modalOverlay, onClick: () => setSubmitted(null), children: /* @__PURE__ */ jsxs12("div", { style: { ...styles.modal, maxWidth: 420 }, onClick: (e) => e.stopPropagation(), children: [
2261
+ /* @__PURE__ */ jsxs12("div", { style: styles.modalHeader, children: [
2262
+ /* @__PURE__ */ jsxs12("span", { style: { fontWeight: 600, fontSize: 14, display: "flex", alignItems: "center", gap: 7 }, children: [
2263
+ /* @__PURE__ */ jsx14(PartyPopper, { size: 15, color: "var(--fb-primary)" }),
2044
2264
  " ",
2045
2265
  strings.submittedTitle
2046
2266
  ] }),
2047
- /* @__PURE__ */ jsx12("button", { style: styles.iconBtn, onClick: () => setSubmitted(null), children: /* @__PURE__ */ jsx12(X2, { size: 16 }) })
2267
+ /* @__PURE__ */ jsx14("button", { style: styles.iconBtn, onClick: () => setSubmitted(null), children: /* @__PURE__ */ jsx14(X2, { size: 16 }) })
2048
2268
  ] }),
2049
- /* @__PURE__ */ jsxs11("div", { style: { padding: 16 }, children: [
2050
- /* @__PURE__ */ jsx12("p", { style: { fontSize: 12.5, color: "var(--fb-muted)", marginTop: 0 }, children: strings.submittedBody }),
2051
- /* @__PURE__ */ jsx12("div", { style: styles.submittedList, children: submitted.map((row, i) => /* @__PURE__ */ jsxs11("div", { style: styles.submittedRow, children: [
2052
- /* @__PURE__ */ jsx12("span", { style: styles.submittedLabel, children: row.label }),
2053
- /* @__PURE__ */ jsx12("span", { style: styles.submittedValue, children: row.value })
2269
+ /* @__PURE__ */ jsxs12("div", { style: { padding: 16 }, children: [
2270
+ /* @__PURE__ */ jsx14("p", { style: { fontSize: 12.5, color: "var(--fb-muted)", marginTop: 0 }, children: strings.submittedBody }),
2271
+ /* @__PURE__ */ jsx14("div", { style: styles.submittedList, children: submitted.map((row, i) => /* @__PURE__ */ jsxs12("div", { style: styles.submittedRow, children: [
2272
+ /* @__PURE__ */ jsx14("span", { style: styles.submittedLabel, children: row.label }),
2273
+ /* @__PURE__ */ jsx14("span", { style: styles.submittedValue, children: row.value })
2054
2274
  ] }, i)) }),
2055
- /* @__PURE__ */ jsx12("button", { style: { ...styles.primaryBtn, width: "100%", justifyContent: "center", marginTop: 14 }, onClick: () => setSubmitted(null), children: strings.close })
2275
+ /* @__PURE__ */ jsx14("button", { style: { ...styles.primaryBtn, width: "100%", justifyContent: "center", marginTop: 14 }, onClick: () => setSubmitted(null), children: strings.close })
2056
2276
  ] })
2057
2277
  ] }) })
2058
2278
  ] });
@@ -2060,47 +2280,47 @@ function PreviewPane({ title, sections, onFieldChange, language, strings, chrome
2060
2280
 
2061
2281
  // src/components/modals/JsonModal.tsx
2062
2282
  import { Check, ClipboardCopy, X as X3 } from "lucide-react";
2063
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
2283
+ import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
2064
2284
  function JsonModal({ chrome, jsonString, copied, onCopy, onClose }) {
2065
- return /* @__PURE__ */ jsx13("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ jsxs12("div", { style: styles.modal, onClick: (e) => e.stopPropagation(), children: [
2066
- /* @__PURE__ */ jsxs12("div", { style: styles.modalHeader, children: [
2067
- /* @__PURE__ */ jsx13("span", { style: { fontWeight: 600, fontSize: 14 }, children: chrome.formJson }),
2068
- /* @__PURE__ */ jsxs12("div", { style: { display: "flex", gap: 8 }, children: [
2069
- /* @__PURE__ */ jsxs12("button", { style: styles.ghostBtn, onClick: onCopy, children: [
2070
- copied ? /* @__PURE__ */ jsx13(Check, { size: 14 }) : /* @__PURE__ */ jsx13(ClipboardCopy, { size: 14 }),
2285
+ return /* @__PURE__ */ jsx15("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ jsxs13("div", { style: styles.modal, onClick: (e) => e.stopPropagation(), children: [
2286
+ /* @__PURE__ */ jsxs13("div", { style: styles.modalHeader, children: [
2287
+ /* @__PURE__ */ jsx15("span", { style: { fontWeight: 600, fontSize: 14 }, children: chrome.formJson }),
2288
+ /* @__PURE__ */ jsxs13("div", { style: { display: "flex", gap: 8 }, children: [
2289
+ /* @__PURE__ */ jsxs13("button", { style: styles.ghostBtn, onClick: onCopy, children: [
2290
+ copied ? /* @__PURE__ */ jsx15(Check, { size: 14 }) : /* @__PURE__ */ jsx15(ClipboardCopy, { size: 14 }),
2071
2291
  copied ? chrome.copied : chrome.copy
2072
2292
  ] }),
2073
- /* @__PURE__ */ jsx13("button", { style: styles.iconBtn, onClick: onClose, children: /* @__PURE__ */ jsx13(X3, { size: 16 }) })
2293
+ /* @__PURE__ */ jsx15("button", { style: styles.iconBtn, onClick: onClose, children: /* @__PURE__ */ jsx15(X3, { size: 16 }) })
2074
2294
  ] })
2075
2295
  ] }),
2076
- /* @__PURE__ */ jsx13("pre", { style: styles.jsonPre, children: jsonString })
2296
+ /* @__PURE__ */ jsx15("pre", { style: styles.jsonPre, children: jsonString })
2077
2297
  ] }) });
2078
2298
  }
2079
2299
 
2080
- // src/components/modals/LibraryModal.tsx
2300
+ // src/components/modals/TemplatesModal.tsx
2081
2301
  import { Trash2 as Trash24, X as X4 } from "lucide-react";
2082
- import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
2083
- function LibraryModal({ chrome, savedForms, currentFormId, onOpen, onDelete, onClose }) {
2084
- return /* @__PURE__ */ jsx14("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ jsxs13("div", { style: styles.modal, onClick: (e) => e.stopPropagation(), children: [
2085
- /* @__PURE__ */ jsxs13("div", { style: styles.modalHeader, children: [
2086
- /* @__PURE__ */ jsx14("span", { style: { fontWeight: 600, fontSize: 14 }, children: chrome.myForms }),
2087
- /* @__PURE__ */ jsx14("button", { style: styles.iconBtn, onClick: onClose, children: /* @__PURE__ */ jsx14(X4, { size: 16 }) })
2302
+ import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
2303
+ function TemplatesModal({ chrome, savedForms, currentFormId, onOpen, onDelete, onClose }) {
2304
+ return /* @__PURE__ */ jsx16("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ jsxs14("div", { style: styles.modal, onClick: (e) => e.stopPropagation(), children: [
2305
+ /* @__PURE__ */ jsxs14("div", { style: styles.modalHeader, children: [
2306
+ /* @__PURE__ */ jsx16("span", { style: { fontWeight: 600, fontSize: 14 }, children: chrome.templates }),
2307
+ /* @__PURE__ */ jsx16("button", { style: styles.iconBtn, onClick: onClose, children: /* @__PURE__ */ jsx16(X4, { size: 16 }) })
2088
2308
  ] }),
2089
- /* @__PURE__ */ jsx14("div", { style: styles.libraryBody, children: savedForms.length === 0 ? /* @__PURE__ */ jsx14("div", { style: styles.inspectorEmpty, children: chrome.nothingSaved }) : savedForms.map((f) => /* @__PURE__ */ jsxs13("div", { style: styles.libraryRow, children: [
2090
- /* @__PURE__ */ jsxs13("div", { style: { minWidth: 0 }, children: [
2091
- /* @__PURE__ */ jsxs13("div", { style: styles.libraryRowTitle, children: [
2309
+ /* @__PURE__ */ jsx16("div", { style: styles.libraryBody, children: savedForms.length === 0 ? /* @__PURE__ */ jsx16("div", { style: styles.inspectorEmpty, children: chrome.noTemplates }) : savedForms.map((f) => /* @__PURE__ */ jsxs14("div", { style: styles.libraryRow, children: [
2310
+ /* @__PURE__ */ jsxs14("div", { style: { minWidth: 0 }, children: [
2311
+ /* @__PURE__ */ jsxs14("div", { style: styles.libraryRowTitle, children: [
2092
2312
  f.title,
2093
- f.id === currentFormId && /* @__PURE__ */ jsx14("span", { style: styles.currentBadge, children: chrome.current })
2313
+ f.id === currentFormId && /* @__PURE__ */ jsx16("span", { style: styles.currentBadge, children: chrome.current })
2094
2314
  ] }),
2095
- /* @__PURE__ */ jsxs13("div", { style: styles.libraryRowMeta, children: [
2315
+ /* @__PURE__ */ jsxs14("div", { style: styles.libraryRowMeta, children: [
2096
2316
  chrome.updated,
2097
2317
  " ",
2098
2318
  new Date(f.updatedAt).toLocaleString()
2099
2319
  ] })
2100
2320
  ] }),
2101
- /* @__PURE__ */ jsxs13("div", { style: { display: "flex", gap: 6, flexShrink: 0 }, children: [
2102
- /* @__PURE__ */ jsx14("button", { style: styles.ghostBtn, onClick: () => onOpen(f.id), children: chrome.open }),
2103
- /* @__PURE__ */ jsx14("button", { style: { ...styles.iconBtn, ...styles.iconBtnDanger }, title: chrome.delete, onClick: () => onDelete(f.id), children: /* @__PURE__ */ jsx14(Trash24, { size: 13 }) })
2321
+ /* @__PURE__ */ jsxs14("div", { style: { display: "flex", gap: 6, flexShrink: 0 }, children: [
2322
+ /* @__PURE__ */ jsx16("button", { style: styles.ghostBtn, onClick: () => onOpen(f.id), children: chrome.open }),
2323
+ /* @__PURE__ */ jsx16("button", { style: { ...styles.iconBtn, ...styles.iconBtnDanger }, title: chrome.delete, onClick: () => onDelete(f.id), children: /* @__PURE__ */ jsx16(Trash24, { size: 13 }) })
2104
2324
  ] })
2105
2325
  ] }, f.id)) })
2106
2326
  ] }) });
@@ -2109,19 +2329,19 @@ function LibraryModal({ chrome, savedForms, currentFormId, onOpen, onDelete, onC
2109
2329
  // src/components/modals/SaveAsModal.tsx
2110
2330
  import { useState as useState7 } from "react";
2111
2331
  import { Save as Save2, X as X5 } from "lucide-react";
2112
- import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
2332
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
2113
2333
  function SaveAsModal({ chrome, suggestedName, onSave, onClose }) {
2114
2334
  const [name, setName] = useState7(suggestedName);
2115
- return /* @__PURE__ */ jsx15("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ jsxs14("div", { style: { ...styles.modal, width: 380 }, onClick: (e) => e.stopPropagation(), children: [
2116
- /* @__PURE__ */ jsxs14("div", { style: styles.modalHeader, children: [
2117
- /* @__PURE__ */ jsx15("span", { style: { fontWeight: 600, fontSize: 14 }, children: chrome.saveForm }),
2118
- /* @__PURE__ */ jsx15("button", { style: styles.iconBtn, onClick: onClose, children: /* @__PURE__ */ jsx15(X5, { size: 16 }) })
2335
+ return /* @__PURE__ */ jsx17("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ jsxs15("div", { style: { ...styles.modal, maxWidth: 380 }, onClick: (e) => e.stopPropagation(), children: [
2336
+ /* @__PURE__ */ jsxs15("div", { style: styles.modalHeader, children: [
2337
+ /* @__PURE__ */ jsx17("span", { style: { fontWeight: 600, fontSize: 14 }, children: chrome.saveForm }),
2338
+ /* @__PURE__ */ jsx17("button", { style: styles.iconBtn, onClick: onClose, children: /* @__PURE__ */ jsx17(X5, { size: 16 }) })
2119
2339
  ] }),
2120
- /* @__PURE__ */ jsxs14("div", { style: { padding: 16 }, children: [
2121
- /* @__PURE__ */ jsx15("label", { style: styles.propLabel, children: chrome.formName }),
2122
- /* @__PURE__ */ jsx15("input", { autoFocus: true, style: styles.propInput, value: name, onChange: (e) => setName(e.target.value), onKeyDown: (e) => e.key === "Enter" && name.trim() && onSave(name.trim()) }),
2123
- /* @__PURE__ */ jsxs14("button", { style: { ...styles.primaryBtn, width: "100%", justifyContent: "center", marginTop: 14 }, disabled: !name.trim(), onClick: () => onSave(name.trim()), children: [
2124
- /* @__PURE__ */ jsx15(Save2, { size: 14 }),
2340
+ /* @__PURE__ */ jsxs15("div", { style: { padding: 16 }, children: [
2341
+ /* @__PURE__ */ jsx17("label", { style: styles.propLabel, children: chrome.formName }),
2342
+ /* @__PURE__ */ jsx17("input", { autoFocus: true, style: styles.propInput, value: name, onChange: (e) => setName(e.target.value), onKeyDown: (e) => e.key === "Enter" && name.trim() && onSave(name.trim()) }),
2343
+ /* @__PURE__ */ jsxs15("button", { style: { ...styles.primaryBtn, width: "100%", justifyContent: "center", marginTop: 14 }, disabled: !name.trim(), onClick: () => onSave(name.trim()), children: [
2344
+ /* @__PURE__ */ jsx17(Save2, { size: 14 }),
2125
2345
  " ",
2126
2346
  chrome.saveToLibrary
2127
2347
  ] })
@@ -2129,45 +2349,6 @@ function SaveAsModal({ chrome, suggestedName, onSave, onClose }) {
2129
2349
  ] }) });
2130
2350
  }
2131
2351
 
2132
- // src/components/modals/SettingsModal.tsx
2133
- import { X as X6 } from "lucide-react";
2134
- import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
2135
- function SettingsModal({
2136
- chrome,
2137
- strings,
2138
- submitLabel,
2139
- language,
2140
- submitMode,
2141
- submitStyle,
2142
- onSubmitLabelChange,
2143
- onSubmitModeChange,
2144
- onSubmitStyleChange,
2145
- onClose
2146
- }) {
2147
- return /* @__PURE__ */ jsx16("div", { style: styles.modalOverlay, onClick: onClose, children: /* @__PURE__ */ jsxs15("div", { style: { ...styles.modal, width: 400 }, onClick: (e) => e.stopPropagation(), children: [
2148
- /* @__PURE__ */ jsxs15("div", { style: styles.modalHeader, children: [
2149
- /* @__PURE__ */ jsx16("span", { style: { fontWeight: 600, fontSize: 14 }, children: chrome.formSettings }),
2150
- /* @__PURE__ */ jsx16("button", { style: styles.iconBtn, onClick: onClose, children: /* @__PURE__ */ jsx16(X6, { size: 16 }) })
2151
- ] }),
2152
- /* @__PURE__ */ jsxs15("div", { style: { padding: 16 }, children: [
2153
- /* @__PURE__ */ jsx16("div", { style: styles.panelHeading, children: chrome.submitSectionTitle }),
2154
- /* @__PURE__ */ jsx16("label", { style: styles.propLabel, children: chrome.submitLabel }),
2155
- /* @__PURE__ */ jsx16("input", { style: styles.propInput, placeholder: strings.submit, value: t(submitLabel, language), onChange: (e) => onSubmitLabelChange(e.target.value) }),
2156
- /* @__PURE__ */ jsx16("label", { style: styles.propLabel, children: chrome.submitMode }),
2157
- /* @__PURE__ */ jsx16(Segmented, { options: [{ value: "combined", label: chrome.combined }, { value: "perSection", label: chrome.perSection }], value: submitMode, onChange: onSubmitModeChange }),
2158
- /* @__PURE__ */ jsx16("div", { style: styles.inspectorDivider }),
2159
- /* @__PURE__ */ jsx16("div", { style: styles.panelHeading, children: chrome.submitStyle }),
2160
- /* @__PURE__ */ jsx16("label", { style: styles.propLabel, children: chrome.color }),
2161
- /* @__PURE__ */ jsxs15("div", { style: styles.swatchRow, children: [
2162
- BUTTON_COLOR_SWATCHES.map((c) => /* @__PURE__ */ jsx16("button", { type: "button", title: c || chrome.none, style: { ...styles.swatchBtn, background: c || "var(--fb-primary)", ...(submitStyle.color || "") === c ? styles.swatchBtnActive : {} }, onClick: () => onSubmitStyleChange({ color: c }) }, c || "default")),
2163
- /* @__PURE__ */ jsx16("input", { type: "color", value: submitStyle.color || "#5B5FEF", onChange: (e) => onSubmitStyleChange({ color: e.target.value }), style: styles.colorPickerInput })
2164
- ] }),
2165
- /* @__PURE__ */ jsx16("label", { style: styles.propLabel, children: chrome.buttonSize }),
2166
- /* @__PURE__ */ jsx16(Segmented, { options: SUBMIT_SIZE_OPTIONS, value: submitStyle.size, onChange: (v) => onSubmitStyleChange({ size: v }) })
2167
- ] })
2168
- ] }) });
2169
- }
2170
-
2171
2352
  // src/styles/globalCss.ts
2172
2353
  var css = `
2173
2354
  * { box-sizing: border-box; }
@@ -2175,19 +2356,58 @@ var css = `
2175
2356
  input, textarea, select { font-family: inherit; }
2176
2357
  @keyframes fb-spin { to { transform: rotate(360deg); } }
2177
2358
  .spin { animation: fb-spin 0.8s linear infinite; }
2359
+ /* Caps the widget at the viewport height so it scrolls internally rather
2360
+ than growing past whatever space its host container gives it; the
2361
+ second declaration upgrades to the dynamic viewport unit on browsers
2362
+ that support it (mobile browser chrome resizing the viewport), and is
2363
+ simply ignored by ones that don't. */
2364
+ .fb-root { max-height: 100vh; max-height: 100dvh; }
2365
+
2366
+ /* Below this width the fixed 200px Palette + 270px Inspector columns
2367
+ don't leave room for a usable Canvas, so instead of stacking all
2368
+ three in flow (which buries Canvas under a tall Palette), Palette
2369
+ and Inspector become narrow drawers over Canvas (which stays
2370
+ partially visible behind them), toggled by .fb-mobile-bar's two
2371
+ buttons, tracked by .fb-work-area's data-mobile-panel attribute,
2372
+ and dismissible via .fb-mobile-backdrop. */
2373
+ .fb-mobile-bar { display: none; align-items: center; gap: 6px; padding: 6px 10px; border-bottom: 1px solid var(--fb-border); background: var(--fb-surface); flex-shrink: 0; }
2374
+ .fb-mobile-btn { display: flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 7px; border: 1px solid var(--fb-border); background: var(--fb-surface); color: var(--fb-muted); font-size: 12.5px; font-weight: 600; }
2375
+ .fb-mobile-btn[aria-pressed="true"] { border-color: var(--fb-primary); background: var(--fb-primary-soft); color: var(--fb-primary); }
2376
+ .fb-mobile-backdrop { display: none; }
2377
+ @media (max-width: 720px) {
2378
+ .fb-mobile-bar { display: flex; }
2379
+ .fb-work-area { flex-direction: column !important; min-height: 0; }
2380
+ .fb-canvas-area { position: relative; overflow: hidden; }
2381
+ .fb-canvas { width: 100%; }
2382
+ .fb-mobile-backdrop { display: block; position: absolute; inset: 0; z-index: 6; background: rgba(15,16,20,0.35); }
2383
+ .fb-palette, .fb-inspector {
2384
+ position: absolute; top: 0; bottom: 0; z-index: 7;
2385
+ width: min(260px, 80vw) !important; max-height: none !important;
2386
+ border: none !important;
2387
+ box-shadow: 0 0 24px rgba(0,0,0,0.18);
2388
+ transition: transform 0.18s ease;
2389
+ }
2390
+ .fb-palette { left: 0; transform: translateX(-100%); }
2391
+ .fb-inspector { right: 0; transform: translateX(100%); }
2392
+ .fb-work-area[data-mobile-panel="palette"] .fb-palette,
2393
+ .fb-work-area[data-mobile-panel="inspector"] .fb-inspector { transform: translateX(0); }
2394
+ }
2178
2395
  `;
2179
2396
 
2180
2397
  // src/FormBuilder.tsx
2181
- import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
2182
- function FormBuilder({
2398
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
2399
+ var FormBuilder = forwardRef(function FormBuilder2({
2183
2400
  theme: themeOverrideProp,
2184
2401
  language: languageOverride,
2185
2402
  languages = DEFAULT_LANGUAGES,
2186
2403
  strings: stringsOverride,
2187
2404
  chrome: chromeOverride,
2188
- themeEditable = false,
2189
- storage: storageProp
2190
- } = {}) {
2405
+ features: featuresProp,
2406
+ storage: storageProp,
2407
+ onSubmit,
2408
+ initialDocument
2409
+ }, ref) {
2410
+ const features = resolveFeatures(featuresProp);
2191
2411
  const storage = storageProp ?? localStorageAdapter;
2192
2412
  const { theme, updateThemeColor, updateThemeLayout, resetTheme, replaceThemeOverrides, themeOverrides } = useTheme(themeOverrideProp);
2193
2413
  const [language, setLanguage] = useState8(languageOverride || languages[0]?.code || "en");
@@ -2197,20 +2417,16 @@ function FormBuilder({
2197
2417
  const drag = useDragReorder(doc.reorderWithinSection);
2198
2418
  const [mode, setMode] = useState8("build");
2199
2419
  const [showJson, setShowJson] = useState8(false);
2200
- const [showSettings, setShowSettings] = useState8(false);
2201
2420
  const [showLibrary, setShowLibrary] = useState8(false);
2202
2421
  const [copied, setCopied] = useState8(false);
2422
+ const [mobilePanel, setMobilePanel] = useState8("none");
2203
2423
  const persistence = usePersistence({
2204
2424
  storage,
2425
+ autosave: features.autosave,
2205
2426
  language,
2206
- document: {
2207
- title: doc.title,
2208
- submitLabel: doc.submitLabel,
2209
- submitMode: doc.submitMode,
2210
- submitStyle: doc.submitStyle,
2211
- themeOverrides,
2212
- sections: doc.sections
2213
- },
2427
+ chrome,
2428
+ document: { title: doc.title, themeOverrides, sections: doc.sections },
2429
+ initialDocument,
2214
2430
  onLoadDocument: doc.loadDocument,
2215
2431
  onLoadThemeOverrides: replaceThemeOverrides,
2216
2432
  onTitleChange: doc.setTitle,
@@ -2221,13 +2437,11 @@ function FormBuilder({
2221
2437
  ensureActiveSection: () => doc.setActiveSectionId((prev) => prev ?? doc.sections[0]?.id ?? null)
2222
2438
  });
2223
2439
  const jsonDoc = {
2224
- version: 4,
2440
+ version: 5,
2225
2441
  title: doc.title,
2226
- submitLabel: doc.submitLabel,
2227
- submitMode: doc.submitMode,
2228
- submitStyle: doc.submitStyle,
2442
+ theme,
2229
2443
  themeOverrides,
2230
- sections: doc.sections.map((s) => ({ id: s.id, title: s.title, background: s.background, collapsed: s.collapsed, submitStyle: s.submitStyle, fields: s.fields }))
2444
+ sections: doc.sections.map((s) => ({ id: s.id, title: s.title, background: s.background, collapsed: s.collapsed, fields: s.fields }))
2231
2445
  };
2232
2446
  const jsonString = JSON.stringify(jsonDoc, null, 2);
2233
2447
  function copyJson() {
@@ -2237,6 +2451,17 @@ function FormBuilder({
2237
2451
  }).catch(() => {
2238
2452
  });
2239
2453
  }
2454
+ useImperativeHandle(ref, () => ({
2455
+ getDocument: () => jsonDoc,
2456
+ exportJson: () => jsonString,
2457
+ loadDocument: (raw) => {
2458
+ const migrated = migrateDocument(raw);
2459
+ if (!migrated) return;
2460
+ doc.loadDocument(migrated);
2461
+ replaceThemeOverrides(migrated.themeOverrides);
2462
+ }
2463
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2464
+ }), [jsonDoc, jsonString]);
2240
2465
  const activeSectionIdx = doc.sections.findIndex((s) => s.id === doc.activeSection?.id);
2241
2466
  const activeSectionLabel = t(doc.activeSection?.title, language) || `#${activeSectionIdx + 1}`;
2242
2467
  const rootStyle = {
@@ -2251,6 +2476,7 @@ function FormBuilder({
2251
2476
  "--fb-surface": theme.surface,
2252
2477
  "--fb-canvas": theme.canvas,
2253
2478
  "--fb-page-bg": theme.pageBackground,
2479
+ "--fb-surface-2": mixHex(theme.surface, theme.ink, 0.06),
2254
2480
  "--fb-space-page": `${theme.layout.pagePadding}px`,
2255
2481
  "--fb-space-canvas": `${theme.layout.canvasPadding}px`,
2256
2482
  "--fb-space-section": `${theme.layout.sectionGap}px`,
@@ -2259,9 +2485,9 @@ function FormBuilder({
2259
2485
  "--fb-space-panel": `${theme.layout.panelPadding}px`,
2260
2486
  "--fb-space-ticket": `${theme.layout.ticketPadding}px`
2261
2487
  };
2262
- return /* @__PURE__ */ jsxs16("div", { style: rootStyle, children: [
2263
- /* @__PURE__ */ jsx17("style", { children: css }),
2264
- /* @__PURE__ */ jsx17(
2488
+ return /* @__PURE__ */ jsxs16("div", { className: "fb-root", style: rootStyle, children: [
2489
+ /* @__PURE__ */ jsx18("style", { children: css }),
2490
+ /* @__PURE__ */ jsx18(
2265
2491
  Toolbar,
2266
2492
  {
2267
2493
  title: doc.title,
@@ -2270,75 +2496,117 @@ function FormBuilder({
2270
2496
  mode,
2271
2497
  saveState: persistence.saveState,
2272
2498
  chrome,
2273
- themeEditable,
2274
- theme,
2499
+ features,
2275
2500
  savedFormsCount: persistence.savedForms.length,
2276
2501
  onTitleChange: doc.updateTitle,
2277
2502
  onLanguageChange: setLanguage,
2278
2503
  onModeChange: setMode,
2279
- onOpenSettings: () => setShowSettings(true),
2280
2504
  onNewForm: persistence.newForm,
2281
2505
  onOpenLibrary: () => setShowLibrary(true),
2282
2506
  onSaveExisting: persistence.saveExisting,
2283
- onOpenJson: () => setShowJson(true),
2284
- updateThemeColor,
2285
- updateThemeLayout,
2286
- resetTheme
2507
+ onOpenJson: () => setShowJson(true)
2287
2508
  }
2288
2509
  ),
2289
2510
  persistence.loadingDraft ? /* @__PURE__ */ jsxs16("div", { style: styles.loadingScreen, children: [
2290
- /* @__PURE__ */ jsx17(Loader22, { size: 20, className: "spin" }),
2291
- /* @__PURE__ */ jsx17("span", { style: { marginTop: 8, fontSize: 13, color: "var(--fb-muted)" }, children: chrome.loadingDraft })
2292
- ] }) : mode === "build" ? /* @__PURE__ */ jsxs16("div", { style: styles.workArea, children: [
2293
- /* @__PURE__ */ jsx17(Palette, { activeSectionLabel, chrome, onAddField: doc.addField }),
2294
- /* @__PURE__ */ jsx17(
2295
- Canvas,
2296
- {
2297
- sections: doc.sections,
2298
- activeSectionId: doc.activeSectionId,
2299
- submitMode: doc.submitMode,
2300
- submitStyle: doc.submitStyle,
2301
- selectedId: doc.selectedId,
2302
- dragOverKey: drag.dragOverKey,
2303
- chrome,
2304
- strings,
2305
- language,
2306
- onActivateSection: doc.setActiveSectionId,
2307
- onToggleSectionCollapse: doc.toggleSectionCollapse,
2308
- onUpdateSectionTitle: doc.updateSectionTitle,
2309
- onUpdateSectionBackground: doc.updateSectionBackground,
2310
- onDuplicateSection: doc.duplicateSection,
2311
- onMoveSection: doc.moveSection,
2312
- onDeleteSection: doc.deleteSection,
2313
- onUpdateSectionSubmitStyle: doc.updateSectionSubmitStyle,
2314
- onClearSectionSubmitStyle: doc.clearSectionSubmitStyle,
2315
- onAddSection: doc.addSection,
2316
- onSelectField: (sectionId, fieldId) => {
2317
- doc.setSelectedId(fieldId);
2318
- doc.setActiveSectionId(sectionId);
2319
- },
2320
- onFieldChange: doc.updateField,
2321
- onMoveField: doc.moveField,
2322
- onDuplicateField: doc.duplicateField,
2323
- onDeleteField: doc.deleteField,
2324
- getDropZoneHandlers: drag.getDropZoneHandlers,
2325
- getDragHandleProps: drag.getDragHandleProps
2326
- }
2327
- ),
2328
- /* @__PURE__ */ jsx17(
2329
- Inspector,
2330
- {
2331
- selected: doc.selected,
2332
- language,
2333
- chrome,
2334
- onUpdateField: (patch) => doc.selected && doc.updateField(doc.selected.id, patch),
2335
- onDeleteField: () => doc.selected && doc.deleteField(doc.selected.id),
2336
- onUpdateOption: (optIdx, patch) => doc.selected && doc.updateOption(doc.selected.id, optIdx, patch),
2337
- onAddOption: () => doc.selected && doc.addOption(doc.selected.id),
2338
- onRemoveOption: (optIdx) => doc.selected && doc.removeOption(doc.selected.id, optIdx)
2339
- }
2340
- )
2341
- ] }) : /* @__PURE__ */ jsx17(
2511
+ /* @__PURE__ */ jsx18(Loader22, { size: 20, className: "spin" }),
2512
+ /* @__PURE__ */ jsx18("span", { style: { marginTop: 8, fontSize: 13, color: "var(--fb-muted)" }, children: chrome.loadingDraft })
2513
+ ] }) : mode === "build" ? /* @__PURE__ */ jsxs16("div", { className: "fb-work-area", style: styles.workArea, "data-mobile-panel": mobilePanel, children: [
2514
+ /* @__PURE__ */ jsxs16("div", { className: "fb-mobile-bar", children: [
2515
+ /* @__PURE__ */ jsxs16(
2516
+ "button",
2517
+ {
2518
+ type: "button",
2519
+ className: "fb-mobile-btn",
2520
+ "aria-pressed": mobilePanel === "palette",
2521
+ onClick: () => setMobilePanel((p) => p === "palette" ? "none" : "palette"),
2522
+ children: [
2523
+ /* @__PURE__ */ jsx18(Menu, { size: 14 }),
2524
+ " ",
2525
+ chrome.paletteTabBlocks
2526
+ ]
2527
+ }
2528
+ ),
2529
+ /* @__PURE__ */ jsxs16(
2530
+ "button",
2531
+ {
2532
+ type: "button",
2533
+ className: "fb-mobile-btn",
2534
+ "aria-pressed": mobilePanel === "inspector",
2535
+ onClick: () => setMobilePanel((p) => p === "inspector" ? "none" : "inspector"),
2536
+ children: [
2537
+ /* @__PURE__ */ jsx18(SlidersHorizontal, { size: 14 }),
2538
+ " ",
2539
+ chrome.properties
2540
+ ]
2541
+ }
2542
+ )
2543
+ ] }),
2544
+ /* @__PURE__ */ jsxs16("div", { className: "fb-canvas-area", style: styles.workArea, children: [
2545
+ mobilePanel !== "none" && /* @__PURE__ */ jsx18("div", { className: "fb-mobile-backdrop", onClick: () => setMobilePanel("none") }),
2546
+ /* @__PURE__ */ jsx18(
2547
+ Palette,
2548
+ {
2549
+ activeSectionLabel,
2550
+ chrome,
2551
+ onAddField: (type) => {
2552
+ doc.addField(type);
2553
+ setMobilePanel("none");
2554
+ },
2555
+ features,
2556
+ theme,
2557
+ updateThemeColor,
2558
+ updateThemeLayout,
2559
+ resetTheme
2560
+ }
2561
+ ),
2562
+ /* @__PURE__ */ jsx18(
2563
+ Canvas,
2564
+ {
2565
+ sections: doc.sections,
2566
+ activeSectionId: doc.activeSectionId,
2567
+ selectedId: doc.selectedId,
2568
+ dragOverKey: drag.dragOverKey,
2569
+ chrome,
2570
+ strings,
2571
+ language,
2572
+ features,
2573
+ onActivateSection: doc.setActiveSectionId,
2574
+ onToggleSectionCollapse: doc.toggleSectionCollapse,
2575
+ onUpdateSectionTitle: doc.updateSectionTitle,
2576
+ onUpdateSectionBackground: doc.updateSectionBackground,
2577
+ onDuplicateSection: doc.duplicateSection,
2578
+ onMoveSection: doc.moveSection,
2579
+ onDeleteSection: doc.deleteSection,
2580
+ onAddSection: doc.addSection,
2581
+ onSelectField: (sectionId, fieldId) => {
2582
+ doc.setSelectedId(fieldId);
2583
+ doc.setActiveSectionId(sectionId);
2584
+ setMobilePanel("inspector");
2585
+ },
2586
+ onFieldChange: doc.updateField,
2587
+ onMoveField: doc.moveField,
2588
+ onDuplicateField: doc.duplicateField,
2589
+ onDeleteField: doc.deleteField,
2590
+ getDropZoneHandlers: drag.getDropZoneHandlers,
2591
+ getDragHandleProps: drag.getDragHandleProps
2592
+ }
2593
+ ),
2594
+ /* @__PURE__ */ jsx18(
2595
+ Inspector,
2596
+ {
2597
+ selected: doc.selected,
2598
+ language,
2599
+ chrome,
2600
+ features,
2601
+ onUpdateField: (patch) => doc.selected && doc.updateField(doc.selected.id, patch),
2602
+ onDeleteField: () => doc.selected && doc.deleteField(doc.selected.id),
2603
+ onUpdateOption: (optIdx, patch) => doc.selected && doc.updateOption(doc.selected.id, optIdx, patch),
2604
+ onAddOption: () => doc.selected && doc.addOption(doc.selected.id),
2605
+ onRemoveOption: (optIdx) => doc.selected && doc.removeOption(doc.selected.id, optIdx)
2606
+ }
2607
+ )
2608
+ ] })
2609
+ ] }) : /* @__PURE__ */ jsx18(
2342
2610
  PreviewPane,
2343
2611
  {
2344
2612
  title: doc.title,
@@ -2348,14 +2616,12 @@ function FormBuilder({
2348
2616
  strings,
2349
2617
  chrome,
2350
2618
  baseMaxWidth: theme.layout.maxWidth,
2351
- submitLabel: doc.submitLabel,
2352
- submitMode: doc.submitMode,
2353
- submitStyle: doc.submitStyle
2619
+ onSubmit
2354
2620
  }
2355
2621
  ),
2356
- showJson && /* @__PURE__ */ jsx17(JsonModal, { chrome, jsonString, copied, onCopy: copyJson, onClose: () => setShowJson(false) }),
2357
- showLibrary && /* @__PURE__ */ jsx17(
2358
- LibraryModal,
2622
+ showJson && /* @__PURE__ */ jsx18(JsonModal, { chrome, jsonString, copied, onCopy: copyJson, onClose: () => setShowJson(false) }),
2623
+ showLibrary && /* @__PURE__ */ jsx18(
2624
+ TemplatesModal,
2359
2625
  {
2360
2626
  chrome,
2361
2627
  savedForms: persistence.savedForms,
@@ -2368,7 +2634,7 @@ function FormBuilder({
2368
2634
  onClose: () => setShowLibrary(false)
2369
2635
  }
2370
2636
  ),
2371
- persistence.saveAsPrompt && /* @__PURE__ */ jsx17(
2637
+ persistence.saveAsPrompt && /* @__PURE__ */ jsx18(
2372
2638
  SaveAsModal,
2373
2639
  {
2374
2640
  chrome,
@@ -2376,27 +2642,30 @@ function FormBuilder({
2376
2642
  onSave: persistence.saveAs,
2377
2643
  onClose: persistence.dismissSaveAsPrompt
2378
2644
  }
2379
- ),
2380
- showSettings && /* @__PURE__ */ jsx17(
2381
- SettingsModal,
2382
- {
2383
- chrome,
2384
- strings,
2385
- submitLabel: doc.submitLabel,
2386
- language,
2387
- submitMode: doc.submitMode,
2388
- submitStyle: doc.submitStyle,
2389
- onSubmitLabelChange: doc.updateSubmitLabel,
2390
- onSubmitModeChange: doc.setSubmitMode,
2391
- onSubmitStyleChange: doc.updateSubmitStyle,
2392
- onClose: () => setShowSettings(false)
2393
- }
2394
2645
  )
2395
2646
  ] });
2396
- }
2647
+ });
2648
+ var FormBuilder_default = FormBuilder;
2649
+
2650
+ // src/theme/darkTheme.ts
2651
+ var DARK_THEME = {
2652
+ primary: "#8B8FF5",
2653
+ primarySoft: "#262A45",
2654
+ danger: "#F0715B",
2655
+ dangerSoft: "#3A2420",
2656
+ ink: "#EDEEF2",
2657
+ muted: "#9096A8",
2658
+ border: "#2E313D",
2659
+ surface: "#1A1B23",
2660
+ canvas: "#121319",
2661
+ pageBackground: "#1A1B23",
2662
+ layout: DEFAULT_THEME.layout
2663
+ };
2397
2664
  export {
2398
- FormBuilder,
2399
- FormBuilder as default,
2665
+ DARK_THEME,
2666
+ DEFAULT_THEME,
2667
+ FormBuilder_default as FormBuilder,
2668
+ FormBuilder_default as default,
2400
2669
  localStorageAdapter
2401
2670
  };
2402
2671
  //# sourceMappingURL=index.js.map