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/LICENSE +0 -0
- package/README.md +183 -9
- package/dist/index.cjs +1086 -816
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +129 -32
- package/dist/index.d.ts +129 -32
- package/dist/index.js +1083 -814
- package/dist/index.js.map +1 -1
- package/package.json +12 -4
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
|
-
|
|
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
|
-
|
|
106
|
-
saveToLibraryTitle: "Save this form
|
|
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
|
-
|
|
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
|
|
123
|
-
formName: "
|
|
124
|
-
saveToLibrary: "Save
|
|
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
|
-
|
|
157
|
-
|
|
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
|
-
|
|
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
|
-
|
|
235
|
-
saveToLibraryTitle: "\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u3092\
|
|
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
|
-
|
|
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: "\
|
|
252
|
-
formName: "\
|
|
253
|
-
saveToLibrary: "\
|
|
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
|
-
|
|
286
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
806
|
-
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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)",
|
|
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: "
|
|
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: "
|
|
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
|
|
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: "
|
|
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
|
|
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: "
|
|
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: "
|
|
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
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
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: "
|
|
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: "
|
|
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
|
|
1018
|
-
previewRadio: { display: "flex", alignItems: "center", gap: 6, fontSize: 13, color: "
|
|
1019
|
-
ticketActions: { display: "flex", flexDirection: "column", gap: 3, padding: 8, borderLeft: "1px solid
|
|
1020
|
-
iconBtn: { width: 24, height: 24, borderRadius: 6, border: "1px solid
|
|
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: "
|
|
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
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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/
|
|
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__ */
|
|
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__ */
|
|
1072
|
-
Icon && /* @__PURE__ */
|
|
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/
|
|
1079
|
-
import {
|
|
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/
|
|
1120
|
-
import { jsx as
|
|
1121
|
-
function
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
/* @__PURE__ */
|
|
1139
|
-
/* @__PURE__ */
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
] })
|
|
1148
|
-
|
|
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/
|
|
1161
|
-
import { Fragment, jsx as
|
|
1162
|
-
function
|
|
1163
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
chrome.
|
|
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
|
-
|
|
1229
|
-
savedFormsCount > 0 && /* @__PURE__ */ jsx3("span", { style: styles.countBadge, children: savedFormsCount })
|
|
1426
|
+
/* @__PURE__ */ jsx5("strong", { children: activeSectionLabel })
|
|
1230
1427
|
] }),
|
|
1231
|
-
/* @__PURE__ */
|
|
1232
|
-
/* @__PURE__ */
|
|
1233
|
-
|
|
1234
|
-
|
|
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__ */
|
|
1237
|
-
/* @__PURE__ */
|
|
1238
|
-
|
|
1239
|
-
|
|
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
|
|
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
|
|
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__ */
|
|
1397
|
-
return field.link ? /* @__PURE__ */
|
|
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
|
|
1402
|
-
function FieldBlock({ field, lang, onFieldChange, strings, chrome, error, isBuild }) {
|
|
1403
|
-
if (field.type === "image") return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1415
|
-
/* @__PURE__ */
|
|
1416
|
-
showLabel && /* @__PURE__ */
|
|
1417
|
-
IconComp && /* @__PURE__ */
|
|
1418
|
-
labelText || (isBuild ? /* @__PURE__ */
|
|
1419
|
-
field.required && /* @__PURE__ */
|
|
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__ */
|
|
1606
|
+
/* @__PURE__ */ jsx8("div", { style: { flex: 1, minWidth: 0 }, children: renderInteractive(field, lang, onFieldChange, IconComp, !!error, strings) })
|
|
1422
1607
|
] }),
|
|
1423
|
-
error && /* @__PURE__ */
|
|
1424
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1625
|
+
return /* @__PURE__ */ jsx8("input", { type: "email", ...common });
|
|
1441
1626
|
case "password":
|
|
1442
|
-
return /* @__PURE__ */
|
|
1627
|
+
return /* @__PURE__ */ jsx8("input", { type: "password", ...common, maxLength: field.maxLength || void 0 });
|
|
1443
1628
|
case "phone":
|
|
1444
|
-
return /* @__PURE__ */
|
|
1629
|
+
return /* @__PURE__ */ jsx8("input", { type: "tel", ...common });
|
|
1445
1630
|
case "date":
|
|
1446
|
-
return /* @__PURE__ */
|
|
1631
|
+
return /* @__PURE__ */ jsx8("input", { type: "date", ...common });
|
|
1447
1632
|
case "time":
|
|
1448
|
-
return /* @__PURE__ */
|
|
1633
|
+
return /* @__PURE__ */ jsx8("input", { type: "time", ...common });
|
|
1449
1634
|
default:
|
|
1450
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
1640
|
+
return /* @__PURE__ */ jsx8("textarea", { ...common, rows: 3, maxLength: field.maxLength || void 0 });
|
|
1456
1641
|
case "select":
|
|
1457
|
-
return /* @__PURE__ */
|
|
1458
|
-
/* @__PURE__ */
|
|
1459
|
-
(field.options || []).map((o) => /* @__PURE__ */
|
|
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__ */
|
|
1463
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1471
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1481
|
-
/* @__PURE__ */
|
|
1482
|
-
IconComp && /* @__PURE__ */
|
|
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__ */
|
|
1669
|
+
field.required && /* @__PURE__ */ jsx8("span", { style: { color: "var(--fb-danger)" }, children: " *" })
|
|
1485
1670
|
] });
|
|
1486
1671
|
case "toggle":
|
|
1487
|
-
return /* @__PURE__ */
|
|
1488
|
-
/* @__PURE__ */
|
|
1489
|
-
IconComp && /* @__PURE__ */
|
|
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__ */
|
|
1678
|
+
return /* @__PURE__ */ jsx8("input", { type: "text", ...common });
|
|
1494
1679
|
}
|
|
1495
1680
|
}
|
|
1496
1681
|
|
|
1497
1682
|
// src/components/FieldTicket.tsx
|
|
1498
|
-
import { jsx as
|
|
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__ */
|
|
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__ */
|
|
1533
|
-
/* @__PURE__ */
|
|
1534
|
-
/* @__PURE__ */
|
|
1535
|
-
/* @__PURE__ */
|
|
1536
|
-
/* @__PURE__ */
|
|
1537
|
-
/* @__PURE__ */
|
|
1538
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
1545
|
-
field.width && field.width !== "1/1" && /* @__PURE__ */
|
|
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__ */
|
|
1551
|
-
field.verticalAlign !== "top" && /* @__PURE__ */
|
|
1552
|
-
field.hideLabel && /* @__PURE__ */
|
|
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__ */
|
|
1740
|
+
/* @__PURE__ */ jsx9("div", { style: { marginTop: 8 }, children: /* @__PURE__ */ jsx9(FieldBlock, { field, lang: language, onFieldChange, strings, chrome, isBuild: true }) })
|
|
1555
1741
|
] }),
|
|
1556
|
-
/* @__PURE__ */
|
|
1557
|
-
/* @__PURE__ */
|
|
1558
|
-
/* @__PURE__ */
|
|
1559
|
-
/* @__PURE__ */
|
|
1560
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
1605
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1609
|
-
/* @__PURE__ */
|
|
1610
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1621
|
-
/* @__PURE__ */
|
|
1622
|
-
!section.collapsed && /* @__PURE__ */
|
|
1623
|
-
SECTION_BG_SWATCHES.map((c) => /* @__PURE__ */
|
|
1624
|
-
/* @__PURE__ */
|
|
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
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
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__ */
|
|
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
|
|
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__ */
|
|
1699
|
-
sections.map((section, sIdx) => /* @__PURE__ */
|
|
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__ */
|
|
1733
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
1750
|
-
/* @__PURE__ */
|
|
1751
|
-
/* @__PURE__ */
|
|
1752
|
-
/* @__PURE__ */
|
|
1753
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1760
|
-
/* @__PURE__ */
|
|
1761
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1764
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1775
|
-
/* @__PURE__ */
|
|
1776
|
-
/* @__PURE__ */
|
|
1777
|
-
/* @__PURE__ */
|
|
1778
|
-
(f.options || []).map((o) => /* @__PURE__ */
|
|
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__ */
|
|
1784
|
-
/* @__PURE__ */
|
|
1785
|
-
/* @__PURE__ */
|
|
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
|
|
1791
|
-
function Inspector({ selected, language, chrome, onUpdateField, onDeleteField, onUpdateOption, onAddOption, onRemoveOption }) {
|
|
1792
|
-
return /* @__PURE__ */
|
|
1793
|
-
/* @__PURE__ */
|
|
1794
|
-
!selected ? /* @__PURE__ */
|
|
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__ */
|
|
1813
|
-
!meta.isContent && /* @__PURE__ */
|
|
1814
|
-
/* @__PURE__ */
|
|
1815
|
-
/* @__PURE__ */
|
|
1816
|
-
/* @__PURE__ */
|
|
1817
|
-
/* @__PURE__ */
|
|
1818
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1822
|
-
/* @__PURE__ */
|
|
1823
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1826
|
-
/* @__PURE__ */
|
|
1827
|
-
/* @__PURE__ */
|
|
1828
|
-
/* @__PURE__ */
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
/* @__PURE__ */
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
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__ */
|
|
1848
|
-
/* @__PURE__ */
|
|
1849
|
-
/* @__PURE__ */
|
|
1850
|
-
/* @__PURE__ */
|
|
1851
|
-
/* @__PURE__ */
|
|
1852
|
-
/* @__PURE__ */
|
|
1853
|
-
/* @__PURE__ */
|
|
1854
|
-
/* @__PURE__ */
|
|
1855
|
-
/* @__PURE__ */
|
|
1856
|
-
/* @__PURE__ */
|
|
1857
|
-
/* @__PURE__ */
|
|
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
|
-
|
|
1860
|
-
/* @__PURE__ */
|
|
1861
|
-
/* @__PURE__ */
|
|
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
|
-
|
|
1864
|
-
/* @__PURE__ */
|
|
1865
|
-
/* @__PURE__ */
|
|
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 === "
|
|
1868
|
-
/* @__PURE__ */
|
|
1869
|
-
/* @__PURE__ */
|
|
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 === "
|
|
1874
|
-
/* @__PURE__ */
|
|
1875
|
-
/* @__PURE__ */
|
|
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
|
-
|
|
1878
|
-
/* @__PURE__ */
|
|
1879
|
-
/* @__PURE__ */
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
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__ */
|
|
1885
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1892
|
-
!meta.isContent && /* @__PURE__ */
|
|
1893
|
-
/* @__PURE__ */
|
|
1894
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1897
|
-
/* @__PURE__ */
|
|
1898
|
-
/* @__PURE__ */
|
|
1899
|
-
/* @__PURE__ */
|
|
1900
|
-
/* @__PURE__ */
|
|
1901
|
-
/* @__PURE__ */
|
|
1902
|
-
!meta.boolean && !meta.isContent && /* @__PURE__ */
|
|
1903
|
-
/* @__PURE__ */
|
|
1904
|
-
/* @__PURE__ */
|
|
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__ */
|
|
1907
|
-
/* @__PURE__ */
|
|
1908
|
-
/* @__PURE__ */
|
|
1909
|
-
/* @__PURE__ */
|
|
1910
|
-
/* @__PURE__ */
|
|
1911
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
1920
|
-
/* @__PURE__ */
|
|
1921
|
-
/* @__PURE__ */
|
|
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 {
|
|
1967
|
-
function PreviewPane({ title, sections, onFieldChange, language, strings, chrome, baseMaxWidth,
|
|
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
|
|
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__ */
|
|
2007
|
-
/* @__PURE__ */
|
|
2008
|
-
/* @__PURE__ */
|
|
2009
|
-
/* @__PURE__ */
|
|
2010
|
-
/* @__PURE__ */
|
|
2011
|
-
allFields.length === 0 && /* @__PURE__ */
|
|
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
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
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__ */
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
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__ */
|
|
2041
|
-
/* @__PURE__ */
|
|
2042
|
-
/* @__PURE__ */
|
|
2043
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2267
|
+
/* @__PURE__ */ jsx14("button", { style: styles.iconBtn, onClick: () => setSubmitted(null), children: /* @__PURE__ */ jsx14(X2, { size: 16 }) })
|
|
2048
2268
|
] }),
|
|
2049
|
-
/* @__PURE__ */
|
|
2050
|
-
/* @__PURE__ */
|
|
2051
|
-
/* @__PURE__ */
|
|
2052
|
-
/* @__PURE__ */
|
|
2053
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
2283
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2064
2284
|
function JsonModal({ chrome, jsonString, copied, onCopy, onClose }) {
|
|
2065
|
-
return /* @__PURE__ */
|
|
2066
|
-
/* @__PURE__ */
|
|
2067
|
-
/* @__PURE__ */
|
|
2068
|
-
/* @__PURE__ */
|
|
2069
|
-
/* @__PURE__ */
|
|
2070
|
-
copied ? /* @__PURE__ */
|
|
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__ */
|
|
2293
|
+
/* @__PURE__ */ jsx15("button", { style: styles.iconBtn, onClick: onClose, children: /* @__PURE__ */ jsx15(X3, { size: 16 }) })
|
|
2074
2294
|
] })
|
|
2075
2295
|
] }),
|
|
2076
|
-
/* @__PURE__ */
|
|
2296
|
+
/* @__PURE__ */ jsx15("pre", { style: styles.jsonPre, children: jsonString })
|
|
2077
2297
|
] }) });
|
|
2078
2298
|
}
|
|
2079
2299
|
|
|
2080
|
-
// src/components/modals/
|
|
2300
|
+
// src/components/modals/TemplatesModal.tsx
|
|
2081
2301
|
import { Trash2 as Trash24, X as X4 } from "lucide-react";
|
|
2082
|
-
import { jsx as
|
|
2083
|
-
function
|
|
2084
|
-
return /* @__PURE__ */
|
|
2085
|
-
/* @__PURE__ */
|
|
2086
|
-
/* @__PURE__ */
|
|
2087
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2090
|
-
/* @__PURE__ */
|
|
2091
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2313
|
+
f.id === currentFormId && /* @__PURE__ */ jsx16("span", { style: styles.currentBadge, children: chrome.current })
|
|
2094
2314
|
] }),
|
|
2095
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2102
|
-
/* @__PURE__ */
|
|
2103
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
2116
|
-
/* @__PURE__ */
|
|
2117
|
-
/* @__PURE__ */
|
|
2118
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2121
|
-
/* @__PURE__ */
|
|
2122
|
-
/* @__PURE__ */
|
|
2123
|
-
/* @__PURE__ */
|
|
2124
|
-
/* @__PURE__ */
|
|
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
|
|
2182
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
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:
|
|
2440
|
+
version: 5,
|
|
2225
2441
|
title: doc.title,
|
|
2226
|
-
|
|
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,
|
|
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__ */
|
|
2264
|
-
/* @__PURE__ */
|
|
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
|
-
|
|
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__ */
|
|
2291
|
-
/* @__PURE__ */
|
|
2292
|
-
] }) : mode === "build" ? /* @__PURE__ */ jsxs16("div", { style: styles.workArea, children: [
|
|
2293
|
-
/* @__PURE__ */
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
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
|
-
|
|
2352
|
-
submitMode: doc.submitMode,
|
|
2353
|
-
submitStyle: doc.submitStyle
|
|
2619
|
+
onSubmit
|
|
2354
2620
|
}
|
|
2355
2621
|
),
|
|
2356
|
-
showJson && /* @__PURE__ */
|
|
2357
|
-
showLibrary && /* @__PURE__ */
|
|
2358
|
-
|
|
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__ */
|
|
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
|
-
|
|
2399
|
-
|
|
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
|