@squaredr/fieldcraft-pro 1.4.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1032,6 +1032,14 @@ var QUESTION_TYPE_INFO = {
1032
1032
  icon: "Phone",
1033
1033
  description: "US phone number input"
1034
1034
  },
1035
+ phone_international: {
1036
+ type: "phone_international",
1037
+ label: "Intl Phone",
1038
+ category: "text",
1039
+ icon: "Globe2",
1040
+ description: "Phone with country code",
1041
+ defaultConfig: { type: "phone_international", defaultCountry: "US" }
1042
+ },
1035
1043
  url: {
1036
1044
  type: "url",
1037
1045
  label: "URL",
@@ -1125,6 +1133,14 @@ var QUESTION_TYPE_INFO = {
1125
1133
  requiresOptions: true,
1126
1134
  defaultConfig: { type: "ranking", items: [] }
1127
1135
  },
1136
+ country_select: {
1137
+ type: "country_select",
1138
+ label: "Country",
1139
+ category: "selection",
1140
+ icon: "Globe",
1141
+ description: "Country dropdown with search",
1142
+ defaultConfig: { type: "country_select" }
1143
+ },
1128
1144
  // ── Date/Time ──
1129
1145
  date: {
1130
1146
  type: "date",
@@ -1176,6 +1192,14 @@ var QUESTION_TYPE_INFO = {
1176
1192
  description: "Canvas signature pad",
1177
1193
  defaultConfig: { type: "signature" }
1178
1194
  },
1195
+ image_capture: {
1196
+ type: "image_capture",
1197
+ label: "Camera",
1198
+ category: "media",
1199
+ icon: "Camera",
1200
+ description: "Capture photo from camera",
1201
+ defaultConfig: { type: "image_capture", allowGallery: true }
1202
+ },
1179
1203
  date_range: {
1180
1204
  type: "date_range",
1181
1205
  label: "Date Range",
@@ -1184,6 +1208,14 @@ var QUESTION_TYPE_INFO = {
1184
1208
  description: "Start and end date picker",
1185
1209
  defaultConfig: { type: "date_range" }
1186
1210
  },
1211
+ appointment: {
1212
+ type: "appointment",
1213
+ label: "Appointment",
1214
+ category: "datetime",
1215
+ icon: "CalendarCheck",
1216
+ description: "Date & time slot booking",
1217
+ defaultConfig: { type: "appointment", duration: 30 }
1218
+ },
1187
1219
  // ── Advanced ──
1188
1220
  repeater: {
1189
1221
  type: "repeater",
@@ -1255,6 +1287,14 @@ var QUESTION_TYPE_INFO = {
1255
1287
  description: "Hidden value from URL or static",
1256
1288
  defaultConfig: { type: "hidden", source: "static" }
1257
1289
  },
1290
+ payment: {
1291
+ type: "payment",
1292
+ label: "Payment",
1293
+ category: "advanced",
1294
+ icon: "CreditCard",
1295
+ description: "Collect payment via Stripe",
1296
+ defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD" }
1297
+ },
1258
1298
  // ── Structural ──
1259
1299
  section_header: {
1260
1300
  type: "section_header",
@@ -1359,7 +1399,7 @@ var DEFAULT_PALETTE = [
1359
1399
  {
1360
1400
  category: "text",
1361
1401
  label: "Text Input",
1362
- types: ["short_text", "long_text", "email", "phone", "url", "legal_name", "address"]
1402
+ types: ["short_text", "long_text", "email", "phone", "phone_international", "url", "legal_name", "address"]
1363
1403
  },
1364
1404
  {
1365
1405
  category: "numeric",
@@ -1369,17 +1409,17 @@ var DEFAULT_PALETTE = [
1369
1409
  {
1370
1410
  category: "selection",
1371
1411
  label: "Selection",
1372
- types: ["single_select", "multi_select", "dropdown", "boolean", "ranking"]
1412
+ types: ["single_select", "multi_select", "dropdown", "boolean", "ranking", "country_select"]
1373
1413
  },
1374
1414
  {
1375
1415
  category: "datetime",
1376
1416
  label: "Date & Time",
1377
- types: ["date", "time", "date_range"]
1417
+ types: ["date", "time", "date_range", "appointment"]
1378
1418
  },
1379
1419
  {
1380
1420
  category: "media",
1381
1421
  label: "Media",
1382
- types: ["file_upload", "signature"]
1422
+ types: ["file_upload", "signature", "image_capture"]
1383
1423
  },
1384
1424
  {
1385
1425
  category: "content",
@@ -1394,7 +1434,7 @@ var DEFAULT_PALETTE = [
1394
1434
  {
1395
1435
  category: "advanced",
1396
1436
  label: "Advanced",
1397
- types: ["repeater", "likert", "scoring", "matrix", "calculated", "hidden"]
1437
+ types: ["repeater", "likert", "scoring", "matrix", "calculated", "hidden", "payment"]
1398
1438
  }
1399
1439
  ];
1400
1440
 
@@ -5008,57 +5048,271 @@ function FormBuilderInner(props) {
5008
5048
 
5009
5049
  // src/form-builder/components/FormBuilderGated.tsx
5010
5050
  var FormBuilder = requireLicense(FormBuilderInner, "FormBuilder");
5011
-
5012
- // src/form-builder/theme/presets.ts
5013
- var squaredrDarkPreset = {
5014
- background: "#0F1A1F",
5015
- foreground: "#E8EFF1",
5016
- card: "#16242A",
5017
- primary: "#63BDB4",
5018
- primaryForeground: "#0F1A1F",
5019
- secondary: "#182F31",
5020
- secondaryForeground: "#E8EFF1",
5021
- muted: "#182F31",
5022
- mutedForeground: "#8CA1A9",
5023
- accent: "#182F31",
5024
- accentForeground: "#E8EFF1",
5025
- destructive: "#E08072",
5026
- destructiveForeground: "#0F1A1F",
5027
- border: "#2A3B42",
5028
- input: "#2A3B42",
5029
- ring: "#63BDB4",
5030
- radius: "0px",
5031
- surface: "#16242A",
5032
- surfaceHover: "#182F31",
5033
- canvas: "#0F1A1F",
5034
- panel: "#16242A",
5035
- borderStrong: "#2F4F4C",
5036
- textDim: "#5E7680"
5037
- };
5038
- var cleanPreset = {
5039
- background: "#F4F7F8",
5040
- foreground: "#12222A",
5041
- card: "#FFFFFF",
5042
- primary: "#1F6B6E",
5043
- primaryForeground: "#FFFFFF",
5044
- secondary: "#EDF3F2",
5045
- secondaryForeground: "#12222A",
5046
- muted: "#EDF3F2",
5047
- mutedForeground: "#6A7B85",
5048
- accent: "#EDF3F2",
5049
- accentForeground: "#12222A",
5050
- destructive: "#B04A3C",
5051
- destructiveForeground: "#FFFFFF",
5052
- border: "#DCE4E8",
5053
- input: "#DCE4E8",
5054
- ring: "#1F6B6E",
5055
- radius: "0px",
5056
- surface: "#FAFCFC",
5057
- surfaceHover: "#EDF3F2",
5058
- canvas: "#F4F7F8",
5059
- panel: "#FFFFFF",
5060
- borderStrong: "#B9D1CF",
5061
- textDim: "#6A7B85"
5051
+ function formatCurrency(amount, currency) {
5052
+ if (amount == null) return "";
5053
+ try {
5054
+ return new Intl.NumberFormat(void 0, {
5055
+ style: "currency",
5056
+ currency: currency ?? "USD"
5057
+ }).format(amount);
5058
+ } catch {
5059
+ return `${currency ?? "USD"} ${amount.toFixed(2)}`;
5060
+ }
5061
+ }
5062
+ function ProPaymentField(props) {
5063
+ const { field, value, error, touched, disabled, readonly, onChange, onBlur, customProps } = props;
5064
+ const config = field.config;
5065
+ const current = value ?? { status: "pending" };
5066
+ const provider = config?.provider ?? "stripe";
5067
+ const publicKey = config?.publicKey;
5068
+ const amount = customProps?.amount ?? config?.amount;
5069
+ const currency = config?.currency ?? "USD";
5070
+ const directSecret = customProps?.clientSecret;
5071
+ const onCreateIntent = customProps?.onCreatePaymentIntent;
5072
+ const onPaymentComplete = customProps?.onPaymentComplete;
5073
+ const serverUrl = config?.serverUrl;
5074
+ const [clientSecret, setClientSecret] = react.useState(directSecret);
5075
+ const [intentLoading, setIntentLoading] = react.useState(false);
5076
+ const [intentError, setIntentError] = react.useState(null);
5077
+ const mode = directSecret ? "direct" : onCreateIntent ? "callback" : serverUrl ? "url" : "setup";
5078
+ react.useEffect(() => {
5079
+ if (directSecret) {
5080
+ setClientSecret(directSecret);
5081
+ return;
5082
+ }
5083
+ if (mode === "setup" || !amount || !publicKey) return;
5084
+ if (clientSecret) return;
5085
+ const fetchIntent = async () => {
5086
+ setIntentLoading(true);
5087
+ setIntentError(null);
5088
+ try {
5089
+ if (mode === "callback" && onCreateIntent) {
5090
+ const result = await onCreateIntent({ amount, currency, provider, metadata: { fieldId: field.id } });
5091
+ setClientSecret(result.clientSecret);
5092
+ } else if (mode === "url" && serverUrl) {
5093
+ const res = await fetch(serverUrl, {
5094
+ method: "POST",
5095
+ headers: { "Content-Type": "application/json" },
5096
+ body: JSON.stringify({ amount, currency, provider, metadata: { fieldId: field.id } })
5097
+ });
5098
+ if (!res.ok) throw new Error(`Server error (${res.status})`);
5099
+ const data = await res.json();
5100
+ setClientSecret(data.clientSecret);
5101
+ }
5102
+ } catch (err) {
5103
+ setIntentError(err instanceof Error ? err.message : "Failed to create payment intent");
5104
+ } finally {
5105
+ setIntentLoading(false);
5106
+ }
5107
+ };
5108
+ fetchIntent();
5109
+ }, [mode, amount, currency, provider, publicKey, directSecret, clientSecret, onCreateIntent, serverUrl, field.id]);
5110
+ const handleSuccess = (chargeId) => {
5111
+ const result = { status: "succeeded", chargeId };
5112
+ onChange(result);
5113
+ onPaymentComplete?.(result);
5114
+ onBlur();
5115
+ };
5116
+ const handleError = (message) => {
5117
+ const result = { status: "failed", error: message };
5118
+ onChange(result);
5119
+ onPaymentComplete?.(result);
5120
+ onBlur();
5121
+ };
5122
+ if (!publicKey) {
5123
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-2 border-dashed border-input p-4 text-center", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
5124
+ "Payment field \u2014 configure a ",
5125
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "bg-muted px-1 rounded text-xs", children: "publicKey" }),
5126
+ " in the field properties panel."
5127
+ ] }) }) });
5128
+ }
5129
+ if (provider !== "stripe") {
5130
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-input bg-muted/50 p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
5131
+ 'Provider "',
5132
+ provider,
5133
+ '" \u2014 coming soon.'
5134
+ ] }) }) });
5135
+ }
5136
+ if (current.status === "succeeded") {
5137
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-input p-4", children: [
5138
+ amount != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground mb-2", children: [
5139
+ formatCurrency(amount, currency),
5140
+ config?.description && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5141
+ " \u2014 ",
5142
+ config.description
5143
+ ] })
5144
+ ] }),
5145
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm font-medium", style: { color: "var(--success, #22c55e)" }, children: [
5146
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, width: 16, height: 16, children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" }) }),
5147
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5148
+ "Payment successful",
5149
+ current.chargeId ? ` (${current.chargeId})` : ""
5150
+ ] })
5151
+ ] })
5152
+ ] }) });
5153
+ }
5154
+ if (current.status === "failed") {
5155
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-destructive/50 p-4", children: [
5156
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-destructive font-medium", children: [
5157
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, width: 16, height: 16, children: [
5158
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
5159
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
5160
+ ] }),
5161
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5162
+ "Payment failed",
5163
+ current.error ? `: ${current.error}` : ""
5164
+ ] })
5165
+ ] }),
5166
+ /* @__PURE__ */ jsxRuntime.jsx(
5167
+ "button",
5168
+ {
5169
+ type: "button",
5170
+ className: "mt-2 text-xs text-primary hover:underline",
5171
+ onClick: () => {
5172
+ onChange({ status: "pending" });
5173
+ setClientSecret(void 0);
5174
+ },
5175
+ children: "Retry"
5176
+ }
5177
+ )
5178
+ ] }) });
5179
+ }
5180
+ if (intentLoading || mode !== "setup" && mode !== "direct" && !clientSecret) {
5181
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-input p-4", children: [
5182
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
5183
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: "Payment" }),
5184
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs bg-muted px-2 py-0.5 rounded", children: provider })
5185
+ ] }),
5186
+ amount != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground mb-3", children: [
5187
+ "Amount: ",
5188
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: formatCurrency(amount, currency) }),
5189
+ config?.description && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5190
+ " \u2014 ",
5191
+ config.description
5192
+ ] })
5193
+ ] }),
5194
+ intentError ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5195
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: intentError }),
5196
+ /* @__PURE__ */ jsxRuntime.jsx(
5197
+ "button",
5198
+ {
5199
+ type: "button",
5200
+ className: "mt-2 text-xs text-primary hover:underline",
5201
+ onClick: () => {
5202
+ setIntentError(null);
5203
+ setClientSecret(void 0);
5204
+ },
5205
+ children: "Retry"
5206
+ }
5207
+ )
5208
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
5209
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "animate-spin size-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "60", strokeDashoffset: "20" }) }),
5210
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Preparing payment..." })
5211
+ ] })
5212
+ ] }) });
5213
+ }
5214
+ if (!clientSecret) {
5215
+ const waitingForAmount = config?.amountField && !amount;
5216
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-input p-4", children: [
5217
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
5218
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: "Payment" }),
5219
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs bg-muted px-2 py-0.5 rounded", children: provider })
5220
+ ] }),
5221
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: waitingForAmount ? "Select an option above to proceed with payment." : "Provide a clientSecret via customProps, an onCreatePaymentIntent callback, or a serverUrl." })
5222
+ ] }) });
5223
+ }
5224
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-input p-4", children: [
5225
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
5226
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: "Payment" }),
5227
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs bg-muted px-2 py-0.5 rounded", children: provider })
5228
+ ] }),
5229
+ amount != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground mb-3", children: [
5230
+ "Amount: ",
5231
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: formatCurrency(amount, currency) }),
5232
+ config?.description && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5233
+ " \u2014 ",
5234
+ config.description
5235
+ ] })
5236
+ ] }),
5237
+ /* @__PURE__ */ jsxRuntime.jsx(
5238
+ react.Suspense,
5239
+ {
5240
+ fallback: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground py-4", children: [
5241
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "animate-spin size-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "60", strokeDashoffset: "20" }) }),
5242
+ "Loading payment form..."
5243
+ ] }),
5244
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5245
+ PayKitCheckout,
5246
+ {
5247
+ publicKey,
5248
+ clientSecret,
5249
+ amount,
5250
+ currency,
5251
+ disabled: disabled || readonly,
5252
+ onSuccess: handleSuccess,
5253
+ onError: handleError
5254
+ }
5255
+ )
5256
+ }
5257
+ )
5258
+ ] }) });
5259
+ }
5260
+ function PayKitCheckout({
5261
+ publicKey,
5262
+ clientSecret,
5263
+ amount,
5264
+ currency,
5265
+ disabled,
5266
+ onSuccess,
5267
+ onError
5268
+ }) {
5269
+ const [PayKit, setPayKit] = react.useState(null);
5270
+ const [loadError, setLoadError] = react.useState(null);
5271
+ react.useEffect(() => {
5272
+ let cancelled = false;
5273
+ Promise.all([
5274
+ // @ts-expect-error — optional peer dep, resolved at runtime
5275
+ import('@squaredr/paykit-react'),
5276
+ // @ts-expect-error — optional peer dep, resolved at runtime
5277
+ import('@squaredr/paykit-stripe/client')
5278
+ ]).then(([paykit, stripe]) => {
5279
+ if (cancelled) return;
5280
+ setPayKit({
5281
+ Provider: paykit.PayKitProvider,
5282
+ Form: paykit.CheckoutForm,
5283
+ adapter: new stripe.StripeClientAdapter(publicKey)
5284
+ });
5285
+ }).catch((err) => {
5286
+ if (cancelled) return;
5287
+ setLoadError(
5288
+ `Failed to load payment SDK. Ensure @squaredr/paykit-react and @squaredr/paykit-stripe are installed. (${err.message})`
5289
+ );
5290
+ });
5291
+ return () => {
5292
+ cancelled = true;
5293
+ };
5294
+ }, [publicKey]);
5295
+ if (loadError) {
5296
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: loadError });
5297
+ }
5298
+ if (!PayKit) {
5299
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground py-2", children: [
5300
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "animate-spin size-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "60", strokeDashoffset: "20" }) }),
5301
+ "Loading Stripe..."
5302
+ ] });
5303
+ }
5304
+ return /* @__PURE__ */ jsxRuntime.jsx(PayKit.Provider, { clientAdapter: PayKit.adapter, children: /* @__PURE__ */ jsxRuntime.jsx(
5305
+ PayKit.Form,
5306
+ {
5307
+ clientSecret,
5308
+ submitLabel: disabled ? "Payment disabled" : `Pay ${formatCurrency(amount, currency)}`,
5309
+ onSuccess: (result) => onSuccess(result.chargeId),
5310
+ onError: (err) => onError(err.message)
5311
+ }
5312
+ ) });
5313
+ }
5314
+ var PRO_FIELD_OVERRIDES = {
5315
+ payment: ProPaymentField
5062
5316
  };
5063
5317
 
5064
5318
  // src/response-viewer/clinical-display-data.ts
@@ -6802,6 +7056,7 @@ function ResponseViewerInner({
6802
7056
  return /* @__PURE__ */ jsxRuntime.jsxs(
6803
7057
  "div",
6804
7058
  {
7059
+ "data-fcrv-root": "",
6805
7060
  className: "flex flex-col border border-border rounded-lg overflow-hidden bg-background text-foreground",
6806
7061
  style: { height: heightValue, width: widthValue },
6807
7062
  children: [
@@ -7648,7 +7903,7 @@ function PaletteGenerator({ theme, onApply, onClose }) {
7648
7903
  }
7649
7904
 
7650
7905
  // src/theme-editor/presets.ts
7651
- var draftingTealPreset = {
7906
+ var cleanPreset = {
7652
7907
  colors: {
7653
7908
  primary: "#1F6B6E",
7654
7909
  primaryForeground: "#FFFFFF",
@@ -7668,45 +7923,312 @@ var draftingTealPreset = {
7668
7923
  inputBackground: "#FFFFFF"
7669
7924
  },
7670
7925
  typography: {
7671
- fontFamily: "'Space Grotesk', 'IBM Plex Sans', system-ui, sans-serif",
7926
+ fontFamily: "Inter, system-ui, sans-serif",
7672
7927
  scale: "comfortable",
7673
- questionSize: "1.1875rem",
7674
- labelSize: "0.8125rem",
7928
+ questionSize: "1.125rem",
7929
+ labelSize: "0.875rem",
7675
7930
  helpTextSize: "0.8125rem",
7676
7931
  bodySize: "0.9375rem"
7677
7932
  },
7678
- shape: {
7679
- radius: "none",
7680
- inputRadius: "0px",
7681
- buttonRadius: "0px",
7682
- cardRadius: "0px"
7933
+ shape: { radius: "none", inputRadius: "0px", buttonRadius: "0px", cardRadius: "0px" },
7934
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
7935
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "card" }
7936
+ };
7937
+ var cleanDarkPreset = {
7938
+ colors: {
7939
+ primary: "#63BDB4",
7940
+ primaryForeground: "#0F1A1F",
7941
+ secondary: "#2F4F4C",
7942
+ secondaryForeground: "#E8EFF1",
7943
+ error: "#E08072",
7944
+ errorForeground: "#0F1A1F",
7945
+ warning: "#E0A94F",
7946
+ success: "#5DB89A",
7947
+ surface: "#16242A",
7948
+ background: "#0F1A1F",
7949
+ text: "#E8EFF1",
7950
+ textMuted: "#8CA1A9",
7951
+ textDisabled: "#3D5259",
7952
+ border: "#2A3B42",
7953
+ borderFocus: "#63BDB4",
7954
+ inputBackground: "#16242A"
7683
7955
  },
7684
- spacing: {
7685
- base: 16,
7686
- sectionGap: 32,
7687
- fieldGap: 24,
7688
- inputPaddingX: 12,
7689
- inputPaddingY: 10
7956
+ typography: {
7957
+ fontFamily: "Inter, system-ui, sans-serif",
7958
+ scale: "comfortable",
7959
+ questionSize: "1.125rem",
7960
+ labelSize: "0.875rem",
7961
+ helpTextSize: "0.8125rem",
7962
+ bodySize: "0.9375rem"
7690
7963
  },
7691
- layout: {
7692
- maxWidth: "640px",
7693
- alignment: "left",
7694
- progressPosition: "top",
7695
- sectionLayout: "flat"
7696
- }
7964
+ shape: { radius: "none", inputRadius: "0px", buttonRadius: "0px", cardRadius: "0px" },
7965
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
7966
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "card" }
7967
+ };
7968
+ var modernPreset = {
7969
+ colors: {
7970
+ primary: "#6366F1",
7971
+ primaryForeground: "#ffffff",
7972
+ secondary: "#8B5CF6",
7973
+ secondaryForeground: "#ffffff",
7974
+ error: "#F43F5E",
7975
+ errorForeground: "#ffffff",
7976
+ warning: "#F59E0B",
7977
+ success: "#22C55E",
7978
+ surface: "#ffffff",
7979
+ background: "#FAFAFA",
7980
+ text: "#18181B",
7981
+ textMuted: "#71717A",
7982
+ textDisabled: "#D4D4D8",
7983
+ border: "#E4E4E7",
7984
+ borderFocus: "#6366F1",
7985
+ inputBackground: "#FAFAFA"
7986
+ },
7987
+ typography: {
7988
+ fontFamily: "'Plus Jakarta Sans', Inter, system-ui, sans-serif",
7989
+ scale: "comfortable",
7990
+ questionSize: "1.25rem",
7991
+ labelSize: "0.875rem",
7992
+ helpTextSize: "0.8125rem",
7993
+ bodySize: "1rem"
7994
+ },
7995
+ shape: { radius: "lg", inputRadius: "12px", buttonRadius: "12px", cardRadius: "16px" },
7996
+ spacing: { base: 16, sectionGap: 40, fieldGap: 28, inputPaddingX: 16, inputPaddingY: 12 },
7997
+ layout: { maxWidth: "680px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
7998
+ };
7999
+ var modernDarkPreset = {
8000
+ colors: {
8001
+ primary: "#818CF8",
8002
+ primaryForeground: "#1E1B4B",
8003
+ secondary: "#A78BFA",
8004
+ secondaryForeground: "#1E1B4B",
8005
+ error: "#FB7185",
8006
+ errorForeground: "#1E1B4B",
8007
+ warning: "#FBBF24",
8008
+ success: "#4ADE80",
8009
+ surface: "#1E1B4B",
8010
+ background: "#13111C",
8011
+ text: "#E8E6F0",
8012
+ textMuted: "#A1A1AA",
8013
+ textDisabled: "#3F3F46",
8014
+ border: "#2E2B4A",
8015
+ borderFocus: "#818CF8",
8016
+ inputBackground: "#1E1B4B"
8017
+ },
8018
+ typography: {
8019
+ fontFamily: "'Plus Jakarta Sans', Inter, system-ui, sans-serif",
8020
+ scale: "comfortable",
8021
+ questionSize: "1.25rem",
8022
+ labelSize: "0.875rem",
8023
+ helpTextSize: "0.8125rem",
8024
+ bodySize: "1rem"
8025
+ },
8026
+ shape: { radius: "lg", inputRadius: "12px", buttonRadius: "12px", cardRadius: "16px" },
8027
+ spacing: { base: 16, sectionGap: 40, fieldGap: 28, inputPaddingX: 16, inputPaddingY: 12 },
8028
+ layout: { maxWidth: "680px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
8029
+ };
8030
+ var clinicalPreset = {
8031
+ colors: {
8032
+ primary: "#0284C7",
8033
+ primaryForeground: "#ffffff",
8034
+ secondary: "#0891B2",
8035
+ secondaryForeground: "#ffffff",
8036
+ error: "#DC2626",
8037
+ errorForeground: "#ffffff",
8038
+ warning: "#D97706",
8039
+ success: "#16A34A",
8040
+ surface: "#ffffff",
8041
+ background: "#F0F9FF",
8042
+ text: "#0C4A6E",
8043
+ textMuted: "#64748B",
8044
+ textDisabled: "#CBD5E1",
8045
+ border: "#BAE6FD",
8046
+ borderFocus: "#0284C7",
8047
+ inputBackground: "#ffffff"
8048
+ },
8049
+ typography: {
8050
+ fontFamily: "'Source Sans 3', 'Segoe UI', system-ui, sans-serif",
8051
+ scale: "comfortable",
8052
+ questionSize: "1.0625rem",
8053
+ labelSize: "0.875rem",
8054
+ helpTextSize: "0.8125rem",
8055
+ bodySize: "0.9375rem"
8056
+ },
8057
+ shape: { radius: "sm", inputRadius: "6px", buttonRadius: "6px", cardRadius: "8px" },
8058
+ spacing: { base: 16, sectionGap: 28, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8059
+ layout: { maxWidth: "680px", alignment: "left", progressPosition: "top", sectionLayout: "bordered" }
8060
+ };
8061
+ var clinicalDarkPreset = {
8062
+ colors: {
8063
+ primary: "#38BDF8",
8064
+ primaryForeground: "#0C1929",
8065
+ secondary: "#22D3EE",
8066
+ secondaryForeground: "#0C1929",
8067
+ error: "#F87171",
8068
+ errorForeground: "#0C1929",
8069
+ warning: "#FBBF24",
8070
+ success: "#34D399",
8071
+ surface: "#0F2438",
8072
+ background: "#0C1929",
8073
+ text: "#E0F2FE",
8074
+ textMuted: "#7DD3FC",
8075
+ textDisabled: "#1E3A5F",
8076
+ border: "#1E3A5F",
8077
+ borderFocus: "#38BDF8",
8078
+ inputBackground: "#0F2438"
8079
+ },
8080
+ typography: {
8081
+ fontFamily: "'Source Sans 3', 'Segoe UI', system-ui, sans-serif",
8082
+ scale: "comfortable",
8083
+ questionSize: "1.0625rem",
8084
+ labelSize: "0.875rem",
8085
+ helpTextSize: "0.8125rem",
8086
+ bodySize: "0.9375rem"
8087
+ },
8088
+ shape: { radius: "sm", inputRadius: "6px", buttonRadius: "6px", cardRadius: "8px" },
8089
+ spacing: { base: 16, sectionGap: 28, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8090
+ layout: { maxWidth: "680px", alignment: "left", progressPosition: "top", sectionLayout: "bordered" }
7697
8091
  };
7698
- var COMPARISON_PRESETS = {
7699
- "drafting-teal": { label: "Drafting Teal", theme: draftingTealPreset },
7700
- clean: { label: "Clean", theme: fieldcraftReact.cleanPreset },
7701
- dark: { label: "Dark", theme: fieldcraftReact.darkPreset },
7702
- modern: { label: "Modern", theme: fieldcraftReact.modernPreset },
7703
- "high-contrast": { label: "High Contrast", theme: fieldcraftReact.highContrastPreset },
7704
- clinical: { label: "Clinical", theme: fieldcraftReact.clinicalPreset },
7705
- playful: { label: "Playful", theme: fieldcraftReact.playfulPreset }
8092
+ var playfulPreset = {
8093
+ colors: {
8094
+ primary: "#EC4899",
8095
+ primaryForeground: "#ffffff",
8096
+ secondary: "#8B5CF6",
8097
+ secondaryForeground: "#ffffff",
8098
+ error: "#EF4444",
8099
+ errorForeground: "#ffffff",
8100
+ warning: "#F59E0B",
8101
+ success: "#10B981",
8102
+ surface: "#ffffff",
8103
+ background: "#FFF7ED",
8104
+ text: "#1C1917",
8105
+ textMuted: "#78716C",
8106
+ textDisabled: "#D6D3D1",
8107
+ border: "#FDE68A",
8108
+ borderFocus: "#EC4899",
8109
+ inputBackground: "#FFFBEB"
8110
+ },
8111
+ typography: {
8112
+ fontFamily: "'Nunito', 'Comic Neue', system-ui, sans-serif",
8113
+ scale: "spacious",
8114
+ questionSize: "1.25rem",
8115
+ labelSize: "0.9375rem",
8116
+ helpTextSize: "0.875rem",
8117
+ bodySize: "1rem"
8118
+ },
8119
+ shape: { radius: "full", inputRadius: "9999px", buttonRadius: "9999px", cardRadius: "20px" },
8120
+ spacing: { base: 18, sectionGap: 36, fieldGap: 28, inputPaddingX: 18, inputPaddingY: 12 },
8121
+ layout: { maxWidth: "600px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
8122
+ };
8123
+ var playfulDarkPreset = {
8124
+ colors: {
8125
+ primary: "#F472B6",
8126
+ primaryForeground: "#1A0A14",
8127
+ secondary: "#A78BFA",
8128
+ secondaryForeground: "#1A0A14",
8129
+ error: "#FCA5A5",
8130
+ errorForeground: "#1A0A14",
8131
+ warning: "#FCD34D",
8132
+ success: "#6EE7B7",
8133
+ surface: "#2D1F2B",
8134
+ background: "#1A0F19",
8135
+ text: "#FDF2F8",
8136
+ textMuted: "#D4A9C4",
8137
+ textDisabled: "#4A3248",
8138
+ border: "#5C3D56",
8139
+ borderFocus: "#F472B6",
8140
+ inputBackground: "#2D1F2B"
8141
+ },
8142
+ typography: {
8143
+ fontFamily: "'Nunito', 'Comic Neue', system-ui, sans-serif",
8144
+ scale: "spacious",
8145
+ questionSize: "1.25rem",
8146
+ labelSize: "0.9375rem",
8147
+ helpTextSize: "0.875rem",
8148
+ bodySize: "1rem"
8149
+ },
8150
+ shape: { radius: "full", inputRadius: "9999px", buttonRadius: "9999px", cardRadius: "20px" },
8151
+ spacing: { base: 18, sectionGap: 36, fieldGap: 28, inputPaddingX: 18, inputPaddingY: 12 },
8152
+ layout: { maxWidth: "600px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
7706
8153
  };
8154
+ var highContrastPreset = {
8155
+ colors: {
8156
+ primary: "#0000EE",
8157
+ primaryForeground: "#ffffff",
8158
+ secondary: "#6B21A8",
8159
+ secondaryForeground: "#ffffff",
8160
+ error: "#B91C1C",
8161
+ errorForeground: "#ffffff",
8162
+ warning: "#92400E",
8163
+ success: "#166534",
8164
+ surface: "#ffffff",
8165
+ background: "#ffffff",
8166
+ text: "#000000",
8167
+ textMuted: "#374151",
8168
+ textDisabled: "#9CA3AF",
8169
+ border: "#000000",
8170
+ borderFocus: "#0000EE",
8171
+ inputBackground: "#ffffff"
8172
+ },
8173
+ typography: {
8174
+ fontFamily: "Arial, Helvetica, sans-serif",
8175
+ scale: "spacious",
8176
+ questionSize: "1.25rem",
8177
+ labelSize: "1rem",
8178
+ helpTextSize: "0.9375rem",
8179
+ bodySize: "1rem"
8180
+ },
8181
+ shape: { radius: "sm", inputRadius: "4px", buttonRadius: "4px", cardRadius: "4px" },
8182
+ spacing: { base: 20, sectionGap: 40, fieldGap: 32, inputPaddingX: 14, inputPaddingY: 12 },
8183
+ layout: { maxWidth: "720px", alignment: "left", progressPosition: "top", sectionLayout: "bordered" }
8184
+ };
8185
+ var highContrastDarkPreset = {
8186
+ colors: {
8187
+ primary: "#93C5FD",
8188
+ primaryForeground: "#000000",
8189
+ secondary: "#C084FC",
8190
+ secondaryForeground: "#000000",
8191
+ error: "#FCA5A5",
8192
+ errorForeground: "#000000",
8193
+ warning: "#FCD34D",
8194
+ success: "#86EFAC",
8195
+ surface: "#000000",
8196
+ background: "#000000",
8197
+ text: "#FFFFFF",
8198
+ textMuted: "#D1D5DB",
8199
+ textDisabled: "#6B7280",
8200
+ border: "#FFFFFF",
8201
+ borderFocus: "#93C5FD",
8202
+ inputBackground: "#000000"
8203
+ },
8204
+ typography: {
8205
+ fontFamily: "Arial, Helvetica, sans-serif",
8206
+ scale: "spacious",
8207
+ questionSize: "1.25rem",
8208
+ labelSize: "1rem",
8209
+ helpTextSize: "0.9375rem",
8210
+ bodySize: "1rem"
8211
+ },
8212
+ shape: { radius: "sm", inputRadius: "4px", buttonRadius: "4px", cardRadius: "4px" },
8213
+ spacing: { base: 20, sectionGap: 40, fieldGap: 32, inputPaddingX: 14, inputPaddingY: 12 },
8214
+ layout: { maxWidth: "720px", alignment: "left", progressPosition: "top", sectionLayout: "bordered" }
8215
+ };
8216
+ var PRESET_FAMILIES = {
8217
+ clean: { light: cleanPreset, dark: cleanDarkPreset, label: "Clean" },
8218
+ modern: { light: modernPreset, dark: modernDarkPreset, label: "Modern" },
8219
+ clinical: { light: clinicalPreset, dark: clinicalDarkPreset, label: "Clinical" },
8220
+ playful: { light: playfulPreset, dark: playfulDarkPreset, label: "Playful" },
8221
+ "high-contrast": { light: highContrastPreset, dark: highContrastDarkPreset, label: "High contrast" }
8222
+ };
8223
+ var COMPARISON_PRESETS = Object.fromEntries(
8224
+ Object.entries(PRESET_FAMILIES).map(([key, family]) => [
8225
+ key,
8226
+ { label: family.label, theme: family.light }
8227
+ ])
8228
+ );
7707
8229
  function ThemeComparison({ currentTheme, onClose }) {
7708
8230
  const [compareKey, setCompareKey] = react.useState("clean");
7709
- const compareTheme = COMPARISON_PRESETS[compareKey]?.theme ?? fieldcraftReact.cleanPreset;
8231
+ const compareTheme = COMPARISON_PRESETS[compareKey]?.theme ?? PRESET_FAMILIES.clean.light;
7710
8232
  const diffs = getColorDiffs(currentTheme, compareTheme);
7711
8233
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fcte-compare", children: [
7712
8234
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fcte-compare__header", children: [
@@ -7804,7 +8326,54 @@ function getColorDiffs(a, b) {
7804
8326
  }
7805
8327
  return diffs;
7806
8328
  }
8329
+
8330
+ // src/utils/resolve-theme-from-dom.ts
8331
+ function resolveThemeFromDOM() {
8332
+ if (typeof window === "undefined") return {};
8333
+ const styles = getComputedStyle(document.documentElement);
8334
+ const get = (prop) => {
8335
+ const val = styles.getPropertyValue(prop).trim();
8336
+ return val || void 0;
8337
+ };
8338
+ return {
8339
+ colors: {
8340
+ primary: get("--primary"),
8341
+ primaryForeground: get("--primary-foreground"),
8342
+ secondary: get("--secondary"),
8343
+ secondaryForeground: get("--secondary-foreground"),
8344
+ error: get("--destructive"),
8345
+ errorForeground: get("--destructive-foreground"),
8346
+ warning: get("--fc-color-warning"),
8347
+ success: get("--fc-color-success"),
8348
+ surface: get("--card"),
8349
+ background: get("--background"),
8350
+ text: get("--foreground"),
8351
+ textMuted: get("--muted-foreground"),
8352
+ textDisabled: void 0,
8353
+ border: get("--border"),
8354
+ borderFocus: get("--ring"),
8355
+ inputBackground: get("--input-background") ?? get("--card")
8356
+ },
8357
+ typography: {
8358
+ fontFamily: get("--fc-font-family"),
8359
+ // scale is an enum ("compact" | "comfortable" | "spacious") — not resolvable from CSS
8360
+ questionSize: get("--fc-font-question"),
8361
+ labelSize: get("--fc-font-label"),
8362
+ helpTextSize: get("--fc-font-help"),
8363
+ bodySize: get("--fc-font-body")
8364
+ },
8365
+ shape: {
8366
+ // radius is an enum ("none" | "sm" | "md" | "lg" | "full") — not resolvable from CSS
8367
+ inputRadius: get("--fc-radius-input"),
8368
+ buttonRadius: get("--fc-radius-button"),
8369
+ cardRadius: get("--fc-radius-card")
8370
+ }
8371
+ };
8372
+ }
7807
8373
  var ThemeCtx2 = react.createContext({});
8374
+ function useEditorTheme() {
8375
+ return react.useContext(ThemeCtx2);
8376
+ }
7808
8377
  function themeToCssVars2(theme) {
7809
8378
  const vars = {};
7810
8379
  if (theme.background) vars["--fcte-bg"] = theme.background;
@@ -7825,15 +8394,15 @@ function ThemeEditorThemeProvider({ theme, children }) {
7825
8394
  const cssVars = react.useMemo(() => themeToCssVars2(resolved), [resolved]);
7826
8395
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeCtx2.Provider, { value: resolved, children: /* @__PURE__ */ jsxRuntime.jsx("div", { "data-fcte-root": "", style: cssVars, className: "fcte-provider-root", children }) });
7827
8396
  }
7828
- var PRESETS = {
7829
- "drafting-teal": draftingTealPreset,
7830
- clean: fieldcraftReact.cleanPreset,
7831
- dark: fieldcraftReact.darkPreset,
7832
- modern: fieldcraftReact.modernPreset,
7833
- "high-contrast": fieldcraftReact.highContrastPreset,
7834
- clinical: fieldcraftReact.clinicalPreset,
7835
- playful: fieldcraftReact.playfulPreset
7836
- };
8397
+ function isDarkTheme(theme) {
8398
+ const bg = theme.colors?.background ?? "#FFFFFF";
8399
+ const hex = bg.replace("#", "");
8400
+ if (hex.length < 6) return false;
8401
+ const r = parseInt(hex.slice(0, 2), 16);
8402
+ const g = parseInt(hex.slice(2, 4), 16);
8403
+ const b = parseInt(hex.slice(4, 6), 16);
8404
+ return 0.299 * r + 0.587 * g + 0.114 * b < 128;
8405
+ }
7837
8406
  var SECTIONS = [
7838
8407
  {
7839
8408
  id: "colors",
@@ -7963,9 +8532,17 @@ function ThemeEditorInner({
7963
8532
  toolbarExtra,
7964
8533
  showPreview = true
7965
8534
  }) {
7966
- const [theme, setTheme] = react.useState(initialTheme ?? draftingTealPreset);
8535
+ const resolvedInitial = react.useMemo(
8536
+ () => initialTheme ?? resolveThemeFromDOM(),
8537
+ // eslint-disable-next-line react-hooks/exhaustive-deps
8538
+ []
8539
+ );
8540
+ const [theme, setTheme] = react.useState(resolvedInitial);
7967
8541
  const [activeSection, setActiveSection] = react.useState("colors");
7968
- const [presetKey, setPresetKey] = react.useState(initialTheme ? "custom" : "drafting-teal");
8542
+ const [presetKey, setPresetKey] = react.useState("custom");
8543
+ const [mode, setMode] = react.useState(
8544
+ () => isDarkTheme(resolvedInitial) ? "dark" : "light"
8545
+ );
7969
8546
  const [showPalette, setShowPalette] = react.useState(false);
7970
8547
  const [showComparison, setShowComparison] = react.useState(false);
7971
8548
  const themeRef = react.useRef(theme);
@@ -7995,16 +8572,30 @@ function ThemeEditorInner({
7995
8572
  [onChange]
7996
8573
  );
7997
8574
  const loadPreset = react.useCallback(
7998
- (key) => {
7999
- const preset = PRESETS[key];
8000
- if (preset) {
8575
+ (key, forceMode) => {
8576
+ const family = PRESET_FAMILIES[key];
8577
+ if (family) {
8578
+ const m = forceMode ?? mode;
8579
+ const preset = family[m];
8001
8580
  setTheme(preset);
8002
8581
  setPresetKey(key);
8003
8582
  onChange?.(preset);
8004
8583
  }
8005
8584
  },
8006
- [onChange]
8585
+ [onChange, mode]
8007
8586
  );
8587
+ const toggleMode = react.useCallback(() => {
8588
+ setMode((prev) => {
8589
+ const next = prev === "light" ? "dark" : "light";
8590
+ const family = PRESET_FAMILIES[presetKey];
8591
+ if (family) {
8592
+ const preset = family[next];
8593
+ setTheme(preset);
8594
+ onChange?.(preset);
8595
+ }
8596
+ return next;
8597
+ });
8598
+ }, [presetKey, onChange]);
8008
8599
  const exportJson = react.useCallback(() => {
8009
8600
  const blob = new Blob([JSON.stringify(theme, null, 2)], { type: "application/json" });
8010
8601
  const url = URL.createObjectURL(blob);
@@ -8070,9 +8661,18 @@ function ThemeEditorInner({
8070
8661
  className: "fcte-toolbar__preset",
8071
8662
  children: [
8072
8663
  /* @__PURE__ */ jsxRuntime.jsx("option", { value: "custom", disabled: true, children: "Custom" }),
8073
- Object.keys(PRESETS).map((k) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: k, children: k.charAt(0).toUpperCase() + k.slice(1).replace("-", " ") }, k))
8664
+ Object.entries(PRESET_FAMILIES).map(([k, fam]) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: k, children: fam.label }, k))
8074
8665
  ]
8075
8666
  }
8667
+ ),
8668
+ /* @__PURE__ */ jsxRuntime.jsx(
8669
+ "button",
8670
+ {
8671
+ onClick: toggleMode,
8672
+ className: "fcte-btn fcte-btn--secondary fcte-toolbar__mode",
8673
+ title: mode === "light" ? "Switch to dark mode" : "Switch to light mode",
8674
+ children: mode === "light" ? "\u2600" : "\u263E"
8675
+ }
8076
8676
  )
8077
8677
  ] }),
8078
8678
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fcte-toolbar__right", children: [
@@ -8241,10 +8841,38 @@ function ThemeEditorInner({
8241
8841
  // src/theme-editor/ThemeEditor.tsx
8242
8842
  var ThemeEditor = requireLicense(ThemeEditorInner, "ThemeEditor");
8243
8843
 
8844
+ // src/theme-editor/theme/presets.ts
8845
+ var themeEditorLightPreset = {
8846
+ background: "#F4F7F8",
8847
+ surface: "#FFFFFF",
8848
+ surfaceHover: "#EDF3F2",
8849
+ text: "#12222A",
8850
+ textMuted: "#6A7B85",
8851
+ textDim: "#96A5AD",
8852
+ border: "#DCE4E8",
8853
+ borderStrong: "#B9D1CF",
8854
+ inputBackground: "#FAFCFC",
8855
+ accent: "#1F6B6E",
8856
+ accentForeground: "#FFFFFF"
8857
+ };
8858
+ var themeEditorDarkPreset = {
8859
+ background: "#0F1A1F",
8860
+ surface: "#16242A",
8861
+ surfaceHover: "#182F31",
8862
+ text: "#E8EFF1",
8863
+ textMuted: "#8CA1A9",
8864
+ textDim: "#5E7680",
8865
+ border: "#2A3B42",
8866
+ borderStrong: "#2F4F4C",
8867
+ inputBackground: "#12222A",
8868
+ accent: "#63BDB4",
8869
+ accentForeground: "#0F1A1F"
8870
+ };
8871
+
8244
8872
  // src/index.ts
8245
8873
  if (typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" && globalThis.process.env?.NODE_ENV !== "production") {
8246
8874
  const _fc_banner = `
8247
- %c FieldCraft Pro %c v1.4.0
8875
+ %c FieldCraft Pro %c v1.6.0
8248
8876
 
8249
8877
  %cForm Builder \xB7 Response Viewer \xB7 Theme Editor
8250
8878
 
@@ -8267,16 +8895,19 @@ exports.DEFAULT_SCHEMA = DEFAULT_SCHEMA;
8267
8895
  exports.FieldCraftProProvider = FieldCraftProProvider;
8268
8896
  exports.FormBuilder = FormBuilder;
8269
8897
  exports.FormBuilderThemeProvider = FormBuilderThemeProvider;
8898
+ exports.PRESET_FAMILIES = PRESET_FAMILIES;
8270
8899
  exports.PREVIEW_SCHEMA = PREVIEW_SCHEMA;
8900
+ exports.PRO_FIELD_OVERRIDES = PRO_FIELD_OVERRIDES;
8901
+ exports.ProPaymentField = ProPaymentField;
8271
8902
  exports.QUESTION_TYPE_INFO = QUESTION_TYPE_INFO;
8272
8903
  exports.ResponseViewer = ResponseViewer;
8273
8904
  exports.ThemeEditor = ThemeEditor;
8274
8905
  exports.ThemeEditorInner = ThemeEditorInner;
8906
+ exports.ThemeEditorThemeProvider = ThemeEditorThemeProvider;
8275
8907
  exports.UnlicensedOverlay = UnlicensedOverlay;
8276
8908
  exports.addOption = addOption;
8277
8909
  exports.addQuestion = addQuestion;
8278
8910
  exports.addSection = addSection;
8279
- exports.cleanPreset = cleanPreset;
8280
8911
  exports.cn = cn;
8281
8912
  exports.duplicateQuestion = duplicateQuestion;
8282
8913
  exports.duplicateSection = duplicateSection;
@@ -8294,13 +8925,16 @@ exports.removeOption = removeOption;
8294
8925
  exports.removeQuestion = removeQuestion;
8295
8926
  exports.removeSection = removeSection;
8296
8927
  exports.requireLicense = requireLicense;
8297
- exports.squaredrDarkPreset = squaredrDarkPreset;
8928
+ exports.resolveThemeFromDOM = resolveThemeFromDOM;
8929
+ exports.themeEditorDarkPreset = themeEditorDarkPreset;
8930
+ exports.themeEditorLightPreset = themeEditorLightPreset;
8298
8931
  exports.updateOption = updateOption;
8299
8932
  exports.updateQuestion = updateQuestion;
8300
8933
  exports.updateSection = updateSection;
8301
8934
  exports.useBuilderState = useBuilderState;
8302
8935
  exports.useBuilderTheme = useBuilderTheme;
8303
8936
  exports.useDragDrop = useDragDrop;
8937
+ exports.useEditorTheme = useEditorTheme;
8304
8938
  exports.useLicense = useLicense;
8305
8939
  exports.useUndoRedo = useUndoRedo;
8306
8940
  exports.validateLicense = validateLicense;